View Javadoc

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  import org.codehaus.aspectwerkz.reflect.MethodInfo;
11  import org.codehaus.aspectwerkz.reflect.ClassInfo;
12  import org.codehaus.aspectwerkz.reflect.ConstructorInfo;
13  import org.codehaus.aspectwerkz.reflect.FieldInfo;
14  import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo;
15  import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfoRepository;
16  import org.codehaus.aspectwerkz.transform.ReflectHelper;
17  import org.codehaus.aspectwerkz.exception.DefinitionException;
18  import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAnnotations;
19  
20  import java.lang.reflect.Constructor;
21  import java.lang.reflect.Field;
22  import java.lang.reflect.Method;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.Iterator;
26  
27  /***
28   * Utility class for annotation retrieval.
29   * <br/>Note: Annotations are extracted out of ASMClassInfo
30   * <br/>Note: caution when changing that to use reflection, since it might lead to load target class during aspect
31   * system startup.
32   *
33   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
34   */
35  public final class Annotations {
36      /***
37       * Return the annotation with a specific name for a specific class.
38       *
39       * @param annotationName the annotation name
40       * @param klass          the java.lang.Class object to find the annotation on.
41       * @return the annotation or null
42       */
43      public static Annotation getAnnotation(final String annotationName, final Class klass) {
44          ClassInfo classInfo = AsmClassInfo.getClassInfo(klass.getName(), klass.getClassLoader());
45          return AsmAnnotations.getAnnotation(annotationName, classInfo);
46      }
47  
48      /***
49       * Return the annotation with a specific name for a specific method.
50       *
51       * @param annotationName the annotation name
52       * @param method         the java.lang.refect.Method object to find the annotation on.
53       * @return the annotation or null
54       */
55      public static Annotation getAnnotation(final String annotationName, final Method method) {
56          ClassLoader loader = method.getDeclaringClass().getClassLoader();
57          ClassInfo classInfo = AsmClassInfo.getClassInfo(method.getDeclaringClass().getName(), loader);
58          MethodInfo methodInfo = classInfo.getMethod(ReflectHelper.calculateHash(method));
59          return AsmAnnotations.getAnnotation(annotationName, methodInfo);
60      }
61  
62      /***
63       * Return the annotation with a specific name for a specific constructor.
64       *
65       * @param annotationName the annotation name
66       * @param constructor    the java.lang.refect.Constructor object to find the annotation on.
67       * @return the annotation or null
68       */
69      public static Annotation getAnnotation(final String annotationName, final Constructor constructor) {
70          ClassLoader loader = constructor.getDeclaringClass().getClassLoader();
71          ClassInfo classInfo = AsmClassInfo.getClassInfo(constructor.getDeclaringClass().getName(), loader);
72          ConstructorInfo constructorInfo = classInfo.getConstructor(ReflectHelper.calculateHash(constructor));
73          return AsmAnnotations.getAnnotation(annotationName, constructorInfo);
74      }
75  
76      /***
77       * Return the annotation with a specific name for a specific field.
78       *
79       * @param annotationName the annotation name
80       * @param field          the java.lang.reflect.Field object to find the annotation on.
81       * @return the annotation or null
82       */
83      public static Annotation getAnnotation(final String annotationName, final Field field) {
84          ClassLoader loader = field.getDeclaringClass().getClassLoader();
85          ClassInfo classInfo = AsmClassInfo.getClassInfo(field.getDeclaringClass().getName(), loader);
86          FieldInfo fieldInfo = classInfo.getField(ReflectHelper.calculateHash(field));
87          return AsmAnnotations.getAnnotation(annotationName, fieldInfo);
88      }
89  
90      /***
91       * Return a list with the annotations with a specific name for a specific class.
92       *
93       * @param annotationName the annotation name
94       * @param klass          the java.lang.Class object to find the annotation on.
95       * @return the annotations in a list (can be empty)
96       */
97      public static List getAnnotations(final String annotationName, final Class klass) {
98          ClassInfo classInfo = AsmClassInfo.getClassInfo(klass.getName(), klass.getClassLoader());
99          return AsmAnnotations.getAnnotations(annotationName, classInfo);
100     }
101 
102     /***
103      * Return a list with the annotations with a specific name for a specific method.
104      *
105      * @param annotationName the annotation name
106      * @param method         the java.lang.refect.Method object to find the annotation on.
107      * @return the annotations in a list (can be empty)
108      */
109     public static List getAnnotations(final String annotationName, final Method method) {
110         ClassLoader loader = method.getDeclaringClass().getClassLoader();
111         ClassInfo classInfo = AsmClassInfo.getClassInfo(method.getDeclaringClass().getName(), loader);
112         MethodInfo methodInfo = classInfo.getMethod(ReflectHelper.calculateHash(method));
113         return AsmAnnotations.getAnnotations(annotationName, methodInfo);
114     }
115 
116     /***
117      * Return a list with the annotations with a specific name for a specific constructor.
118      *
119      * @param annotationName the annotation name
120      * @param constructor    the java.lang.refect.Constructor object to find the annotation on.
121      * @return the annotations in a list (can be empty)
122      */
123     public static List getAnnotations(final String annotationName, final Constructor constructor) {
124         ClassLoader loader = constructor.getDeclaringClass().getClassLoader();
125         ClassInfo classInfo = AsmClassInfo.getClassInfo(constructor.getDeclaringClass().getName(), loader);
126         ConstructorInfo constructorInfo = classInfo.getConstructor(ReflectHelper.calculateHash(constructor));
127         return AsmAnnotations.getAnnotations(annotationName, constructorInfo);
128     }
129 
130     /***
131      * Return a list with the annotations with a specific name for a specific field.
132      *
133      * @param annotationName the annotation name
134      * @param field          the java.lang.reflect.Field object to find the annotation on.
135      * @return the annotations in a list (can be empty)
136      */
137     public static List getAnnotations(final String annotationName, final Field field) {
138         ClassLoader loader = field.getDeclaringClass().getClassLoader();
139         ClassInfo classInfo = AsmClassInfo.getClassInfo(field.getDeclaringClass().getName(), loader);
140         FieldInfo fieldInfo = classInfo.getField(ReflectHelper.calculateHash(field));
141         return AsmAnnotations.getAnnotations(annotationName, fieldInfo);
142     }
143 
144     /***
145      * Return a list with the annotations for a specific class. <p/>Each annotation is wrapped in {@link
146      * org.codehaus.aspectwerkz.annotation.AnnotationInfo}instance.
147      *
148      * @param klass the java.lang.Class object to find the annotation on.
149      * @return a list with the annotations
150      */
151     public static List getAnnotationInfos(final Class klass) {
152         return AsmClassInfo.getClassInfo(klass.getName(), klass.getClassLoader()).getAnnotations();
153     }
154 
155     /***
156      * Return the annotations for a specific method. <p/>Each annotation is wrapped in {@link
157      * org.codehaus.aspectwerkz.annotation.AnnotationInfo}instance.
158      *
159      * @param method the java.lang.refect.Method object to find the annotation on.
160      * @return a list with the annotations
161      */
162     public static List getAnnotationInfos(final Method method) {
163         ClassLoader loader = method.getDeclaringClass().getClassLoader();
164         ClassInfo classInfo = AsmClassInfo.getClassInfo(method.getDeclaringClass().getName(), loader);
165         return classInfo.getMethod(ReflectHelper.calculateHash(method)).getAnnotations();
166     }
167 
168     /***
169      * Return the annotations for a specific constructor. <p/>Each annotation is wrapped in {@link
170      * org.codehaus.aspectwerkz.annotation.AnnotationInfo}instance.
171      *
172      * @param constructor the java.lang.reflect.Constructor object to find the annotation on.
173      * @return a list with the annotations
174      */
175     public static List getAnnotationInfos(final Constructor constructor) {
176         ClassLoader loader = constructor.getDeclaringClass().getClassLoader();
177         ClassInfo classInfo = AsmClassInfo.getClassInfo(constructor.getDeclaringClass().getName(), loader);
178         return classInfo.getConstructor(ReflectHelper.calculateHash(constructor)).getAnnotations();
179     }
180 
181     /***
182      * Return the annotations for a specific field. <p/>Each annotation is wrapped in {@link
183      * org.codehaus.aspectwerkz.annotation.AnnotationInfo}instance.
184      *
185      * @param field the java.lang.reflect.Field object to find the annotation on.
186      * @return a list with the annotations
187      */
188     public static List getAnnotationInfos(final Field field) {
189         ClassLoader loader = field.getDeclaringClass().getClassLoader();
190         ClassInfo classInfo = AsmClassInfo.getClassInfo(field.getDeclaringClass().getName(), loader);
191         return classInfo.getField(ReflectHelper.calculateHash(field)).getAnnotations();
192     }
193 
194     /***
195      * Returns the annotation proxy class for a specific annotation loaded in a specific loader.
196      *
197      * @param annotationName
198      * @param loader
199      * @return
200      */
201     public static Class getProxyClass(final String annotationName, final ClassLoader loader) {
202         Class proxyClass;
203         AsmClassInfoRepository classInfoRepository = AsmClassInfoRepository.getRepository(loader);
204         String proxyClassName = (String)classInfoRepository.getAnnotationProperties().get(annotationName);
205         if (proxyClassName == null) {
206             return null;
207         }
208         if (proxyClassName.equals("")) {
209             throw new DefinitionException("untyped annotations can not be used with Java5 annotations");
210         } else {
211             try {
212                 proxyClass = loader.loadClass(proxyClassName);
213             } catch (ClassNotFoundException e) {
214                 String message = proxyClassName
215                                  +
216                                  " could not be found on system classpath or class path provided as argument to the compiler";
217                 throw new DefinitionException(message);
218             }
219         }
220         return proxyClass;
221     }
222 }