struts-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lukaszlen...@apache.org
Subject [16/33] struts git commit: Adds annotation to support AllowedMethods
Date Mon, 28 Sep 2015 18:53:05 GMT
Adds annotation to support AllowedMethods


Project: http://git-wip-us.apache.org/repos/asf/struts/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/ab5fb27d
Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/ab5fb27d
Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/ab5fb27d

Branch: refs/heads/master
Commit: ab5fb27d368f8857e137bc3a319c21fc85b519ee
Parents: dd406fb
Author: Lukasz Lenart <lukasz.lenart@gmail.com>
Authored: Thu Sep 3 13:03:55 2015 +0200
Committer: Lukasz Lenart <lukasz.lenart@gmail.com>
Committed: Thu Sep 3 13:03:55 2015 +0200

----------------------------------------------------------------------
 .../xwork2/config/entities/PackageConfig.java   | 13 ++++-
 .../PackageBasedActionConfigBuilder.java        | 30 ++++++++--
 .../convention/annotation/AllowedMethods.java   | 30 ++++++++++
 .../PackageBasedActionConfigBuilderTest.java    | 60 ++++++++++++++++++--
 .../ClassLevelAllowedMethodsAction.java         | 10 ++++
 .../PackageLevelAllowedMethodsAction.java       |  7 +++
 .../actions/allowedmethods/package-info.java    | 23 ++++++++
 .../PackageLevelAllowedMethodsChildAction.java  |  9 +++
 8 files changed, 171 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/struts/blob/ab5fb27d/core/src/main/java/com/opensymphony/xwork2/config/entities/PackageConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/PackageConfig.java
b/core/src/main/java/com/opensymphony/xwork2/config/entities/PackageConfig.java
index 19ce36f..093985c 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/entities/PackageConfig.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/entities/PackageConfig.java
@@ -531,7 +531,18 @@ public class PackageConfig extends Located implements Comparable, Serializable,
         }
 
         public Set<String> getGlobalAllowedMethods() {
-            return target.globalAllowedMethods;
+            Set <String> allowedMethods = target.globalAllowedMethods;
+            allowedMethods.addAll(getParentsAllowedMethods(target.parents));
+            return allowedMethods;
+        }
+
+        public Set<String> getParentsAllowedMethods(List<PackageConfig> parents)
{
+            Set<String> allowedMethods = new HashSet<>();
+            for (PackageConfig parent : parents) {
+                allowedMethods.addAll(parent.globalAllowedMethods);
+                allowedMethods.addAll(getParentsAllowedMethods(parent.getParents()));
+            }
+            return allowedMethods;
         }
 
         public Builder addGlobalAllowedMethods(Set<String> allowedMethods) {

http://git-wip-us.apache.org/repos/asf/struts/blob/ab5fb27d/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java
----------------------------------------------------------------------
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 b4a8be9..64a0e98 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
@@ -42,6 +42,7 @@ import org.apache.logging.log4j.Logger;
 import org.apache.struts2.StrutsConstants;
 import org.apache.struts2.StrutsException;
 import org.apache.struts2.convention.annotation.*;
+import org.apache.struts2.convention.annotation.AllowedMethods;
 
 import java.io.IOException;
 import java.lang.reflect.Method;
@@ -652,6 +653,8 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder
{
             String actionPackage = actionClass.getPackage().getName();
             LOG.debug("Processing class [{}] in package [{}]", actionClass.getName(), actionPackage);
 
+            Set<String> allowedMethods = getAllowedMethods(actionClass);
+
             // Determine the default namespace and action name
             List<String> namespaces = determineActionNamespace(actionClass);
             for (String namespace : namespaces) {
@@ -692,7 +695,7 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder
{
 
                     // Build the default
                     if (!found) {
-                        createActionConfig(defaultPackageConfig, actionClass, defaultActionName,
DEFAULT_METHOD, null);
+                        createActionConfig(defaultPackageConfig, actionClass, defaultActionName,
DEFAULT_METHOD, null, allowedMethods);
                     }
                 }
 
@@ -706,14 +709,14 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder
{
                                     actionClass, action);
                         }
 
-                        createActionConfig(pkgCfg, actionClass, defaultActionName, method,
action);
+                        createActionConfig(pkgCfg, actionClass, defaultActionName, method,
action, allowedMethods);
                     }
                 }
 
                 // some actions will not have any @Action or a default method, like the rest
