169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.bytecode.annotation; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.lang.reflect.InvocationHandler; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.lang.reflect.Method; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.lang.reflect.Proxy; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.ClassPool; 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtClass; 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.NotFoundException; 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.AnnotationDefaultAttribute; 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ClassFile; 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.MethodInfo; 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Internal-use only. This is a helper class internally used for implementing 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>toAnnotationType()</code> in <code>Annotation</code>. 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @author Shigeru Chiba 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @author <a href="mailto:bill@jboss.org">Bill Burke</a> 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @author <a href="mailto:adrian@jboss.org">Adrian Brock</a> 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class AnnotationImpl implements InvocationHandler { 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static final String JDK_ANNOTATION_CLASS_NAME = "java.lang.annotation.Annotation"; 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static Method JDK_ANNOTATION_TYPE_METHOD = null; 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Annotation annotation; 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ClassPool pool; 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ClassLoader classLoader; 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private transient Class annotationType; 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private transient int cachedHashCode = Integer.MIN_VALUE; 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static { 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Try to resolve the JDK annotation type method 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class clazz = Class.forName(JDK_ANNOTATION_CLASS_NAME); 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal JDK_ANNOTATION_TYPE_METHOD = clazz.getMethod("annotationType", (Class[])null); 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (Exception ignored) { 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Probably not JDK5+ 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs an annotation object. 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param cl class loader for obtaining annotation types. 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param clazz the annotation type. 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param cp class pool for containing an annotation 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * type (or null). 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param anon the annotation. 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return the annotation 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static Object make(ClassLoader cl, Class clazz, ClassPool cp, 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Annotation anon) { 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal AnnotationImpl handler = new AnnotationImpl(anon, cp, cl); 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return Proxy.newProxyInstance(cl, new Class[] { clazz }, handler); 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private AnnotationImpl(Annotation a, ClassPool cp, ClassLoader loader) { 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal annotation = a; 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pool = cp; 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal classLoader = loader; 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Obtains the name of the annotation type. 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return the type name 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public String getTypeName() { 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return annotation.getTypeName(); 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Get the annotation type 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return the annotation class 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @throws NoClassDefFoundError when the class could not loaded 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Class getAnnotationType() { 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (annotationType == null) { 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String typeName = annotation.getTypeName(); 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal annotationType = classLoader.loadClass(typeName); 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (ClassNotFoundException e) { 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal NoClassDefFoundError error = new NoClassDefFoundError("Error loading annotation class: " + typeName); 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal error.setStackTrace(e.getStackTrace()); 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw error; 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return annotationType; 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Obtains the internal data structure representing the annotation. 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return the annotation 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Annotation getAnnotation() { 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return annotation; 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Executes a method invocation on a proxy instance. 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The implementations of <code>toString()</code>, <code>equals()</code>, 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * and <code>hashCode()</code> are directly supplied by the 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>AnnotationImpl</code>. The <code>annotationType()</code> method 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is also available on the proxy instance. 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Object invoke(Object proxy, Method method, Object[] args) 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws Throwable 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = method.getName(); 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (Object.class == method.getDeclaringClass()) { 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if ("equals".equals(name)) { 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Object obj = args[0]; 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Boolean(checkEquals(obj)); 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if ("toString".equals(name)) 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return annotation.toString(); 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if ("hashCode".equals(name)) 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Integer(hashCode()); 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if ("annotationType".equals(name) 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal && method.getParameterTypes().length == 0) 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return getAnnotationType(); 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MemberValue mv = annotation.getMemberValue(name); 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (mv == null) 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return getDefault(name, method); 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return mv.getValue(classLoader, pool, method); 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Object getDefault(String name, Method method) 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws ClassNotFoundException, RuntimeException 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String classname = annotation.getTypeName(); 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (pool != null) { 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass cc = pool.get(classname); 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ClassFile cf = cc.getClassFile2(); 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MethodInfo minfo = cf.getMethod(name); 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (minfo != null) { 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal AnnotationDefaultAttribute ainfo 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = (AnnotationDefaultAttribute) 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal minfo.getAttribute(AnnotationDefaultAttribute.tag); 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (ainfo != null) { 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MemberValue mv = ainfo.getDefaultValue(); 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return mv.getValue(classLoader, pool, method); 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotFoundException e) { 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException("cannot find a class file: " 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + classname); 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException("no default value: " + classname + "." 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + name + "()"); 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns a hash code value for this object. 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int hashCode() { 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (cachedHashCode == Integer.MIN_VALUE) { 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int hashCode = 0; 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Load the annotation class 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal getAnnotationType(); 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Method[] methods = annotationType.getDeclaredMethods(); 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < methods.length; ++ i) { 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = methods[i].getName(); 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int valueHashCode = 0; 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Get the value 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MemberValue mv = annotation.getMemberValue(name); 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Object value = null; 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (mv != null) 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal value = mv.getValue(classLoader, pool, methods[i]); 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (value == null) 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal value = getDefault(name, methods[i]); 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (RuntimeException e) { 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw e; 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (Exception e) { 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException("Error retrieving value " + name + " for annotation " + annotation.getTypeName(), e); 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Calculate the hash code 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (value != null) { 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (value.getClass().isArray()) 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal valueHashCode = arrayHashCode(value); 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal valueHashCode = value.hashCode(); 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal hashCode += 127 * name.hashCode() ^ valueHashCode; 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cachedHashCode = hashCode; 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return cachedHashCode; 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Check that another annotation equals ourselves. 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param obj the other annotation 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return the true when equals false otherwise 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @throws Exception for any problem 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private boolean checkEquals(Object obj) throws Exception { 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (obj == null) 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Optimization when the other is one of ourselves 23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (obj instanceof Proxy) { 23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal InvocationHandler ih = Proxy.getInvocationHandler(obj); 24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (ih instanceof AnnotationImpl) { 24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal AnnotationImpl other = (AnnotationImpl) ih; 24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return annotation.equals(other.annotation); 24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class otherAnnotationType = (Class) JDK_ANNOTATION_TYPE_METHOD.invoke(obj, (Object[])null); 24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (getAnnotationType().equals(otherAnnotationType) == false) 24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Method[] methods = annotationType.getDeclaredMethods(); 25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < methods.length; ++ i) { 25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = methods[i].getName(); 25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Get the value 25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MemberValue mv = annotation.getMemberValue(name); 25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Object value = null; 25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Object otherValue = null; 25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (mv != null) 26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal value = mv.getValue(classLoader, pool, methods[i]); 26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (value == null) 26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal value = getDefault(name, methods[i]); 26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal otherValue = methods[i].invoke(obj, (Object[])null); 26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (RuntimeException e) { 26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw e; 26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (Exception e) { 26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException("Error retrieving value " + name + " for annotation " + annotation.getTypeName(), e); 27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (value == null && otherValue != null) 27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (value != null && value.equals(otherValue) == false) 27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return true; 27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Calculates the hashCode of an array using the same 28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * algorithm as java.util.Arrays.hashCode() 28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param object the object 28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return the hashCode 28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static int arrayHashCode(Object object) 28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (object == null) 29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return 0; 29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int result = 1; 29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Object[] array = (Object[]) object; 29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < array.length; ++i) { 29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int elementHashCode = 0; 29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (array[i] != null) 29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal elementHashCode = array[i].hashCode(); 30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal result = 31 * result + elementHashCode; 30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return result; 30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 305