1 package org.codehaus.plexus.metadata.gleaner;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 import java.util.*;
28
29 import com.thoughtworks.qdox.JavaProjectBuilder;
30 import com.thoughtworks.qdox.model.DocletTag;
31 import com.thoughtworks.qdox.model.JavaClass;
32 import com.thoughtworks.qdox.model.JavaField;
33 import org.codehaus.plexus.component.repository.ComponentDescriptor;
34 import org.codehaus.plexus.component.repository.ComponentRequirement;
35 import org.codehaus.plexus.component.repository.ComponentRequirementList;
36 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
37 import org.codehaus.plexus.logging.LogEnabled;
38 import org.codehaus.plexus.personality.plexus.lifecycle.phase.*;
39 import org.codehaus.plexus.util.StringUtils;
40
41
42
43
44
45
46 public class QDoxComponentGleaner extends ComponentGleanerSupport implements SourceComponentGleaner {
47 public static final String PLEXUS_COMPONENT_TAG = "plexus.component";
48
49 public static final String PLEXUS_REQUIREMENT_TAG = "plexus.requirement";
50
51 public static final String PLEXUS_CONFIGURATION_TAG = "plexus.configuration";
52
53 public static final String PLEXUS_VERSION_PARAMETER = "version";
54
55 public static final String PLEXUS_ROLE_PARAMETER = "role";
56
57 public static final String PLEXUS_ROLE_HINT_PARAMETER = "role-hint";
58
59 public static final String PLEXUS_ROLE_HINT_LIST_PARAMETER = "role-hints";
60
61 public static final String PLEXUS_ALIAS_PARAMETER = "alias";
62
63 public static final String PLEXUS_DEFAULT_VALUE_PARAMETER = "default-value";
64
65 public static final String PLEXUS_LIFECYCLE_HANDLER_PARAMETER = "lifecycle-handler";
66
67 public static final String PLEXUS_INSTANTIATION_STARTEGY_PARAMETER = "instantiation-strategy";
68
69 public static final String PLEXUS_OPTIONAL_PARAMETER = "optional";
70
71 public static final String PLEXUS_DEFAULT_HINT = "default";
72
73
74
75
76
77 public ComponentDescriptor<?> glean(JavaProjectBuilder classCache, JavaClass javaClass)
78 throws ComponentGleanerException {
79 DocletTag tag = javaClass.getTagByName(PLEXUS_COMPONENT_TAG);
80
81 if (tag == null) {
82 return null;
83 }
84
85 Map<String, String> parameters = tag.getNamedParameterMap();
86
87
88
89
90
91 String fqn = javaClass.getFullyQualifiedName();
92
93
94
95 ComponentDescriptor<?> componentDescriptor = new ComponentDescriptor<Object>();
96
97 componentDescriptor.setImplementation(fqn);
98
99
100
101
102
103 String role = getParameter(parameters, PLEXUS_ROLE_PARAMETER);
104
105 if (role == null) {
106 role = findRole(javaClass);
107
108 if (role == null) {
109
110
111
112
113
114
115 return null;
116 }
117 }
118
119 componentDescriptor.setRole(role);
120
121
122
123
124
125 String roleHint = getParameter(parameters, PLEXUS_ROLE_HINT_PARAMETER);
126
127 if (roleHint != null) {
128
129 }
130
131 componentDescriptor.setRoleHint(roleHint);
132
133
134
135
136
137 String version = getParameter(parameters, PLEXUS_VERSION_PARAMETER);
138
139 componentDescriptor.setVersion(version);
140
141
142
143
144
145 String lifecycleHandler = getParameter(parameters, PLEXUS_LIFECYCLE_HANDLER_PARAMETER);
146
147 componentDescriptor.setLifecycleHandler(lifecycleHandler);
148
149
150
151
152
153 String instatiationStrategy = getParameter(parameters, PLEXUS_INSTANTIATION_STARTEGY_PARAMETER);
154
155 componentDescriptor.setInstantiationStrategy(instatiationStrategy);
156
157
158
159
160
161 componentDescriptor.setAlias(getParameter(parameters, PLEXUS_ALIAS_PARAMETER));
162
163
164
165
166
167 findExtraParameters(PLEXUS_COMPONENT_TAG, parameters);
168
169
170
171
172
173 findRequirements(classCache, componentDescriptor, javaClass);
174
175
176
177
178
179 String comment = javaClass.getComment();
180
181 if (comment != null) {
182 int i = comment.indexOf('.');
183
184 if (i > 0) {
185 comment = comment.substring(0, i + 1);
186 }
187 }
188
189 componentDescriptor.setDescription(comment);
190
191
192
193
194
195 XmlPlexusConfiguration configuration = new XmlPlexusConfiguration("configuration");
196
197 findConfiguration(configuration, javaClass);
198
199 componentDescriptor.setConfiguration(configuration);
200
201 return componentDescriptor;
202 }
203
204
205
206
207
208 private static final List<String> IGNORED_INTERFACES = Collections.unmodifiableList(Arrays.asList(new String[] {
209 LogEnabled.class.getName(),
210 Initializable.class.getName(),
211 Configurable.class.getName(),
212 Contextualizable.class.getName(),
213 Disposable.class.getName(),
214 Startable.class.getName(),
215 }));
216
217 private static String getPackage(JavaClass javaClass) {
218 if (javaClass.getPackage() != null) {
219 return javaClass.getPackage().getName();
220 } else {
221 return "";
222 }
223 }
224
225 private String findRole(JavaClass javaClass) {
226
227
228
229
230 List<JavaClass> interfaces = new ArrayList<JavaClass>(javaClass.getInterfaces());
231
232 for (Iterator<JavaClass> it = interfaces.iterator(); it.hasNext(); ) {
233 JavaClass ifc = it.next();
234
235 if (IGNORED_INTERFACES.contains(ifc.getFullyQualifiedName())) {
236 it.remove();
237 }
238 }
239
240
241
242
243
244
245 String role = null;
246
247 String className = javaClass.getName();
248
249 for (JavaClass ifc : interfaces) {
250 String fqn = ifc.getFullyQualifiedName();
251
252 String pkg = getPackage(ifc);
253
254 if (pkg == null) {
255 int index = fqn.lastIndexOf('.');
256
257 if (index == -1) {
258
259
260
261
262
263
264
265
266
267
268 pkg = getPackage(javaClass);
269
270 fqn = pkg + "." + fqn;
271 } else {
272 pkg = fqn.substring(0, index);
273 }
274 }
275
276 if (fqn == null) {
277 fqn = ifc.getName();
278 }
279
280 String name = fqn.substring(pkg.length() + 1);
281
282 if (className.endsWith(name)) {
283 if (role != null) {
284
285
286
287
288 }
289
290 role = fqn;
291 }
292 }
293
294 if (role == null) {
295 JavaClass superClass = javaClass.getSuperJavaClass();
296
297 if (superClass != null) {
298 role = findRole(superClass);
299 }
300 }
301
302 return role;
303 }
304
305 private void findRequirements(
306 JavaProjectBuilder classCache, ComponentDescriptor<?> componentDescriptor, JavaClass javaClass) {
307 List<JavaField> fields = javaClass.getFields();
308
309
310
311
312
313 if (javaClass.getSuperJavaClass() != null) {
314 findRequirements(classCache, componentDescriptor, javaClass.getSuperJavaClass());
315 }
316
317
318
319
320
321 for (JavaField field : fields) {
322 DocletTag tag = field.getTagByName(PLEXUS_REQUIREMENT_TAG);
323
324 if (tag == null) {
325 continue;
326 }
327
328 Map<String, String> parameters = new HashMap<String, String>(tag.getNamedParameterMap());
329
330
331
332
333
334 String requirementClass = field.getType().getFullyQualifiedName();
335
336 boolean isMap =
337 requirementClass.equals(Map.class.getName()) || requirementClass.equals(Collection.class.getName());
338
339 try {
340 isMap = isMap || Collection.class.isAssignableFrom(Class.forName(requirementClass));
341 } catch (ClassNotFoundException e) {
342
343 }
344
345 boolean isList = requirementClass.equals(List.class.getName());
346
347 ComponentRequirement cr;
348
349 String hint = getParameter(parameters, PLEXUS_ROLE_HINT_PARAMETER);
350
351 if (isMap || isList) {
352 cr = new ComponentRequirementList();
353
354 String hintList = getParameter(parameters, PLEXUS_ROLE_HINT_LIST_PARAMETER);
355
356 if (hintList != null) {
357 String[] hintArr = hintList.split(",");
358
359 ((ComponentRequirementList) cr).setRoleHints(Arrays.asList(hintArr));
360 }
361 } else {
362 cr = new ComponentRequirement();
363
364 cr.setRoleHint(hint);
365 }
366
367 String role = getParameter(parameters, PLEXUS_ROLE_PARAMETER);
368
369 if (role == null) {
370 cr.setRole(requirementClass);
371 } else {
372 cr.setRole(role);
373 }
374
375 String optional = getParameter(parameters, PLEXUS_OPTIONAL_PARAMETER);
376
377 cr.setOptional(Boolean.parseBoolean(optional));
378
379 cr.setFieldName(field.getName());
380
381 if (isMap || isList) {
382 if (hint != null) {
383
384
385
386
387
388 continue;
389 }
390
391 if (role == null) {
392
393
394
395
396
397
398
399 continue;
400 }
401
402 JavaClass roleClass = classCache.getClassByName(role);
403
404 if (role.indexOf('.') == -1 && StringUtils.isEmpty(getPackage(roleClass))) {
405 role = getPackage(javaClass) + "." + roleClass.getName();
406 }
407
408 cr.setRole(role);
409
410 findExtraParameters(PLEXUS_REQUIREMENT_TAG, parameters);
411 }
412
413
414
415
416
417 componentDescriptor.addRequirement(cr);
418 }
419 }
420
421 private void findConfiguration(XmlPlexusConfiguration configuration, JavaClass javaClass)
422 throws ComponentGleanerException {
423 List<JavaField> fields = javaClass.getFields();
424
425
426
427
428
429 if (javaClass.getSuperJavaClass() != null) {
430 findConfiguration(configuration, javaClass.getSuperJavaClass());
431 }
432
433
434
435
436
437 for (JavaField field : fields) {
438 DocletTag tag = field.getTagByName(PLEXUS_CONFIGURATION_TAG);
439
440 if (tag == null) {
441 continue;
442 }
443
444 Map<String, String> parameters = new HashMap<String, String>(tag.getNamedParameterMap());
445
446
447 String defaultValue = parameters.remove(PLEXUS_DEFAULT_VALUE_PARAMETER);
448
449 if (defaultValue == null) {
450
451
452
453
454
455 continue;
456 }
457
458 String name = deHump(field.getName());
459
460 XmlPlexusConfiguration c;
461
462 c = new XmlPlexusConfiguration(name);
463
464 c.setValue(defaultValue);
465
466
467
468 configuration.addChild(c);
469
470 findExtraParameters(PLEXUS_CONFIGURATION_TAG, parameters);
471 }
472 }
473
474
475
476
477
478 private void findExtraParameters(String tagName, Map<String, String> parameters) {
479 for (String s : parameters.keySet()) {
480
481 }
482 }
483
484 private String getParameter(Map<String, String> parameters, String parameter) {
485 String value = parameters.remove(parameter);
486
487 if (StringUtils.isEmpty(value)) {
488 return null;
489 }
490
491 return value;
492 }
493 }