< prev index next >

src/java.base/share/classes/sun/reflect/annotation/AnnotationSupport.java

Print this page




 165         // Search declared
 166         A[] result = getDirectlyAndIndirectlyPresent(declaredAnnotations, annoClass);
 167 
 168         // Search inherited
 169         if(AnnotationType.getInstance(annoClass).isInherited()) {
 170             Class<?> superDecl = decl.getSuperclass();
 171             while (result.length == 0 && superDecl != null) {
 172                 result = getDirectlyAndIndirectlyPresent(LANG_ACCESS.getDeclaredAnnotationMap(superDecl), annoClass);
 173                 superDecl = superDecl.getSuperclass();
 174             }
 175         }
 176 
 177         return result;
 178     }
 179 
 180 
 181     /* Reflectively invoke the values-method of the given annotation
 182      * (container), cast it to an array of annotations and return the result.
 183      */
 184     private static <A extends Annotation> A[] getValueArray(Annotation container) {
 185         try {
 186             // According to JLS the container must have an array-valued value
 187             // method. Get the AnnotationType, get the "value" method and invoke
 188             // it to get the content.
 189 
 190             Class<? extends Annotation> containerClass = container.annotationType();
 191             AnnotationType annoType = AnnotationType.getInstance(containerClass);
 192             if (annoType == null)
 193                 throw invalidContainerException(container, null);
 194             Method m = annoType.members().get("value");
 195             if (m == null)
 196                 throw invalidContainerException(container, null);
 197 
 198             if (Proxy.isProxyClass(container.getClass())) {
 199                 // Invoke by invocation handler
 200                 InvocationHandler handler = Proxy.getInvocationHandler(container);
 201 
 202                 try {
 203                     // This will erase to (Annotation[]) but we do a runtime cast on the
 204                     // return-value in the method that call this method.
 205                     @SuppressWarnings("unchecked")
 206                     A[] values = (A[]) handler.invoke(container, m, null);
 207                     return values;
 208                 } catch (Throwable t) { // from InvocationHandler::invoke
 209                     throw invalidContainerException(container, t);
 210                 }
 211             } else {
 212                 // In theory there might be instances of Annotations that are not
 213                 // implemented using Proxies. Try to invoke the "value" element with
 214                 // reflection.
 215 
 216                 // Declaring class should be an annotation type
 217                 Class<?> iface = m.getDeclaringClass();
 218                 if (!iface.isAnnotation())
 219                     throw new UnsupportedOperationException("Unsupported container annotation type.");
 220                 // Method must be public
 221                 if (!Modifier.isPublic(m.getModifiers()))
 222                     throw new UnsupportedOperationException("Unsupported value member.");
 223 
 224                 // Interface might not be public though
 225                 final Method toInvoke;
 226                 if (!Modifier.isPublic(iface.getModifiers())) {
 227                     if (System.getSecurityManager() != null) {
 228                         toInvoke = AccessController.doPrivileged(new PrivilegedAction<Method>() {
 229                             @Override
 230                             public Method run() {
 231                                 Method res = ReflectionFactory.getReflectionFactory().leafCopyMethod(m);
 232                                 res.setAccessible(true);
 233                                 return res;
 234                             }
 235                         });
 236                     } else {
 237                         toInvoke = ReflectionFactory.getReflectionFactory().leafCopyMethod(m);
 238                         toInvoke.setAccessible(true);
 239                     }
 240                 } else {
 241                     toInvoke = m;
 242                 }
 243 

 244                 // This will erase to (Annotation[]) but we do a runtime cast on the
 245                 // return-value in the method that call this method.
 246                 @SuppressWarnings("unchecked")
 247                 A[] values = (A[]) toInvoke.invoke(container);
 248 
 249                 return values;


 250             }
 251         } catch (IllegalAccessException    | // couldn't loosen security
 252                  IllegalArgumentException  | // parameters doesn't match
 253                  InvocationTargetException | // the value method threw an exception
 254                  ClassCastException e) {
 255             throw invalidContainerException(container, e);
 256         }
 257     }
 258 
 259 
 260     private static AnnotationFormatError invalidContainerException(Annotation anno,
 261                                                                    Throwable cause) {
 262         return new AnnotationFormatError(
 263                 anno + " is an invalid container for repeating annotations",
 264                 cause);
 265     }
 266 
 267 
 268     /* Sanity check type of all the annotation instances of type {@code annoClass}
 269      * from {@code container}.
 270      */
 271     private static <A extends Annotation> void checkTypes(A[] annotations,
 272                                                           Annotation container,
 273                                                           Class<A> annoClass) {
 274         for (A a : annotations) {
 275             if (!annoClass.isInstance(a)) {


 165         // Search declared
 166         A[] result = getDirectlyAndIndirectlyPresent(declaredAnnotations, annoClass);
 167 
 168         // Search inherited
 169         if(AnnotationType.getInstance(annoClass).isInherited()) {
 170             Class<?> superDecl = decl.getSuperclass();
 171             while (result.length == 0 && superDecl != null) {
 172                 result = getDirectlyAndIndirectlyPresent(LANG_ACCESS.getDeclaredAnnotationMap(superDecl), annoClass);
 173                 superDecl = superDecl.getSuperclass();
 174             }
 175         }
 176 
 177         return result;
 178     }
 179 
 180 
 181     /* Reflectively invoke the values-method of the given annotation
 182      * (container), cast it to an array of annotations and return the result.
 183      */
 184     private static <A extends Annotation> A[] getValueArray(Annotation container) {

 185         // According to JLS the container must have an array-valued value
 186         // method. Usually the annotation will be implemented as a dynamic Proxy
 187         // with AnnotationInvocationHandler as the invocation handler...
 188         AnnotationInvocationHandler oneOfUs = AnnotationInvocationHandler.asOneOfUs(container);
 189         if (oneOfUs != null) {











 190             try {
 191                 // This will erase to (Annotation[]) but we do a runtime cast on the
 192                 // return-value in the method that call this method.
 193                 @SuppressWarnings("unchecked")
 194                 A[] values = (A[]) oneOfUs.getValue(/* interned */ "value");
 195                 return values;
 196             } catch (Throwable t) {
 197                 throw invalidContainerException(container, t);
 198             }
 199         } else {
 200             // In theory there might be instances of Annotations that are not
 201             // implemented using Proxies. Try to invoke the "value" element with
 202             // reflection using accessible Method object.
 203             Method m = AnnotationType.getInstance(container.annotationType())
 204                                      .accessibleMembers().get("value");
 205             if (m == null)
 206                 throw invalidContainerException(container, null);
























 207 
 208             try {
 209                 // This will erase to (Annotation[]) but we do a runtime cast on the
 210                 // return-value in the method that call this method.
 211                 @SuppressWarnings("unchecked")
 212                 A[] values = (A[]) m.invoke(container);

 213                 return values;
 214             } catch (Throwable t) {
 215                 throw invalidContainerException(container, t);
 216             }





 217         }
 218     }
 219 
 220 
 221     private static AnnotationFormatError invalidContainerException(Annotation anno,
 222                                                                    Throwable cause) {
 223         return new AnnotationFormatError(
 224                 anno + " is an invalid container for repeating annotations",
 225                 cause);
 226     }
 227 
 228 
 229     /* Sanity check type of all the annotation instances of type {@code annoClass}
 230      * from {@code container}.
 231      */
 232     private static <A extends Annotation> void checkTypes(A[] annotations,
 233                                                           Annotation container,
 234                                                           Class<A> annoClass) {
 235         for (A a : annotations) {
 236             if (!annoClass.isInstance(a)) {
< prev index next >