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 }