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 }