src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java

Print this page




  23  * have any questions.
  24  */
  25 
  26 package sun.reflect.annotation;
  27 
  28 import java.lang.annotation.*;
  29 import java.lang.reflect.*;
  30 import java.io.Serializable;
  31 import java.util.*;
  32 import java.lang.annotation.*;
  33 import java.security.AccessController;
  34 import java.security.PrivilegedAction;
  35 
  36 /**
  37  * InvocationHandler for dynamic proxy implementation of Annotation.
  38  *
  39  * @author  Josh Bloch
  40  * @since   1.5
  41  */
  42 class AnnotationInvocationHandler implements InvocationHandler, Serializable {
  43     private final Class type;
  44     private final Map<String, Object> memberValues;
  45 
  46     AnnotationInvocationHandler(Class type, Map<String, Object> memberValues) {
  47         this.type = type;
  48         this.memberValues = memberValues;
  49     }
  50 
  51     public Object invoke(Object proxy, Method method, Object[] args) {
  52         String member = method.getName();
  53         Class[] paramTypes = method.getParameterTypes();
  54 
  55         // Handle Object and Annotation methods
  56         if (member.equals("equals") && paramTypes.length == 1 &&
  57             paramTypes[0] == Object.class)
  58             return equalsImpl(args[0]);
  59         assert paramTypes.length == 0;
  60         if (member.equals("toString"))
  61             return toStringImpl();
  62         if (member.equals("hashCode"))
  63             return hashCodeImpl();
  64         if (member.equals("annotationType"))
  65             return type;
  66 
  67         // Handle annotation member accessors
  68         Object result = memberValues.get(member);
  69 
  70         if (result == null)
  71             throw new IncompleteAnnotationException(type, member);
  72 
  73         if (result instanceof ExceptionProxy)
  74             throw ((ExceptionProxy) result).generateException();
  75 
  76         if (result.getClass().isArray() && Array.getLength(result) != 0)
  77             result = cloneArray(result);
  78 
  79         return result;
  80     }
  81 
  82     /**
  83      * This method, which clones its array argument, would not be necessary
  84      * if Cloneable had a public clone method.
  85      */
  86     private Object cloneArray(Object array) {
  87         Class type = array.getClass();
  88 
  89         if (type == byte[].class) {
  90             byte[] byteArray = (byte[])array;
  91             return byteArray.clone();
  92         }
  93         if (type == char[].class) {
  94             char[] charArray = (char[])array;
  95             return charArray.clone();
  96         }
  97         if (type == double[].class) {
  98             double[] doubleArray = (double[])array;
  99             return doubleArray.clone();
 100         }
 101         if (type == float[].class) {
 102             float[] floatArray = (float[])array;
 103             return floatArray.clone();
 104         }
 105         if (type == int[].class) {
 106             int[] intArray = (int[])array;
 107             return intArray.clone();


 134         result.append('(');
 135         boolean firstMember = true;
 136         for (Map.Entry<String, Object> e : memberValues.entrySet()) {
 137             if (firstMember)
 138                 firstMember = false;
 139             else
 140                 result.append(", ");
 141 
 142             result.append(e.getKey());
 143             result.append('=');
 144             result.append(memberValueToString(e.getValue()));
 145         }
 146         result.append(')');
 147         return result.toString();
 148     }
 149 
 150     /**
 151      * Translates a member value (in "dynamic proxy return form") into a string
 152      */
 153     private static String memberValueToString(Object value) {
 154         Class type = value.getClass();
 155         if (!type.isArray())    // primitive, string, class, enum const,
 156                                 // or annotation
 157             return value.toString();
 158 
 159         if (type == byte[].class)
 160             return Arrays.toString((byte[]) value);
 161         if (type == char[].class)
 162             return Arrays.toString((char[]) value);
 163         if (type == double[].class)
 164             return Arrays.toString((double[]) value);
 165         if (type == float[].class)
 166             return Arrays.toString((float[]) value);
 167         if (type == int[].class)
 168             return Arrays.toString((int[]) value);
 169         if (type == long[].class)
 170             return Arrays.toString((long[]) value);
 171         if (type == short[].class)
 172             return Arrays.toString((short[]) value);
 173         if (type == boolean[].class)
 174             return Arrays.toString((boolean[]) value);


 212      * Returns null otherwise.
 213      */
 214     private AnnotationInvocationHandler asOneOfUs(Object o) {
 215         if (Proxy.isProxyClass(o.getClass())) {
 216             InvocationHandler handler = Proxy.getInvocationHandler(o);
 217             if (handler instanceof AnnotationInvocationHandler)
 218                 return (AnnotationInvocationHandler) handler;
 219         }
 220         return null;
 221     }
 222 
 223     /**
 224      * Returns true iff the two member values in "dynamic proxy return form"
 225      * are equal using the appropriate equality function depending on the
 226      * member type.  The two values will be of the same type unless one of
 227      * the containing annotations is ill-formed.  If one of the containing
 228      * annotations is ill-formed, this method will return false unless the
 229      * two members are identical object references.
 230      */
 231     private static boolean memberValueEquals(Object v1, Object v2) {
 232         Class type = v1.getClass();
 233 
 234         // Check for primitive, string, class, enum const, annotation,
 235         // or ExceptionProxy
 236         if (!type.isArray())
 237             return v1.equals(v2);
 238 
 239         // Check for array of string, class, enum const, annotation,
 240         // or ExceptionProxy
 241         if (v1 instanceof Object[] && v2 instanceof Object[])
 242             return Arrays.equals((Object[]) v1, (Object[]) v2);
 243 
 244         // Check for ill formed annotation(s)
 245         if (v2.getClass() != type)
 246             return false;
 247 
 248         // Deal with array of primitives
 249         if (type == byte[].class)
 250             return Arrays.equals((byte[]) v1, (byte[]) v2);
 251         if (type == char[].class)
 252             return Arrays.equals((char[]) v1, (char[]) v2);


 284         return memberMethods;
 285     }
 286     private transient volatile Method[] memberMethods = null;
 287 
 288     /**
 289      * Implementation of dynamicProxy.hashCode()
 290      */
 291     private int hashCodeImpl() {
 292         int result = 0;
 293         for (Map.Entry<String, Object> e : memberValues.entrySet()) {
 294             result += (127 * e.getKey().hashCode()) ^
 295                 memberValueHashCode(e.getValue());
 296         }
 297         return result;
 298     }
 299 
 300     /**
 301      * Computes hashCode of a member value (in "dynamic proxy return form")
 302      */
 303     private static int memberValueHashCode(Object value) {
 304         Class type = value.getClass();
 305         if (!type.isArray())    // primitive, string, class, enum const,
 306                                 // or annotation
 307             return value.hashCode();
 308 
 309         if (type == byte[].class)
 310             return Arrays.hashCode((byte[]) value);
 311         if (type == char[].class)
 312             return Arrays.hashCode((char[]) value);
 313         if (type == double[].class)
 314             return Arrays.hashCode((double[]) value);
 315         if (type == float[].class)
 316             return Arrays.hashCode((float[]) value);
 317         if (type == int[].class)
 318             return Arrays.hashCode((int[]) value);
 319         if (type == long[].class)
 320             return Arrays.hashCode((long[]) value);
 321         if (type == short[].class)
 322             return Arrays.hashCode((short[]) value);
 323         if (type == boolean[].class)
 324             return Arrays.hashCode((boolean[]) value);
 325         return Arrays.hashCode((Object[]) value);
 326     }
 327 
 328     private void readObject(java.io.ObjectInputStream s)
 329         throws java.io.IOException, ClassNotFoundException {
 330         s.defaultReadObject();
 331 
 332 
 333         // Check to make sure that types have not evolved incompatibly
 334 
 335         AnnotationType annotationType = null;
 336         try {
 337             annotationType = AnnotationType.getInstance(type);
 338         } catch(IllegalArgumentException e) {
 339             // Class is no longer an annotation type; all bets are off
 340             return;
 341         }
 342 
 343         Map<String, Class> memberTypes = annotationType.memberTypes();
 344 
 345         for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) {
 346             String name = memberValue.getKey();
 347             Class memberType = memberTypes.get(name);
 348             if (memberType != null) {  // i.e. member still exists
 349                 Object value = memberValue.getValue();
 350                 if (!(memberType.isInstance(value) ||
 351                       value instanceof ExceptionProxy)) {
 352                     memberValue.setValue(
 353                         new AnnotationTypeMismatchExceptionProxy(
 354                             value.getClass() + "[" + value + "]").setMember(
 355                                 annotationType.members().get(name)));
 356                 }
 357             }
 358         }
 359     }
 360 }


  23  * have any questions.
  24  */
  25 
  26 package sun.reflect.annotation;
  27 
  28 import java.lang.annotation.*;
  29 import java.lang.reflect.*;
  30 import java.io.Serializable;
  31 import java.util.*;
  32 import java.lang.annotation.*;
  33 import java.security.AccessController;
  34 import java.security.PrivilegedAction;
  35 
  36 /**
  37  * InvocationHandler for dynamic proxy implementation of Annotation.
  38  *
  39  * @author  Josh Bloch
  40  * @since   1.5
  41  */
  42 class AnnotationInvocationHandler implements InvocationHandler, Serializable {
  43     private final Class<? extends Annotation> type;
  44     private final Map<String, Object> memberValues;
  45 
  46     AnnotationInvocationHandler(Class<? extends Annotation> type, Map<String, Object> memberValues) {
  47         this.type = type;
  48         this.memberValues = memberValues;
  49     }
  50 
  51     public Object invoke(Object proxy, Method method, Object[] args) {
  52         String member = method.getName();
  53         Class<?>[] paramTypes = method.getParameterTypes();
  54 
  55         // Handle Object and Annotation methods
  56         if (member.equals("equals") && paramTypes.length == 1 &&
  57             paramTypes[0] == Object.class)
  58             return equalsImpl(args[0]);
  59         assert paramTypes.length == 0;
  60         if (member.equals("toString"))
  61             return toStringImpl();
  62         if (member.equals("hashCode"))
  63             return hashCodeImpl();
  64         if (member.equals("annotationType"))
  65             return type;
  66 
  67         // Handle annotation member accessors
  68         Object result = memberValues.get(member);
  69 
  70         if (result == null)
  71             throw new IncompleteAnnotationException(type, member);
  72 
  73         if (result instanceof ExceptionProxy)
  74             throw ((ExceptionProxy) result).generateException();
  75 
  76         if (result.getClass().isArray() && Array.getLength(result) != 0)
  77             result = cloneArray(result);
  78 
  79         return result;
  80     }
  81 
  82     /**
  83      * This method, which clones its array argument, would not be necessary
  84      * if Cloneable had a public clone method.
  85      */
  86     private Object cloneArray(Object array) {
  87         Class<?> type = array.getClass();
  88 
  89         if (type == byte[].class) {
  90             byte[] byteArray = (byte[])array;
  91             return byteArray.clone();
  92         }
  93         if (type == char[].class) {
  94             char[] charArray = (char[])array;
  95             return charArray.clone();
  96         }
  97         if (type == double[].class) {
  98             double[] doubleArray = (double[])array;
  99             return doubleArray.clone();
 100         }
 101         if (type == float[].class) {
 102             float[] floatArray = (float[])array;
 103             return floatArray.clone();
 104         }
 105         if (type == int[].class) {
 106             int[] intArray = (int[])array;
 107             return intArray.clone();


 134         result.append('(');
 135         boolean firstMember = true;
 136         for (Map.Entry<String, Object> e : memberValues.entrySet()) {
 137             if (firstMember)
 138                 firstMember = false;
 139             else
 140                 result.append(", ");
 141 
 142             result.append(e.getKey());
 143             result.append('=');
 144             result.append(memberValueToString(e.getValue()));
 145         }
 146         result.append(')');
 147         return result.toString();
 148     }
 149 
 150     /**
 151      * Translates a member value (in "dynamic proxy return form") into a string
 152      */
 153     private static String memberValueToString(Object value) {
 154         Class<?> type = value.getClass();
 155         if (!type.isArray())    // primitive, string, class, enum const,
 156                                 // or annotation
 157             return value.toString();
 158 
 159         if (type == byte[].class)
 160             return Arrays.toString((byte[]) value);
 161         if (type == char[].class)
 162             return Arrays.toString((char[]) value);
 163         if (type == double[].class)
 164             return Arrays.toString((double[]) value);
 165         if (type == float[].class)
 166             return Arrays.toString((float[]) value);
 167         if (type == int[].class)
 168             return Arrays.toString((int[]) value);
 169         if (type == long[].class)
 170             return Arrays.toString((long[]) value);
 171         if (type == short[].class)
 172             return Arrays.toString((short[]) value);
 173         if (type == boolean[].class)
 174             return Arrays.toString((boolean[]) value);


 212      * Returns null otherwise.
 213      */
 214     private AnnotationInvocationHandler asOneOfUs(Object o) {
 215         if (Proxy.isProxyClass(o.getClass())) {
 216             InvocationHandler handler = Proxy.getInvocationHandler(o);
 217             if (handler instanceof AnnotationInvocationHandler)
 218                 return (AnnotationInvocationHandler) handler;
 219         }
 220         return null;
 221     }
 222 
 223     /**
 224      * Returns true iff the two member values in "dynamic proxy return form"
 225      * are equal using the appropriate equality function depending on the
 226      * member type.  The two values will be of the same type unless one of
 227      * the containing annotations is ill-formed.  If one of the containing
 228      * annotations is ill-formed, this method will return false unless the
 229      * two members are identical object references.
 230      */
 231     private static boolean memberValueEquals(Object v1, Object v2) {
 232         Class<?> type = v1.getClass();
 233 
 234         // Check for primitive, string, class, enum const, annotation,
 235         // or ExceptionProxy
 236         if (!type.isArray())
 237             return v1.equals(v2);
 238 
 239         // Check for array of string, class, enum const, annotation,
 240         // or ExceptionProxy
 241         if (v1 instanceof Object[] && v2 instanceof Object[])
 242             return Arrays.equals((Object[]) v1, (Object[]) v2);
 243 
 244         // Check for ill formed annotation(s)
 245         if (v2.getClass() != type)
 246             return false;
 247 
 248         // Deal with array of primitives
 249         if (type == byte[].class)
 250             return Arrays.equals((byte[]) v1, (byte[]) v2);
 251         if (type == char[].class)
 252             return Arrays.equals((char[]) v1, (char[]) v2);


 284         return memberMethods;
 285     }
 286     private transient volatile Method[] memberMethods = null;
 287 
 288     /**
 289      * Implementation of dynamicProxy.hashCode()
 290      */
 291     private int hashCodeImpl() {
 292         int result = 0;
 293         for (Map.Entry<String, Object> e : memberValues.entrySet()) {
 294             result += (127 * e.getKey().hashCode()) ^
 295                 memberValueHashCode(e.getValue());
 296         }
 297         return result;
 298     }
 299 
 300     /**
 301      * Computes hashCode of a member value (in "dynamic proxy return form")
 302      */
 303     private static int memberValueHashCode(Object value) {
 304         Class<?> type = value.getClass();
 305         if (!type.isArray())    // primitive, string, class, enum const,
 306                                 // or annotation
 307             return value.hashCode();
 308 
 309         if (type == byte[].class)
 310             return Arrays.hashCode((byte[]) value);
 311         if (type == char[].class)
 312             return Arrays.hashCode((char[]) value);
 313         if (type == double[].class)
 314             return Arrays.hashCode((double[]) value);
 315         if (type == float[].class)
 316             return Arrays.hashCode((float[]) value);
 317         if (type == int[].class)
 318             return Arrays.hashCode((int[]) value);
 319         if (type == long[].class)
 320             return Arrays.hashCode((long[]) value);
 321         if (type == short[].class)
 322             return Arrays.hashCode((short[]) value);
 323         if (type == boolean[].class)
 324             return Arrays.hashCode((boolean[]) value);
 325         return Arrays.hashCode((Object[]) value);
 326     }
 327 
 328     private void readObject(java.io.ObjectInputStream s)
 329         throws java.io.IOException, ClassNotFoundException {
 330         s.defaultReadObject();
 331 
 332 
 333         // Check to make sure that types have not evolved incompatibly
 334 
 335         AnnotationType annotationType = null;
 336         try {
 337             annotationType = AnnotationType.getInstance(type);
 338         } catch(IllegalArgumentException e) {
 339             // Class is no longer an annotation type; all bets are off
 340             return;
 341         }
 342 
 343         Map<String, Class<?>> memberTypes = annotationType.memberTypes();
 344 
 345         for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) {
 346             String name = memberValue.getKey();
 347             Class<?> memberType = memberTypes.get(name);
 348             if (memberType != null) {  // i.e. member still exists
 349                 Object value = memberValue.getValue();
 350                 if (!(memberType.isInstance(value) ||
 351                       value instanceof ExceptionProxy)) {
 352                     memberValue.setValue(
 353                         new AnnotationTypeMismatchExceptionProxy(
 354                             value.getClass() + "[" + value + "]").setMember(
 355                                 annotationType.members().get(name)));
 356                 }
 357             }
 358         }
 359     }
 360 }