KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > annotation > AnnotationC


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.codehaus.aspectwerkz.annotation.instrumentation.AttributeEnhancer;
18 import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAttributeEnhancer;
19 import org.codehaus.aspectwerkz.exception.DefinitionException;
20 import org.codehaus.aspectwerkz.joinpoint.JoinPoint;
21 import org.codehaus.aspectwerkz.joinpoint.StaticJoinPoint;
22 import org.codehaus.aspectwerkz.DeploymentModel;
23
24 import java.io.BufferedReader JavaDoc;
25 import java.io.File JavaDoc;
26 import java.io.FileInputStream JavaDoc;
27 import java.io.FileReader JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.InputStream JavaDoc;
30 import java.net.MalformedURLException JavaDoc;
31 import java.net.URL JavaDoc;
32 import java.net.URLClassLoader JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.HashMap JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import java.util.List JavaDoc;
37 import java.util.Map JavaDoc;
38 import java.util.Properties JavaDoc;
39 import java.util.StringTokenizer JavaDoc;
40
41 /**
42  * <p/>Annotation compiler. <p/>Extracts the annotations from JavaDoc tags and inserts them into the bytecode of the
43  * class.
44  *
45  * @author <a HREF="mailto:jboner@codehaus.org">Jonas BonŽr </a>
46  * @author <a HREF="mailto:alex@gnilux.com">Alexandre Vasseur </a>
47  */

