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.ReflectHelper;
15  import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo;
16  import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAnnotations;
17  
18  import java.lang.reflect.Constructor;
19  import java.lang.reflect.Field;
20  import java.lang.reflect.Method;
21  import java.util.List;
22  import java.util.ArrayList;
23  
24  /***
25   * Utility class for annotation retrieval.
26   * <br/>Note: Annotations are extracted out of ASMClassInfo
27   * <br/>Note: caution when changing that to use reflection, since it might lead to load target class during aspect
28   * system startup.
29   *
30   * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
31   */
32  public final class Annotations {
33  
34      private final static List EMPTY_LIST = new ArrayList();
35  
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 class.
50       *
51       * @param annotation the annotation class
52       * @param klass      the java.lang.Class object to find the annotation on.
53       * @return the annotation or null
54       */
55      public static Annotation getAnnotation(final Class annotation, final Class klass) {
56          return getAnnotation(getAnnnotationName(annotation), klass);
57      }
58  
59      /***
60       * Return the annotation with a specific name for a specific method.
61       *
62       * @param annotationName the annotation name
63       * @param method         the java.lang.refect.Method object to find the annotation on.
64       * @return the annotation or null
65       */
66      public static Annotation getAnnotation(final String annotationName, final Method method) {
67          ClassLoader loader = method.getDeclaringClass().getClassLoader();
68          ClassInfo classInfo = AsmClassInfo.getClassInfo(method.getDeclaringClass().getName(), loader);
69          MethodInfo methodInfo = classInfo.getMethod(ReflectHelper.calculateHash(method));
70          return AsmAnnotations.getAnnotation(annotationName, methodInfo);
71      }
72  
73      /***
74       * Return the annotation with a specific name for a specific method.
75       *
76       * @param annotation the annotation class
77       * @param method     the java.lang.refect.Method object to find the annotation on.
78       * @return the annotation or null
79       */
80      public static Annotation getAnnotation(final Class annotation, final Method method) {
81          return getAnnotation(getAnnnotationName(annotation), method);
82      }
83  
84      /***
85       * Return the annotation with a specific name for a specific constructor.
86       *
87       * @param annotationName the annotation name
88       * @param constructor    the java.lang.refect.Constructor object to find the annotation on.
89       * @return the annotation or null
90       */
91      public static Annotation getAnnotation(final String annotationName, final Constructor constructor) {
92          ClassLoader loader = constructor.getDeclaringClass().getClassLoader();
93          ClassInfo classInfo = AsmClassInfo.getClassInfo(constructor.getDeclaringClass().getName(), loader);
94          ConstructorInfo constructorInfo = classInfo.getConstructor(ReflectHelper.calculateHash(constructor));
95          return AsmAnnotations.getAnnotation(annotationName, constructorInfo);
96      }
97  
98      /***
99       * Return the annotation with a specific name for a specific constructor.
100      *
101      * @param annotation  the annotation class
102      * @param constructor the java.lang.refect.Constructor object to find the annotation on.
103      * @return the annotation or null
104      */
105     public static Annotation getAnnotation(final Class annotation, final Constructor constructor) {
106         return getAnnotation(getAnnnotationName(annotation), constructor);
107     }
108 
109     /***
110      * Return the annotation with a specific name for a specific field.
111      *
112      * @param annotationName the annotation name
113      * @param field          the java.lang.reflect.Field object to find the annotation on.
114      * @return the annotation or null
115      */
116     public static Annotation getAnnotation(final String annotationName, final Field field) {
117         ClassLoader loader = field.getDeclaringClass().getClassLoader();
118         ClassInfo classInfo = AsmClassInfo.getClassInfo(field.getDeclaringClass().getName(), loader);
119         FieldInfo fieldInfo = classInfo.getField(ReflectHelper.calculateHash(field));
120         return AsmAnnotations.getAnnotation(annotationName, fieldInfo);
121     }
122 
123     /***
124      * Return the annotation with a specific name for a specific field.
125      *
126      * @param annotation the annotation class
127      * @param field      the java.lang.reflect.Field object to find the annotation on.
128      * @return the annotation or null
129      */
130     public static Annotation getAnnotation(final Class annotation, final Field field) {
131         return getAnnotation(getAnnnotationName(annotation), field);
132     }
133 
134     /***
135      * Return a list with the annotations with a specific name for a specific class.
136      *
137      * @param annotationName the annotation name
138      * @param klass          the java.lang.Class object to find the annotation on.
139      * @return the annotations in a list (can be empty)
140      */
141     public static List getAnnotations(final String annotationName, final Class klass) {
142         ClassInfo classInfo = AsmClassInfo.getClassInfo(klass.getName(), klass.getClassLoader());
143         return AsmAnnotations.getAnnotations(annotationName, classInfo);
144     }
145 
146     /***
147      * Return a list with the annotations with a specific name for a specific class.
148      *
149      * @param annotation the annotation class
150      * @param klass      the java.lang.Class object to find the annotation on.
151      * @return the annotations in a list (can be empty)
152      */
153     public static List getAnnotations(final Class annotation, final Class klass) {
154         return getAnnotations(getAnnnotationName(annotation), klass);
155     }
156 
157     /***
158      * Return a list with the annotations with a specific name for a specific method.
159      *
160      * @param annotationName the annotation name
161      * @param method         the java.lang.refect.Method object to find the annotation on.
162      * @return the annotations in a list (can be empty)
163      */
164     public static List getAnnotations(final String annotationName, final Method method) {
165         ClassLoader loader = method.getDeclaringClass().getClassLoader();
166         ClassInfo classInfo = AsmClassInfo.getClassInfo(method.getDeclaringClass().getName(), loader);
167         MethodInfo methodInfo = classInfo.getMethod(ReflectHelper.calculateHash(method));
168         return AsmAnnotations.getAnnotations(annotationName, methodInfo);
169     }
170 
171     /***
172      * Return a list with the annotations with a specific name for a specific method.
173      *
174      * @param annotation the annotation class
175      * @param method     the java.lang.refect.Method object to find the annotation on.
176      * @return the annotations in a list (can be empty)
177      */
178     public static List getAnnotations(final Class annotation, final Method method) {
179         return getAnnotations(getAnnnotationName(annotation), method);
180     }
181 
182     /***
183      * Return a list with the annotations with a specific name for a specific constructor.
184      *
185      * @param annotationName the annotation name
186      * @param constructor    the java.lang.refect.Constructor object to find the annotation on.
187      * @return the annotations in a list (can be empty)
188      */
189     public static List getAnnotations(final String annotationName, final Constructor constructor) {
190         ClassLoader loader = constructor.getDeclaringClass().getClassLoader();
191         ClassInfo classInfo = AsmClassInfo.getClassInfo(constructor.getDeclaringClass().getName(), loader);
192         ConstructorInfo constructorInfo = classInfo.getConstructor(ReflectHelper.calculateHash(constructor));
193         return AsmAnnotations.getAnnotations(annotationName, constructorInfo);
194     }
195 
196     /***
197      * Return a list with the annotations with a specific name for a specific constructor.
198      *
199      * @param annotation  the annotation class
200      * @param constructor the java.lang.refect.Constructor object to find the annotation on.
201      * @return the annotations in a list (can be empty)
202      */
203     public static List getAnnotations(final Class annotation, final Constructor constructor) {
204         return getAnnotations(getAnnnotationName(annotation), constructor);
205     }
206 
207     /***
208      * Return a list with the annotations with a specific name for a specific field.
209      *
210      * @param annotationName the annotation name
211      * @param field          the java.lang.reflect.Field object to find the annotation on.
212      * @return the annotations in a list (can be empty)
213      */
214     public static List getAnnotations(final String annotationName, final Field field) {
215         ClassLoader loader = field.getDeclaringClass().getClassLoader();
216         ClassInfo classInfo = AsmClassInfo.getClassInfo(field.getDeclaringClass().getName(), loader);
217         FieldInfo fieldInfo = classInfo.getField(ReflectHelper.calculateHash(field));
218         return AsmAnnotations.getAnnotations(annotationName, fieldInfo);
219     }
220 
221     /***
222      * Return a list with the annotations with a specific name for a specific field.
223      *
224      * @param annotation the annotation class
225      * @param field      the java.lang.reflect.Field object to find the annotation on.
226      * @return the annotations in a list (can be empty)
227      */
228     public static List getAnnotations(final Class annotation, final Field field) {
229         return getAnnotations(getAnnnotationName(annotation), field);
230     }
231 
232     /***
233      * Return a list with the annotations for a specific class. <p/>Each annotation is wrapped in {@link
234      * org.codehaus.aspectwerkz.annotation.AnnotationInfo}instance.
235      *
236      * @param klass the java.lang.Class object to find the annotation on.
237      * @return a list with the annotations
238      */
239     public static List getAnnotationInfos(final Class klass) {
240         return AsmClassInfo.getClassInfo(klass.getName(), klass.getClassLoader()).getAnnotations();
241     }
242 
243     /***
244      * Return the annotations for a specific method. <p/>Each annotation is wrapped in {@link
245      * org.codehaus.aspectwerkz.annotation.AnnotationInfo}instance.
246      *
247      * @param method the java.lang.refect.Method object to find the annotation on.
248      * @return a list with the annotations
249      */
250     public static List getAnnotationInfos(final Method method) {
251         ClassLoader loader = method.getDeclaringClass().getClassLoader();
252         ClassInfo classInfo = AsmClassInfo.getClassInfo(method.getDeclaringClass().getName(), loader);
253         // AW methods like aw$initJoinPoints may not be visible
254         MethodInfo methodInfo = classInfo.getMethod(ReflectHelper.calculateHash(method));
255         if (methodInfo != null) {
256             return methodInfo.getAnnotations();
257         } else {
258             return EMPTY_LIST;
259         }
260     }
261 
262     /***
263      * Return the annotations for a specific constructor. <p/>Each annotation is wrapped in {@link
264      * org.codehaus.aspectwerkz.annotation.AnnotationInfo}instance.
265      *
266      * @param constructor the java.lang.reflect.Constructor object to find the annotation on.
267      * @return a list with the annotations
268      */
269     public static List getAnnotationInfos(final Constructor constructor) {
270         ClassLoader loader = constructor.getDeclaringClass().getClassLoader();
271         ClassInfo classInfo = AsmClassInfo.getClassInfo(constructor.getDeclaringClass().getName(), loader);
272         return classInfo.getConstructor(ReflectHelper.calculateHash(constructor)).getAnnotations();
273     }
274 
275     /***
276      * Return the annotations for a specific field. <p/>Each annotation is wrapped in {@link
277      * org.codehaus.aspectwerkz.annotation.AnnotationInfo}instance.
278      *
279      * @param field the java.lang.reflect.Field object to find the annotation on.
280      * @return a list with the annotations
281      */
282     public static List getAnnotationInfos(final Field field) {
283         ClassLoader loader = field.getDeclaringClass().getClassLoader();
284         ClassInfo classInfo = AsmClassInfo.getClassInfo(field.getDeclaringClass().getName(), loader);
285         // AW fields like aw$instanceLevelAspects may not be visible
286         FieldInfo fieldInfo = classInfo.getField(ReflectHelper.calculateHash(field));
287         if (fieldInfo != null) {
288             return fieldInfo.getAnnotations();
289         } else {
290             return EMPTY_LIST;
291         }
292     }
293 
294 //    /***
295 //     * Returns the annotation proxy class for a specific annotation loaded in a specific loader.
296 //     *
297 //     * @param annotationName
298 //     * @param loader
299 //     * @return
300 //     */
301 //    public static Class getProxyClass(final String annotationName, final ClassLoader loader) {
302 //        Class proxyClass;
303 //        AsmClassInfoRepository classInfoRepository = AsmClassInfoRepository.getRepository(loader);
304 //        String proxyClassName = (String) classInfoRepository.getAnnotationProperties().get(annotationName);
305 //        if (proxyClassName == null) {
306 //            return null;
307 //        }
308 //        if (proxyClassName.equals("")) {
309 //            throw new DefinitionException("untyped annotations can not be used with Java5 annotations");
310 //        } else {
311 //            try {
312 //                proxyClass = loader.loadClass(proxyClassName);
313 //            } catch (ClassNotFoundException e) {
314 //                String message = proxyClassName
315 //                                 +
316 //                                 " could not be found on system classpath or class path provided as argument to the compiler";
317 //                throw new DefinitionException(message);
318 //            }
319 //        }
320 //        return proxyClass;
321 //    }
322 
323     private static String getAnnnotationName(Class annotation) {
324         return annotation.getName().replace('/', '.');
325     }
326 }