Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 1 | package aQute.bnd.component; |
| 2 | |
| 3 | import java.lang.reflect.*; |
| 4 | import java.util.*; |
| 5 | import java.util.regex.*; |
| 6 | |
| 7 | import org.osgi.service.component.annotations.*; |
| 8 | |
Stuart McCulloch | 39cc9ac | 2012-07-16 13:43:38 +0000 | [diff] [blame] | 9 | import aQute.bnd.osgi.*; |
| 10 | import aQute.bnd.osgi.Clazz.MethodDef; |
| 11 | import aQute.bnd.osgi.Descriptors.TypeRef; |
Stuart McCulloch | 6a04666 | 2012-07-19 13:11:20 +0000 | [diff] [blame] | 12 | import aQute.bnd.version.*; |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 13 | import aQute.lib.collections.*; |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 14 | |
| 15 | /** |
| 16 | * fixup any unbind methods To declare no unbind method, the value "-" must be |
| 17 | * used. If not specified, the name of the unbind method is derived from the |
| 18 | * name of the annotated bind method. If the annotated method name begins with |
| 19 | * set, that is replaced with unset to derive the unbind method name. If the |
| 20 | * annotated method name begins with add, that is replaced with remove to derive |
| 21 | * the unbind method name. Otherwise, un is prefixed to the annotated method |
| 22 | * name to derive the unbind method name. |
| 23 | * |
| 24 | * @return |
| 25 | * @throws Exception |
| 26 | */ |
| 27 | public class AnnotationReader extends ClassDataCollector { |
| 28 | final static TypeRef[] EMPTY = new TypeRef[0]; |
| 29 | final static Pattern PROPERTY_PATTERN = Pattern |
Stuart McCulloch | d602fe1 | 2012-07-20 16:50:39 +0000 | [diff] [blame] | 30 | .compile("\\s*([^=\\s:]+)\\s*(?::\\s*(Boolean|Byte|Character|Short|Integer|Long|Float|Double|String)\\s*)?=(.*)"); |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 31 | |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 32 | public static final Version V1_0 = new Version("1.0.0"); // "1.0.0" |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 33 | public static final Version V1_1 = new Version("1.1.0"); // "1.1.0" |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 34 | public static final Version V1_2 = new Version("1.2.0"); // "1.2.0" |
| 35 | // public static final Version V1_3 = new Version("1.3.0"); // "1.3.0" |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 36 | |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 37 | public static final String FELIX_1_2 = "http://felix.apache.org/xmlns/scr/v1.2.0-felix"; |
| 38 | |
| 39 | static Pattern BINDNAME = Pattern.compile("(set|add|bind)?(.*)"); |
| 40 | |
| 41 | static Pattern BINDDESCRIPTORDS10 = Pattern |
| 42 | .compile("\\(((L([^;]+);)|Lorg/osgi/framework/ServiceReference;)\\)V"); |
| 43 | static Pattern BINDDESCRIPTORDS11 = Pattern |
| 44 | .compile("\\(((L([^;]+);)(Ljava/util/Map;)?|Lorg/osgi/framework/ServiceReference;)\\)V"); |
| 45 | static Pattern BINDDESCRIPTORDS13 = Pattern |
| 46 | .compile("\\(((L([^;]+);)(Ljava/util/Map;)?|Lorg/osgi/framework/ServiceReference;)\\)Ljava/util/Map;"); |
| 47 | static Pattern REFERENCEBINDDESCRIPTOR = Pattern |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 48 | .compile("\\(Lorg/osgi/framework/ServiceReference;\\)V"); |
| 49 | |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 50 | static Pattern LIFECYCLEDESCRIPTORDS10 = Pattern |
| 51 | .compile("\\((Lorg/osgi/service/component/ComponentContext;)\\)V"); |
| 52 | static Pattern LIFECYCLEDESCRIPTORDS11 = Pattern |
| 53 | .compile("\\(((Lorg/osgi/service/component/ComponentContext;)|(Lorg/osgi/framework/BundleContext;)|(Ljava/util/Map;))*\\)V"); |
| 54 | static Pattern LIFECYCLEDESCRIPTORDS13 = Pattern |
| 55 | .compile("\\(((Lorg/osgi/service/component/ComponentContext;)|(Lorg/osgi/framework/BundleContext;)|(Ljava/util/Map;))*\\)Ljava/util/Map;"); |
| 56 | static Pattern DEACTIVATEDESCRIPTORDS11 = Pattern |
| 57 | .compile("\\(((Lorg/osgi/service/component/ComponentContext;)|(Lorg/osgi/framework/BundleContext;)|(Ljava/util/Map;)|(Ljava/lang/Integer;)|(I))*\\)V"); |
| 58 | static Pattern DEACTIVATEDESCRIPTORDS13 = Pattern |
| 59 | .compile("\\(((Lorg/osgi/service/component/ComponentContext;)|(Lorg/osgi/framework/BundleContext;)|(Ljava/util/Map;)|(Ljava/lang/Integer;)|(I))*\\)Ljava/util/Map;"); |
| 60 | |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 61 | ComponentDef component = new ComponentDef(); |
| 62 | |
| 63 | Clazz clazz; |
| 64 | TypeRef interfaces[]; |
| 65 | MethodDef method; |
| 66 | TypeRef className; |
| 67 | Analyzer analyzer; |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame] | 68 | MultiMap<String,String> methods = new MultiMap<String,String>(); |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 69 | TypeRef extendsClass; |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 70 | final boolean inherit; |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 71 | boolean baseclass = true; |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 72 | |
| 73 | final boolean felixExtensions; |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 74 | |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 75 | AnnotationReader(Analyzer analyzer, Clazz clazz, boolean inherit, boolean felixExtensions) { |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 76 | this.analyzer = analyzer; |
| 77 | this.clazz = clazz; |
| 78 | this.inherit = inherit; |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 79 | this.felixExtensions = felixExtensions; |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 80 | } |
| 81 | |
| 82 | public static ComponentDef getDefinition(Clazz c, Analyzer analyzer) throws Exception { |
| 83 | boolean inherit = Processor.isTrue(analyzer.getProperty("-dsannotations-inherit")); |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 84 | boolean felixExtensions = Processor.isTrue(analyzer.getProperty("-ds-felix-extensions")); |
| 85 | AnnotationReader r = new AnnotationReader(analyzer, c, inherit, felixExtensions); |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 86 | return r.getDef(); |
| 87 | } |
| 88 | |
| 89 | private ComponentDef getDef() throws Exception { |
| 90 | clazz.parseClassFileWithCollector(this); |
| 91 | if (component.implementation == null) |
| 92 | return null; |
| 93 | |
| 94 | if (inherit) { |
| 95 | baseclass = false; |
| 96 | while (extendsClass != null) { |
| 97 | if (extendsClass.isJava()) |
| 98 | break; |
| 99 | |
| 100 | Clazz ec = analyzer.findClass(extendsClass); |
| 101 | if (ec == null) { |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame] | 102 | analyzer.error("Missing super class for DS annotations: " + extendsClass + " from " |
| 103 | + clazz.getClassName()); |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 104 | } else { |
| 105 | ec.parseClassFileWithCollector(this); |
| 106 | } |
| 107 | } |
| 108 | } |
| 109 | for (ReferenceDef rdef : component.references.values()) { |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame] | 110 | rdef.unbind = referredMethod(analyzer, rdef, rdef.unbind, "add(.*)", "remove$1", "(.*)", "un$1"); |
| 111 | rdef.updated = referredMethod(analyzer, rdef, rdef.updated, "(add|set|bind)(.*)", "updated$2", "(.*)", |
| 112 | "updated$1"); |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 113 | } |
| 114 | return component; |
| 115 | } |
| 116 | |
| 117 | /** |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 118 | * @param analyzer |
| 119 | * @param rdef |
| 120 | */ |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame] | 121 | protected String referredMethod(Analyzer analyzer, ReferenceDef rdef, String value, String... matches) { |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 122 | if (value == null) { |
| 123 | String bind = rdef.bind; |
| 124 | for (int i = 0; i < matches.length; i += 2) { |
| 125 | Matcher m = Pattern.compile(matches[i]).matcher(bind); |
| 126 | if (m.matches()) { |
| 127 | value = m.replaceFirst(matches[i + 1]); |
| 128 | break; |
| 129 | } |
| 130 | } |
| 131 | } else if (value.equals("-")) |
| 132 | return null; |
| 133 | |
| 134 | if (methods.containsKey(value)) { |
| 135 | for (String descriptor : methods.get(value)) { |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 136 | Matcher matcher = BINDDESCRIPTORDS10.matcher(descriptor); |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 137 | if (matcher.matches()) { |
| 138 | String type = matcher.group(2); |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 139 | if (rdef.service.equals(Clazz.objectDescriptorToFQN(type)) |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 140 | || type.equals("Lorg/osgi/framework/ServiceReference;")) { |
| 141 | |
| 142 | return value; |
| 143 | } |
| 144 | } |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 145 | matcher = BINDDESCRIPTORDS11.matcher(descriptor); |
| 146 | if (matcher.matches()) { |
| 147 | String type = matcher.group(2); |
| 148 | if (rdef.service.equals(Clazz.objectDescriptorToFQN(type)) |
| 149 | || type.equals("Lorg/osgi/framework/ServiceReference;")) { |
| 150 | rdef.updateVersion(V1_1); |
| 151 | return value; |
| 152 | } |
| 153 | } |
| 154 | matcher = BINDDESCRIPTORDS13.matcher(descriptor); |
| 155 | if (felixExtensions && matcher.matches()) { |
| 156 | String type = matcher.group(2); |
| 157 | if (rdef.service.equals(Clazz.objectDescriptorToFQN(type)) |
| 158 | || type.equals("Lorg/osgi/framework/ServiceReference;")) { |
| 159 | rdef.updateVersion(V1_2); |
| 160 | if (component.xmlns == null) { |
| 161 | component.xmlns = FELIX_1_2; |
| 162 | } |
| 163 | return value; |
| 164 | } |
| 165 | } |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 166 | } |
| 167 | analyzer.error( |
| 168 | "A related method to %s from the reference %s has no proper prototype for class %s. Expected void %s(%s s [,Map m] | ServiceReference r)", |
| 169 | rdef.bind, value, component.implementation, value, rdef.service); |
| 170 | } |
| 171 | return null; |
| 172 | } |
| 173 | |
Stuart McCulloch | 55d4dfe | 2012-08-07 10:57:21 +0000 | [diff] [blame] | 174 | @Override |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 175 | public void annotation(Annotation annotation) { |
| 176 | try { |
| 177 | java.lang.annotation.Annotation a = annotation.getAnnotation(); |
| 178 | if (a instanceof Component) |
| 179 | doComponent((Component) a, annotation); |
| 180 | else if (a instanceof Activate) |
| 181 | doActivate(); |
| 182 | else if (a instanceof Deactivate) |
| 183 | doDeactivate(); |
| 184 | else if (a instanceof Modified) |
| 185 | doModified(); |
| 186 | else if (a instanceof Reference) |
| 187 | doReference((Reference) a, annotation); |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame] | 188 | } |
| 189 | catch (Exception e) { |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 190 | e.printStackTrace(); |
| 191 | analyzer.error("During generation of a component on class %s, exception %s", clazz, e); |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | /** |
| 196 | * |
| 197 | */ |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 198 | protected void doActivate() { |
| 199 | String methodDescriptor = method.getDescriptor().toString(); |
| 200 | if ("activate".equals(method.getName()) && LIFECYCLEDESCRIPTORDS10.matcher(methodDescriptor).matches()) { |
| 201 | component.activate = method.getName(); |
| 202 | } else if (LIFECYCLEDESCRIPTORDS11.matcher(methodDescriptor).matches()) { |
| 203 | component.activate = method.getName(); |
| 204 | component.updateVersion(V1_1); |
| 205 | } else if (felixExtensions && LIFECYCLEDESCRIPTORDS13.matcher(methodDescriptor).matches()) { |
| 206 | component.activate = method.getName(); |
| 207 | component.updateVersion(V1_2); |
| 208 | if (component.xmlns == null) { |
| 209 | component.xmlns = FELIX_1_2; |
| 210 | } |
| 211 | } else |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 212 | analyzer.error( |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 213 | "Activate method for %s does not have an acceptable prototype, only Map, ComponentContext, or BundleContext is allowed. Found: %s", |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 214 | clazz, method.getDescriptor()); |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 215 | |
| 216 | } |
| 217 | |
| 218 | /** |
| 219 | * |
| 220 | */ |
| 221 | protected void doDeactivate() { |
| 222 | String methodDescriptor = method.getDescriptor().toString(); |
| 223 | if ( "deactivate".equals(method.getName()) && LIFECYCLEDESCRIPTORDS10.matcher(methodDescriptor).matches()) { |
| 224 | component.deactivate = method.getName(); |
| 225 | } else if (DEACTIVATEDESCRIPTORDS11.matcher(methodDescriptor).matches()) { |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 226 | component.deactivate = method.getName(); |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 227 | component.updateVersion(V1_1); |
| 228 | } else if (felixExtensions && DEACTIVATEDESCRIPTORDS13.matcher(methodDescriptor).matches()) { |
| 229 | component.deactivate = method.getName(); |
| 230 | component.updateVersion(V1_2); |
| 231 | if (component.xmlns == null) { |
| 232 | component.xmlns = FELIX_1_2; |
| 233 | } |
| 234 | } else |
| 235 | analyzer.error( |
| 236 | "Deactivate method for %s does not have an acceptable prototype, only Map, ComponentContext, BundleContext, int, or Integer is allowed. Found: %s", |
| 237 | clazz, method.getDescriptor()); |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 238 | } |
| 239 | |
| 240 | /** |
| 241 | * |
| 242 | */ |
| 243 | protected void doModified() { |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 244 | if (LIFECYCLEDESCRIPTORDS11.matcher(method.getDescriptor().toString()).matches()) { |
| 245 | component.modified = method.getName(); |
| 246 | component.updateVersion(V1_1); |
| 247 | } else if (felixExtensions && LIFECYCLEDESCRIPTORDS13.matcher(method.getDescriptor().toString()).matches()) { |
| 248 | component.modified = method.getName(); |
| 249 | component.updateVersion(V1_2); |
| 250 | if (component.xmlns == null) { |
| 251 | component.xmlns = FELIX_1_2; |
| 252 | } |
| 253 | } else |
| 254 | |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 255 | analyzer.error( |
| 256 | "Modified method for %s does not have an acceptable prototype, only Map, ComponentContext, or BundleContext is allowed. Found: %s", |
| 257 | clazz, method.getDescriptor()); |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 258 | } |
| 259 | |
| 260 | /** |
| 261 | * @param annotation |
| 262 | * @throws Exception |
| 263 | */ |
| 264 | protected void doReference(Reference reference, Annotation raw) throws Exception { |
| 265 | ReferenceDef def = new ReferenceDef(); |
| 266 | def.name = reference.name(); |
| 267 | |
| 268 | if (def.name == null) { |
| 269 | Matcher m = BINDNAME.matcher(method.getName()); |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame] | 270 | if (m.matches()) |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 271 | def.name = m.group(2); |
| 272 | else |
| 273 | analyzer.error("Invalid name for bind method %s", method.getName()); |
| 274 | } |
| 275 | |
| 276 | def.unbind = reference.unbind(); |
| 277 | def.updated = reference.updated(); |
| 278 | def.bind = method.getName(); |
| 279 | |
| 280 | def.service = raw.get("service"); |
| 281 | if (def.service != null) { |
| 282 | def.service = Clazz.objectDescriptorToFQN(def.service); |
| 283 | } else { |
| 284 | // We have to find the type of the current method to |
| 285 | // link it to the referenced service. |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 286 | String methodDescriptor = method.getDescriptor().toString(); |
| 287 | Matcher m = BINDDESCRIPTORDS10.matcher(methodDescriptor); |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 288 | if (m.matches()) { |
| 289 | def.service = Descriptors.binaryToFQN(m.group(3)); |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 290 | } else { |
| 291 | m = BINDDESCRIPTORDS11.matcher(methodDescriptor); |
| 292 | if (m.matches()) { |
| 293 | def.service = Descriptors.binaryToFQN(m.group(3)); |
| 294 | def.updateVersion(V1_1); |
| 295 | } else { |
| 296 | m = BINDDESCRIPTORDS13.matcher(methodDescriptor); |
| 297 | if (felixExtensions && m.matches()) { |
| 298 | def.service = Descriptors.binaryToFQN(m.group(3)); |
| 299 | def.updateVersion(V1_2); |
| 300 | if (component.xmlns == null) { |
| 301 | component.xmlns = FELIX_1_2; |
| 302 | } |
| 303 | } else |
| 304 | throw new IllegalArgumentException( |
| 305 | "Cannot detect the type of a Component Reference from the descriptor: " |
| 306 | + method.getDescriptor()); |
| 307 | } |
| 308 | } |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 309 | } |
| 310 | |
| 311 | // Check if we have a target, this must be a filter |
| 312 | def.target = reference.target(); |
| 313 | |
| 314 | if (component.references.containsKey(def.name)) |
| 315 | analyzer.error( |
| 316 | "In component %s, multiple references with the same name: %s. Previous def: %s, this def: %s", |
| 317 | component.implementation, component.references.get(def.name), def.service, ""); |
| 318 | else |
| 319 | component.references.put(def.name, def); |
| 320 | |
| 321 | def.cardinality = reference.cardinality(); |
| 322 | def.policy = reference.policy(); |
| 323 | def.policyOption = reference.policyOption(); |
| 324 | } |
| 325 | |
| 326 | /** |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 327 | * @param annotation |
| 328 | * @throws Exception |
| 329 | */ |
| 330 | protected void doComponent(Component comp, Annotation annotation) throws Exception { |
| 331 | |
| 332 | // Check if we are doing a super class |
| 333 | if (component.implementation != null) |
| 334 | return; |
| 335 | |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 336 | component.implementation = clazz.getClassName(); |
| 337 | component.name = comp.name(); |
| 338 | component.factory = comp.factory(); |
| 339 | component.configurationPolicy = comp.configurationPolicy(); |
| 340 | if (annotation.get("enabled") != null) |
| 341 | component.enabled = comp.enabled(); |
| 342 | if (annotation.get("factory") != null) |
| 343 | component.factory = comp.factory(); |
| 344 | if (annotation.get("immediate") != null) |
| 345 | component.immediate = comp.immediate(); |
| 346 | if (annotation.get("servicefactory") != null) |
| 347 | component.servicefactory = comp.servicefactory(); |
| 348 | |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 349 | if (annotation.get("configurationPid") != null) { |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 350 | component.configurationPid = comp.configurationPid(); |
Stuart McCulloch | ec47fe7 | 2012-09-19 12:56:05 +0000 | [diff] [blame] | 351 | component.updateVersion(V1_2); |
| 352 | } |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 353 | |
| 354 | if (annotation.get("xmlns") != null) |
| 355 | component.xmlns = comp.xmlns(); |
| 356 | |
| 357 | String properties[] = comp.properties(); |
| 358 | if (properties != null) |
| 359 | for (String entry : properties) |
| 360 | component.properties.add(entry); |
| 361 | |
| 362 | doProperties(comp.property()); |
| 363 | Object[] x = annotation.get("service"); |
| 364 | |
| 365 | if (x == null) { |
| 366 | // Use the found interfaces, but convert from internal to |
| 367 | // fqn. |
| 368 | if (interfaces != null) { |
| 369 | List<TypeRef> result = new ArrayList<TypeRef>(); |
| 370 | for (int i = 0; i < interfaces.length; i++) { |
| 371 | if (!interfaces[i].equals(analyzer.getTypeRef("scala/ScalaObject"))) |
| 372 | result.add(interfaces[i]); |
| 373 | } |
| 374 | component.service = result.toArray(EMPTY); |
| 375 | } |
| 376 | } else { |
| 377 | // We have explicit interfaces set |
| 378 | component.service = new TypeRef[x.length]; |
| 379 | for (int i = 0; i < x.length; i++) { |
| 380 | String s = (String) x[i]; |
| 381 | TypeRef ref = analyzer.getTypeRefFromFQN(s); |
| 382 | component.service[i] = ref; |
| 383 | } |
| 384 | } |
| 385 | |
| 386 | } |
| 387 | |
| 388 | /** |
| 389 | * Parse the properties |
| 390 | */ |
| 391 | |
| 392 | private void doProperties(String[] properties) { |
| 393 | if (properties != null) { |
| 394 | for (String p : properties) { |
| 395 | Matcher m = PROPERTY_PATTERN.matcher(p); |
| 396 | |
| 397 | if (m.matches()) { |
| 398 | String key = m.group(1); |
Stuart McCulloch | 6a04666 | 2012-07-19 13:11:20 +0000 | [diff] [blame] | 399 | String type = m.group(2); |
| 400 | if ( type != null) |
| 401 | key += ":" + type; |
| 402 | |
| 403 | String value = m.group(3); |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 404 | component.property.add(key, value); |
| 405 | } else |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame] | 406 | throw new IllegalArgumentException("Malformed property '" + p + "' on component: " + className); |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 407 | } |
| 408 | } |
| 409 | } |
| 410 | |
| 411 | /** |
| 412 | * Are called during class parsing |
| 413 | */ |
| 414 | |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame] | 415 | @Override |
| 416 | public void classBegin(int access, TypeRef name) { |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 417 | className = name; |
| 418 | } |
| 419 | |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame] | 420 | @Override |
| 421 | public void implementsInterfaces(TypeRef[] interfaces) { |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 422 | this.interfaces = interfaces; |
| 423 | } |
| 424 | |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame] | 425 | @Override |
| 426 | public void method(Clazz.MethodDef method) { |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 427 | int access = method.getAccess(); |
| 428 | |
| 429 | if (Modifier.isAbstract(access) || Modifier.isStatic(access)) |
| 430 | return; |
| 431 | |
| 432 | if (!baseclass && Modifier.isPrivate(access)) |
| 433 | return; |
| 434 | |
| 435 | this.method = method; |
| 436 | methods.add(method.getName(), method.getDescriptor().toString()); |
| 437 | } |
| 438 | |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame] | 439 | @Override |
| 440 | public void extendsClass(TypeRef name) { |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 441 | this.extendsClass = name; |
| 442 | } |
| 443 | |
| 444 | } |