Throw exception if required meta-annotation is not present

It is a configuration error if an alias is declared via @AliasFor for
an attribute in a meta-annotation and the meta-annotation is not
meta-present. However, prior to this commit, the support for validating
the configuration of @AliasFor in AnnotationUtils currently silently
ignored such errors.

This commit fixes this by throwing an AnnotationConfigurationException
whenever a required meta-annotation is not present or meta-present on
an annotation that declares an explicit alias for an attribute in the
meta-annotation.

Issue: SPR-13335
This commit is contained in:
Sam Brannen
2015-08-09 19:14:29 +02:00
parent 78ff4ff542
commit 8289036165
3 changed files with 47 additions and 13 deletions

View File

@@ -65,18 +65,18 @@ import java.lang.annotation.Target;
* <li>Aliased attributes must declare the same return type.</li>
* <li>Aliased attributes must declare a default value.</li>
* <li>Aliased attributes must declare the same default value.</li>
* <li>The {@link #annotation} attribute may remain set to the default,
* although setting it to the declaring class for both attributes in the
* pair is also valid.</li>
* <li>The {@link #annotation} attribute should remain set to the default.</li>
* </ol>
* </li>
* <li><strong>Alias for attribute in meta-annotation</strong>:
* <ol>
* <li>The attribute that is an alias for an attribute in a meta-annotation
* must be annotated with {@code @AliasFor}; the {@link #attribute} must
* reference the aliased attribute in the meta-annotation; and the
* {@link #annotation} must reference the meta-annotation.</li>
* must be annotated with {@code @AliasFor}, and the {@link #attribute} must
* reference the aliased attribute in the meta-annotation.</li>
* <li>Aliased attributes must declare the same return type.</li>
* <li>The {@link #annotation} must reference the meta-annotation.</li>
* <li>The referenced meta-annotation must be <em>meta-present</em> on the
* annotation class that declares {@code @AliasFor}.</li>
* </ol>
* </li>
* </ul>

View File

@@ -1451,6 +1451,7 @@ public abstract class AnnotationUtils {
Assert.isTrue(!Annotation.class.equals(targetAnnotationType),
"targetAnnotationType must not be java.lang.annotation.Annotation");
String attributeName = attribute.getName();
AliasFor aliasFor = attribute.getAnnotation(AliasFor.class);
// Nothing to check
@@ -1470,12 +1471,6 @@ public abstract class AnnotationUtils {
return null;
}
// Wrong search scope?
if (searchWithinSameAnnotation && !sameTargetDeclared) {
return null;
}
String attributeName = attribute.getName();
String aliasedAttributeName = getAliasedAttributeName(aliasFor, attribute);
if (!StringUtils.hasText(aliasedAttributeName)) {
@@ -1485,10 +1480,25 @@ public abstract class AnnotationUtils {
throw new AnnotationConfigurationException(msg);
}
if (sameTargetDeclared) {
if (!sameTargetDeclared) {
// Target annotation is not meta-present?
if (findAnnotation(sourceAnnotationType, aliasedAnnotationType) == null) {
String msg = String.format("@AliasFor declaration on attribute [%s] in annotation [%s] declares "
+ "an alias for attribute [%s] in meta-annotation [%s] which is not meta-present.",
attributeName, sourceAnnotationType.getName(), aliasedAttributeName,
aliasedAnnotationType.getName());
throw new AnnotationConfigurationException(msg);
}
}
else {
aliasedAnnotationType = sourceAnnotationType;
}
// Wrong search scope?
if (searchWithinSameAnnotation && !sameTargetDeclared) {
return null;
}
Method aliasedAttribute;
try {
aliasedAttribute = aliasedAnnotationType.getDeclaredMethod(aliasedAttributeName);