1 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.impl.asm.AsmClassInfo; 13 import org.codehaus.aspectwerkz.exception.WrappedRuntimeException; 14 import org.objectweb.asm.attrs.*; 15 import org.objectweb.asm.attrs.Annotation; 16 import org.objectweb.asm.Type; 17 18 import java.lang.reflect.InvocationHandler ; 19 import java.lang.reflect.Method ; 20 import java.lang.reflect.Proxy ; 21 import java.lang.reflect.Field ; 22 import java.lang.reflect.Array ; 23 import java.util.List ; 24 import java.util.Collection ; 25 import java.util.ArrayList ; 26 import java.util.Iterator ; 27 import java.util.Map ; 28 import java.util.HashMap ; 29 import java.util.Arrays ; 30 import java.io.Serializable ; 31 32 40 public class Java5AnnotationInvocationHandler implements InvocationHandler { 41 42 45 private final String m_annotationClassName; 46 47 51 private final List m_annotationElements; 52 53 59 private Java5AnnotationInvocationHandler(String annotationClassName, Collection annotationElements) { 60 m_annotationClassName = annotationClassName; 61 m_annotationElements = new ArrayList (annotationElements.size()); 62 for (Iterator iterator = annotationElements.iterator(); iterator.hasNext();) { 63 m_annotationElements.add(iterator.next()); 64 } 65 } 66 67 77 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 78 String name = method.getName(); 79 if ("toString".equals(name)) { 80 StringBuffer sb = new StringBuffer (); 81 sb.append('@').append(m_annotationClassName); 82 sb.append("("); 83 String sep = ""; 84 for (Iterator iterator = m_annotationElements.iterator(); iterator.hasNext();) { 85 AnnotationElement annotationElement = (AnnotationElement) iterator.next(); 86 sb.append(sep).append(annotationElement.name + "=" + annotationElement.toString()); 87 sep = ", "; 88 } 89 sb.append(")"); 90 return sb.toString(); 91 } else if ("annotationType".equals(name)) { 92 return Class.forName(m_annotationClassName, false, proxy.getClass().getClassLoader()); 95 } else if ("value".equals(name)) { 96 if (m_annotationElements.isEmpty()) { 97 return null; 98 } else { 99 return ((AnnotationElement) m_annotationElements.get(0)).resolveValueHolderFrom( 102 proxy.getClass().getClassLoader() 103 ); 104 } 105 } else { 106 for (Iterator iterator = m_annotationElements.iterator(); iterator.hasNext();) { 107 AnnotationElement annotationElement = (AnnotationElement) iterator.next(); 108 if (name.equals(annotationElement.name)) { 109 return annotationElement.resolveValueHolderFrom(proxy.getClass().getClassLoader()); 110 } 111 } 112 throw new RuntimeException ("No such element on Annotation @" + m_annotationClassName + " : " + name); 114 } 115 } 116 117 130 public static org.codehaus.aspectwerkz.annotation.Annotation getAnnotationProxy(org.objectweb.asm.attrs.Annotation annotation, ClassLoader loader) { 131 String annotationClassName = Type.getType(annotation.type).getClassName(); 132 133 ClassInfo annotationClassInfo = AsmClassInfo.getClassInfo(annotationClassName, loader); 137 Map annotationElementValueHoldersByName = new HashMap (); 138 139 MethodInfo[] annotationMethods = annotationClassInfo.getMethods(); 141 for (int i = 0; i < annotationMethods.length; i++) { 142 MethodInfo annotationMethod = annotationMethods[i]; 143 for (Iterator iterator = annotationMethod.getAnnotations().iterator(); iterator.hasNext();) { 144 AnnotationInfo annotationInfo = (AnnotationInfo) iterator.next(); 145 if (annotationInfo.getName().equals(AnnotationDefault.NAME)) { 147 Object value = ((AnnotationDefault)annotationInfo.getAnnotation()).value(); 148 Object valueHolder = getAnnotationValueHolder(value, loader); 149 annotationElementValueHoldersByName.put(annotationMethod.getName(), 150 new AnnotationElement(annotationMethod.getName(), 151 valueHolder) 152 ); 153 } 154 } 155 } 156 157 List settedElementValues = annotation.elementValues; 159 for (int i = 0; i < settedElementValues.size(); i++) { 160 Object [] element = (Object []) settedElementValues.get(i); 161 String name = (String ) element[0]; 162 Object valueHolder = getAnnotationValueHolder(element[1], loader); 163 annotationElementValueHoldersByName.put(name, new AnnotationElement(name, valueHolder)); 164 } 165 166 try { 168 Class typeClass = Class.forName(annotationClassName, false, loader); 169 Object proxy = Proxy.newProxyInstance( 170 loader, 171 new Class []{org.codehaus.aspectwerkz.annotation.Annotation.class, typeClass}, 172 new Java5AnnotationInvocationHandler(annotationClassName, 173 annotationElementValueHoldersByName.values() 174 ) 175 ); 176 return (org.codehaus.aspectwerkz.annotation.Annotation) proxy; 177 } catch (ClassNotFoundException e) { 178 throw new WrappedRuntimeException(e); 179 } 180 } 181 182 191 private static Object getAnnotationValueHolder(Object value, ClassLoader loader) { 192 if (value instanceof Annotation.EnumConstValue) { 193 Annotation.EnumConstValue enumAsmValue = (Annotation.EnumConstValue) value; 194 try { 195 Class enumClass = Class.forName(Type.getType(enumAsmValue.typeName).getClassName(), false, loader); 196 Field enumConstValue = enumClass.getField(enumAsmValue.constName); 197 return enumConstValue.get(null); 198 } catch (Exception e) { 199 throw new WrappedRuntimeException(e); 200 } 201 } else if (value instanceof Type) { 202 return new AnnotationElement.LazyClass(((Type) value).getClassName()); 204 } else if (value instanceof Annotation) { 205 return getAnnotationProxy(((Annotation) value), loader); 206 } else if (value instanceof Object []) { 207 Object [] values = (Object []) value; 208 Object [] holders = new Object [values.length]; 209 boolean isLazyClass = false; 210 for (int i = 0; i < values.length; i++) { 211 holders[i] = getAnnotationValueHolder(values[i], loader); 212 if (!isLazyClass && holders[i] instanceof AnnotationElement.LazyClass) { 213 isLazyClass = true; 214 } 215 } 216 if (isLazyClass) { 217 AnnotationElement.LazyClass[] typedHolders = (AnnotationElement.LazyClass[]) Array.newInstance(AnnotationElement.LazyClass.class, values.length); 219 for (int i = 0; i < holders.length; i++) { 220 typedHolders[i] = (AnnotationElement.LazyClass) holders[i]; 221 } 222 return typedHolders; 223 } else { 224 return holders; 225 } 226 } 227 return value; 228 } 229 230 } 231 232 | Popular Tags |