mirror of
https://github.com/apache/struts.git
synced 2026-08-11 01:27:14 +00:00
WW-4694 WW-4472 Imroves annotation processing
This commit is contained in:
+1
-1
@@ -207,7 +207,7 @@ public class DefaultWorkflowInterceptor extends MethodFilterInterceptor {
|
||||
*/
|
||||
protected String processInputConfig(final Object action, final String method, final String currentResultName) throws Exception {
|
||||
String resultName = currentResultName;
|
||||
InputConfig annotation = action.getClass().getMethod(method, EMPTY_CLASS_ARRAY).getAnnotation(InputConfig.class);
|
||||
InputConfig annotation = AnnotationUtils.findAnnotation(action.getClass().getMethod(method, EMPTY_CLASS_ARRAY), InputConfig.class);
|
||||
if (annotation != null) {
|
||||
if (StringUtils.isNotEmpty(annotation.methodName())) {
|
||||
Method m = action.getClass().getMethod(annotation.methodName());
|
||||
|
||||
@@ -122,7 +122,14 @@ public class AnnotationUtils {
|
||||
Collection<Method> toReturn = new HashSet<>();
|
||||
|
||||
for (Method m : clazz.getMethods()) {
|
||||
if (ArrayUtils.isNotEmpty(annotation) && isAnnotatedBy(m, annotation)) {
|
||||
boolean found = false;
|
||||
for( Class<? extends Annotation> c : annotation ){
|
||||
if( null != findAnnotation(m, c) ){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
toReturn.add(m);
|
||||
} else if (ArrayUtils.isEmpty(annotation) && ArrayUtils.isNotEmpty(m.getAnnotations())) {
|
||||
toReturn.add(m);
|
||||
@@ -133,22 +140,100 @@ public class AnnotationUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Varargs version of <code>AnnotatedElement.isAnnotationPresent()</code>
|
||||
* @param annotatedElement element to check
|
||||
* @param annotation the {@link Annotation}s to find
|
||||
* @return true is element is annotated by one of the annotation
|
||||
* @see AnnotatedElement
|
||||
* Find a single {@link Annotation} of {@code annotationType} from the supplied
|
||||
* {@link Method}, traversing its super methods (i.e., from superclasses and
|
||||
* interfaces) if no annotation can be found on the given method itself.
|
||||
* <p>Annotations on methods are not inherited by default, so we need to handle
|
||||
* this explicitly.
|
||||
* @param method the method to look for annotations on
|
||||
* @param annotationType the annotation type to look for
|
||||
* @return the annotation found, or {@code null} if none
|
||||
*/
|
||||
public static boolean isAnnotatedBy(AnnotatedElement annotatedElement, Class<? extends Annotation>... annotation) {
|
||||
if (ArrayUtils.isEmpty(annotation)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for( Class<? extends Annotation> c : annotation ){
|
||||
if( annotatedElement.isAnnotationPresent(c) ) return true;
|
||||
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
|
||||
A result = getAnnotation(method, annotationType);
|
||||
Class<?> clazz = method.getDeclaringClass();
|
||||
if (result == null) {
|
||||
result = searchOnInterfaces(method, annotationType, clazz.getInterfaces());
|
||||
}
|
||||
while (result == null) {
|
||||
clazz = clazz.getSuperclass();
|
||||
if (clazz == null || clazz.equals(Object.class)) {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
Method equivalentMethod = clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
|
||||
result = getAnnotation(equivalentMethod, annotationType);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
// No equivalent method found
|
||||
}
|
||||
if (result == null) {
|
||||
result = searchOnInterfaces(method, annotationType, clazz.getInterfaces());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return false;
|
||||
/**
|
||||
* Get a single {@link Annotation} of {@code annotationType} from the supplied
|
||||
* Method, Constructor or Field. Meta-annotations will be searched if the annotation
|
||||
* is not declared locally on the supplied element.
|
||||
* @param annotatedElement the Method, Constructor or Field from which to get the annotation
|
||||
* @param annotationType the annotation type to look for, both locally and as a meta-annotation
|
||||
* @return the matching annotation, or {@code null} if none found
|
||||
*/
|
||||
public static <T extends Annotation> T getAnnotation(AnnotatedElement annotatedElement, Class<T> annotationType) {
|
||||
try {
|
||||
T ann = annotatedElement.getAnnotation(annotationType);
|
||||
if (ann == null) {
|
||||
for (Annotation metaAnn : annotatedElement.getAnnotations()) {
|
||||
ann = metaAnn.annotationType().getAnnotation(annotationType);
|
||||
if (ann != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ann;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Assuming nested Class values not resolvable within annotation attributes...
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static <A extends Annotation> A searchOnInterfaces(Method method, Class<A> annotationType, Class<?>... ifcs) {
|
||||
A annotation = null;
|
||||
for (Class<?> iface : ifcs) {
|
||||
if (isInterfaceWithAnnotatedMethods(iface)) {
|
||||
try {
|
||||
Method equivalentMethod = iface.getMethod(method.getName(), method.getParameterTypes());
|
||||
annotation = getAnnotation(equivalentMethod, annotationType);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
// Skip this interface - it doesn't have the method...
|
||||
}
|
||||
if (annotation != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return annotation;
|
||||
}
|
||||
|
||||
private static boolean isInterfaceWithAnnotatedMethods(Class<?> iface) {
|
||||
boolean found = false;
|
||||
for (Method ifcMethod : iface.getMethods()) {
|
||||
try {
|
||||
if (ifcMethod.getAnnotations().length > 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Assuming nested Class values not resolvable within annotation attributes...
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,8 +5,11 @@ import com.opensymphony.xwork2.util.annotation.DummyClass;
|
||||
import com.opensymphony.xwork2.util.annotation.DummyClassExt;
|
||||
import com.opensymphony.xwork2.util.annotation.MyAnnotation;
|
||||
import com.opensymphony.xwork2.util.annotation.MyAnnotation2;
|
||||
import com.opensymphony.xwork2.util.annotation.MyAnnotationI;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -15,22 +18,32 @@ import java.util.Collection;
|
||||
*/
|
||||
public class AnnotationUtilsTest extends TestCase {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testIsAnnotatedByWithoutAnnotationArgsReturnsFalse() throws Exception {
|
||||
assertFalse(AnnotationUtils.isAnnotatedBy(DummyClass.class));
|
||||
assertFalse(AnnotationUtils.isAnnotatedBy(DummyClass.class.getMethod("methodWithAnnotation")));
|
||||
public void testGetAnnotationMeta() throws Exception {
|
||||
assertNotNull(AnnotationUtils.getAnnotation(DummyClass.class.getMethod("methodWithAnnotation"), Retention.class));
|
||||
}
|
||||
|
||||
public void testGetAnnotation() throws Exception {
|
||||
assertNull(AnnotationUtils.getAnnotation(DummyClass.class.getMethod("methodWithAnnotation"), Deprecated.class));
|
||||
assertNotNull(AnnotationUtils.getAnnotation(DummyClass.class.getMethod("methodWithAnnotation"), MyAnnotation.class));
|
||||
}
|
||||
|
||||
public void testFindAnnotationFromSuperclass() throws Exception {
|
||||
assertNotNull(AnnotationUtils.findAnnotation(DummyClassExt.class.getMethod("methodWithAnnotation"), MyAnnotation.class));
|
||||
}
|
||||
|
||||
public void testFindAnnotationFromInterface() throws Exception {
|
||||
assertNotNull(AnnotationUtils.findAnnotation(DummyClass.class.getMethod("interfaceMethodWithAnnotation"), MyAnnotationI.class));
|
||||
}
|
||||
|
||||
public void testFindAnnotation() throws Exception {
|
||||
assertNotNull(AnnotationUtils.findAnnotation(DummyClassExt.class.getMethod("anotherAnnotatedMethod"), MyAnnotation2.class));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testIsAnnotatedByWithSingleAnnotationArgMatchingReturnsTrue() throws Exception {
|
||||
assertTrue(AnnotationUtils.isAnnotatedBy(DummyClass.class.getMethod("methodWithAnnotation"), MyAnnotation.class));
|
||||
}
|
||||
public void testGetAnnotatedMethodsIncludingSuperclassAndInterface() throws Exception {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testIsAnnotatedByWithMultiAnnotationArgMatchingReturnsTrue() throws Exception {
|
||||
assertFalse(AnnotationUtils.isAnnotatedBy(DummyClass.class.getMethod("methodWithAnnotation"), Deprecated.class));
|
||||
assertTrue(AnnotationUtils.isAnnotatedBy(DummyClass.class.getMethod("methodWithAnnotation"), MyAnnotation.class, Deprecated.class));
|
||||
assertTrue(AnnotationUtils.isAnnotatedBy(DummyClass.class.getMethod("methodWithAnnotation"), Deprecated.class, MyAnnotation.class));
|
||||
Collection<? extends AnnotatedElement> ans = AnnotationUtils.getAnnotatedMethods(DummyClassExt.class, Deprecated.class, MyAnnotation.class, MyAnnotation2.class, MyAnnotationI.class);
|
||||
assertEquals(3, ans.size());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.opensymphony.xwork2.util.annotation;
|
||||
|
||||
@MyAnnotation("class-test")
|
||||
public class DummyClass {
|
||||
public class DummyClass implements DummyInterface {
|
||||
|
||||
public DummyClass() {
|
||||
}
|
||||
@@ -10,4 +10,7 @@ public class DummyClass {
|
||||
public void methodWithAnnotation() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interfaceMethodWithAnnotation() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,5 +5,8 @@ public final class DummyClassExt extends DummyClass {
|
||||
@MyAnnotation2
|
||||
public void anotherAnnotatedMethod() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void methodWithAnnotation() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.opensymphony.xwork2.util.annotation;
|
||||
|
||||
public interface DummyInterface {
|
||||
|
||||
@MyAnnotationI
|
||||
public void interfaceMethodWithAnnotation();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.opensymphony.xwork2.util.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MyAnnotationI {
|
||||
}
|
||||
Reference in New Issue
Block a user