158 Class<?> decl, 159 Class<A> annoClass) { 160 Objects.requireNonNull(decl); 161 162 // Search declared 163 A[] result = getDirectlyAndIndirectlyPresent(declaredAnnotations, annoClass); 164 165 // Search inherited 166 if(AnnotationType.getInstance(annoClass).isInherited()) { 167 Class<?> superDecl = decl.getSuperclass(); 168 while (result.length == 0 && superDecl != null) { 169 result = getDirectlyAndIndirectlyPresent(LANG_ACCESS.getDeclaredAnnotationMap(superDecl), annoClass); 170 superDecl = superDecl.getSuperclass(); 171 } 172 } 173 174 return result; 175 } 176 177 178 /* Reflectively invoke the values-method of the given annotation 179 * (container), cast it to an array of annotations and return the result. 180 */ 181 private static <A extends Annotation> A[] getValueArray(Annotation container) { 182 try { 183 // According to JLS the container must have an array-valued value 184 // method. Get the AnnotationType, get the "value" method and invoke 185 // it to get the content. 186 187 Class<? extends Annotation> containerClass = container.annotationType(); 188 AnnotationType annoType = AnnotationType.getInstance(containerClass); 189 if (annoType == null) 190 throw invalidContainerException(container, null); 191 192 Method m = annoType.members().get("value"); 193 if (m == null) 194 throw invalidContainerException(container, null); 195 196 m.setAccessible(true); 197 198 // This will erase to (Annotation[]) but we do a runtime cast on the 199 // return-value in the method that call this method. 200 @SuppressWarnings("unchecked") 201 A[] values = (A[]) m.invoke(container); 202 203 return values; 204 205 } catch (IllegalAccessException | // couldn't loosen security 206 IllegalArgumentException | // parameters doesn't match 207 InvocationTargetException | // the value method threw an exception 208 ClassCastException e) { 209 210 throw invalidContainerException(container, e); 211 212 } 213 } 214 215 216 private static AnnotationFormatError invalidContainerException(Annotation anno, 217 Throwable cause) { 218 return new AnnotationFormatError( 219 anno + " is an invalid container for repeating annotations", 220 cause); 221 } 222 223 224 /* Sanity check type of all the annotation instances of type {@code annoClass} 225 * from {@code container}. 226 */ 227 private static <A extends Annotation> void checkTypes(A[] annotations, 228 Annotation container, 229 Class<A> annoClass) { 230 for (A a : annotations) { 231 if (!annoClass.isInstance(a)) { | 158 Class<?> decl, 159 Class<A> annoClass) { 160 Objects.requireNonNull(decl); 161 162 // Search declared 163 A[] result = getDirectlyAndIndirectlyPresent(declaredAnnotations, annoClass); 164 165 // Search inherited 166 if(AnnotationType.getInstance(annoClass).isInherited()) { 167 Class<?> superDecl = decl.getSuperclass(); 168 while (result.length == 0 && superDecl != null) { 169 result = getDirectlyAndIndirectlyPresent(LANG_ACCESS.getDeclaredAnnotationMap(superDecl), annoClass); 170 superDecl = superDecl.getSuperclass(); 171 } 172 } 173 174 return result; 175 } 176 177 178 /* 179 * Reflectively invoke the values-method of the given annotation 180 * (container), cast it to an array of annotations and return the 181 * result. 182 */ 183 public static <A extends Annotation> A[] getValueArray(Annotation container) { 184 try { 185 // According to JLS the container must have an array-valued value 186 // method. Get the AnnotationType, get the "value" method and invoke 187 // it to get the content. 188 189 Class<? extends Annotation> containerClass = container.annotationType(); 190 AnnotationType annoType = AnnotationType.getInstance(containerClass); 191 if (annoType == null) 192 throw invalidContainerException(container, null); 193 194 Method m = annoType.members().get("value"); 195 if (m == null) 196 throw invalidContainerException(container, null); 197 198 m.setAccessible(true); 199 200 // This will erase to (Annotation[]) but we do a runtime cast on the 201 // return-value in the method that call this method. 202 @SuppressWarnings("unchecked") 203 A[] values = (A[]) m.invoke(container); 204 return values; 205 } catch (IllegalAccessException | // couldn't loosen security 206 IllegalArgumentException | // parameters doesn't match 207 InvocationTargetException | // the value method threw an exception 208 ClassCastException e) { 209 throw invalidContainerException(container, e); 210 } 211 } 212 213 214 private static AnnotationFormatError invalidContainerException(Annotation anno, 215 Throwable cause) { 216 return new AnnotationFormatError( 217 anno + " is an invalid container for repeating annotations", 218 cause); 219 } 220 221 222 /* Sanity check type of all the annotation instances of type {@code annoClass} 223 * from {@code container}. 224 */ 225 private static <A extends Annotation> void checkTypes(A[] annotations, 226 Annotation container, 227 Class<A> annoClass) { 228 for (A a : annotations) { 229 if (!annoClass.isInstance(a)) { |