48 public class AnnotationC {
49     private static final String JavaDoc COMMAND_LINE_OPTION_DASH = "-";
50     private static final String JavaDoc COMMAND_LINE_OPTION_VERBOSE = "-verbose";
51     private static final String JavaDoc COMMAND_LINE_OPTION_CUSTOM = "-custom";
52     private static final String JavaDoc COMMAND_LINE_OPTION_SRC = "-src";
53     private static final String JavaDoc COMMAND_LINE_OPTION_SRCFILES = "-srcfiles";
54     private static final String JavaDoc COMMAND_LINE_OPTION_SRCINCLUDES = "-srcincludes";
55     private static final String JavaDoc COMMAND_LINE_OPTION_CLASSES = "-classes";
56     private static final String JavaDoc COMMAND_LINE_OPTION_DEST = "-dest";
57
58     static final String JavaDoc[] SYSTEM_ANNOTATIONS = new String JavaDoc[]{
59         AnnotationConstants.ASPECT, AnnotationConstants.AROUND, AnnotationConstants.BEFORE,
60         AnnotationConstants.AFTER, AnnotationConstants.AFTER_FINALLY,
61         AnnotationConstants.AFTER_RETURNING, AnnotationConstants.AFTER_THROWING,
62         AnnotationConstants.EXPRESSION, AnnotationConstants.INTRODUCE, AnnotationConstants.MIXIN
63     };
64
65     /**
66      * The annotations properties file define by the user.
67      */

68     public static final Properties JavaDoc ANNOTATION_DEFINITION = new Properties JavaDoc();
69
70     /**
71      * Verbose logging.
72      */

73     private static boolean s_verbose = false;
74
75     /**
76      * The class loader.
77      */

78     private static URLClassLoader JavaDoc s_loader;
79
80     /**
81      * The custom annotations.
82      */

83     private static Map JavaDoc s_customAnnotations = new HashMap JavaDoc();
84     private static final String JavaDoc FILE_SEPARATOR = File.separator;
85
86     /**
87      * Runs the compiler from the command line.
88      *
89      * @param args
90      */

91     public static void main(String JavaDoc[] args) {
92         if (args.length < 4) {
93             printUsage();
94         }
95         Map JavaDoc commandLineOptions = parseCommandLineOptions(args);
96
97         String JavaDoc propertiesFilesPath = (String JavaDoc) commandLineOptions.get(COMMAND_LINE_OPTION_CUSTOM);
98         List JavaDoc propertiesFilesList = new ArrayList JavaDoc();
99         if (propertiesFilesPath != null) {
100             StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(propertiesFilesPath, File.pathSeparator);
101             while (st.hasMoreTokens()) {
102                 propertiesFilesList.add(st.nextToken());
103             }
104         }
105         String JavaDoc[] propertiesFiles = (String JavaDoc[]) propertiesFilesList.toArray(new String JavaDoc[0]);
106
107         compile(
108                 (String JavaDoc) commandLineOptions.get(COMMAND_LINE_OPTION_SRC),
109                 (String JavaDoc) commandLineOptions.get(COMMAND_LINE_OPTION_SRCFILES),
110                 (String JavaDoc) commandLineOptions.get(COMMAND_LINE_OPTION_SRCINCLUDES),
111                 (String JavaDoc) commandLineOptions.get(COMMAND_LINE_OPTION_CLASSES),
112                 (String JavaDoc) commandLineOptions.get(COMMAND_LINE_OPTION_DEST),
113                 propertiesFiles
114         );
115     }
116
117     /**
118      * Compiles the annotations.
119      *
120      * @param srcDirList
121      * @param srcFileList
122      * @param classPath
123      * @param destDir
124      * @param annotationPropetiesFiles
125      */

126     private static void compile(final String JavaDoc srcDirList,
127                                 final String JavaDoc srcFileList,
128                                 final String JavaDoc srcFileIncludes,
129                                 final String JavaDoc classPath,
130                                 String JavaDoc destDir,
131                                 final String JavaDoc[] annotationPropetiesFiles) {
132         if (srcDirList == null && srcFileList == null && srcFileIncludes == null) {
133             throw new IllegalArgumentException JavaDoc("one of src or srcfiles or srcincludes must be not null");
134         }
135         if ((srcDirList != null && srcFileList != null) ||
136             (srcDirList != null && srcFileIncludes != null) ||
137             (srcFileList != null && srcFileIncludes != null)) { // FIXME: refactor
138
throw new IllegalArgumentException JavaDoc("maximum one of src, srcfiles or srcincludes must be not null");
139         }
140         if (classPath == null) {
141             throw new IllegalArgumentException JavaDoc("class path can not be null");
142         }
143         if (destDir == null) {
144             destDir = classPath;
145         }
146
147         String JavaDoc[] srcDirs = new String JavaDoc[0];
148         String JavaDoc[] srcFiles = new String JavaDoc[0];
149         if (srcDirList != null) {
150             srcDirs = split(srcDirList, File.pathSeparator);
151         } else if (srcFileList != null) {
152             srcFiles = split(srcFileList, FILE_SEPARATOR);
153         } else {
154             srcFiles = loadSourceList(srcFileIncludes);
155         }
156
157         compile(s_verbose, srcDirs, srcFiles, split(classPath, File.pathSeparator), destDir, annotationPropetiesFiles);
158     }
159
160     /**
161      * Compiles the annotations.
162      *
163      * @param verbose
164      * @param srcDirs
165      * @param srcFiles
166      * @param classpath
167      * @param destDir
168      * @param annotationPropertiesFiles
169      */

170     public static void compile(final boolean verbose,
171                                final String JavaDoc[] srcDirs,
172                                final String JavaDoc[] srcFiles,
173                                final String JavaDoc[] classpath,
174                                final String JavaDoc destDir,
175                                final String JavaDoc[] annotationPropertiesFiles) {
176
177         s_verbose = verbose;
178         URL JavaDoc[] classPath = new URL JavaDoc[classpath.length];
179         try {
180             for (int i = 0; i < classpath.length; i++) {
181                 classPath[i] = new File JavaDoc(classpath[i]).toURL();
182             }
183             s_loader = new URLClassLoader JavaDoc(classPath, AnnotationC.class.getClassLoader());
184         } catch (MalformedURLException JavaDoc e) {
185             String JavaDoc message = "URL [" + classPath + "] is not valid: " + e.toString();
186             logError(message);
187             throw new DefinitionException(message, e);
188         }
189
190         String JavaDoc destDirToUse = destDir;
191         if (destDir == null) {
192             if (classpath.length != 1) {
193                 throw new DefinitionException("destDir must be specified since classpath is composite");
194             }
195             destDirToUse = classpath[0];
196         }
197
198         final AnnotationManager manager = new AnnotationManager(s_loader);
199
200         logInfo("parsing source dirs:");
201         for (int i = 0; i < srcDirs.length; i++) {
202             logInfo(" " + srcDirs[i]);
203         }
204         manager.addSourceTrees(srcDirs);
205
206         for (int i = 0; i < srcFiles.length; i++) {
207             logInfo(" " + srcFiles[i]);
208             manager.addSource(srcFiles[i]);
209         }
210
211         doCompile(annotationPropertiesFiles, classPath, manager, destDirToUse);
212     }
213
214     /**
215      * Compiles the annotations.
216      *
217      * @param annotationPropetiesFiles
218      * @param classPath
219      * @param manager
220      * @param destDir
221      */

222     private static void doCompile(final String JavaDoc[] annotationPropetiesFiles,
223                                   final URL JavaDoc[] classPath,
224                                   final AnnotationManager manager,
225                                   final String JavaDoc destDir) {
226
227         logInfo("compiling annotations...");
228         logInfo("note: if no output is seen, then nothing is compiled");
229
230         // register annotations
231
registerSystemAnnotations(manager);
232         registerUserDefinedAnnotations(manager, annotationPropetiesFiles);
233
234         // get all the classes
235
JavaClass[] classes = manager.getAllClasses();
236         for (int i = 0; i < classes.length; i++) {
237             JavaClass clazz = classes[i];
238             logInfo("class [" + clazz.getFullyQualifiedName() + ']');
239             try {
240                 AttributeEnhancer enhancer = new AsmAttributeEnhancer();
241                 if (enhancer.initialize(clazz.getFullyQualifiedName(), classPath)) {
242                     handleClassAnnotations(manager, enhancer, clazz);
243                     handleInnerClassAnnotations(manager, enhancer, clazz);
244                     JavaMethod[] methods = clazz.getMethods();
245                     for (int j = 0; j < methods.length; j++) {
246                         JavaMethod method = methods[j];
247                         if (method.isConstructor()) {
248                             handleConstructorAnnotations(manager, enhancer, method);
249                         } else {
250                             handleMethodAnnotations(manager, enhancer, method);
251                         }
252                     }
253                     JavaField[] fields = clazz.getFields();
254                     for (int j = 0; j < fields.length; j++) {
255                         handleFieldAnnotations(manager, enhancer, fields[j]);
256                     }
257
258                     // write enhanced class to disk
259
enhancer.write(destDir);
260                 }
261             } catch (Throwable JavaDoc e) {
262                 e.printStackTrace();
263                 logWarning(
264                         "could not compile annotations for class ["
265                         + clazz.getFullyQualifiedName() + "] due to: " + e.toString()
266                 );
267             }
268         }
269         logInfo("compiled classes written to " + destDir);
270         logInfo("compilation successful");
271     }
272
273     /**
274      * Handles the class annotations.
275      *
276      * @param manager
277      * @param enhancer
278      * @param clazz
279      */

280     private static void handleClassAnnotations(final AnnotationManager manager,
281                                                final AttributeEnhancer enhancer,
282                                                final JavaClass clazz) {
283         parseCustomClassAnnotations(clazz, manager, enhancer);
284         parseAspectAnnotations(clazz, manager, enhancer);
285         parseMixinAnnotations(clazz, manager, enhancer);
286     }
287
288     /**
289      * Parses the custom annotations.
290      *
291      * @param clazz
292      * @param manager
293      * @param enhancer
294      */

295     private static void parseCustomClassAnnotations(final JavaClass clazz,
296                                                     final AnnotationManager manager,
297                                                     final AttributeEnhancer enhancer) {
298         for (Iterator JavaDoc it = s_customAnnotations.keySet().iterator(); it.hasNext();) {
299             String JavaDoc annotationName = (String JavaDoc) it.next();
300             Annotation[] customAnnotations = manager.getAnnotations(annotationName, clazz);
301             for (int i = 0; i < customAnnotations.length; i++) {
302                 Annotation customAnnotation = customAnnotations[i];
303                 if (customAnnotation != null) {
304                     enhancer.insertClassAttribute(
305                             new AnnotationInfo(
306                                     annotationName,
307                                     customAnnotation
308                             )
309                     );
310                     logInfo(
311                             " custom class annotation [" + annotationName + " @ "
312                             + clazz.getFullyQualifiedName() + ']'
313                     );
314                 }
315             }
316         }
317     }
318
319     /**
320      * Parses the aspect annotations.
321      *
322      * @param clazz
323      * @param manager
324      * @param enhancer
325      */

326     private static void parseAspectAnnotations(final JavaClass clazz,
327                                                final AnnotationManager manager,
328                                                final AttributeEnhancer enhancer) {
329         Annotation[] annotations = manager.getAnnotations(AnnotationConstants.ASPECT, clazz);
330         for (int i = 0; i < annotations.length; i++) {
331             Annotation annotation = annotations[i];
332             if (annotation != null) {
333                 enhancer.insertClassAttribute(
334                         new AnnotationInfo(AnnotationConstants.ASPECT, annotation)
335                 );
336                 String JavaDoc name = ((Aspect) annotation).name();
337                 if (name == null) {
338                     name = clazz.getFullyQualifiedName();
339                 }
340                 String JavaDoc deploymentModel = ((Aspect) annotation).deploymentModel();
341                 if (((Aspect) annotation).value() != null) {
342                     deploymentModel = ((Aspect) annotation).value();
343                 }
344                 logInfo("aspect [" + name + ']');
345                 logInfo(" deployment model [" + deploymentModel + ']');
346             }
347         }
348     }
349
350     /**
351      * Parses mixin annotations.
352      *
353      * @param clazz
354      * @param manager
355      * @param enhancer
356      */

357     private static void parseMixinAnnotations(final JavaClass clazz,
358                                               final AnnotationManager manager,
359                                               final AttributeEnhancer enhancer) {
360         final Annotation[] introduceAnnotations = manager.getAnnotations(
361                 AnnotationConstants.MIXIN_DOCLET, clazz
362         );
363         final String JavaDoc className = clazz.getFullyQualifiedName();
364         for (int k = 0; k < introduceAnnotations.length; k++) {
365             Annotation introduceAnnotation = introduceAnnotations[k];
366             if (introduceAnnotation != null && introduceAnnotation instanceof Mixin) {
367                 //directly implemented interfaces
368
JavaClass[] introducedInterfaceClasses = clazz.getImplementedInterfaces();
369                 String JavaDoc[] introducedInterfaceNames = new String JavaDoc[introducedInterfaceClasses.length];
370                 for (int j = 0; j < introducedInterfaceClasses.length; j++) {
371                     introducedInterfaceNames[j] = introducedInterfaceClasses[j].getFullyQualifiedName();
372                     logInfo(" interface introduction [" + introducedInterfaceNames[j] + ']');
373                 }
374                 if (introducedInterfaceNames.length == 0) {
375                     introducedInterfaceNames = enhancer.getNearestInterfacesInHierarchy(className);
376                     if (introducedInterfaceNames.length == 0) {
377                         throw new RuntimeException JavaDoc("no implicit interfaces found for " + className);
378                     }
379                     for (int j = 0; j < introducedInterfaceNames.length; j++) {
380                         logInfo(" interface introduction [" + introducedInterfaceNames[j] + ']');
381                     }
382                 }
383                 String JavaDoc deploymentModel = DeploymentModel.PER_JVM.toString();
384                 if (((Mixin) introduceAnnotation).deploymentModel() != null) {
385                     deploymentModel = ((Mixin) introduceAnnotation).deploymentModel();
386                 }
387                 String JavaDoc expression = ((Mixin) introduceAnnotation).pointcut();
388                 if (expression == null) {
389                     expression = ((Mixin) introduceAnnotation).value();
390                 }
391                 logInfo(
392                         " mixin introduction [" + clazz.getFullyQualifiedName()
393                         + " :: " + expression +
394                         "] deployment model ["
395                         + deploymentModel + ']'
396                 );
397                 enhancer.insertClassAttribute(
398                         new AnnotationInfo(AnnotationConstants.MIXIN, introduceAnnotation)
399                 );
400             }
401         }
402     }
403
404     /**
405      * Handles the method annotations.
406      *
407      * @param manager
408      * @param enhancer
409      * @param method
410      */

411     private static void handleMethodAnnotations(final AnnotationManager manager,
412                                                 final AttributeEnhancer enhancer,
413                                                 final JavaMethod method) {
414         // Pointcut with signature
415
Annotation[] expressionAnnotations = manager.getAnnotations(
416                 AnnotationConstants.EXPRESSION_DOCLET, method
417         );
418         for (int i = 0; i < expressionAnnotations.length; i++) {
419             Annotation expressionAnnotation = expressionAnnotations[i];
420             if (expressionAnnotation != null && expressionAnnotation instanceof Expression) {
421                 enhancer.insertMethodAttribute(
422                         method, new AnnotationInfo(
423                                 AnnotationConstants.EXPRESSION,
424                                 expressionAnnotation
425                         )
426                 );
427                 logInfo(
428                         " pointcut [" + AnnotationC.getShortCallSignature(method) + " :: "
429                         + ((Expression) expressionAnnotation).value() + ']'
430                 );
431             }
432         }
433         Annotation[] aroundAnnotations = manager.getAnnotations(AnnotationConstants.AROUND_DOCLET, method);
434         for (int i = 0; i < aroundAnnotations.length; i++) {
435             Annotation aroundAnnotation = aroundAnnotations[i];
436             if (aroundAnnotation != null && aroundAnnotation instanceof Around) {
437                 enhancer.insertMethodAttribute(
438                         method, new AnnotationInfo(
439                                 AnnotationConstants.AROUND,
440                                 aroundAnnotation
441                         )
442                 );
443                 logInfo(
444                         " around advice [" + AnnotationC.getShortCallSignature(method) + " :: "
445                         + ((Around) aroundAnnotation).value() + ']'
446                 );
447             }
448         }
449         Annotation[] beforeAnnotations = manager.getAnnotations(AnnotationConstants.BEFORE_DOCLET, method);
450         for (int i = 0; i < beforeAnnotations.length; i++) {
451             Annotation beforeAnnotation = beforeAnnotations[i];
452             if (beforeAnnotation != null && beforeAnnotation instanceof Before) {
453                 enhancer.insertMethodAttribute(
454                         method, new AnnotationInfo(
455                                 AnnotationConstants.BEFORE,
456                                 beforeAnnotation
457                         )
458                 );
459                 logInfo(
460                         " before [" + AnnotationC.getShortCallSignature(method) + " :: "
461                         + ((Before) beforeAnnotation).value() + ']'
462                 );
463             }
464         }
465         Annotation[] afterAnnotations = manager.getAnnotations(AnnotationConstants.AFTER_DOCLET, method);
466         for (int i = 0; i < afterAnnotations.length; i++) {
467             Annotation afterAnnotation = afterAnnotations[i];
468             if (afterAnnotation != null && afterAnnotation instanceof After) {
469                 enhancer.insertMethodAttribute(
470                         method, new AnnotationInfo(AnnotationConstants.AFTER, afterAnnotation)
471                 );
472                 logInfo(
473                         " after advice [" + AnnotationC.getShortCallSignature(method) + " :: "
474                         + ((After) afterAnnotation).value() + ']'
475                 );
476             }
477         }
478         Annotation[] afterFinallyAnnotations = manager.getAnnotations(
479                 AnnotationConstants.AFTER_FINALLY_DOCLET, method
480         );
481         for (int i = 0; i < afterFinallyAnnotations.length; i++) {
482             Annotation afterAnnotation = afterFinallyAnnotations[i];
483             if (afterAnnotation != null && afterAnnotation instanceof AfterFinally) {
484                 enhancer.insertMethodAttribute(
485                         method, new AnnotationInfo(AnnotationConstants.AFTER_FINALLY, afterAnnotation)
486                 );
487                 logInfo(
488                         " after finally advice [" + AnnotationC.getShortCallSignature(method) + " :: "
489                         + ((AfterFinally) afterAnnotation).value() + ']'
490                 );
491             }
492         }
493         Annotation[] afterReturningAnnotations = manager.getAnnotations(
494                 AnnotationConstants.AFTER_RETURNING_DOCLET, method
495         );
496         for (int i = 0; i < afterReturningAnnotations.length; i++) {
497             Annotation afterAnnotation = afterReturningAnnotations[i];
498             if (afterAnnotation != null && afterAnnotation instanceof AfterReturning) {
499                 enhancer.insertMethodAttribute(
500                         method,
501                         new AnnotationInfo(AnnotationConstants.AFTER_RETURNING, afterAnnotation)
502                 );
503                 logInfo(
504                         " after returning advice [" + AnnotationC.getShortCallSignature(method) + " :: "
505                         +
506                         AspectAnnotationParser.getExpressionElseValue(
507                                 ((AfterReturning) afterAnnotation).value(),
508                                 ((AfterReturning) afterAnnotation).pointcut()
509                         )
510                         + " :: " + ((AfterReturning) afterAnnotation).type() + ']'
511                 );
512             }
513         }
514         Annotation[] afterThrowingAnnotations = manager.getAnnotations(
515                 AnnotationConstants.AFTER_THROWING_DOCLET, method
516         );
517         for (int i = 0; i < afterThrowingAnnotations.length; i++) {
518             Annotation afterAnnotation = afterThrowingAnnotations[i];
519             if (afterAnnotation != null && afterAnnotation instanceof AfterThrowing) {
520                 enhancer.insertMethodAttribute(
521                         method,
522                         new AnnotationInfo(AnnotationConstants.AFTER_THROWING, afterAnnotation)
523                 );
524                 logInfo(
525                         " after throwing advice [" + AnnotationC.getShortCallSignature(method) + " :: "
526                         +
527                         AspectAnnotationParser.getExpressionElseValue(
528                                 ((AfterThrowing) afterAnnotation).value(),
529                                 ((AfterThrowing) afterAnnotation).pointcut()
530                         )
531                         + " :: " + ((AfterThrowing) afterAnnotation).type() + ']'
532                 );
533             }
534         }
535         for (Iterator JavaDoc it = s_customAnnotations.keySet().iterator(); it.hasNext();) {
536             String JavaDoc annotationName = (String JavaDoc) it.next();
537             Annotation[] customAnnotations = manager.getAnnotations(annotationName, method);
538             for (int i = 0; i < customAnnotations.length; i++) {
539                 Annotation customAnnotation = customAnnotations[i];
540                 if (customAnnotation != null) {
541                     enhancer.insertMethodAttribute(method, new AnnotationInfo(
542                                 annotationName,
543                                 customAnnotation)
544                     );
545                     logInfo(
546                             " custom method annotation [" + annotationName + " @ "
547                             + method.getParentClass().getName() + '.' + method.getName() +
548                             ']'
549                     );
550                 }
551             }
552         }
553     }
554
555     /**
556      * Handles the constructor annotations.
557      *
558      * @param manager
559      * @param enhancer
560      * @param constructor
561      */

562     private static void handleConstructorAnnotations(final AnnotationManager manager,
563                                                      final AttributeEnhancer enhancer,
564                                                      final JavaMethod constructor) {
565         for (Iterator JavaDoc it = s_customAnnotations.keySet().iterator(); it.hasNext();) {
566             String JavaDoc annotationName = (String JavaDoc) it.next();
567             Annotation[] customAnnotations = manager.getAnnotations(annotationName, constructor);
568             for (int i = 0; i < customAnnotations.length; i++) {
569                 Annotation customAnnotation = customAnnotations[i];
570                 if (customAnnotation != null) {
571                     enhancer.insertConstructorAttribute(
572                             constructor, new AnnotationInfo(annotationName,
573                                                             customAnnotation)
574                     );
575                     logInfo(
576                             " custom constructor annotation [" + annotationName + " @ "
577                             + constructor.getParentClass().getName() + '.' +
578                             constructor.getName()
579                             + ']'
580                     );
581                 }
582             }
583         }
584     }
585
586     /**
587      * Handles the field annotations.
588      *
589      * @param manager
590      * @param enhancer
591      * @param field
592      */

593     private static void handleFieldAnnotations(final AnnotationManager manager,
594                                                final AttributeEnhancer enhancer,
595                                                final JavaField field) {
596
597         Annotation[] expressionAnnotations = manager.getAnnotations(
598                 AnnotationConstants.EXPRESSION_DOCLET, field
599         );
600         for (int i = 0; i < expressionAnnotations.length; i++) {
601             Annotation expressionAnnotation = expressionAnnotations[i];
602             if (expressionAnnotation != null && expressionAnnotation instanceof Expression) {
603                 enhancer.insertFieldAttribute(
604                         field, new AnnotationInfo(
605                                 AnnotationConstants.EXPRESSION,
606                                 expressionAnnotation
607                         )
608                 );
609                 logInfo(
610                         " pointcut [" + field.getName() + " :: " + ((Expression) expressionAnnotation).value()
611                         + ']'
612                 );
613             }
614         }
615         Annotation[] introduceAnnotations = manager.getAnnotations(
616                 AnnotationConstants.INTRODUCE_DOCLET, field
617         );
618         for (int i = 0; i < introduceAnnotations.length; i++) {
619             Annotation introduceAnnotation = introduceAnnotations[i];
620             if (introduceAnnotation != null && introduceAnnotation instanceof Introduce) {
621                 enhancer.insertFieldAttribute(
622                         field, new AnnotationInfo(
623                                 AnnotationConstants.INTRODUCE,
624                                 introduceAnnotation
625                         )
626                 );
627                 logInfo(
628                         " interface introduction [" + field.getName() + " :: "
629                         + ((Introduce) introduceAnnotation).value() + ']'
630                 );
631             }
632         }
633         for (Iterator JavaDoc it = s_customAnnotations.keySet().iterator(); it.hasNext();) {
634             String JavaDoc annotationName = (String JavaDoc) it.next();
635             Annotation[] customAnnotations = manager.getAnnotations(annotationName, field);
636             for (int i = 0; i < customAnnotations.length; i++) {
637                 Annotation customAnnotation = customAnnotations[i];
638                 if (customAnnotation != null) {
639                     enhancer.insertFieldAttribute(
640                             field, new AnnotationInfo(
641                                     annotationName,
642                                     customAnnotation
643                             )
644                     );
645                     logInfo(
646                             " custom field annotation [" + annotationName + " @ "
647                             + field.getName() + ']'
648                     );
649                 }
650             }
651         }
652     }
653
654     /**
655      * Handles the inner class annotations.
656      *
657      * @param manager
658      * @param enhancer
659      * @param clazz
660      */

661     private static void handleInnerClassAnnotations(final AnnotationManager manager,
662                                                     final AttributeEnhancer enhancer,
663                                                     final JavaClass clazz) {
664         JavaClass[] innerClasses = clazz.getInnerClasses();
665         for (int i = 0; i < innerClasses.length; i++) {
666             parseMixinAnnotations(innerClasses[i], manager, enhancer);
667         }
668     }
669
670     /**
671      * Registers the system annotations.
672      *
673      * @param manager the annotations manager
674      */

675     private static void registerSystemAnnotations(final AnnotationManager manager) {
676         manager.registerAnnotationProxy(Aspect.class, AnnotationConstants.ASPECT_DOCLET);
677         manager.registerAnnotationProxy(Around.class, AnnotationConstants.AROUND_DOCLET);
678         manager.registerAnnotationProxy(Before.class, AnnotationConstants.BEFORE_DOCLET);
679         manager.registerAnnotationProxy(After.class, AnnotationConstants.AFTER_DOCLET);
680         manager.registerAnnotationProxy(AfterReturning.class, AnnotationConstants.AFTER_RETURNING_DOCLET);
681         manager.registerAnnotationProxy(AfterThrowing.class, AnnotationConstants.AFTER_THROWING_DOCLET);
682         manager.registerAnnotationProxy(AfterFinally.class, AnnotationConstants.AFTER_FINALLY_DOCLET);
683         manager.registerAnnotationProxy(Expression.class, AnnotationConstants.EXPRESSION_DOCLET);
684         manager.registerAnnotationProxy(Introduce.class, AnnotationConstants.INTRODUCE_DOCLET);
685         manager.registerAnnotationProxy(Mixin.class, AnnotationConstants.MIXIN_DOCLET);
686     }
687
688     /**
689      * Registers the user defined annotations.
690      *
691      * @param manager the annotations manager
692      * @param propertiesFiles
693      */

694     private static void registerUserDefinedAnnotations(final AnnotationManager manager,
695                                                        final String JavaDoc[] propertiesFiles) {
696         if (propertiesFiles == null) {
697             return;
698         }
699         InputStream JavaDoc in = null;
700         for (int i = 0; i < propertiesFiles.length; i++) {
701             String JavaDoc propertiesFile = propertiesFiles[i];
702             try {
703                 in = new FileInputStream JavaDoc(propertiesFile);
704                 ANNOTATION_DEFINITION.load(in);
705             } catch (Exception JavaDoc e) {
706                 String JavaDoc message = "custom annotation properties " + propertiesFile + " can not be loaded: " +
707                                  e.toString();
708                 logWarning(message);
709                 throw new DefinitionException(message);
710             } finally {
711                 try {
712                     in.close();
713                 } catch (Exception JavaDoc e) {
714                     ;
715                 }
716             }
717         }
718
719         for (Iterator JavaDoc it = ANNOTATION_DEFINITION.entrySet().iterator(); it.hasNext();) {
720             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
721             String JavaDoc name = ((String JavaDoc) entry.getKey()).trim();
722             String JavaDoc className = ((String JavaDoc) entry.getValue()).trim();
723             Class JavaDoc klass;
724             if (className.equals("")) {
725                 // use default untyped annotation
726
klass = UntypedAnnotation.class;
727                 className = klass.getName();
728             } else {
729                 try {
730                     klass = Class.forName(className, false, s_loader);
731                 } catch (ClassNotFoundException JavaDoc e) {
732                     String JavaDoc message = className
733                                      +
734                                      " could not be found on system classpath or class path provided as argument to the compiler";
735                     logError(message);
736                     throw new DefinitionException(message);
737                 }
738             }
739             logInfo("register custom annotation [" + name + " :: " + className + ']');
740             manager.registerAnnotationProxy(klass, name);
741             s_customAnnotations.put(name, className);
742         }
743     }
744
745     /**
746      * Prints the usage.
747      */

748     private static void printUsage() {
749         System.out.println("AspectWerkz (c) 2002-2005 Jonas BonŽr, Alexandre Vasseur");
750         System.out.println(
751                 "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>]"
752         );
753         System.out.println(
754                 " -src <path to src dir> provides the list of source directories separated by File.pathSeparator"
755         );
756         System.out.println(" -srcpath <list of files> provides a comma separated list of source files");
757         System.out.println(
758                 " -srcincludes <path to file> provides the path to a file containing the list of source files (one name per line)"
759         );
760         System.out.println(
761                 " -dest <path to destination dir> is optional, if omitted the compiled classes will be written to the initial directory"
762         );
763         System.out.println(
764                 " -custom <property file for cutom annotations> is optional, only needed if you have custom annotations you want to compile"
765         );
766         System.out.println(" -verbose activates compilation status information");
767         System.out.println("");
768         System.out.println("Note: only one of -src -srcpath and -srcincludes may be used");
769
770         System.exit(0);
771     }
772
773     /**
774      * Parses the command line options.
775      *
776      * @param args the arguments
777      * @return a map with the options
778      */

779     private static Map JavaDoc parseCommandLineOptions(final String JavaDoc[] args) {
780         final Map JavaDoc arguments = new HashMap JavaDoc();
781         try {
782             for (int i = 0; i < args.length; i++) {
783                 if (args[i].equals(COMMAND_LINE_OPTION_VERBOSE)) {
784                     s_verbose = true;
785                 } else if (args[i].startsWith(COMMAND_LINE_OPTION_DASH)) {
786                     String JavaDoc option = args[i++];
787                     String JavaDoc value = args[i];
788                     arguments.put(option, value);
789                 }
790             }
791         } catch (Exception JavaDoc e) {
792             logError("options list to compiler is not valid");
793             System.exit(1);
794         }
795         return arguments;
796     }
797
798     /**
799      * Logs an INFO message.
800      *
801      * @param message the message
802      */

803     private static void logInfo(final String JavaDoc message) {
804         if (s_verbose) {
805             System.out.println("AnnotationC::INFO - " + message);
806         }
807     }
808
809     /**
810      * Logs an ERROR message.
811      *
812      * @param message the message
813      */

814     private static void logError(final String JavaDoc message) {
815         if (s_verbose) {
816             System.err.println("AnnotationC::ERROR - " + message);
817         }
818     }
819
820     /**
821      * Logs an WARNING message.
822      *
823      * @param message the message
824      */

825     private static void logWarning(final String JavaDoc message) {
826         if (s_verbose) {
827             System.err.println("AnnotationC::WARNING - " + message);
828         }
829     }
830
831     /**
832      * Helper method to get a pretty printable method signature (no FQN class names)
833      *
834      * @param method
835      * @return
836      */

837     private static String JavaDoc getShortCallSignature(final JavaMethod method) {
838         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(method.getName());
839         buffer.append("(");
840         for (int i = 0; i < method.getParameters().length; i++) {
841             JavaParameter javaParameter = method.getParameters()[i];
842             if (javaParameter.getType().toString().equals(JoinPoint.class.getName())) {
843                 buffer.append("JoinPoint");
844             } else if (javaParameter.getType().toString().equals(StaticJoinPoint.class.getName())) {
845                 buffer.append("StaticJoinPoint");
846             } else {
847                 buffer.append(javaParameter.getType().toString());
848                 buffer.append(" ");
849                 buffer.append(javaParameter.getName());
850             }
851             if (i + 1 < method.getParameters().length) {
852                 buffer.append(", ");
853             }
854         }
855         buffer.append(")");
856         return buffer.toString();
857     }
858
859     private static String JavaDoc[] split(String JavaDoc str, String JavaDoc sep) {
860         if (str == null || str.length() == 0) {
861             return new String JavaDoc[0];
862         }
863
864         int start = 0;
865         int idx = str.indexOf(sep, start);
866         int len = sep.length();
867         List JavaDoc strings = new ArrayList JavaDoc();
868
869         while (idx != -1) {
870             strings.add(str.substring(start, idx));
871             start = idx + len;
872             idx = str.indexOf(sep, start);
873         }
874
875         strings.add(str.substring(start));
876
877         return (String JavaDoc[]) strings.toArray(new String JavaDoc[strings.size()]);
878     }
879
880     /**
881      * Load and solve relative to working directory the list of files.
882      *
883      * @param srcIncludes
884      * @return
885      */

886     private static String JavaDoc[] loadSourceList(final String JavaDoc srcIncludes) {
887         File JavaDoc currentDir = new File JavaDoc(".");
888         List JavaDoc files = new ArrayList JavaDoc();
889         BufferedReader JavaDoc reader = null;
890
891         try {
892             reader = new BufferedReader JavaDoc(new FileReader JavaDoc(srcIncludes));
893
894             String JavaDoc line = reader.readLine();
895             File JavaDoc tmpFile = null;
896             while (line != null) {
897                 if (line.length() > 0) {
898                     tmpFile = new File JavaDoc(currentDir, line);
899                     if (!tmpFile.isFile()) {
900                         logWarning("file not found: [" + tmpFile + "]");
901                     } else {
902                         files.add(tmpFile.getAbsolutePath());
903                     }
904                 }
905                 line = reader.readLine();
906             }
907         } catch (IOException JavaDoc ioe) {
908             throw new BuildException(
909                     "an error occured while reading from pattern file: "
910                     + srcIncludes, ioe
911             );
912         } finally {
913             if (null != reader) {
914                 try {
915                     reader.close();
916                 } catch (IOException JavaDoc ioe) {
917                     //Ignore exception
918
}
919             }
920         }
921
922         return (String JavaDoc[]) files.toArray(new String JavaDoc[files.size()]);
923     }
924
925 }
Popular Tags