Avoid sensitive Proxy.getInvocationHandler call in synthesizeAnnotation
Issue: SPR-13829
(cherry picked from commit aecb8b6
)
This commit is contained in:
parent
4a863c9066
commit
acecda7153
|
@ -495,8 +495,8 @@ public abstract class AnnotationUtils {
|
||||||
|
|
||||||
// Do NOT store result in the findAnnotationCache since doing so could break
|
// Do NOT store result in the findAnnotationCache since doing so could break
|
||||||
// findAnnotation(Class, Class) and findAnnotation(Method, Class).
|
// findAnnotation(Class, Class) and findAnnotation(Method, Class).
|
||||||
return synthesizeAnnotation(
|
A ann = findAnnotation(annotatedElement, annotationType, new HashSet<Annotation>());
|
||||||
findAnnotation(annotatedElement, annotationType, new HashSet<Annotation>()), annotatedElement);
|
return synthesizeAnnotation(ann, annotatedElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1360,8 +1360,7 @@ public abstract class AnnotationUtils {
|
||||||
if (annotation == null) {
|
if (annotation == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (annotation instanceof SynthesizedAnnotation || (Proxy.isProxyClass(annotation.getClass()) &&
|
if (annotation instanceof SynthesizedAnnotation) {
|
||||||
Proxy.getInvocationHandler(annotation) instanceof SynthesizedAnnotationInvocationHandler)) {
|
|
||||||
return annotation;
|
return annotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1373,8 +1372,10 @@ public abstract class AnnotationUtils {
|
||||||
DefaultAnnotationAttributeExtractor attributeExtractor =
|
DefaultAnnotationAttributeExtractor attributeExtractor =
|
||||||
new DefaultAnnotationAttributeExtractor(annotation, annotatedElement);
|
new DefaultAnnotationAttributeExtractor(annotation, annotatedElement);
|
||||||
InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor);
|
InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor);
|
||||||
Class<?>[] exposedInterfaces = (canExposeSynthesizedMarker(annotationType) ?
|
|
||||||
new Class<?>[] {annotationType, SynthesizedAnnotation.class} : new Class<?>[] {annotationType});
|
// Can always expose Spring's SynthesizedAnnotation marker since we explicitly check for a
|
||||||
|
// synthesizable annotation before (which needs to declare @AliasFor from the same package)
|
||||||
|
Class<?>[] exposedInterfaces = new Class<?>[] {annotationType, SynthesizedAnnotation.class};
|
||||||
return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler);
|
return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1945,11 +1946,11 @@ public abstract class AnnotationUtils {
|
||||||
|
|
||||||
this.sourceAttribute = sourceAttribute;
|
this.sourceAttribute = sourceAttribute;
|
||||||
this.sourceAnnotationType = (Class<? extends Annotation>) declaringClass;
|
this.sourceAnnotationType = (Class<? extends Annotation>) declaringClass;
|
||||||
this.sourceAttributeName = this.sourceAttribute.getName();
|
this.sourceAttributeName = sourceAttribute.getName();
|
||||||
|
|
||||||
this.aliasedAnnotationType = (Annotation.class == aliasFor.annotation() ?
|
this.aliasedAnnotationType = (Annotation.class == aliasFor.annotation() ?
|
||||||
this.sourceAnnotationType : aliasFor.annotation());
|
this.sourceAnnotationType : aliasFor.annotation());
|
||||||
this.aliasedAttributeName = getAliasedAttributeName(aliasFor, this.sourceAttribute);
|
this.aliasedAttributeName = getAliasedAttributeName(aliasFor, sourceAttribute);
|
||||||
try {
|
try {
|
||||||
this.aliasedAttribute = this.aliasedAnnotationType.getDeclaredMethod(this.aliasedAttributeName);
|
this.aliasedAttribute = this.aliasedAnnotationType.getDeclaredMethod(this.aliasedAttributeName);
|
||||||
}
|
}
|
||||||
|
@ -1977,16 +1978,14 @@ public abstract class AnnotationUtils {
|
||||||
if (this.isAliasPair) {
|
if (this.isAliasPair) {
|
||||||
AliasFor mirrorAliasFor = this.aliasedAttribute.getAnnotation(AliasFor.class);
|
AliasFor mirrorAliasFor = this.aliasedAttribute.getAnnotation(AliasFor.class);
|
||||||
if (mirrorAliasFor == null) {
|
if (mirrorAliasFor == null) {
|
||||||
String msg = String.format(
|
String msg = String.format("Attribute [%s] in annotation [%s] must be declared as an @AliasFor [%s].",
|
||||||
"Attribute [%s] in annotation [%s] must be declared as an @AliasFor [%s].",
|
|
||||||
this.aliasedAttributeName, this.sourceAnnotationType.getName(), this.sourceAttributeName);
|
this.aliasedAttributeName, this.sourceAnnotationType.getName(), this.sourceAttributeName);
|
||||||
throw new AnnotationConfigurationException(msg);
|
throw new AnnotationConfigurationException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
String mirrorAliasedAttributeName = getAliasedAttributeName(mirrorAliasFor, this.aliasedAttribute);
|
String mirrorAliasedAttributeName = getAliasedAttributeName(mirrorAliasFor, this.aliasedAttribute);
|
||||||
if (!this.sourceAttributeName.equals(mirrorAliasedAttributeName)) {
|
if (!this.sourceAttributeName.equals(mirrorAliasedAttributeName)) {
|
||||||
String msg = String.format(
|
String msg = String.format("Attribute [%s] in annotation [%s] must be declared as an @AliasFor [%s], not [%s].",
|
||||||
"Attribute [%s] in annotation [%s] must be declared as an @AliasFor [%s], not [%s].",
|
|
||||||
this.aliasedAttributeName, this.sourceAnnotationType.getName(), this.sourceAttributeName,
|
this.aliasedAttributeName, this.sourceAnnotationType.getName(), this.sourceAttributeName,
|
||||||
mirrorAliasedAttributeName);
|
mirrorAliasedAttributeName);
|
||||||
throw new AnnotationConfigurationException(msg);
|
throw new AnnotationConfigurationException(msg);
|
||||||
|
@ -2124,13 +2123,6 @@ public abstract class AnnotationUtils {
|
||||||
return AliasDescriptor.from(this.aliasedAttribute);
|
return AliasDescriptor.from(this.aliasedAttribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("%s: @%s(%s) is an alias for @%s(%s)", getClass().getSimpleName(),
|
|
||||||
this.sourceAnnotationType.getSimpleName(), this.sourceAttributeName,
|
|
||||||
this.aliasedAnnotationType.getSimpleName(), this.aliasedAttributeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of the aliased attribute configured via the supplied
|
* Get the name of the aliased attribute configured via the supplied
|
||||||
* {@link AliasFor @AliasFor} annotation on the supplied {@code attribute}.
|
* {@link AliasFor @AliasFor} annotation on the supplied {@code attribute}.
|
||||||
|
@ -2145,9 +2137,8 @@ public abstract class AnnotationUtils {
|
||||||
* @return the name of the aliased attribute (never {@code null} or empty)
|
* @return the name of the aliased attribute (never {@code null} or empty)
|
||||||
* @throws AnnotationConfigurationException if invalid configuration of
|
* @throws AnnotationConfigurationException if invalid configuration of
|
||||||
* {@code @AliasFor} is detected
|
* {@code @AliasFor} is detected
|
||||||
* @since 4.2
|
|
||||||
*/
|
*/
|
||||||
private static String getAliasedAttributeName(AliasFor aliasFor, Method attribute) {
|
private String getAliasedAttributeName(AliasFor aliasFor, Method attribute) {
|
||||||
String attributeName = aliasFor.attribute();
|
String attributeName = aliasFor.attribute();
|
||||||
String value = aliasFor.value();
|
String value = aliasFor.value();
|
||||||
boolean attributeDeclared = StringUtils.hasText(attributeName);
|
boolean attributeDeclared = StringUtils.hasText(attributeName);
|
||||||
|
@ -2155,10 +2146,10 @@ public abstract class AnnotationUtils {
|
||||||
|
|
||||||
// Ensure user did not declare both 'value' and 'attribute' in @AliasFor
|
// Ensure user did not declare both 'value' and 'attribute' in @AliasFor
|
||||||
if (attributeDeclared && valueDeclared) {
|
if (attributeDeclared && valueDeclared) {
|
||||||
throw new AnnotationConfigurationException(String.format(
|
String msg = String.format("In @AliasFor declared on attribute [%s] in annotation [%s], attribute 'attribute' " +
|
||||||
"In @AliasFor declared on attribute [%s] in annotation [%s], attribute 'attribute' and its " +
|
"and its alias 'value' are present with values of [%s] and [%s], but only one is permitted.",
|
||||||
"alias 'value' are present with values of [%s] and [%s], but only one is permitted.",
|
attribute.getName(), attribute.getDeclaringClass().getName(), attributeName, value);
|
||||||
attribute.getName(), attribute.getDeclaringClass().getName(), attributeName, value));
|
throw new AnnotationConfigurationException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
attributeName = (attributeDeclared ? attributeName : value);
|
attributeName = (attributeDeclared ? attributeName : value);
|
||||||
|
@ -2173,6 +2164,13 @@ public abstract class AnnotationUtils {
|
||||||
|
|
||||||
return attributeName.trim();
|
return attributeName.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s: @%s(%s) is an alias for @%s(%s)", getClass().getSimpleName(),
|
||||||
|
this.sourceAnnotationType.getSimpleName(), this.sourceAttributeName,
|
||||||
|
this.aliasedAnnotationType.getSimpleName(), this.aliasedAttributeName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue