From d5926b7a2196fab0735acac094b6438bb7cf4a94 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Thu, 25 Jan 2018 12:27:54 +0100 Subject: [PATCH 1/7] Searches hierarchy down to Object class for annotation --- .../com/opensymphony/xwork2/util/AnnotationUtils.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) 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 42c113f34..c37103526 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java @@ -139,16 +139,13 @@ public class AnnotationUtils { */ public static T findAnnotation(Class clazz, Class annotationClass) { T ann = clazz.getAnnotation(annotationClass); - while (ann == null && clazz != null) { + if (ann == null && clazz != Object.class) { ann = clazz.getAnnotation(annotationClass); if (ann == null) { ann = clazz.getPackage().getAnnotation(annotationClass); } - if (ann == null) { - clazz = clazz.getSuperclass(); - if (clazz != null) { - ann = clazz.getAnnotation(annotationClass); - } + if (ann == null && clazz != Object.class) { + ann = findAnnotation(clazz.getSuperclass(), annotationClass); } } From a3180e3069b225ec857d39d66c3629cd757345ce Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Thu, 25 Jan 2018 12:28:09 +0100 Subject: [PATCH 2/7] Adds test to cover searching down the hierarchy --- .../xwork2/util/AnnotationUtilsTest.java | 8 ++++++ .../xwork2/util/annotation/Dummy3Class.java | 25 +++++++++++++++++++ .../xwork2/util/annotation/MyAnnotation2.java | 2 ++ .../pkg1/AbstractAbstractDummyAction.java | 7 ++++++ .../annotation/pkg1/AbstractDummyAction.java | 4 +++ 5 files changed, 46 insertions(+) create mode 100644 core/src/test/java/com/opensymphony/xwork2/util/annotation/Dummy3Class.java create mode 100644 core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractAbstractDummyAction.java create mode 100644 core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractDummyAction.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 c1d7ecafa..94323831a 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java @@ -19,9 +19,11 @@ package com.opensymphony.xwork2.util; import com.opensymphony.xwork2.util.annotation.Dummy2Class; +import com.opensymphony.xwork2.util.annotation.Dummy3Class; import com.opensymphony.xwork2.util.annotation.DummyClass; import com.opensymphony.xwork2.util.annotation.MyAnnotation; +import com.opensymphony.xwork2.util.annotation.MyAnnotation2; import junit.framework.TestCase; /** @@ -41,4 +43,10 @@ public class AnnotationUtilsTest extends TestCase { assertEquals("package-test", ns.value()); } + public void testFindAnnotationOnParents() { + MyAnnotation2 ns = AnnotationUtils.findAnnotation(Dummy3Class.class, MyAnnotation2.class); + assertNotNull(ns); + assertEquals("abstract-abstract", ns.value()); + } + } diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/Dummy3Class.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/Dummy3Class.java new file mode 100644 index 000000000..f25c852c7 --- /dev/null +++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/Dummy3Class.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.opensymphony.xwork2.util.annotation; + +import com.opensymphony.xwork2.util.annotation.pkg1.AbstractDummyAction; + +public class Dummy3Class extends AbstractDummyAction{ + +} diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotation2.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotation2.java index baeef0da8..c3700551b 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotation2.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotation2.java @@ -23,4 +23,6 @@ import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation2 { + + String value() default ""; } diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractAbstractDummyAction.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractAbstractDummyAction.java new file mode 100644 index 000000000..1ecc47cf5 --- /dev/null +++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractAbstractDummyAction.java @@ -0,0 +1,7 @@ +package com.opensymphony.xwork2.util.annotation.pkg1; + +import com.opensymphony.xwork2.util.annotation.MyAnnotation2; + +@MyAnnotation2("abstract-abstract") +public class AbstractAbstractDummyAction { +} diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractDummyAction.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractDummyAction.java new file mode 100644 index 000000000..54c1b5d99 --- /dev/null +++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractDummyAction.java @@ -0,0 +1,4 @@ +package com.opensymphony.xwork2.util.annotation.pkg1; + +public class AbstractDummyAction extends AbstractAbstractDummyAction { +} From a9899b662212b10a73ebc8b9e15a3e95785bf0fe Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Fri, 26 Jan 2018 11:47:10 +0100 Subject: [PATCH 3/7] Introduces new method find all annotations --- .../xwork2/util/AnnotationUtils.java | 32 ++++++++++++++++++- .../xwork2/util/AnnotationUtilsTest.java | 25 ++++++++++++--- .../pkg1/AbstractAbstractDummyAction.java | 18 +++++++++++ .../annotation/pkg1/AbstractDummyAction.java | 18 +++++++++++ .../PackageBasedActionConfigBuilder.java | 15 ++++----- .../PackageBasedActionConfigBuilderTest.java | 6 +++- 6 files changed, 100 insertions(+), 14 deletions(-) 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 c37103526..567c9fd79 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java @@ -21,6 +21,7 @@ package com.opensymphony.xwork2.util; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Matcher; @@ -129,7 +130,7 @@ public class AnnotationUtils { } /** - * Returns the annotation on the given class or the package of the class. This searchs up the + * Returns the annotation on the given class or the package of the class. This searches up the * class hierarchy and the package hierarchy for the closest match. * * @param class type @@ -151,4 +152,33 @@ public class AnnotationUtils { return ann; } + + /** + * Returns the annotation on the given class or the package of the class. This searches up the + * class hierarchy and the package hierarchy for the closest match. + * + * @param class type + * @param clazz The class to search for the annotation. + * @param annotationClass The Class of the annotation. + * @return The annotation or null. + */ + public static List findAnnotations(Class clazz, Class annotationClass) { + List anns = new ArrayList<>(); + + T ann = clazz.getAnnotation(annotationClass); + if (ann != null) { + anns.add(ann); + } + + ann = clazz.getPackage().getAnnotation(annotationClass); + if (ann != null) { + anns.add(ann); + } + + if (clazz.getSuperclass() != Object.class) { + anns.addAll(findAnnotations(clazz.getSuperclass(), annotationClass)); + } + + return anns; + } } 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 94323831a..67f190126 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java @@ -22,13 +22,15 @@ import com.opensymphony.xwork2.util.annotation.Dummy2Class; import com.opensymphony.xwork2.util.annotation.Dummy3Class; import com.opensymphony.xwork2.util.annotation.DummyClass; import com.opensymphony.xwork2.util.annotation.MyAnnotation; - import com.opensymphony.xwork2.util.annotation.MyAnnotation2; import junit.framework.TestCase; -/** - * @author Dan Oxlade, dan d0t oxlade at gmail d0t c0m - */ +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.fest.assertions.Assertions.assertThat; + public class AnnotationUtilsTest extends TestCase { public void testFindAnnotationOnClass() { @@ -49,4 +51,19 @@ public class AnnotationUtilsTest extends TestCase { assertEquals("abstract-abstract", ns.value()); } + public void testFindAnnotationsOnAll() { + List annotations = AnnotationUtils.findAnnotations(DummyClass.class, MyAnnotation.class); + + assertThat(annotations) + .isNotNull() + .isNotEmpty() + .hasSize(2); + + Set values = new HashSet<>(); + for (MyAnnotation annotation : annotations) { + values.add(annotation.value()); + } + assertThat(values).contains("class-test", "package-test"); + } + } diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractAbstractDummyAction.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractAbstractDummyAction.java index 1ecc47cf5..8221b98f8 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractAbstractDummyAction.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractAbstractDummyAction.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ package com.opensymphony.xwork2.util.annotation.pkg1; import com.opensymphony.xwork2.util.annotation.MyAnnotation2; diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractDummyAction.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractDummyAction.java index 54c1b5d99..88f20a293 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractDummyAction.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/AbstractDummyAction.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ package com.opensymphony.xwork2.util.annotation.pkg1; public class AbstractDummyAction extends AbstractAbstractDummyAction { diff --git a/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java b/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java index a4e7eceb8..bc586d4ac 100644 --- a/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java +++ b/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java @@ -749,13 +749,13 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder { } private Set getAllowedMethods(Class actionClass) { - AllowedMethods annotation = AnnotationUtils.findAnnotation(actionClass, AllowedMethods.class); - if (annotation == null) { + List annotations = AnnotationUtils.findAnnotations(actionClass, AllowedMethods.class); + if (annotations == null || annotations.isEmpty()) { return Collections.emptySet(); } else { Set methods = new HashSet<>(); - for (String method : annotation.value()) { - methods.add(method); + for (AllowedMethods allowedMethods : annotations) { + methods.addAll(Arrays.asList(allowedMethods.value())); } return methods; } @@ -924,7 +924,7 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder { String actionMethod, Action annotation, Set allowedMethods) { String className = actionClass.getName(); if (annotation != null) { - actionName = annotation.value() != null && annotation.value().equals(Action.DEFAULT_VALUE) ? actionName : annotation.value(); + actionName = annotation.value().equals(Action.DEFAULT_VALUE) ? actionName : annotation.value(); actionName = StringUtils.contains(actionName, "/") && !slashesInActionNames ? StringUtils.substringAfterLast(actionName, "/") : actionName; if(!Action.DEFAULT_VALUE.equals(annotation.className())){ className = annotation.className(); @@ -960,7 +960,7 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder { actionConfig.addParams(StringTools.createParameterMap(annotation.params())); //add exception mappings from annotation - if (annotation != null && annotation.exceptionMappings() != null) + if (annotation != null) actionConfig.addExceptionMappings(buildExceptionMappings(annotation.exceptionMappings(), actionName)); //add exception mapping from class @@ -997,8 +997,7 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder { exceptionMapping.result(), actionName); ExceptionMappingConfig.Builder builder = new ExceptionMappingConfig.Builder(null, exceptionMapping .exception(), exceptionMapping.result()); - if (exceptionMapping.params() != null) - builder.addParams(StringTools.createParameterMap(exceptionMapping.params())); + builder.addParams(StringTools.createParameterMap(exceptionMapping.params())); exceptionMappings.add(builder.build()); } diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java b/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java index 6c97dec38..d9e60f63b 100644 --- a/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java +++ b/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java @@ -544,10 +544,14 @@ public class PackageBasedActionConfigBuilderTest extends TestCase { assertEquals("struts-default", pkgConfig.getParents().get(0).getName()); ActionConfig actionConfig = pkgConfig.getActionConfigs().get("class-level-allowed-methods"); - assertEquals(actionConfig.getAllowedMethods().size(), 5); + assertEquals(7, actionConfig.getAllowedMethods().size()); assertTrue(actionConfig.getAllowedMethods().contains("execute")); assertTrue(actionConfig.getAllowedMethods().contains("end")); assertTrue(actionConfig.getAllowedMethods().contains("input")); + assertTrue(actionConfig.getAllowedMethods().contains("cancel")); + assertTrue(actionConfig.getAllowedMethods().contains("start")); + assertTrue(actionConfig.getAllowedMethods().contains("home")); + assertTrue(actionConfig.getAllowedMethods().contains("browse")); /* org.apache.struts2.convention.actions.allowedmethods.sub package level */ pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.allowedmethods.sub#struts-default#/allowedmethods/sub"); From 46462b3d00f5fb5843ca9a748ea214934ffcd4b5 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 29 Jan 2018 08:51:17 +0100 Subject: [PATCH 4/7] Rephrases JavaDoc to better express function's meaning --- .../java/com/opensymphony/xwork2/util/AnnotationUtils.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 567c9fd79..1273b5036 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java @@ -154,13 +154,13 @@ public class AnnotationUtils { } /** - * Returns the annotation on the given class or the package of the class. This searches up the - * class hierarchy and the package hierarchy for the closest match. + * Returns a list of the annotation on the given class or the package of the class. + * This searches up the class hierarchy and the package hierarchy. * * @param class type * @param clazz The class to search for the annotation. * @param annotationClass The Class of the annotation. - * @return The annotation or null. + * @return List of the annotations or an empty list. */ public static List findAnnotations(Class clazz, Class annotationClass) { List anns = new ArrayList<>(); From 72058bf4c6dc7491aee48a519c0e0eb5961b10a5 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 29 Jan 2018 09:04:03 +0100 Subject: [PATCH 5/7] Reverts findAnnotation to its previous state --- .../com/opensymphony/xwork2/util/AnnotationUtils.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 1273b5036..c08841c63 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java @@ -140,13 +140,16 @@ public class AnnotationUtils { */ public static T findAnnotation(Class clazz, Class annotationClass) { T ann = clazz.getAnnotation(annotationClass); - if (ann == null && clazz != Object.class) { + while (ann == null && clazz != null) { ann = clazz.getAnnotation(annotationClass); if (ann == null) { ann = clazz.getPackage().getAnnotation(annotationClass); } - if (ann == null && clazz != Object.class) { - ann = findAnnotation(clazz.getSuperclass(), annotationClass); + if (ann == null) { + clazz = clazz.getSuperclass(); + if (clazz != null) { + ann = clazz.getAnnotation(annotationClass); + } } } From cf71e0f34f4a0d7da55d280592ac61e8a2d3482c Mon Sep 17 00:00:00 2001 From: Yasser Zamani Date: Tue, 30 Jan 2018 11:35:16 +0330 Subject: [PATCH 6/7] add support finding annotations on interfaces and their packages See also WW-4912 --- .../xwork2/util/AnnotationUtils.java | 25 +++++++++++-------- .../xwork2/util/AnnotationUtilsTest.java | 7 +++--- .../xwork2/util/annotation/DummyClass.java | 4 ++- .../pkg2/Package2DummyInterface.java | 25 +++++++++++++++++++ .../util/annotation/pkg2/package-info.java | 23 +++++++++++++++++ 5 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg2/Package2DummyInterface.java create mode 100644 core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg2/package-info.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 c08841c63..dd148550e 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java @@ -18,6 +18,8 @@ */ package com.opensymphony.xwork2.util; +import org.apache.commons.lang3.ClassUtils; + import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -168,18 +170,21 @@ public class AnnotationUtils { public static List findAnnotations(Class clazz, Class annotationClass) { List anns = new ArrayList<>(); - T ann = clazz.getAnnotation(annotationClass); - if (ann != null) { - anns.add(ann); - } + List> classes = new ArrayList<>(); + classes.add(clazz); - ann = clazz.getPackage().getAnnotation(annotationClass); - if (ann != null) { - anns.add(ann); - } + classes.addAll(ClassUtils.getAllSuperclasses(clazz)); + classes.addAll(ClassUtils.getAllInterfaces(clazz)); + for (Class aClass : classes) { + T ann = aClass.getAnnotation(annotationClass); + if (ann != null && !anns.contains(ann)) { + anns.add(ann); + } - if (clazz.getSuperclass() != Object.class) { - anns.addAll(findAnnotations(clazz.getSuperclass(), annotationClass)); + ann = aClass.getPackage().getAnnotation(annotationClass); + if (ann != null && !anns.contains(ann)) { + anns.add(ann); + } } return anns; 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 67f190126..12ce2936c 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java @@ -21,6 +21,7 @@ package com.opensymphony.xwork2.util; import com.opensymphony.xwork2.util.annotation.Dummy2Class; import com.opensymphony.xwork2.util.annotation.Dummy3Class; 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 junit.framework.TestCase; @@ -52,18 +53,18 @@ public class AnnotationUtilsTest extends TestCase { } public void testFindAnnotationsOnAll() { - List annotations = AnnotationUtils.findAnnotations(DummyClass.class, MyAnnotation.class); + List annotations = AnnotationUtils.findAnnotations(DummyClassExt.class, MyAnnotation.class); assertThat(annotations) .isNotNull() .isNotEmpty() - .hasSize(2); + .hasSize(4); Set values = new HashSet<>(); for (MyAnnotation annotation : annotations) { values.add(annotation.value()); } - assertThat(values).contains("class-test", "package-test"); + assertThat(values).contains("class-test", "package-test", "interface-test", "package2-test"); } } 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 707b73592..bb65b5c6e 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 @@ -18,8 +18,10 @@ */ package com.opensymphony.xwork2.util.annotation; +import com.opensymphony.xwork2.util.annotation.pkg2.Package2DummyInterface; + @MyAnnotation("class-test") -public class DummyClass { +public class DummyClass implements Package2DummyInterface { public DummyClass() { } diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg2/Package2DummyInterface.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg2/Package2DummyInterface.java new file mode 100644 index 000000000..ea1aa1279 --- /dev/null +++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg2/Package2DummyInterface.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.opensymphony.xwork2.util.annotation.pkg2; + +import com.opensymphony.xwork2.util.annotation.MyAnnotation; + +@MyAnnotation("interface-test") +public interface Package2DummyInterface { +} diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg2/package-info.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg2/package-info.java new file mode 100644 index 000000000..2eee0a823 --- /dev/null +++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg2/package-info.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +@MyAnnotation("package2-test") +package com.opensymphony.xwork2.util.annotation.pkg2; + +import com.opensymphony.xwork2.util.annotation.MyAnnotation; \ No newline at end of file From 8d4194bbf7364625a5b4f407ef48208c4ba524fd Mon Sep 17 00:00:00 2001 From: Yasser Zamani Date: Tue, 30 Jan 2018 12:21:33 +0330 Subject: [PATCH 7/7] allow duplicate in AnnotationUtils.findAnnotations result See also WW-4912 --- .../java/com/opensymphony/xwork2/util/AnnotationUtils.java | 4 ++-- .../com/opensymphony/xwork2/util/AnnotationUtilsTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 dd148550e..cbebc8003 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java @@ -177,12 +177,12 @@ public class AnnotationUtils { classes.addAll(ClassUtils.getAllInterfaces(clazz)); for (Class aClass : classes) { T ann = aClass.getAnnotation(annotationClass); - if (ann != null && !anns.contains(ann)) { + if (ann != null) { anns.add(ann); } ann = aClass.getPackage().getAnnotation(annotationClass); - if (ann != null && !anns.contains(ann)) { + if (ann != null) { anns.add(ann); } } 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 12ce2936c..16fbab4fe 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.java @@ -58,7 +58,7 @@ public class AnnotationUtilsTest extends TestCase { assertThat(annotations) .isNotNull() .isNotEmpty() - .hasSize(4); + .hasSize(5); Set values = new HashSet<>(); for (MyAnnotation annotation : annotations) {