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 66af3b358..4f356907d 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 @@ -767,12 +767,13 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder { if (pkgPart == null && packageLocators != null) { for (String packageLocator : packageLocators) { - int index = pkg.lastIndexOf(packageLocator); + // check subpackage and not a part of package name, eg. actions -> my.actions.transactions - WW-3803 + int index = pkg.lastIndexOf("." + packageLocator + "."); // This ensures that the match is at the end, beginning or has a dot on each side of it if (index >= 0 && (index + packageLocator.length() == pkg.length() || index == 0 || - (pkg.charAt(index - 1) == '.' && pkg.charAt(index + packageLocator.length()) == '.'))) { - pkgPart = actionClass.getName().substring(index + packageLocator.length() + 1); + (pkg.charAt(index) == '.' && pkg.charAt(index + 1 + packageLocator.length()) == '.'))) { + pkgPart = actionClass.getName().substring(index + packageLocator.length() + 2); } } } 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 473062018..10912ca9c 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 @@ -80,6 +80,7 @@ import org.apache.struts2.convention.actions.result.OverrideResultAction; import org.apache.struts2.convention.actions.resultpath.ClassLevelResultPathAction; import org.apache.struts2.convention.actions.resultpath.PackageLevelResultPathAction; import org.apache.struts2.convention.actions.skip.Index; +import org.apache.struts2.convention.actions.transactions.TransNameAction; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Actions; import org.apache.struts2.convention.dontfind.DontFindMeAction; @@ -193,6 +194,8 @@ public class PackageBasedActionConfigBuilderTest extends TestCase { "/skip", strutsDefault, null); PackageConfig chainPkg = makePackageConfig("org.apache.struts2.convention.actions.chain#struts-default#/chain", "/chain", strutsDefault, null); + PackageConfig transPkg = makePackageConfig("org.apache.struts2.convention.actions.transactions#struts-default#/transactions", + "/transactions", strutsDefault, null); ResultMapBuilder resultMapBuilder = createStrictMock(ResultMapBuilder.class); checkOrder(resultMapBuilder, false); @@ -293,6 +296,10 @@ public class PackageBasedActionConfigBuilderTest extends TestCase { expect(resultMapBuilder.build(ChainedAction.class, getAnnotation(ChainedAction.class, "foo", Action.class), "foo", chainPkg)).andReturn(results); expect(resultMapBuilder.build(ChainedAction.class, getAnnotation(ChainedAction.class, "bar", Action.class), "foo-bar", chainPkg)).andReturn(results); + /* org.apache.struts2.convention.actions.transactions */ + expect(resultMapBuilder.build(TransNameAction.class, getAnnotation(TransNameAction.class, "trans1", Action.class), "trans1", transPkg)).andReturn(results); + expect(resultMapBuilder.build(TransNameAction.class, getAnnotation(TransNameAction.class, "trans2", Action.class), "trans2", transPkg)).andReturn(results); + EasyMock.replay(resultMapBuilder); final DummyContainer mockContainer = new DummyContainer(); @@ -552,6 +559,11 @@ public class PackageBasedActionConfigBuilderTest extends TestCase { verifyActionConfig(pkgConfig, "idx", org.apache.struts2.convention.actions.idx.Index.class, "execute", "org.apache.struts2.convention.actions.idx#struts-default#/idx"); + /* org.apache.struts2.convention.actions.transactions */ + pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.transactions#struts-default#/transactions"); + verifyActionConfig(pkgConfig, "trans1", TransNameAction.class, "trans1", pkgConfig.getName()); + verifyActionConfig(pkgConfig, "trans2", TransNameAction.class, "trans2", pkgConfig.getName()); + //test unknown handler automatic chaining pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.chain#struts-default#/chain"); ServletContext context = EasyMock.createNiceMock(ServletContext.class); diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/actions/transactions/TransNameAction.java b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/transactions/TransNameAction.java new file mode 100644 index 000000000..d7ffc7b5a --- /dev/null +++ b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/transactions/TransNameAction.java @@ -0,0 +1,40 @@ +/* + * $Id: ActionNameAction.java 655902 2008-05-13 15:15:12Z bpontarelli $ + * + * 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.transactions; + +import org.apache.struts2.convention.annotation.Action; + +/** + *

+ * This is a test action. + *

+ */ +public class TransNameAction { + @Action("trans1") + public String trans1() { + return null; + } + + @Action("trans2") + public String trans2() { + return null; + } +}