1 /***************************************************************************************
2 * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
3 * http://aspectwerkz.codehaus.org *
4 * ---------------------------------------------------------------------------------- *
5 * The software in this package is published under the terms of the LGPL license *
6 * a copy of which has been included with this distribution in the license.txt file. *
7 **************************************************************************************/
8 package org.codehaus.aspectwerkz.annotation;
9
10
11 import com.thoughtworks.qdox.model.JavaClass;
12 import com.thoughtworks.qdox.model.JavaField;
13 import com.thoughtworks.qdox.model.JavaMethod;
14 import com.thoughtworks.qdox.model.JavaParameter;
15
16 import org.apache.tools.ant.BuildException;
17 import org.apache.tools.ant.Project;
18 import org.codehaus.aspectwerkz.annotation.instrumentation.AttributeEnhancer;
19 import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAttributeEnhancer;
20 import org.codehaus.aspectwerkz.exception.DefinitionException;
21 import org.codehaus.aspectwerkz.joinpoint.JoinPoint;
22 import org.codehaus.aspectwerkz.joinpoint.StaticJoinPoint;
23
24 import java.io.BufferedReader;
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.FileReader;
28 import java.io.IOException;
29 import java.net.MalformedURLException;
30 import java.net.URL;
31 import java.net.URLClassLoader;
32 import java.util.ArrayList;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Properties;
38 import java.util.StringTokenizer;
39
40 /***
41 * <p/>Annotation compiler. <p/>Extracts the annotations from JavaDoc tags and inserts them into the bytecode of the
42 * class.
43 *
44 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
45 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
46 */
47 public class AnnotationC {
48 public static final String ANNOTATION_ASPECT = "Aspect";
49 public static final String ANNOTATION_AROUND = "Around";
50 public static final String ANNOTATION_BEFORE = "Before";
51 public static final String ANNOTATION_AFTER = "After";
52 public static final String ANNOTATION_EXPRESSION = "Expression";
53 public static final String ANNOTATION_IMPLEMENTS = "Implements";
54 public static final String ANNOTATION_INTRODUCE = "Introduce";
55
56 private static final String COMMAND_LINE_OPTION_DASH = "-";
57 private static final String COMMAND_LINE_OPTION_VERBOSE = "-verbose";
58 private static final String COMMAND_LINE_OPTION_CUSTOM = "-custom";
59 private static final String COMMAND_LINE_OPTION_SRC = "-src";
60 private static final String COMMAND_LINE_OPTION_SRCFILES = "-srcfiles";
61 private static final String COMMAND_LINE_OPTION_SRCINCLUDES = "-srcincludes";
62 private static final String COMMAND_LINE_OPTION_CLASSES = "-classes";
63 private static final String COMMAND_LINE_OPTION_DEST = "-dest";
64
65 static final String[] SYSTEM_ANNOTATIONS = new String[]{
66 ANNOTATION_ASPECT, ANNOTATION_AROUND, ANNOTATION_BEFORE, ANNOTATION_AFTER,
67 ANNOTATION_EXPRESSION, ANNOTATION_IMPLEMENTS, ANNOTATION_INTRODUCE
68 };
69
70 /***
71 * The annotations properties file define by the user.
72 */
73 public static final Properties ANNOTATION_DEFINITION = new Properties();
74
75 /***
76 * Verbose logging.
77 */
78 private static boolean s_verbose = false;
79
80 /***
81 * The class loader.
82 */
83 private static URLClassLoader s_loader;
84
85 /***
86 * The custom annotations.
87 */
88 private static Map s_customAnnotations = new HashMap();
89 private static final String FILE_SEPARATOR = ",";
90
91 /***
92 * Runs the compiler from the command line.
93 *
94 * @param args
95 */
96 public static void main(String[] args) {
97 if (args.length < 4) {
98 printUsage();
99 }
100 Map commandLineOptions = parseCommandLineOptions(args);
101
102 String propertiesFilesPath = (String) commandLineOptions.get(COMMAND_LINE_OPTION_CUSTOM);
103 List propertiesFilesList = new ArrayList();
104 if (propertiesFilesPath != null) {
105 StringTokenizer st = new StringTokenizer(propertiesFilesPath, File.pathSeparator);
106 while (st.hasMoreTokens()) {
107 propertiesFilesList.add(st.nextToken());
108 }
109 }
110 String[] propertiesFiles = (String[]) propertiesFilesList.toArray(new String[0]);
111
112 compile(
113 (String) commandLineOptions.get(COMMAND_LINE_OPTION_SRC),
114 (String) commandLineOptions.get(COMMAND_LINE_OPTION_SRCFILES),
115 (String) commandLineOptions.get(COMMAND_LINE_OPTION_SRCINCLUDES),
116 (String) commandLineOptions.get(COMMAND_LINE_OPTION_CLASSES),
117 (String) commandLineOptions.get(COMMAND_LINE_OPTION_DEST),
118 propertiesFiles
119 );
120 }
121
122 /***
123 * Compiles the annotations.
124 *
125 * @param srcDirList
126 * @param srcFileList
127 * @param classPath
128 * @param destDir
129 * @param annotationPropetiesFiles
130 */
131 private static void compile(final String srcDirList,
132 final String srcFileList,
133 final String srcFileIncludes,
134 final String classPath,
135 String destDir,
136 final String[] annotationPropetiesFiles) {
137 if (srcDirList == null && srcFileList == null && srcFileIncludes == null) {
138 throw new IllegalArgumentException("one of src or srcfiles or srcincludes must be not null");
139 }
140 if ((srcDirList != null && srcFileList != null) || (srcDirList != null && srcFileIncludes != null)
141 || (srcFileList != null && srcFileIncludes != null)) {
142 throw new IllegalArgumentException("maximum one of src, srcfiles or srcincludes must be not null");
143 }
144 if (classPath == null) {
145 throw new IllegalArgumentException("class path can not be null");
146 }
147 if (destDir == null) {
148 destDir = classPath;
149 }
150
151 String[] srcDirs = new String[0];
152 String[] srcFiles = new String[0];
153 if (srcDirList != null) {
154 srcDirs = split(srcDirList, File.pathSeparator);
155 } else if (srcFileList != null) {
156 srcFiles = split(srcFileList, FILE_SEPARATOR);
157 } else {
158 srcFiles = loadSourceList(srcFileIncludes);
159 }
160
161 compile(s_verbose, srcDirs, srcFiles, split(classPath, File.pathSeparator), destDir, annotationPropetiesFiles);
162 }
163
164 /***
165 * Compiles the annotations.
166 *
167 * @param verbose
168 * @param srcDirs
169 * @param srcFiles
170 * @param classpath
171 * @param destDir
172 * @param annotationPropertiesFiles
173 */
174 public static void compile(final boolean verbose,
175 final String[] srcDirs,
176 final String[] srcFiles,
177 final String[] classpath,
178 final String destDir,
179 final String[] annotationPropertiesFiles) {
180
181 s_verbose = verbose;
182 URL[] classPath = new URL[classpath.length];
183 try {
184 for (int i = 0; i < classpath.length; i++) {
185 classPath[i] = new File(classpath[i]).toURL();
186 }
187 s_loader = new URLClassLoader(classPath, AnnotationC.class.getClassLoader());
188 } catch (MalformedURLException e) {
189 String message = "URL [" + classPath + "] is not valid: " + e.toString();
190 logError(message);
191 throw new DefinitionException(message, e);
192 }
193
194 String destDirToUse = destDir;
195 if (destDir == null) {
196 if (classpath.length != 1) {
197 throw new DefinitionException("destDir must be specified since classpath is composite");
198 }
199 destDirToUse = classpath[0];
200 }
201
202 final AnnotationManager manager = new AnnotationManager(s_loader);
203
204 logInfo("parsing source dirs:");
205 for (int i = 0; i < srcDirs.length; i++) {
206 logInfo(" " + srcDirs[i]);
207 }
208 manager.addSourceTrees(srcDirs);
209
210 for (int i = 0; i < srcFiles.length; i++) {
211 logInfo(" " + srcFiles[i]);
212 manager.addSource(srcFiles[i]);
213 }
214
215 doCompile(annotationPropertiesFiles, classPath, manager, destDirToUse);
216 }
217
218 /***
219 * Compiles the annotations.
220 *
221 * @param annotationPropetiesFiles
222 * @param classPath
223 * @param manager
224 * @param destDir
225 */
226 private static void doCompile(final String[] annotationPropetiesFiles,
227 final URL[] classPath,
228 final AnnotationManager manager,
229 final String destDir) {
230
231 logInfo("compiling annotations...");
232 logInfo("note: if no output is seen, then nothing is compiled");
233
234
235 registerSystemAnnotations(manager);
236 registerUserDefinedAnnotations(manager, annotationPropetiesFiles);
237
238
239 JavaClass[] classes = manager.getAllClasses();
240 for (int i = 0; i < classes.length; i++) {
241 JavaClass clazz = classes[i];
242 logInfo("class [" + clazz.getFullyQualifiedName() + ']');
243 try {
244 AttributeEnhancer enhancer = new AsmAttributeEnhancer();
245 if (enhancer.initialize(clazz.getFullyQualifiedName(), classPath)) {
246 handleClassAnnotations(manager, enhancer, clazz);
247 handleInnerClassAnnotations(manager, enhancer, clazz, classPath, destDir);
248 JavaMethod[] methods = clazz.getMethods();
249 for (int j = 0; j < methods.length; j++) {
250 JavaMethod method = methods[j];
251 if (method.isConstructor()) {
252 handleConstructorAnnotations(manager, enhancer, method);
253 } else {
254 handleMethodAnnotations(manager, enhancer, method);
255 }
256 }
257 JavaField[] fields = clazz.getFields();
258 for (int j = 0; j < fields.length; j++) {
259 handleFieldAnnotations(manager, enhancer, fields[j]);
260 }
261
262
263 enhancer.write(destDir);
264 }
265 } catch (Throwable e) {
266 e.printStackTrace();
267 logWarning(
268 "could not compile annotations for class ["
269 + clazz.getFullyQualifiedName() + "] due to: " + e.toString()
270 );
271 }
272 }
273 logInfo("compiled classes written to " + destDir);
274 logInfo("compilation successful");
275 }
276
277 /***
278 * Handles the class annotations.
279 *
280 * @param manager
281 * @param enhancer
282 * @param clazz
283 */
284 private static void handleClassAnnotations(final AnnotationManager manager,
285 final AttributeEnhancer enhancer,
286 final JavaClass clazz) {
287
288 Annotation[] annotations = manager.getAnnotations(ANNOTATION_ASPECT, clazz);
289 for (int i = 0; i < annotations.length; i++) {
290 Annotation annotation = annotations[i];
291 if (annotation != null) {
292 AspectAnnotationProxy aspectProxy = (AspectAnnotationProxy) annotation;
293 if (aspectProxy.aspectName() == null) {
294 aspectProxy.setAspectName(clazz.getFullyQualifiedName());
295 }
296 enhancer.insertClassAttribute(new AnnotationInfo(ANNOTATION_ASPECT, aspectProxy));
297 logInfo("aspect [" + clazz.getFullyQualifiedName() + ']');
298 logInfo(" deployment model [" + aspectProxy.deploymentModel() + ']');
299 }
300 }
301 for (Iterator it = s_customAnnotations.keySet().iterator(); it.hasNext();) {
302 String annotationName = (String) it.next();
303 Annotation[] customAnnotations = manager.getAnnotations(annotationName, clazz);
304 for (int i = 0; i < customAnnotations.length; i++) {
305 Annotation customAnnotation = customAnnotations[i];
306 if (customAnnotation != null) {
307 enhancer.insertClassAttribute(
308 new AnnotationInfo(
309 annotationName,
310 customAnnotation
311 )
312 );
313 logInfo(
314 " custom class annotation [" + annotationName + " @ "
315 + clazz.getFullyQualifiedName() + ']'
316 );
317 }
318 }
319 }
320 }
321
322 /***
323 * Handles the method annotations.
324 *
325 * @param manager
326 * @param enhancer
327 * @param method
328 */
329 private static void handleMethodAnnotations(final AnnotationManager manager,
330 final AttributeEnhancer enhancer,
331 final JavaMethod method) {
332
333 Annotation[] expressionAnnotations = manager.getAnnotations(ANNOTATION_EXPRESSION, method);
334 for (int i = 0; i < expressionAnnotations.length; i++) {
335 Annotation expressionAnnotation = expressionAnnotations[i];
336 if (expressionAnnotation != null) {
337 ExpressionAnnotationProxy expressionProxy = (ExpressionAnnotationProxy) expressionAnnotation;
338 AnnotationC.registerCallParameters(expressionProxy, method);
339 enhancer.insertMethodAttribute(
340 method, new AnnotationInfo(
341 ANNOTATION_EXPRESSION,
342 expressionProxy
343 )
344 );
345 logInfo(
346 " pointcut [" + AnnotationC.getShortCallSignature(method) + " :: "
347 + expressionProxy.expression() + ']'
348 );
349 }
350 }
351 Annotation[] aroundAnnotations = manager.getAnnotations(ANNOTATION_AROUND, method);
352 for (int i = 0; i < aroundAnnotations.length; i++) {
353 Annotation aroundAnnotation = aroundAnnotations[i];
354 if (aroundAnnotation != null) {
355 AroundAnnotationProxy aroundProxy = (AroundAnnotationProxy) aroundAnnotation;
356 AnnotationC.registerCallParameters(aroundProxy, method);
357 enhancer.insertMethodAttribute(
358 method, new AnnotationInfo(
359 ANNOTATION_AROUND,
360 aroundProxy
361 )
362 );
363 logInfo(
364 " around advice [" + AnnotationC.getShortCallSignature(method) + " :: "
365 + aroundProxy.pointcut() + ']'
366 );
367 }
368 }
369 Annotation[] beforeAnnotations = manager.getAnnotations(ANNOTATION_BEFORE, method);
370 for (int i = 0; i < beforeAnnotations.length; i++) {
371 Annotation beforeAnnotation = beforeAnnotations[i];
372 if (beforeAnnotation != null) {
373 BeforeAnnotationProxy beforeProxy = (BeforeAnnotationProxy) beforeAnnotation;
374 AnnotationC.registerCallParameters(beforeProxy, method);
375 enhancer.insertMethodAttribute(
376 method, new AnnotationInfo(
377 ANNOTATION_BEFORE,
378 beforeProxy
379 )
380 );
381 logInfo(
382 " before [" + AnnotationC.getShortCallSignature(method) + " :: "
383 + beforeProxy.pointcut() + ']'
384 );
385 }
386 }
387 Annotation[] afterAnnotations = manager.getAnnotations(ANNOTATION_AFTER, method);
388 for (int i = 0; i < afterAnnotations.length; i++) {
389 Annotation afterAnnotation = afterAnnotations[i];
390 if (afterAnnotation != null) {
391 AfterAnnotationProxy afterProxy = (AfterAnnotationProxy) afterAnnotation;
392 AnnotationC.registerCallParameters(afterProxy, method);
393 enhancer.insertMethodAttribute(
394 method, new AnnotationInfo(
395 ANNOTATION_AFTER,
396 afterProxy
397 )
398 );
399 logInfo(
400 " after advice [" + AnnotationC.getShortCallSignature(method) + " :: "
401 + afterProxy.pointcut() + ']'
402 );
403 }
404 }
405 for (Iterator it = s_customAnnotations.keySet().iterator(); it.hasNext();) {
406 String annotationName = (String) it.next();
407 Annotation[] customAnnotations = manager.getAnnotations(annotationName, method);
408 for (int i = 0; i < customAnnotations.length; i++) {
409 Annotation customAnnotation = customAnnotations[i];
410 if (customAnnotation != null) {
411 enhancer.insertMethodAttribute(
412 method, new AnnotationInfo(
413 annotationName,
414 customAnnotation
415 )
416 );
417 logInfo(
418 " custom method annotation [" + annotationName + " @ "
419 + method.getParentClass().getName() + '.' + method.getName() +
420 ']'
421 );
422 }
423 }
424 }
425 }
426
427 /***
428 * Handles the constructor annotations.
429 *
430 * @param manager
431 * @param enhancer
432 * @param constructor
433 */
434 private static void handleConstructorAnnotations(final AnnotationManager manager,
435 final AttributeEnhancer enhancer,
436 final JavaMethod constructor) {
437
438 Annotation[] aroundAnnotations = manager.getAnnotations(ANNOTATION_AROUND, constructor);
439 for (int i = 0; i < aroundAnnotations.length; i++) {
440 Annotation aroundAnnotation = aroundAnnotations[i];
441 if (aroundAnnotation != null) {
442 AroundAnnotationProxy aroundProxy = (AroundAnnotationProxy) aroundAnnotation;
443 enhancer.insertConstructorAttribute(constructor, new AnnotationInfo(ANNOTATION_AROUND, aroundProxy));
444 logInfo(
445 " around advice [" + constructor.getName() + " :: "
446 + aroundProxy.pointcut() + ']'
447 );
448 }
449 }
450 Annotation[] beforeAnnotations = manager.getAnnotations(ANNOTATION_BEFORE, constructor);
451 for (int i = 0; i < beforeAnnotations.length; i++) {
452 Annotation beforeAnnotation = beforeAnnotations[i];
453 if (beforeAnnotation != null) {
454 BeforeAnnotationProxy beforeProxy = (BeforeAnnotationProxy) beforeAnnotation;
455 enhancer.insertConstructorAttribute(constructor, new AnnotationInfo(ANNOTATION_BEFORE, beforeProxy));
456 logInfo(
457 " before [" + constructor.getName() + " :: " + beforeProxy.pointcut()
458 + ']'
459 );
460 }
461 }
462 Annotation[] afterAnnotations = manager.getAnnotations(ANNOTATION_AFTER, constructor);
463 for (int i = 0; i < afterAnnotations.length; i++) {
464 Annotation afterAnnotation = afterAnnotations[i];
465 if (afterAnnotation != null) {
466 AfterAnnotationProxy afterProxy = (AfterAnnotationProxy) afterAnnotation;
467 enhancer.insertConstructorAttribute(constructor, new AnnotationInfo(ANNOTATION_AFTER, afterProxy));
468 logInfo(
469 " after advice [" + constructor.getName() + " :: "
470 + afterProxy.pointcut() + ']'
471 );
472 }
473 }
474 for (Iterator it = s_customAnnotations.keySet().iterator(); it.hasNext();) {
475 String annotationName = (String) it.next();
476 Annotation[] customAnnotations = manager.getAnnotations(annotationName, constructor);
477 for (int i = 0; i < customAnnotations.length; i++) {
478 Annotation customAnnotation = customAnnotations[i];
479 if (customAnnotation != null) {
480 enhancer.insertConstructorAttribute(
481 constructor, new AnnotationInfo(annotationName, customAnnotation)
482 );
483 logInfo(
484 " custom constructor annotation [" + annotationName + " @ "
485 + constructor.getParentClass().getName() + '.' +
486 constructor.getName()
487 + ']'
488 );
489 }
490 }
491 }
492 }
493
494 /***
495 * Handles the field annotations.
496 *
497 * @param manager
498 * @param enhancer
499 * @param field
500 */
501 private static void handleFieldAnnotations(final AnnotationManager manager,
502 final AttributeEnhancer enhancer,
503 final JavaField field) {
504
505 Annotation[] expressionAnnotations = manager.getAnnotations(ANNOTATION_EXPRESSION, field);
506 for (int i = 0; i < expressionAnnotations.length; i++) {
507 Annotation expressionAnnotation = expressionAnnotations[i];
508 if (expressionAnnotation != null) {
509 ExpressionAnnotationProxy expressionProxy = (ExpressionAnnotationProxy) expressionAnnotation;
510 enhancer.insertFieldAttribute(
511 field, new AnnotationInfo(
512 ANNOTATION_EXPRESSION,
513 expressionProxy
514 )
515 );
516 logInfo(
517 " pointcut [" + field.getName() + " :: " + expressionProxy.expression()
518 + ']'
519 );
520 }
521 }
522 Annotation[] implementsAnnotations = manager.getAnnotations(ANNOTATION_IMPLEMENTS, field);
523 for (int i = 0; i < implementsAnnotations.length; i++) {
524 Annotation implementsAnnotation = implementsAnnotations[i];
525 if (implementsAnnotation != null) {
526 ImplementsAnnotationProxy implementsProxy = (ImplementsAnnotationProxy) implementsAnnotation;
527 enhancer.insertFieldAttribute(
528 field, new AnnotationInfo(
529 ANNOTATION_IMPLEMENTS,
530 implementsProxy
531 )
532 );
533 logInfo(
534 " interface introduction [" + field.getName() + " :: "
535 + implementsProxy.expression() + ']'
536 );
537 }
538 }
539 for (Iterator it = s_customAnnotations.keySet().iterator(); it.hasNext();) {
540 String annotationName = (String) it.next();
541 Annotation[] customAnnotations = manager.getAnnotations(annotationName, field);
542 for (int i = 0; i < customAnnotations.length; i++) {
543 Annotation customAnnotation = customAnnotations[i];
544 if (customAnnotation != null) {
545 enhancer.insertFieldAttribute(
546 field, new AnnotationInfo(
547 annotationName,
548 customAnnotation
549 )
550 );
551 logInfo(
552 " custom field annotation [" + annotationName + " @ "
553 + field.getName() + ']'
554 );
555 }
556 }
557 }
558 }
559
560 /***
561 * Handles the inner class annotations.
562 *
563 * @param manager
564 * @param enhancer
565 * @param clazz
566 * @param classPath
567 * @param destDir
568 */
569 private static void handleInnerClassAnnotations(final AnnotationManager manager,
570 final AttributeEnhancer enhancer,
571 final JavaClass clazz,
572 final URL[] classPath,
573 final String destDir) {
574
575 JavaClass[] innerClasses = clazz.getInnerClasses();
576 for (int i = 0; i < innerClasses.length; i++) {
577 JavaClass innerClass = innerClasses[i];
578 String innerClassName = innerClass.getFullyQualifiedName();
579 Annotation[] introduceAnnotations = manager.getAnnotations(
580 ANNOTATION_INTRODUCE,
581 innerClass
582 );
583 for (int k = 0; k < introduceAnnotations.length; k++) {
584 Annotation introduceAnnotation = introduceAnnotations[k];
585 if (introduceAnnotation != null) {
586 IntroduceAnnotationProxy introduceProxy = (IntroduceAnnotationProxy) introduceAnnotation;
587 if (introduceProxy != null) {
588
589 JavaClass[] introducedInterfaceClasses = innerClass
590 .getImplementedInterfaces();
591 String[] introducedInterfaceNames = new String[introducedInterfaceClasses.length];
592 for (int j = 0; j < introducedInterfaceClasses.length; j++) {
593 introducedInterfaceNames[j] = introducedInterfaceClasses[j]
594 .getFullyQualifiedName();
595 logInfo(
596 " interface introduction [" + introducedInterfaceNames[j]
597 + ']'
598 );
599 }
600 if (introducedInterfaceNames.length == 0) {
601 introducedInterfaceNames = enhancer
602 .getNearestInterfacesInHierarchy(innerClassName);
603 if (introducedInterfaceNames.length == 0) {
604 throw new RuntimeException(
605 "no implicit interfaces found for "
606 + innerClassName
607 );
608 }
609 for (int j = 0; j < introducedInterfaceNames.length; j++) {
610 logInfo(
611 " interface introduction ["
612 + introducedInterfaceNames[j] + ']'
613 );
614 }
615 }
616 introduceProxy.setIntroducedInterfaces(introducedInterfaceNames);
617 introduceProxy.setInnerClassName(innerClassName);
618 logInfo(
619 " mixin introduction [" + innerClass.getFullyQualifiedName()
620 + " :: " + introduceProxy.expression() +
621 "] deployment model ["
622 + introduceProxy.deploymentModel() + ']'
623 );
624 enhancer.insertClassAttribute(
625 new AnnotationInfo(
626 ANNOTATION_INTRODUCE,
627 introduceProxy
628 )
629 );
630 }
631 }
632 }
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656 }
657 }
658
659 /***
660 * Registers the system annotations.
661 *
662 * @param manager the annotations manager
663 */
664 private static void registerSystemAnnotations(final AnnotationManager manager) {
665 manager.registerAnnotationProxy(AspectAnnotationProxy.class, ANNOTATION_ASPECT);
666 manager.registerAnnotationProxy(AroundAnnotationProxy.class, ANNOTATION_AROUND);
667 manager.registerAnnotationProxy(BeforeAnnotationProxy.class, ANNOTATION_BEFORE);
668 manager.registerAnnotationProxy(AfterAnnotationProxy.class, ANNOTATION_AFTER);
669 manager.registerAnnotationProxy(ExpressionAnnotationProxy.class, ANNOTATION_EXPRESSION);
670 manager.registerAnnotationProxy(ImplementsAnnotationProxy.class, ANNOTATION_IMPLEMENTS);
671 manager.registerAnnotationProxy(IntroduceAnnotationProxy.class, ANNOTATION_INTRODUCE);
672 }
673
674 /***
675 * Registers the user defined annotations.
676 *
677 * @param manager the annotations manager
678 * @param propertiesFiles
679 */
680 private static void registerUserDefinedAnnotations(final AnnotationManager manager,
681 final String[] propertiesFiles) {
682 if (propertiesFiles == null) {
683 return;
684 }
685 for (int i = 0; i < propertiesFiles.length; i++) {
686 String propertiesFile = propertiesFiles[i];
687 try {
688 ANNOTATION_DEFINITION.load(new FileInputStream(propertiesFile));
689 } catch (Exception e) {
690 String message = "custom annotation properties " + propertiesFile
691 + " can not be loaded: " + e.toString();
692 logWarning(message);
693 throw new DefinitionException(message);
694 }
695 }
696 for (Iterator it = ANNOTATION_DEFINITION.entrySet().iterator(); it.hasNext();) {
697 Map.Entry entry = (Map.Entry) it.next();
698 String name = ((String) entry.getKey()).trim();
699 String className = ((String) entry.getValue()).trim();
700 Class klass;
701 if (className.equals("")) {
702
703 klass = UntypedAnnotationProxy.class;
704 className = klass.getName();
705 } else {
706 try {
707 klass = s_loader.loadClass(className);
708 } catch (ClassNotFoundException e) {
709 String message = className
710 +
711 " could not be found on system classpath or class path provided as argument to the compiler";
712 logError(message);
713 throw new DefinitionException(message);
714 }
715 }
716 logInfo("register custom annotation [" + name + " :: " + className + ']');
717 manager.registerAnnotationProxy(klass, name);
718 s_customAnnotations.put(name, className);
719 }
720 }
721
722 /***
723 * Prints the usage.
724 */
725 private static void printUsage() {
726 System.out.println("AspectWerkz (c) 2002-2005 Jonas Bonér, Alexandre Vasseur");
727 System.out
728 .println(
729 "usage: java [options...] org.codehaus.aspectwerkz.annotation.AnnotationC [-verbose] -src <path to src dir> | -srcfiles <list of files> | -srcincludes <path to file> -classes <path to classes dir> [-dest <path to destination dir>] [-custom <property file for custom annotations>]"
730 );
731 System.out.println(
732 " -src <path to src dir> provides the list of source directories separated by File.pathSeparator"
733 );
734 System.out.println(" -srcpath <list of files> provides a comma separated list of source files");
735 System.out.println(
736 " -srcincludes <path to file> provides the path to a file containing the list of source files (one name per line)"
737 );
738 System.out
739 .println(
740 " -dest <path to destination dir> is optional, if omitted the compiled classes will be written to the initial directory"
741 );
742 System.out
743 .println(
744 " -custom <property file for cutom annotations> is optional, only needed if you have custom annotations you want to compile." +
745 " You can use several properties file by using a path separator (; or : depending on the OS)."
746 );
747 System.out.println(" -verbose activates compilation status information");
748 System.out.println("");
749 System.out.println("Note: only one of -src -srcpath and -srcincludes may be used");
750
751 System.exit(0);
752 }
753
754 /***
755 * Parses the command line options.
756 *
757 * @param args the arguments
758 * @return a map with the options
759 */
760 private static Map parseCommandLineOptions(final String[] args) {
761 final Map arguments = new HashMap();
762 try {
763 for (int i = 0; i < args.length; i++) {
764 if (args[i].equals(COMMAND_LINE_OPTION_VERBOSE)) {
765 s_verbose = true;
766 } else if (args[i].startsWith(COMMAND_LINE_OPTION_DASH)) {
767 String option = args[i++];
768 String value = args[i];
769 arguments.put(option, value);
770 }
771 }
772 } catch (Exception e) {
773 logError("options list to compiler is not valid");
774 System.exit(1);
775 }
776 return arguments;
777 }
778
779 /***
780 * Logs an INFO message.
781 *
782 * @param message the message
783 */
784 private static void logInfo(final String message) {
785 if (s_verbose) {
786 System.out.println("AnnotationC::INFO - " + message);
787 }
788 }
789
790 /***
791 * Logs an ERROR message.
792 *
793 * @param message the message
794 */
795 private static void logError(final String message) {
796 if (s_verbose) {
797 System.err.println("AnnotationC::ERROR - " + message);
798 }
799 }
800
801 /***
802 * Logs an WARNING message.
803 *
804 * @param message the message
805 */
806 private static void logWarning(final String message) {
807 if (s_verbose) {
808 System.err.println("AnnotationC::WARNING - " + message);
809 }
810 }
811
812 private static String getShortCallSignature(final JavaMethod method) {
813 StringBuffer buffer = new StringBuffer(method.getName());
814 buffer.append("(");
815 for (int i = 0; i < method.getParameters().length; i++) {
816 JavaParameter javaParameter = method.getParameters()[i];
817 if (javaParameter.getType().toString().equals(JoinPoint.class.getName())) {
818 buffer.append("JoinPoint");
819 } else if (javaParameter.getType().toString().equals(StaticJoinPoint.class.getName())) {
820 buffer.append("StaticJoinPoint");
821 } else {
822 buffer.append(javaParameter.getType().toString());
823 buffer.append(" ");
824 buffer.append(javaParameter.getName());
825 }
826 if (i + 1 < method.getParameters().length) {
827 buffer.append(", ");
828 }
829 }
830 buffer.append(")");
831 return buffer.toString();
832 }
833
834 private static void registerCallParameters(final ParameterizedAnnotationProxy proxy, final JavaMethod method) {
835 for (int j = 0; j < method.getParameters().length; j++) {
836 JavaParameter javaParameter = method.getParameters()[j];
837 proxy.addArgument(javaParameter.getName(), javaParameter.getType().toString());
838 }
839 }
840
841 private static String[] split(String str, String sep) {
842 if (str == null || str.length() == 0) {
843 return new String[0];
844 }
845
846 int start = 0;
847 int idx = str.indexOf(sep, start);
848 int len = sep.length();
849 List strings = new ArrayList();
850
851 while (idx != -1) {
852 strings.add(str.substring(start, idx));
853 start = idx + len;
854 idx = str.indexOf(sep, start);
855 }
856
857 strings.add(str.substring(start));
858
859 return (String[]) strings.toArray(new String[strings.size()]);
860 }
861
862 /***
863 * Load and solve relative to working directory the list of files.
864 *
865 * @param srcIncludes
866 * @return
867 */
868 private static String[] loadSourceList(final String srcIncludes) {
869 File currentDir = new File(".");
870 List files = new ArrayList();
871 BufferedReader reader = null;
872
873 try {
874 reader = new BufferedReader(new FileReader(srcIncludes));
875
876 String line = reader.readLine();
877 File tmpFile = null;
878 while (line != null) {
879 if (line.length() > 0) {
880 tmpFile = new File(currentDir, line);
881 if (!tmpFile.isFile()) {
882 logWarning("file not found: [" + tmpFile + "]");
883 } else {
884 files.add(tmpFile.getAbsolutePath());
885 }
886 }
887 line = reader.readLine();
888 }
889 } catch (IOException ioe) {
890 throw new BuildException(
891 "an error occured while reading from pattern file: "
892 + srcIncludes, ioe
893 );
894 } finally {
895 if (null != reader) {
896 try {
897 reader.close();
898 } catch (IOException ioe) {
899
900 }
901 }
902 }
903
904 return (String[]) files.toArray(new String[files.size()]);
905 }
906 }