From issues-return-31719-archive-asf-public=cust-asf.ponee.io@struts.apache.org Tue Jan 30 10:48:08 2018 Return-Path: X-Original-To: archive-asf-public@eu.ponee.io Delivered-To: archive-asf-public@eu.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by mx-eu-01.ponee.io (Postfix) with ESMTP id 02E6918061A for ; Tue, 30 Jan 2018 10:48:08 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id E6BA4160C55; Tue, 30 Jan 2018 09:48:07 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id BA3E0160C53 for ; Tue, 30 Jan 2018 10:48:06 +0100 (CET) Received: (qmail 6092 invoked by uid 500); 30 Jan 2018 09:48:05 -0000 Mailing-List: contact issues-help@struts.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@struts.apache.org Delivered-To: mailing list issues@struts.apache.org Received: (qmail 6082 invoked by uid 99); 30 Jan 2018 09:48:05 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd4-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 30 Jan 2018 09:48:05 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd4-us-west.apache.org (ASF Mail Server at spamd4-us-west.apache.org) with ESMTP id 5923BC03A7 for ; Tue, 30 Jan 2018 09:48:05 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd4-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -109.511 X-Spam-Level: X-Spam-Status: No, score=-109.511 tagged_above=-999 required=6.31 tests=[ENV_AND_HDR_SPF_MATCH=-0.5, KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_MED=-2.3, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01, USER_IN_DEF_SPF_WL=-7.5, USER_IN_WHITELIST=-100] autolearn=disabled Received: from mx1-lw-us.apache.org ([10.40.0.8]) by localhost (spamd4-us-west.apache.org [10.40.0.11]) (amavisd-new, port 10024) with ESMTP id 9awYgWkgFcvb for ; Tue, 30 Jan 2018 09:48:01 +0000 (UTC) Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139]) by mx1-lw-us.apache.org (ASF Mail Server at mx1-lw-us.apache.org) with ESMTP id 96D305F30C for ; Tue, 30 Jan 2018 09:48:01 +0000 (UTC) Received: from jira-lw-us.apache.org (unknown [207.244.88.139]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id 0F43DE01AA for ; Tue, 30 Jan 2018 09:48:01 +0000 (UTC) Received: from jira-lw-us.apache.org (localhost [127.0.0.1]) by jira-lw-us.apache.org (ASF Mail Server at jira-lw-us.apache.org) with ESMTP id B7F0A240F2 for ; Tue, 30 Jan 2018 09:48:00 +0000 (UTC) Date: Tue, 30 Jan 2018 09:48:00 +0000 (UTC) From: "ASF GitHub Bot (JIRA)" To: issues@struts.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Commented] (WW-4912) Allowed methods inheritance MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 [ https://issues.apache.org/jira/browse/WW-4912?page=3Dcom.atlassian.ji= ra.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=3D1634476= 0#comment-16344760 ]=20 ASF GitHub Bot commented on WW-4912: ------------------------------------ yasserzamani closed pull request #206: WW-4912: scan package-info and class= at the same time URL: https://github.com/apache/struts/pull/206 =20 =20 =20 This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtil= s.java b/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.ja= va index 42c113f34..cbebc8003 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java @@ -18,9 +18,12 @@ */ package com.opensymphony.xwork2.util; =20 +import org.apache.commons.lang3.ClassUtils; + 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 +132,7 @@ public static String resolvePropertyName(Method method)= { } =20 /** - * Returns the annotation on the given class or the package of the cla= ss. This searchs up the + * Returns the annotation on the given class or the package of the cla= ss. This searches up the * class hierarchy and the package hierarchy for the closest match. * * @param class type @@ -154,4 +157,36 @@ public static String resolvePropertyName(Method method= ) { =20 return ann; } + + /** + * 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 List of the annotations or an empty list. + */ + public static List findAnnotations(Class = clazz, Class annotationClass) { + List anns =3D new ArrayList<>(); + + List> classes =3D new ArrayList<>(); + classes.add(clazz); + + classes.addAll(ClassUtils.getAllSuperclasses(clazz)); + classes.addAll(ClassUtils.getAllInterfaces(clazz)); + for (Class aClass : classes) { + T ann =3D aClass.getAnnotation(annotationClass); + if (ann !=3D null) { + anns.add(ann); + } + + ann =3D aClass.getPackage().getAnnotation(annotationClass); + if (ann !=3D null) { + anns.add(ann); + } + } + + return anns; + } } diff --git a/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtil= sTest.java b/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtil= sTest.java index c1d7ecafa..16fbab4fe 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.j= ava +++ b/core/src/test/java/com/opensymphony/xwork2/util/AnnotationUtilsTest.j= ava @@ -19,14 +19,19 @@ package com.opensymphony.xwork2.util; =20 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; =20 -/** - * @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 { =20 public void testFindAnnotationOnClass() { @@ -41,4 +46,25 @@ public void testFindAnnotationOnPackage() { assertEquals("package-test", ns.value()); } =20 + public void testFindAnnotationOnParents() { + MyAnnotation2 ns =3D AnnotationUtils.findAnnotation(Dummy3Class.cl= ass, MyAnnotation2.class); + assertNotNull(ns); + assertEquals("abstract-abstract", ns.value()); + } + + public void testFindAnnotationsOnAll() { + List annotations =3D AnnotationUtils.findAnnotations= (DummyClassExt.class, MyAnnotation.class); + + assertThat(annotations) + .isNotNull() + .isNotEmpty() + .hasSize(5); + + Set values =3D new HashSet<>(); + for (MyAnnotation annotation : annotations) { + values.add(annotation.value()); + } + assertThat(values).contains("class-test", "package-test", "interfa= ce-test", "package2-test"); + } + } diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/Dum= my3Class.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/Dummy3Clas= s.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/Dum= myClass.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/D= ummyClass.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; =20 +import com.opensymphony.xwork2.util.annotation.pkg2.Package2DummyInterface= ; + @MyAnnotation("class-test") -public class DummyClass { +public class DummyClass implements Package2DummyInterface { =20 public DummyClass() { } diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyA= nnotation2.java b/core/src/test/java/com/opensymphony/xwork2/util/annotatio= n/MyAnnotation2.java index baeef0da8..c3700551b 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotati= on2.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotati= on2.java @@ -23,4 +23,6 @@ =20 @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation2 { + + String value() default ""; } diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg= 1/AbstractAbstractDummyAction.java b/core/src/test/java/com/opensymphony/xw= ork2/util/annotation/pkg1/AbstractAbstractDummyAction.java new file mode 100644 index 000000000..8221b98f8 --- /dev/null +++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/Abstr= actAbstractDummyAction.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.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/pkg= 1/AbstractDummyAction.java b/core/src/test/java/com/opensymphony/xwork2/uti= l/annotation/pkg1/AbstractDummyAction.java new file mode 100644 index 000000000..88f20a293 --- /dev/null +++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg1/Abstr= actDummyAction.java @@ -0,0 +1,22 @@ +/* + * 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/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg= 2/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/Packa= ge2DummyInterface.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/pkg= 2/package-info.java b/core/src/test/java/com/opensymphony/xwork2/util/annot= ation/pkg2/package-info.java new file mode 100644 index 000000000..2eee0a823 --- /dev/null +++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/pkg2/packa= ge-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 diff --git a/plugins/convention/src/main/java/org/apache/struts2/convention= /PackageBasedActionConfigBuilder.java b/plugins/convention/src/main/java/or= g/apache/struts2/convention/PackageBasedActionConfigBuilder.java index a4e7eceb8..bc586d4ac 100644 --- a/plugins/convention/src/main/java/org/apache/struts2/convention/Packag= eBasedActionConfigBuilder.java +++ b/plugins/convention/src/main/java/org/apache/struts2/convention/Packag= eBasedActionConfigBuilder.java @@ -749,13 +749,13 @@ protected void buildConfiguration(Set classes)= { } =20 private Set getAllowedMethods(Class actionClass) { - AllowedMethods annotation =3D AnnotationUtils.findAnnotation(actio= nClass, AllowedMethods.class); - if (annotation =3D=3D null) { + List annotations =3D AnnotationUtils.findAnnotatio= ns(actionClass, AllowedMethods.class); + if (annotations =3D=3D null || annotations.isEmpty()) { return Collections.emptySet(); } else { Set methods =3D 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 @@ protected void createActionConfig(PackageConfig.Builder= pkgCfg, Class actionC String actionMethod, Action annotati= on, Set allowedMethods) { =09String className =3D actionClass.getName(); if (annotation !=3D null) { - actionName =3D annotation.value() !=3D null && annotation.valu= e().equals(Action.DEFAULT_VALUE) ? actionName : annotation.value(); + actionName =3D annotation.value().equals(Action.DEFAULT_VALUE)= ? actionName : annotation.value(); actionName =3D StringUtils.contains(actionName, "/") && !slash= esInActionNames ? StringUtils.substringAfterLast(actionName, "/") : actionN= ame; if(!Action.DEFAULT_VALUE.equals(annotation.className())){ =09className =3D annotation.className(); @@ -960,7 +960,7 @@ protected void createActionConfig(PackageConfig.Builder= pkgCfg, Class actionC actionConfig.addParams(StringTools.createParameterMap(annotati= on.params())); =20 //add exception mappings from annotation - if (annotation !=3D null && annotation.exceptionMappings() !=3D nu= ll) + if (annotation !=3D null) actionConfig.addExceptionMappings(buildExceptionMappings(annot= ation.exceptionMappings(), actionName)); =20 //add exception mapping from class @@ -997,8 +997,7 @@ protected void createActionConfig(PackageConfig.Builder= pkgCfg, Class actionC exceptionMapping.result(), actionName); ExceptionMappingConfig.Builder builder =3D new ExceptionMappin= gConfig.Builder(null, exceptionMapping .exception(), exceptionMapping.result()); - if (exceptionMapping.params() !=3D null) - builder.addParams(StringTools.createParameterMap(exception= Mapping.params())); + builder.addParams(StringTools.createParameterMap(exceptionMapp= ing.params())); exceptionMappings.add(builder.build()); } =20 diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention= /PackageBasedActionConfigBuilderTest.java b/plugins/convention/src/test/jav= a/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java index 6c97dec38..d9e60f63b 100644 --- a/plugins/convention/src/test/java/org/apache/struts2/convention/Packag= eBasedActionConfigBuilderTest.java +++ b/plugins/convention/src/test/java/org/apache/struts2/convention/Packag= eBasedActionConfigBuilderTest.java @@ -544,10 +544,14 @@ public Container getContainer() { assertEquals("struts-default", pkgConfig.getParents().get(0).getNa= me()); =20 ActionConfig actionConfig =3D pkgConfig.getActionConfigs().get("cl= ass-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")); =20 /* org.apache.struts2.convention.actions.allowedmethods.sub packag= e level */ pkgConfig =3D configuration.getPackageConfig("org.apache.struts2.c= onvention.actions.allowedmethods.sub#struts-default#/allowedmethods/sub"); =20 ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. =20 For queries about this service, please contact Infrastructure at: users@infra.apache.org > Allowed methods inheritance > --------------------------- > > Key: WW-4912 > URL: https://issues.apache.org/jira/browse/WW-4912 > Project: Struts 2 > Issue Type: Improvement > Affects Versions: 2.5.14.1 > Reporter: Britta Katzenbach > Assignee: Lukasz Lenart > Priority: Minor > Fix For: 2.5.15 > > > As we use a lot of inheritance on action classes we would appreciate, if = the allowed methods would be inherited as well. > For example: > We do not declare actions in struts.xml and just use the Convention. > struts.xml: > {code:xml} > > =C2=A0=C2=A0 =C2=A0... > =C2=A0=C2=A0 =C2=A0 abort,execute,search,reset,do= wnload,refresh,delegate,forward,release,saveComments > > {code} > Java: > {code:java} > @AllowedMethods(value =3D \{"changeLanguage", "deleteAttachment", "upload= MailAttachment"}) > public class SpecifyMailTask extends AbstractTask { > @AllowedMethods(value =3D \{"saveInputAndSuccess"}) > public abstract class AbstractTask extends AbstractBasicJbpmTask implemen= ts ModelDriven, Preparable \{...} > @AllowedMethods(value =3D { "abort", "cancel", "claim", "claimAndStart", = "claimAndSkip", "complete", "delegate", "forward", > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 "incomplete", "release", "skip= AndComplete", "start", "suspend", "uploadTaskAttachment"}) > public abstract class AbstractBasicJbpmTask extends AbstractCrmAction imp= lements ModelDriven, Preparable \{...} > {code} > I tried to add the allowed methods in the package-info.java. It worked as= long as I did not add an additional method to a certain action, i.e. Speci= fyMailTask. If I add here the annotation to allow the methods "changeLangua= ge", "deleteAttachment", "uploadMailAttachment" additionally, the other met= hods, which are allowed via the package-info.java, are not allowed anymore. > =C2=A0 -- This message was sent by Atlassian JIRA (v7.6.3#76005)