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 f4df68255..14b11c42d 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 @@ -76,7 +76,9 @@ import java.util.regex.Pattern; *

*/ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder { + private static final Logger LOG = LoggerFactory.getLogger(PackageBasedActionConfigBuilder.class); + private final Configuration configuration; private final ActionNameBuilder actionNameBuilder; private final ResultMapBuilder resultMapBuilder; @@ -353,7 +355,7 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder { if (ctx != null) classLoaderInterface = (ClassLoaderInterface) ctx.get(ClassLoaderInterface.CLASS_LOADER_INTERFACE); - return (ClassLoaderInterface) ObjectUtils.defaultIfNull(classLoaderInterface, new ClassLoaderInterfaceDelegate(getClassLoader())); + return ObjectUtils.defaultIfNull(classLoaderInterface, new ClassLoaderInterfaceDelegate(getClassLoader())); } } @@ -841,14 +843,16 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder { */ protected void createActionConfig(PackageConfig.Builder pkgCfg, Class actionClass, String actionName, String actionMethod, Action annotation) { + String className = actionClass.getName(); if (annotation != null) { - actionName = annotation.value() != null && annotation.value().equals(Action.DEFAULT_VALUE) ? - actionName : annotation.value(); + actionName = annotation.value() != null && 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(); + } } - - ActionConfig.Builder actionConfig = new ActionConfig.Builder(pkgCfg.getName(), - actionName, actionClass.getName()); + + ActionConfig.Builder actionConfig = new ActionConfig.Builder(pkgCfg.getName(), actionName, className); actionConfig.methodName(actionMethod); if (LOG.isDebugEnabled()) { diff --git a/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Action.java b/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Action.java index fc8020f4d..a72fae698 100644 --- a/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Action.java +++ b/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Action.java @@ -92,4 +92,11 @@ public @interface Action { * @return Maps return codes to exceptions. The "exceptions" interceptor must be applied to the action. */ ExceptionMapping[] exceptionMappings() default {}; + + /** + * Allows actions to specify different class name. + * + * @return The class name for the action. + */ + String className() default DEFAULT_VALUE; } \ No newline at end of file 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 29584c64d..694984aa8 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 @@ -20,22 +20,39 @@ */ package org.apache.struts2.convention; -import static org.apache.struts2.convention.ReflectionTools.getAnnotation; -import static org.easymock.EasyMock.checkOrder; -import static org.easymock.EasyMock.createStrictMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.verify; - -import java.util.*; -import java.net.MalformedURLException; - +import com.opensymphony.xwork2.ActionChainResult; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.Result; +import com.opensymphony.xwork2.config.Configuration; +import com.opensymphony.xwork2.config.entities.ActionConfig; +import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig; +import com.opensymphony.xwork2.config.entities.InterceptorConfig; +import com.opensymphony.xwork2.config.entities.InterceptorMapping; +import com.opensymphony.xwork2.config.entities.InterceptorStackConfig; +import com.opensymphony.xwork2.config.entities.PackageConfig; +import com.opensymphony.xwork2.config.entities.ResultConfig; +import com.opensymphony.xwork2.config.entities.ResultTypeConfig; +import com.opensymphony.xwork2.config.impl.DefaultConfiguration; +import com.opensymphony.xwork2.inject.Container; +import com.opensymphony.xwork2.inject.Scope.Strategy; +import com.opensymphony.xwork2.ognl.OgnlReflectionProvider; +import com.opensymphony.xwork2.util.reflection.ReflectionException; import junit.framework.TestCase; - 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.ActionNameAction; +import org.apache.struts2.convention.actions.action.ActionNamesAction; +import org.apache.struts2.convention.actions.action.ClassLevelAnnotationAction; +import org.apache.struts2.convention.actions.action.ClassLevelAnnotationDefaultMethodAction; +import org.apache.struts2.convention.actions.action.ClassLevelAnnotationsAction; +import org.apache.struts2.convention.actions.action.ClassLevelAnnotationsDefaultMethodAction; +import org.apache.struts2.convention.actions.action.ClassNameAction; +import org.apache.struts2.convention.actions.action.SingleActionNameAction; +import org.apache.struts2.convention.actions.action.TestAction; +import org.apache.struts2.convention.actions.action.TestExtends; import org.apache.struts2.convention.actions.chain.ChainedAction; -import org.apache.struts2.convention.actions.action.*; import org.apache.struts2.convention.actions.defaultinterceptor.SingleActionNameAction2; import org.apache.struts2.convention.actions.exception.ExceptionsActionLevelAction; import org.apache.struts2.convention.actions.exception.ExceptionsMethodLevelAction; @@ -68,26 +85,20 @@ import org.apache.struts2.convention.annotation.Actions; import org.apache.struts2.dispatcher.ServletDispatcherResult; import org.easymock.EasyMock; -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.Result; -import com.opensymphony.xwork2.ActionChainResult; -import com.opensymphony.xwork2.util.reflection.ReflectionException; -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig; -import com.opensymphony.xwork2.config.entities.InterceptorConfig; -import com.opensymphony.xwork2.config.entities.InterceptorMapping; -import com.opensymphony.xwork2.config.entities.InterceptorStackConfig; -import com.opensymphony.xwork2.config.entities.PackageConfig; -import com.opensymphony.xwork2.config.entities.ResultConfig; -import com.opensymphony.xwork2.config.entities.ResultTypeConfig; -import com.opensymphony.xwork2.config.impl.DefaultConfiguration; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Scope.Strategy; -import com.opensymphony.xwork2.ognl.OgnlReflectionProvider; - import javax.servlet.ServletContext; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.apache.struts2.convention.ReflectionTools.getAnnotation; +import static org.easymock.EasyMock.checkOrder; +import static org.easymock.EasyMock.createStrictMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.verify; /** *

@@ -95,6 +106,7 @@ import javax.servlet.ServletContext; *

*/ public class PackageBasedActionConfigBuilderTest extends TestCase { + public void testActionPackages() throws MalformedURLException { run("org.apache.struts2.convention.actions", null, null); } @@ -183,6 +195,7 @@ public class PackageBasedActionConfigBuilderTest extends TestCase { /* org.apache.struts2.convention.actions.action */ expect(resultMapBuilder.build(ActionNameAction.class, getAnnotation(ActionNameAction.class, "run1", Action.class), "action1", actionPkg)).andReturn(results); + expect(resultMapBuilder.build(ClassNameAction.class, getAnnotation(ClassNameAction.class, "run1", Action.class), "action3", actionPkg)).andReturn(results); expect(resultMapBuilder.build(ActionNameAction.class, getAnnotation(ActionNameAction.class, "run2", Action.class), "action2", actionPkg)).andReturn(results); expect(resultMapBuilder.build(ActionNamesAction.class, getAnnotation(ActionNamesAction.class, "run", Actions.class).value()[0], "actions1", actionPkg)).andReturn(results); expect(resultMapBuilder.build(ActionNamesAction.class, getAnnotation(ActionNamesAction.class, "run", Actions.class).value()[1], "actions2", actionPkg)).andReturn(results); @@ -321,9 +334,10 @@ public class PackageBasedActionConfigBuilderTest extends TestCase { /* org.apache.struts2.convention.actions.action */ PackageConfig pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.action#struts-default#/action"); assertNotNull(pkgConfig); - assertEquals(13, pkgConfig.getActionConfigs().size()); + assertEquals(14, pkgConfig.getActionConfigs().size()); verifyActionConfig(pkgConfig, "action1", ActionNameAction.class, "run1", pkgConfig.getName()); verifyActionConfig(pkgConfig, "action2", ActionNameAction.class, "run2", pkgConfig.getName()); + verifyActionConfig(pkgConfig, "action3", "someClassName", "run1", pkgConfig.getName()); verifyActionConfig(pkgConfig, "actions1", ActionNamesAction.class, "run", pkgConfig.getName()); verifyActionConfig(pkgConfig, "actions2", ActionNamesAction.class, "run", pkgConfig.getName()); verifyActionConfig(pkgConfig, "action", SingleActionNameAction.class, "run", pkgConfig.getName()); @@ -557,6 +571,14 @@ public class PackageBasedActionConfigBuilderTest extends TestCase { assertEquals(packageName, ac.getPackageName()); } + private void verifyActionConfig(PackageConfig pkgConfig, String actionName, String actionClass, String methodName, String packageName) { + ActionConfig ac = pkgConfig.getAllActionConfigs().get(actionName); + assertNotNull(ac); + assertEquals(actionClass, ac.getClassName()); + assertEquals(methodName, ac.getMethodName()); + assertEquals(packageName, ac.getPackageName()); + } + private void verifyActionConfigInterceptors(PackageConfig pkgConfig, String actionName, String... refs) { ActionConfig ac = pkgConfig.getAllActionConfigs().get(actionName); assertNotNull(ac); diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassNameAction.java b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassNameAction.java new file mode 100644 index 000000000..ccd7255ce --- /dev/null +++ b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassNameAction.java @@ -0,0 +1,37 @@ +/* + * $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. + */ +package org.apache.struts2.convention.actions.action; + +import org.apache.struts2.convention.annotation.Action; + +/** + *

+ * This is a test action. + *

+ */ +public class ClassNameAction { + + @Action(value = "action3", className = "someClassName") + public String run1() { + return null; + } + +} \ No newline at end of file