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