You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2017/02/13 10:55:19 UTC
[1/3] struts git commit: [WW-4694] annotation processing improved in
order to navigate around proxies, superclasses and interfaces
Repository: struts
Updated Branches:
refs/heads/master 4b96958be -> 534dfc6bd
[WW-4694] annotation processing improved in order to navigate around
proxies, superclasses and interfaces
Project: http://git-wip-us.apache.org/repos/asf/struts/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/c84b7967
Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/c84b7967
Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/c84b7967
Branch: refs/heads/master
Commit: c84b7967e9eb2f6307466b1644977423831d2ef1
Parents: 0023d96
Author: Yasser Zamani <ya...@live.com>
Authored: Sun Feb 5 17:54:28 2017 +0330
Committer: Yasser Zamani <ya...@live.com>
Committed: Sun Feb 5 17:54:28 2017 +0330
----------------------------------------------------------------------
.../xwork2/util/AnnotationUtils.java | 111 ++++++++++++++++---
.../xwork2/util/AnnotationUtilsTest.java | 35 ++++--
.../xwork2/util/annotation/DummyClass.java | 5 +-
.../xwork2/util/annotation/DummyClassExt.java | 5 +-
.../xwork2/util/annotation/DummyInterface.java | 7 ++
.../xwork2/util/annotation/MyAnnotationI.java | 8 ++
6 files changed, 145 insertions(+), 26 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/struts/blob/c84b7967/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java b/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java
index ef0ee53..1c37918 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java
+++ b/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java
@@ -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;
- }
+ 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;
+ }
+
+ /**
+ * 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;
+ }
+ }
- for( Class<? extends Annotation> c : annotation ){
- if( annotatedElement.isAnnotationPresent(c) ) return true;
+ 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;
+ }
- return false;
+ 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;
}
/**
http://git-wip-us.apache.org/repos/asf/struts/blob/c84b7967/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java b/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java
index e59abe6..8ad4f35 100644
--- a/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java
@@ -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));
}
- @SuppressWarnings("unchecked")
- public void testIsAnnotatedByWithSingleAnnotationArgMatchingReturnsTrue() throws Exception {
- assertTrue(AnnotationUtils.isAnnotatedBy(DummyClass.class.getMethod("methodWithAnnotation"), MyAnnotation.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 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));
+ public void testGetAnnotatedMethodsIncludingSuperclassAndInterface() throws Exception {
+
+ Collection<? extends AnnotatedElement> ans = AnnotationUtils.getAnnotatedMethods(DummyClassExt.class, Deprecated.class, MyAnnotation.class, MyAnnotation2.class, MyAnnotationI.class);
+ assertEquals(3, ans.size());
}
@SuppressWarnings("unchecked")
http://git-wip-us.apache.org/repos/asf/struts/blob/c84b7967/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClass.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClass.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClass.java
index 22d6e07..da2f80e 100644
--- a/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClass.java
+++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClass.java
@@ -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() {
+ }
}
http://git-wip-us.apache.org/repos/asf/struts/blob/c84b7967/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClassExt.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClassExt.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClassExt.java
index cfeebdf..7c024f6 100644
--- a/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClassExt.java
+++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClassExt.java
@@ -5,5 +5,8 @@ public final class DummyClassExt extends DummyClass {
@MyAnnotation2
public void anotherAnnotatedMethod() {
}
-
+
+ @Override
+ public void methodWithAnnotation() {
+ }
}
http://git-wip-us.apache.org/repos/asf/struts/blob/c84b7967/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyInterface.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyInterface.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyInterface.java
new file mode 100644
index 0000000..6faa3e4
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyInterface.java
@@ -0,0 +1,7 @@
+package com.opensymphony.xwork2.util.annotation;
+
+public interface DummyInterface {
+
+ @MyAnnotationI
+ public void interfaceMethodWithAnnotation();
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/struts/blob/c84b7967/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotationI.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotationI.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotationI.java
new file mode 100644
index 0000000..ea866b9
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotationI.java
@@ -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 {
+}
[3/3] struts git commit: WW-4694 WW-4472 Imroves annotation processing
Posted by lu...@apache.org.
WW-4694 WW-4472 Imroves annotation processing
Project: http://git-wip-us.apache.org/repos/asf/struts/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/534dfc6b
Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/534dfc6b
Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/534dfc6b
Branch: refs/heads/master
Commit: 534dfc6bd8840bc2aa64022570b2225977ece5f6
Parents: 4b96958 301844b
Author: Lukasz Lenart <lu...@apache.org>
Authored: Mon Feb 13 11:55:11 2017 +0100
Committer: Lukasz Lenart <lu...@apache.org>
Committed: Mon Feb 13 11:55:11 2017 +0100
----------------------------------------------------------------------
.../interceptor/DefaultWorkflowInterceptor.java | 2 +-
.../xwork2/util/AnnotationUtils.java | 111 ++++++++++++++++---
.../xwork2/util/AnnotationUtilsTest.java | 35 ++++--
.../xwork2/util/annotation/DummyClass.java | 5 +-
.../xwork2/util/annotation/DummyClassExt.java | 5 +-
.../xwork2/util/annotation/DummyInterface.java | 7 ++
.../xwork2/util/annotation/MyAnnotationI.java | 8 ++
7 files changed, 146 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
[2/3] struts git commit: [WW-4472] using improved AnnotationUtils to
navigate around proxies
Posted by lu...@apache.org.
[WW-4472] using improved AnnotationUtils to navigate around proxies
Project: http://git-wip-us.apache.org/repos/asf/struts/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/301844bb
Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/301844bb
Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/301844bb
Branch: refs/heads/master
Commit: 301844bbaadf52b6c07914ca7a4b327af7856538
Parents: c84b796
Author: Yasser Zamani <ya...@live.com>
Authored: Wed Feb 8 00:07:13 2017 +0330
Committer: Yasser Zamani <ya...@live.com>
Committed: Wed Feb 8 00:07:13 2017 +0330
----------------------------------------------------------------------
.../xwork2/interceptor/DefaultWorkflowInterceptor.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/struts/blob/301844bb/core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java
index 271fa6d..a9f2565 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java
@@ -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());