actions
                 // where the action mapper is the one that finds the right method at runtime
                 if (map.isEmpty() && mapAllMatches && actionAnnotation ==
null && actionsAnnotation == null) {
-                    createActionConfig(defaultPackageConfig, actionClass, defaultActionName,
null, actionAnnotation);
+                    createActionConfig(defaultPackageConfig, actionClass, defaultActionName,
null, actionAnnotation, allowedMethods);
                 }
 
                 //if there are @Actions or @Action at the class level, create the mappings
for them
@@ -721,9 +724,9 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder
{
                 if (actionsAnnotation != null) {
                     List<Action> actionAnnotations = checkActionsAnnotation(actionsAnnotation);
                     for (Action actionAnnotation2 : actionAnnotations)
-                        createActionConfig(defaultPackageConfig, actionClass, defaultActionName,
methodName, actionAnnotation2);
+                        createActionConfig(defaultPackageConfig, actionClass, defaultActionName,
methodName, actionAnnotation2, allowedMethods);
                 } else if (actionAnnotation != null)
-                    createActionConfig(defaultPackageConfig, actionClass, defaultActionName,
methodName, actionAnnotation);
+                    createActionConfig(defaultPackageConfig, actionClass, defaultActionName,
methodName, actionAnnotation, allowedMethods);
             }
         }
 
@@ -736,6 +739,15 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder
{
         }
     }
 
