From 873d150890efddae9402bb04a8cdec981bd30e41 Mon Sep 17 00:00:00 2001 From: "Donald J. Brown" Date: Sat, 14 Jun 2008 04:20:22 +0000 Subject: [PATCH] Adding support for multiple parent packages to be defined at the package level, adding more restrictions on the namespace, parentpackage, and results annotations git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667742 13f79535-47bb-0310-9956-ffa450edef68 --- .../config/ClasspathPackageProvider.java | 47 +++++++++++++++---- .../org/apache/struts2/config/Namespace.java | 3 ++ .../apache/struts2/config/ParentPackage.java | 7 ++- .../org/apache/struts2/config/Results.java | 3 ++ .../config/ClasspathPackageProviderTest.java | 32 +++++++++++-- .../struts2/config/parenttest/SomeAction.java | 30 ++++++++++++ .../config/parenttest/package-info.java | 24 ++++++++++ 7 files changed, 129 insertions(+), 17 deletions(-) create mode 100644 plugins/codebehind/src/test/java/org/apache/struts2/config/parenttest/SomeAction.java create mode 100644 plugins/codebehind/src/test/java/org/apache/struts2/config/parenttest/package-info.java diff --git a/plugins/codebehind/src/main/java/org/apache/struts2/config/ClasspathPackageProvider.java b/plugins/codebehind/src/main/java/org/apache/struts2/config/ClasspathPackageProvider.java index c308296a1..32cf6ee98 100644 --- a/plugins/codebehind/src/main/java/org/apache/struts2/config/ClasspathPackageProvider.java +++ b/plugins/codebehind/src/main/java/org/apache/struts2/config/ClasspathPackageProvider.java @@ -387,17 +387,14 @@ public class ClasspathPackageProvider implements PackageProvider { actionPackage = pkgConfig.getName(); } - Annotation annotation = cls.getAnnotation(ParentPackage.class); - if (annotation != null) { - String parent = ((ParentPackage)annotation).value(); - PackageConfig parentPkg = configuration.getPackageConfig(parent); - if (parentPkg == null) { - throw new ConfigurationException("ClasspathPackageProvider: Unable to locate parent package "+parent, annotation); - } - pkgConfig.addParent(parentPkg); + List parents = findAllParentPackages(cls); + if (parents.size() > 0) { + pkgConfig.addParents(parents); - if (!TextUtils.stringSet(pkgConfig.getNamespace()) && TextUtils.stringSet(parentPkg.getNamespace())) { - pkgConfig.namespace(parentPkg.getNamespace()); + // Try to guess the namespace from the first package + PackageConfig firstParent = parents.get(0); + if (!TextUtils.stringSet(pkgConfig.getNamespace()) && TextUtils.stringSet(firstParent.getNamespace())) { + pkgConfig.namespace(firstParent.getNamespace()); } } @@ -409,6 +406,36 @@ public class ClasspathPackageProvider implements PackageProvider { pkgConfig.addActionConfig(actionName, actionConfig); } + /** + * Finds all parent packages by first looking at the ParentPackage annotation on the package, then the class + * @param cls The action class + * @return A list of unique packages to add + */ + private List findAllParentPackages(Class cls) { + + List parents = new ArrayList(); + // Favor parent package annotations from the package + Set parentNames = new LinkedHashSet(); + ParentPackage annotation = cls.getPackage().getAnnotation(ParentPackage.class); + if (annotation != null) { + parentNames.addAll(Arrays.asList(annotation.value())); + } + annotation = cls.getAnnotation(ParentPackage.class); + if (annotation != null) { + parentNames.addAll(Arrays.asList(annotation.value())); + } + if (parentNames.size() > 0) { + for (String parent : parentNames) { + PackageConfig parentPkg = configuration.getPackageConfig(parent); + if (parentPkg == null) { + throw new ConfigurationException("ClasspathPackageProvider: Unable to locate parent package "+parent, annotation); + } + parents.add(parentPkg); + } + } + return parents; + } + /** * Finds or creates the package configuration for an Action class. * diff --git a/plugins/codebehind/src/main/java/org/apache/struts2/config/Namespace.java b/plugins/codebehind/src/main/java/org/apache/struts2/config/Namespace.java index 8396825f4..636f942a7 100644 --- a/plugins/codebehind/src/main/java/org/apache/struts2/config/Namespace.java +++ b/plugins/codebehind/src/main/java/org/apache/struts2/config/Namespace.java @@ -23,11 +23,14 @@ package org.apache.struts2.config; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; /** * Allows an action class to specify its namespace */ @Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) public @interface Namespace { String value(); } diff --git a/plugins/codebehind/src/main/java/org/apache/struts2/config/ParentPackage.java b/plugins/codebehind/src/main/java/org/apache/struts2/config/ParentPackage.java index 0a86c9c7b..2d23d4ad1 100644 --- a/plugins/codebehind/src/main/java/org/apache/struts2/config/ParentPackage.java +++ b/plugins/codebehind/src/main/java/org/apache/struts2/config/ParentPackage.java @@ -23,11 +23,14 @@ package org.apache.struts2.config; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; /** - * Allows an action class to specify an xwork package to inherit + * Allows an action class or package to specify an xwork package to inherit */ @Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.PACKAGE}) public @interface ParentPackage { - String value(); + String[] value(); } diff --git a/plugins/codebehind/src/main/java/org/apache/struts2/config/Results.java b/plugins/codebehind/src/main/java/org/apache/struts2/config/Results.java index d299a5bed..a7d909661 100644 --- a/plugins/codebehind/src/main/java/org/apache/struts2/config/Results.java +++ b/plugins/codebehind/src/main/java/org/apache/struts2/config/Results.java @@ -23,11 +23,14 @@ package org.apache.struts2.config; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; /** * Defines multiple XWork Results */ @Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) public @interface Results { Result[] value(); } diff --git a/plugins/codebehind/src/test/java/org/apache/struts2/config/ClasspathPackageProviderTest.java b/plugins/codebehind/src/test/java/org/apache/struts2/config/ClasspathPackageProviderTest.java index 1a84a97a0..0a9fd89ab 100644 --- a/plugins/codebehind/src/test/java/org/apache/struts2/config/ClasspathPackageProviderTest.java +++ b/plugins/codebehind/src/test/java/org/apache/struts2/config/ClasspathPackageProviderTest.java @@ -39,7 +39,13 @@ public class ClasspathPackageProviderTest extends TestCase { public void setUp() throws Exception { provider = new ClasspathPackageProvider(); provider.setActionPackages("org.apache.struts2.config"); - config = new DefaultConfiguration(); + config = createNewConfiguration(); + provider.init(config); + provider.loadPackages(); + } + + private Configuration createNewConfiguration() { + Configuration config = new DefaultConfiguration(); PackageConfig strutsDefault = new PackageConfig.Builder("struts-default") .addResultTypeConfig(new ResultTypeConfig.Builder("dispatcher", ServletDispatcherResult.class.getName()) .defaultResultParam("location") @@ -51,17 +57,16 @@ public class ClasspathPackageProviderTest extends TestCase { .namespace("/custom") .build(); config.addPackageConfig("custom-package", customPackage); - provider.init(config); - provider.loadPackages(); + return config; } - + public void tearDown() throws Exception { provider = null; config = null; } public void testFoundRootPackages() { - assertEquals(6, config.getPackageConfigs().size()); + assertEquals(7, config.getPackageConfigs().size()); PackageConfig pkg = config.getPackageConfig("org.apache.struts2.config"); assertNotNull(pkg); Map configs = pkg.getActionConfigs(); @@ -91,6 +96,23 @@ public class ClasspathPackageProviderTest extends TestCase { assertEquals("/custom", pkg.getNamespace()); } + public void testParentPackageOnPackage() { + provider = new ClasspathPackageProvider(); + provider.setActionPackages("org.apache.struts2.config.parenttest"); + provider.init(createNewConfiguration()); + provider.loadPackages(); + + + PackageConfig pkg = config.getPackageConfig("org.apache.struts2.config.parenttest"); + // assertEquals(2, pkg.getParents().size()); + assertNotNull(pkg); + + assertEquals("custom-package", pkg.getParents().get(0).getName()); + Map configs = pkg.getActionConfigs(); + ActionConfig config = (ActionConfig) configs.get("some"); + assertNotNull(config); + } + public void testCustomNamespace() { PackageConfig pkg = config.getPackageConfig("org.apache.struts2.config.CustomNamespaceAction"); Map configs = pkg.getAllActionConfigs(); diff --git a/plugins/codebehind/src/test/java/org/apache/struts2/config/parenttest/SomeAction.java b/plugins/codebehind/src/test/java/org/apache/struts2/config/parenttest/SomeAction.java new file mode 100644 index 000000000..08263af81 --- /dev/null +++ b/plugins/codebehind/src/test/java/org/apache/struts2/config/parenttest/SomeAction.java @@ -0,0 +1,30 @@ +/* + * $Id: ParentPackage.java 651946 2008-04-27 13:41:38Z apetrelli $ + * + * 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 org.apache.struts2.config.parenttest; + +import com.opensymphony.xwork2.Action; + +public class SomeAction implements Action { + + public String execute() throws Exception { + return null; //To change body of implemented methods use File | Settings | File Templates. + } +} diff --git a/plugins/codebehind/src/test/java/org/apache/struts2/config/parenttest/package-info.java b/plugins/codebehind/src/test/java/org/apache/struts2/config/parenttest/package-info.java new file mode 100644 index 000000000..fdb5c9229 --- /dev/null +++ b/plugins/codebehind/src/test/java/org/apache/struts2/config/parenttest/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: ParentPackage.java 651946 2008-04-27 13:41:38Z apetrelli $ + * + * 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. + */ +@ParentPackage("custom-package") +package org.apache.struts2.config.parenttest; + +import org.apache.struts2.config.ParentPackage; \ No newline at end of file