From fd809cd18ec1603bfb2b77eda9e4c2b86de5b396 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 24 Jun 2014 11:01:37 +0200 Subject: [PATCH] AnnotationUtils defensively catches unexpected exceptions from retrieval attempts (proceeding like the annotation wasn't there) This is analogous to what the JVM does for cases where the annotation type itself isn't present on the classpath. We're effectively extending that policy to values referenced within an annotation declaration. Issue: SPR-11874 --- .../core/annotation/AnnotationUtils.java | 96 ++++++++++++++----- 1 file changed, 71 insertions(+), 25 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java index fa418d3b02..2352134e33 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java @@ -79,7 +79,14 @@ public abstract class AnnotationUtils { if (annotationType.isInstance(ann)) { return (T) ann; } - return ann.annotationType().getAnnotation(annotationType); + try { + return ann.annotationType().getAnnotation(annotationType); + } + catch (Exception ex) { + // Assuming nested Class values not resolvable within annotation attributes... + // We're probably hitting a non-present optional arrangement - let's back out. + return null; + } } /** @@ -92,16 +99,23 @@ public abstract class AnnotationUtils { * @since 3.1 */ public static T getAnnotation(AnnotatedElement ae, Class annotationType) { - T ann = ae.getAnnotation(annotationType); - if (ann == null) { - for (Annotation metaAnn : ae.getAnnotations()) { - ann = metaAnn.annotationType().getAnnotation(annotationType); - if (ann != null) { - break; + try { + T ann = ae.getAnnotation(annotationType); + if (ann == null) { + for (Annotation metaAnn : ae.getAnnotations()) { + ann = metaAnn.annotationType().getAnnotation(annotationType); + if (ann != null) { + break; + } } } + return ann; + } + catch (Exception ex) { + // Assuming nested Class values not resolvable within annotation attributes... + // We're probably hitting a non-present optional arrangement - let's back out. + return null; } - return ann; } /** @@ -112,7 +126,14 @@ public abstract class AnnotationUtils { * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method) */ public static Annotation[] getAnnotations(Method method) { - return BridgeMethodResolver.findBridgedMethod(method).getAnnotations(); + try { + return BridgeMethodResolver.findBridgedMethod(method).getAnnotations(); + } + catch (Exception ex) { + // Assuming nested Class values not resolvable within annotation attributes... + // We're probably hitting a non-present optional arrangement - let's back out. + return null; + } } /** @@ -162,10 +183,16 @@ public abstract class AnnotationUtils { public static Set getRepeatableAnnotation(AnnotatedElement annotatedElement, Class containerAnnotationType, Class annotationType) { - if (annotatedElement.getAnnotations().length == 0) { - return Collections.emptySet(); + try { + if (annotatedElement.getAnnotations().length > 0) { + return new AnnotationCollector(containerAnnotationType, annotationType).getResult(annotatedElement); + } } - return new AnnotationCollector(containerAnnotationType, annotationType).getResult(annotatedElement); + catch (Exception ex) { + // Assuming nested Class values not resolvable within annotation attributes... + // We're probably hitting a non-present optional arrangement - let's back out. + } + return Collections.emptySet(); } /** @@ -230,9 +257,15 @@ public abstract class AnnotationUtils { } boolean found = false; for (Method ifcMethod : iface.getMethods()) { - if (ifcMethod.getAnnotations().length > 0) { - found = true; - break; + try { + if (ifcMethod.getAnnotations().length > 0) { + found = true; + break; + } + } + catch (Exception ex) { + // Assuming nested Class values not resolvable within annotation attributes... + // We're probably hitting a non-present optional arrangement - let's back out. } } annotatedInterfaceCache.put(iface, found); @@ -278,7 +311,14 @@ public abstract class AnnotationUtils { private static A findAnnotation(Class clazz, Class annotationType, Set visited) { Assert.notNull(clazz, "Class must not be null"); if (isAnnotationDeclaredLocally(annotationType, clazz)) { - return clazz.getAnnotation(annotationType); + try { + return clazz.getAnnotation(annotationType); + } + catch (Exception ex) { + // Assuming nested Class values not resolvable within annotation attributes... + // We're probably hitting a non-present optional arrangement - let's back out. + return null; + } } for (Class ifc : clazz.getInterfaces()) { A annotation = findAnnotation(ifc, annotationType, visited); @@ -390,12 +430,18 @@ public abstract class AnnotationUtils { Assert.notNull(annotationType, "Annotation type must not be null"); Assert.notNull(clazz, "Class must not be null"); boolean declaredLocally = false; - for (Annotation annotation : clazz.getDeclaredAnnotations()) { - if (annotation.annotationType().equals(annotationType)) { - declaredLocally = true; - break; + try { + for (Annotation annotation : clazz.getDeclaredAnnotations()) { + if (annotation.annotationType().equals(annotationType)) { + declaredLocally = true; + break; + } } } + catch (Exception ex) { + // Assuming nested Class values not resolvable within annotation attributes... + // We're probably hitting a non-present optional arrangement - let's back out. + } return declaredLocally; } @@ -632,7 +678,7 @@ public abstract class AnnotationUtils { this.result.add((A) annotation); } else if (ObjectUtils.nullSafeEquals(this.containerAnnotationType, annotation.annotationType())) { - this.result.addAll(Arrays.asList(getValue(annotation))); + this.result.addAll(getValue(annotation)); } else if (!isInJavaLangAnnotationPackage(annotation)) { process(annotation.annotationType()); @@ -642,15 +688,15 @@ public abstract class AnnotationUtils { } @SuppressWarnings("unchecked") - private A[] getValue(Annotation annotation) { + private List getValue(Annotation annotation) { try { Method method = annotation.annotationType().getDeclaredMethod("value"); ReflectionUtils.makeAccessible(method); - return (A[]) method.invoke(annotation); + return Arrays.asList((A[]) method.invoke(annotation)); } catch (Exception ex) { - throw new IllegalStateException("Unable to read value from repeating annotation container " + - this.containerAnnotationType.getName(), ex); + // Unable to read value from repeating annotation container -> ignore it. + return Collections.emptyList(); } } }