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)) { |