+    private Set<String> getAllowedMethods(Class<?> actionClass) {
+        AllowedMethods annotation = AnnotationUtils.findAnnotation(actionClass, AllowedMethods.class);
+        if (annotation == null) {
+            return Collections.emptySet();
+        } else {
+            return TextParseUtil.commaDelimitedStringToSet(annotation.value());
+        }
+    }
+
     /**
      * Interfaces, enums, annotations, and abstract classes cannot be instantiated.
      * @param actionClass class to check
@@ -896,7 +908,7 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder
{
      * @param annotation   The ActionName annotation that might override the action name
and possibly
      */
     protected void createActionConfig(PackageConfig.Builder pkgCfg, Class<?> actionClass,
String actionName,
-                                      String actionMethod, Action annotation) {
+                                      String actionMethod, Action annotation, Set<String>
allowedMethods) {
     	String className = actionClass.getName();
         if (annotation != null) {
             actionName = annotation.value() != null && annotation.value().equals(Action.DEFAULT_VALUE)
? actionName : annotation.value();
@@ -909,6 +921,12 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder
{
         ActionConfig.Builder actionConfig = new ActionConfig.Builder(pkgCfg.getName(), actionName,
className);
         actionConfig.methodName(actionMethod);
 
+        if (!allowedMethods.contains(actionMethod)) {
+            actionConfig.addAllowedMethod(actionMethod);
+        }
+        actionConfig.addAllowedMethod(allowedMethods);
+        actionConfig.addAllowedMethod(pkgCfg.getGlobalAllowedMethods());
+
         if (LOG.isDebugEnabled()) {
             LOG.debug("Creating action config for class [{}], name [{}] and package name
[{}] in namespace [{}]",
                     actionClass.toString(), actionName, pkgCfg.getName(), pkgCfg.getNamespace());

http://git-wip-us.apache.org/repos/asf/struts/blob/ab5fb27d/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/AllowedMethods.java
----------------------------------------------------------------------
diff --git a/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/AllowedMethods.java
b/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/AllowedMethods.java
new file mode 100644
index 0000000..8e3c9ab
--- /dev/null
+++ b/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/AllowedMethods.java
@@ -0,0 +1,30 @@
+package org.apache.struts2.convention.annotation;
+
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <!-- START SNIPPET: javadoc -->
+ * <p>
+ * This annotation allows actions to specify allowed action methods
+ * to limit access to any other public action's methods
+ * </p>
+ *
+ * <p>
+ * This annotation can be used directly on Action classes or
+ * in the <strong>package-info.java</strong> class in order
+ * to specify global allowed methods for all sub-packages.
+ * </p>
+ * <!-- END SNIPPET: javadoc -->
+ */
+@Target({ElementType.TYPE, ElementType.PACKAGE})
+@Retention(value = RetentionPolicy.RUNTIME)
+public @interface AllowedMethods {
+
+    String value() default ActionConfig.DEFAULT_METHOD;
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/ab5fb27d/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
----------------------------------------------------------------------
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 38403a0..61ed3eb 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
@@ -29,6 +29,7 @@ import com.opensymphony.xwork2.factory.DefaultResultFactory;
 import com.opensymphony.xwork2.inject.Container;
 import com.opensymphony.xwork2.inject.Scope.Strategy;
 import com.opensymphony.xwork2.ognl.OgnlReflectionProvider;
+import com.opensymphony.xwork2.util.TextParseUtil;
 import com.opensymphony.xwork2.util.fs.DefaultFileManager;
 import com.opensymphony.xwork2.util.fs.DefaultFileManagerFactory;
 import com.opensymphony.xwork2.util.reflection.ReflectionException;
@@ -37,6 +38,9 @@ import org.apache.struts2.convention.actions.DefaultResultPathAction;
 import org.apache.struts2.convention.actions.NoAnnotationAction;
 import org.apache.struts2.convention.actions.Skip;
 import org.apache.struts2.convention.actions.action.*;
+import org.apache.struts2.convention.actions.allowedmethods.ClassLevelAllowedMethodsAction;
+import org.apache.struts2.convention.actions.allowedmethods.PackageLevelAllowedMethodsAction;
+import org.apache.struts2.convention.actions.allowedmethods.sub.PackageLevelAllowedMethodsChildAction;
 import org.apache.struts2.convention.actions.chain.ChainedAction;
 import org.apache.struts2.convention.actions.defaultinterceptor.SingleActionNameAction2;
 import org.apache.struts2.convention.actions.exception.ExceptionsActionLevelAction;
@@ -125,8 +129,10 @@ public class PackageBasedActionConfigBuilderTest extends TestCase {
                 new ResultTypeConfig.Builder("chain",
                         ActionChainResult.class.getName()).defaultResultParam("actionName").build()};
 
+        Set<String> globalAllowedMethods = TextParseUtil.commaDelimitedStringToSet("execute,browse,cancel,input");
+
         PackageConfig strutsDefault = makePackageConfig("struts-default", null, null, "dispatcher",
-                defaultResults, defaultInterceptors, defaultInterceptorStacks);
+                defaultResults, defaultInterceptors, defaultInterceptorStacks, globalAllowedMethods);
 
         PackageConfig packageLevelParentPkg = makePackageConfig("package-level", null, null,
null);
         PackageConfig classLevelParentPkg = makePackageConfig("class-level", null, null,
null);
@@ -151,6 +157,16 @@ public class PackageBasedActionConfigBuilderTest extends TestCase {
             "/parentpackage", packageLevelParentPkg, null);
         PackageConfig packageLevelSubPkg = makePackageConfig("org.apache.struts2.convention.actions.parentpackage.sub#package-level#/parentpackage/sub",
             "/parentpackage/sub", packageLevelParentPkg, null);
+
+        // Unexpected method call build(class org.apache.struts2.convention.actions.allowedmethods.PackageLevelAllowedMethodsAction,
null, "package-level-allowed-methods", PackageConfig: [org.apache.struts2.convention.actions.allowedmethods#struts-default#/allowedmethods]
for namespace [/allowedmethods] with parents [[PackageConfig: [struts-default] for namespace
[] with parents [[]]]]):
+        PackageConfig packageLevelAllowedMethodsPkg = makePackageConfig("org.apache.struts2.convention.actions.allowedmethods#struts-default#/allowedmethods",
+                "/allowedmethods", strutsDefault, null);
+        PackageConfig packageLevelAllowedMethodsSubPkg = makePackageConfig("org.apache.struts2.convention.actions.allowedmethods.sub#struts-default#/allowedmethods/sub",
+                "/allowedmethods/sub", strutsDefault, null);
+
+        PackageConfig classLevelAllowedMethodsPkg = makePackageConfig("org.apache.struts2.convention.actions.allowedmethods#struts-default#/allowedmethods",
+                "/allowedmethods", strutsDefault, null);
+
         PackageConfig differentPkg = makePackageConfig("org.apache.struts2.convention.actions.parentpackage#class-level#/parentpackage",
             "/parentpackage", classLevelParentPkg, null);
         PackageConfig differentSubPkg = makePackageConfig("org.apache.struts2.convention.actions.parentpackage.sub#class-level#/parentpackage/sub",
@@ -261,6 +277,11 @@ public class PackageBasedActionConfigBuilderTest extends TestCase {
         expect(resultMapBuilder.build(ClassLevelParentPackageAction.class, null, "class-level-parent-package",
differentPkg)).andReturn(results);
         expect(resultMapBuilder.build(ClassLevelParentPackageChildAction.class, null, "class-level-parent-package-child",
differentSubPkg)).andReturn(results);
 
+        /* org.apache.struts2.convention.actions.allowedmethods */
+        expect(resultMapBuilder.build(ClassLevelAllowedMethodsAction.class, null, "class-level-allowed-methods",
classLevelAllowedMethodsPkg)).andReturn(results);
+        expect(resultMapBuilder.build(PackageLevelAllowedMethodsAction.class, null, "package-level-allowed-methods",
packageLevelAllowedMethodsPkg)).andReturn(results);
+        expect(resultMapBuilder.build(PackageLevelAllowedMethodsChildAction.class, null,
"package-level-allowed-methods-child", packageLevelAllowedMethodsSubPkg)).andReturn(results);
+
         /* org.apache.struts2.convention.actions.result */
         expect(resultMapBuilder.build(ClassLevelResultAction.class, null, "class-level-result",
resultPkg)).andReturn(results);
         expect(resultMapBuilder.build(ClassLevelResultsAction.class, null, "class-level-results",
resultPkg)).andReturn(results);
@@ -450,7 +471,7 @@ public class PackageBasedActionConfigBuilderTest extends TestCase {
         verifyActionConfig(pkgConfig, "", org.apache.struts2.convention.actions.idx.Index.class,
"execute", pkgConfig.getName());
         verifyActionConfig(pkgConfig, "index", org.apache.struts2.convention.actions.idx.Index.class,
"execute", pkgConfig.getName());
         verifyActionConfig(pkgConfig, "idx2", org.apache.struts2.convention.actions.idx.idx2.Index.class,
"execute",
-            "org.apache.struts2.convention.actions.idx.idx2#struts-default#/idx/idx2");
+                "org.apache.struts2.convention.actions.idx.idx2#struts-default#/idx/idx2");
 
         /* org.apache.struts2.convention.actions.defaultinterceptor */
         pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.defaultinterceptor#struts-default#/defaultinterceptor");
@@ -514,6 +535,33 @@ public class PackageBasedActionConfigBuilderTest extends TestCase {
         verifyActionConfig(pkgConfig, "package-level-parent-package-child", PackageLevelParentPackageChildAction.class,
"execute", pkgConfig.getName());
         assertEquals("package-level", pkgConfig.getParents().get(0).getName());
 
+        /* org.apache.struts2.convention.actions.allowedmethods class level */
+        pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.allowedmethods#struts-default#/allowedmethods");
+        assertNotNull(pkgConfig);
+        assertEquals(2, pkgConfig.getActionConfigs().size());
+        verifyActionConfig(pkgConfig, "class-level-allowed-methods", ClassLevelAllowedMethodsAction.class,
"execute", pkgConfig.getName());
+        assertEquals("struts-default", pkgConfig.getParents().get(0).getName());
+
+        ActionConfig actionConfig = pkgConfig.getActionConfigs().get("class-level-allowed-methods");
+        assertEquals(actionConfig.getAllowedMethods().size(), 5);
+        assertTrue(actionConfig.getAllowedMethods().contains("execute"));
+        assertTrue(actionConfig.getAllowedMethods().contains("end"));
+        assertTrue(actionConfig.getAllowedMethods().contains("input"));
+
+        /* org.apache.struts2.convention.actions.allowedmethods.sub package level */
+        pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.allowedmethods.sub#struts-default#/allowedmethods/sub");
+        assertNotNull(pkgConfig);
+        assertEquals(1, pkgConfig.getActionConfigs().size());
+        verifyActionConfig(pkgConfig, "package-level-allowed-methods-child", PackageLevelAllowedMethodsChildAction.class,
"execute", pkgConfig.getName());
+        assertEquals("struts-default", pkgConfig.getParents().get(0).getName());
+
+        actionConfig = pkgConfig.getActionConfigs().get("package-level-allowed-methods-child");
+        assertEquals(actionConfig.getAllowedMethods().size(), 6);
+        assertTrue(actionConfig.getAllowedMethods().contains("execute"));
+        assertTrue(actionConfig.getAllowedMethods().contains("home"));
+        assertTrue(actionConfig.getAllowedMethods().contains("start"));
+        assertTrue(actionConfig.getAllowedMethods().contains("input"));
+
         /* org.apache.struts2.convention.actions.result */
         pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.result#struts-default#/result");
         assertNotNull(pkgConfig);
@@ -631,12 +679,12 @@ public class PackageBasedActionConfigBuilderTest extends TestCase {
 
     private PackageConfig makePackageConfig(String name, String namespace, PackageConfig
parent,
             String defaultResultType, ResultTypeConfig... results) {
-        return makePackageConfig(name, namespace, parent, defaultResultType, results, null,
null);
+        return makePackageConfig(name, namespace, parent, defaultResultType, results, null,
null, null);
     }
 
     private PackageConfig makePackageConfig(String name, String namespace, PackageConfig
parent,
             String defaultResultType, ResultTypeConfig[] results, List<InterceptorConfig>
interceptors,
-            List<InterceptorStackConfig> interceptorStacks) {
+            List<InterceptorStackConfig> interceptorStacks, Set<String> globalAllowedMethods)
{
         PackageConfig.Builder builder = new PackageConfig.Builder(name);
         if (namespace != null) {
             builder.namespace(namespace);
@@ -663,6 +711,10 @@ public class PackageBasedActionConfigBuilderTest extends TestCase {
             }
         }
 
+        if (globalAllowedMethods != null) {
+            builder.addGlobalAllowedMethods(globalAllowedMethods);
+        }
+
         return new MyPackageConfig(builder.build());
     }
 

http://git-wip-us.apache.org/repos/asf/struts/blob/ab5fb27d/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/ClassLevelAllowedMethodsAction.java
----------------------------------------------------------------------
diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/ClassLevelAllowedMethodsAction.java
b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/ClassLevelAllowedMethodsAction.java
new file mode 100644
index 0000000..24ea489
--- /dev/null
+++ b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/ClassLevelAllowedMethodsAction.java
@@ -0,0 +1,10 @@
+package org.apache.struts2.convention.actions.allowedmethods;
+
+import org.apache.struts2.convention.annotation.AllowedMethods;
+
+@AllowedMethods("end")
+public class ClassLevelAllowedMethodsAction {
+
+    public String execute() { return null; }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/ab5fb27d/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/PackageLevelAllowedMethodsAction.java
----------------------------------------------------------------------
diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/PackageLevelAllowedMethodsAction.java
b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/PackageLevelAllowedMethodsAction.java
new file mode 100644
index 0000000..eab0895
--- /dev/null
+++ b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/PackageLevelAllowedMethodsAction.java
@@ -0,0 +1,7 @@
+package org.apache.struts2.convention.actions.allowedmethods;
+
+public class PackageLevelAllowedMethodsAction {
+
+    public String execute() { return null; }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/ab5fb27d/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/package-info.java
----------------------------------------------------------------------
diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/package-info.java
b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/package-info.java
new file mode 100644
index 0000000..461131f
--- /dev/null
+++ b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * $Id$
+ *
+ * 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.
+ */
+@org.apache.struts2.convention.annotation.AllowedMethods("home,start")
+package org.apache.struts2.convention.actions.allowedmethods;
+

http://git-wip-us.apache.org/repos/asf/struts/blob/ab5fb27d/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/sub/PackageLevelAllowedMethodsChildAction.java
----------------------------------------------------------------------
diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/sub/PackageLevelAllowedMethodsChildAction.java
b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/sub/PackageLevelAllowedMethodsChildAction.java
new file mode 100644
index 0000000..4a6223d
--- /dev/null
+++ b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/allowedmethods/sub/PackageLevelAllowedMethodsChildAction.java
@@ -0,0 +1,9 @@
+package org.apache.struts2.convention.actions.allowedmethods.sub;
+
+import org.apache.struts2.convention.actions.allowedmethods.PackageLevelAllowedMethodsAction;
+
+public class PackageLevelAllowedMethodsChildAction extends PackageLevelAllowedMethodsAction
{
+
+    public String execute() { return null; }
+
+}


Mime
View raw message