Repository: struts Updated Branches: refs/heads/master cae57093b -> 11561cb29
WW-4590 - Allow to use multiple names in result Project: http://git-wip-us.apache.org/repos/asf/struts/repo Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/087cf610 Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/087cf610 Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/087cf610 Branch: refs/heads/master Commit: 087cf610abcd262980a41c30a2f9360aa3f416e1 Parents: d923c7c Author: Aleksandr Mashchenko <[email protected]> Authored: Mon Jan 18 21:23:46 2016 +0200 Committer: Aleksandr Mashchenko <[email protected]> Committed: Mon Jan 18 21:23:46 2016 +0200 ---------------------------------------------------------------------- .../providers/XmlConfigurationProvider.java | 20 +++- .../XmlConfigurationProviderResultsTest.java | 54 ++++++++++ .../providers/xwork-test-result-names.xml | 48 +++++++++ .../convention/DefaultResultMapBuilder.java | 35 +++++-- .../convention/DefaultResultMapBuilderTest.java | 104 +++++++++++++++++++ .../PackageBasedActionConfigBuilderTest.java | 6 +- .../result/ActionLevelResultsNamesAction.java | 61 +++++++++++ 7 files changed, 314 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/struts/blob/087cf610/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java index 5846969..e3b0c19 100644 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java +++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java @@ -777,11 +777,21 @@ public class XmlConfigurationProvider implements ConfigurationProvider { } params.putAll(resultParams); - ResultConfig resultConfig = new ResultConfig.Builder(resultName, resultClass) - .addParams(params) - .location(DomHelper.getLocationObject(element)) - .build(); - results.put(resultConfig.getName(), resultConfig); + Set<String> resultNamesSet; + if (",".equals(resultName.trim())) { + resultNamesSet = new HashSet<>(1); + resultNamesSet.add(resultName); + } else { + resultNamesSet = TextParseUtil.commaDelimitedStringToSet(resultName); + } + + for (String name : resultNamesSet) { + ResultConfig resultConfig = new ResultConfig.Builder(name, resultClass) + .addParams(params) + .location(DomHelper.getLocationObject(element)) + .build(); + results.put(resultConfig.getName(), resultConfig); + } } } http://git-wip-us.apache.org/repos/asf/struts/blob/087cf610/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderResultsTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderResultsTest.java b/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderResultsTest.java index caa9da0..468ea1a 100644 --- a/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderResultsTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderResultsTest.java @@ -15,6 +15,7 @@ */ package com.opensymphony.xwork2.config.providers; +import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionChainResult; import com.opensymphony.xwork2.SimpleAction; import com.opensymphony.xwork2.config.ConfigurationException; @@ -118,4 +119,57 @@ public class XmlConfigurationProviderResultsTest extends ConfigurationTestBase { assertEquals(chainResult, resultTypes.get("chain")); assertEquals(mockResult, resultTypes.get("mock")); } + + public void testResultNames() throws ConfigurationException { + final String filename = "com/opensymphony/xwork2/config/providers/xwork-test-result-names.xml"; + ConfigurationProvider provider = buildConfigurationProvider(filename); + + // execute the configuration + provider.init(configuration); + provider.loadPackages(); + + PackageConfig pkg = configuration.getPackageConfig("default"); + Map<String, ActionConfig> actionConfigs = pkg.getActionConfigs(); + + // assertions + assertNotNull(actionConfigs); + + Map<String, ResultConfig> resultConfigs = actionConfigs.get("noname").getResults(); + assertEquals(1, resultConfigs.size()); + assertTrue(resultConfigs.containsKey(Action.SUCCESS)); + + resultConfigs = actionConfigs.get("success").getResults(); + assertEquals(1, resultConfigs.size()); + assertTrue(resultConfigs.containsKey(Action.SUCCESS)); + + resultConfigs = actionConfigs.get("empty").getResults(); + assertEquals(1, resultConfigs.size()); + assertTrue(resultConfigs.containsKey(Action.SUCCESS)); + + resultConfigs = actionConfigs.get("comma").getResults(); + assertEquals(1, resultConfigs.size()); + assertTrue(resultConfigs.containsKey(" , ")); + + resultConfigs = actionConfigs.get("error-input").getResults(); + assertEquals(2, resultConfigs.size()); + assertTrue(resultConfigs.containsKey(Action.ERROR)); + assertTrue(resultConfigs.containsKey(Action.INPUT)); + + resultConfigs = actionConfigs.get("error-input2").getResults(); + assertEquals(2, resultConfigs.size()); + assertTrue(resultConfigs.containsKey(Action.ERROR)); + assertTrue(resultConfigs.containsKey(Action.INPUT)); + + resultConfigs = actionConfigs.get("noname-error-input").getResults(); + assertEquals(3, resultConfigs.size()); + assertTrue(resultConfigs.containsKey(Action.SUCCESS)); + assertTrue(resultConfigs.containsKey(Action.ERROR)); + assertTrue(resultConfigs.containsKey(Action.INPUT)); + + resultConfigs = actionConfigs.get("noname-error-input2").getResults(); + assertEquals(3, resultConfigs.size()); + assertTrue(resultConfigs.containsKey(Action.SUCCESS)); + assertTrue(resultConfigs.containsKey(Action.ERROR)); + assertTrue(resultConfigs.containsKey(Action.INPUT)); + } } http://git-wip-us.apache.org/repos/asf/struts/blob/087cf610/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-names.xml ---------------------------------------------------------------------- diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-names.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-names.xml new file mode 100644 index 0000000..e740577 --- /dev/null +++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-result-names.xml @@ -0,0 +1,48 @@ +<!DOCTYPE xwork PUBLIC + "-//Apache Struts//XWork 2.5//EN" + "http://struts.apache.org/dtds/xwork-2.5.dtd" + > + +<xwork> + <include file="xwork-test-beans.xml" /> + <package name="default"> + <result-types> + <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult" default="true"/> + </result-types> + + <action name="noname"> + <result /> + </action> + + <action name="success"> + <result name="success" /> + </action> + + <action name="empty"> + <result name="" /> + </action> + + <action name="comma"> + <result name=" , " /> + </action> + + <action name="error-input"> + <result name="error, input" /> + </action> + + <action name="error-input2"> + <result name="error, input, " /> + </action> + + <action name="noname-error-input"> + <result /> + <result name="error, input" /> + </action> + + <action name="noname-error-input2"> + <result /> + <result name="error" /> + <result name="input" /> + </action> + </package> +</xwork> http://git-wip-us.apache.org/repos/asf/struts/blob/087cf610/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultResultMapBuilder.java ---------------------------------------------------------------------- diff --git a/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultResultMapBuilder.java b/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultResultMapBuilder.java index 87fb970..b7c5b51 100644 --- a/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultResultMapBuilder.java +++ b/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultResultMapBuilder.java @@ -28,6 +28,7 @@ import com.opensymphony.xwork2.config.entities.ResultConfig; import com.opensymphony.xwork2.config.entities.ResultTypeConfig; import com.opensymphony.xwork2.inject.Container; import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.util.TextParseUtil; import com.opensymphony.xwork2.util.finder.ClassLoaderInterface; import com.opensymphony.xwork2.util.finder.ClassLoaderInterfaceDelegate; import com.opensymphony.xwork2.util.finder.ResourceFinder; @@ -409,11 +410,21 @@ public class DefaultResultMapBuilder implements ResultMapBuilder { Class<?> actionClass, Map<String, ResultTypeConfig> resultsByExtension) { // Check for multiple results on the class for (Result result : results) { - ResultConfig config = createResultConfig(actionClass, - new ResultInfo(result, packageConfig, resultPath, actionClass, resultsByExtension), - packageConfig, result); - if (config != null) { - resultConfigs.put(config.getName(), config); + Set<String> names; + if (",".equals(result.name().trim())) { + names = new HashSet<>(1); + names.add(result.name()); + } else { + names = TextParseUtil.commaDelimitedStringToSet(result.name()); + } + + for (String name : names) { + ResultConfig config = createResultConfig(actionClass, new ResultInfo( + name, result, packageConfig, resultPath, actionClass, + resultsByExtension), packageConfig, result); + if (config != null) { + resultConfigs.put(config.getName(), config); + } } } } @@ -478,9 +489,10 @@ public class DefaultResultMapBuilder implements ResultMapBuilder { this.type = determineType(location, packageConfig, resultsByExtension); } - public ResultInfo(Result result, PackageConfig packageConfig, String resultPath, - Class<?> actionClass, Map<String, ResultTypeConfig> resultsByExtension) { - this.name = result.name(); + public ResultInfo(String name, Result result, PackageConfig packageConfig, + String resultPath, Class<?> actionClass, + Map<String, ResultTypeConfig> resultsByExtension) { + this.name = name; if (StringUtils.isNotBlank(result.type())) { this.type = result.type(); } else if (StringUtils.isNotBlank(result.location())) { @@ -503,6 +515,13 @@ public class DefaultResultMapBuilder implements ResultMapBuilder { } } + public ResultInfo(Result result, PackageConfig packageConfig, + String resultPath, Class<?> actionClass, + Map<String, ResultTypeConfig> resultsByExtension) { + this(result.name(), result, packageConfig, resultPath, actionClass, + resultsByExtension); + } + String determineType(String location, PackageConfig packageConfig, Map<String, ResultTypeConfig> resultsByExtension) { int indexOfDot = location.lastIndexOf("."); http://git-wip-us.apache.org/repos/asf/struts/blob/087cf610/plugins/convention/src/test/java/org/apache/struts2/convention/DefaultResultMapBuilderTest.java ---------------------------------------------------------------------- diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/DefaultResultMapBuilderTest.java b/plugins/convention/src/test/java/org/apache/struts2/convention/DefaultResultMapBuilderTest.java index abda7b3..b73667a 100644 --- a/plugins/convention/src/test/java/org/apache/struts2/convention/DefaultResultMapBuilderTest.java +++ b/plugins/convention/src/test/java/org/apache/struts2/convention/DefaultResultMapBuilderTest.java @@ -487,6 +487,110 @@ public class DefaultResultMapBuilderTest extends TestCase { EasyMock.verify(context); } + public void testActionLevelMultipleResultNamesAnnotation() throws Exception { + ServletContext context = EasyMock.createStrictMock(ServletContext.class); + + // Setup some mock jsps + Set<String> resources = new HashSet<>(); + EasyMock.expect(context.getResourcePaths("/WEB-INF/location/namespace/")).andReturn(resources); + EasyMock.replay(context); + + PackageConfig packageConfig = createPackageConfigBuilder("/namespace"); + + this.conventionsService = new ConventionsServiceImpl("/WEB-INF/location"); + DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, container, "dispatcher,velocity,freemarker"); + Map<String, ResultConfig> results = builder.build(ActionLevelResultsNamesAction.class, getAnnotation(ActionLevelResultsNamesAction.class, "execute", Action.class), "action-level-results", packageConfig); + assertEquals(4, results.size()); + assertEquals("error", results.get("error").getName()); + assertEquals("input", results.get("input").getName()); + assertEquals("success", results.get("success").getName()); + assertEquals("failure", results.get("failure").getName()); + assertEquals(3, results.get("error").getParams().size()); + assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("error").getParams().get("location")); + assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("error").getClassName()); + assertEquals("value", results.get("success").getParams().get("key")); + assertEquals("value1", results.get("success").getParams().get("key1")); + assertEquals(3, results.get("input").getParams().size()); + assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("input").getParams().get("location")); + assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("input").getClassName()); + assertEquals(3, results.get("failure").getParams().size()); + assertEquals("/WEB-INF/location/namespace/action-failure.jsp", results.get("failure").getParams().get("location")); + assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("failure").getClassName()); + assertEquals(3, results.get("success").getParams().size()); + assertEquals("/WEB-INF/location/namespace/action-success.jsp", results.get("success").getParams().get("location")); + assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("success").getClassName()); + EasyMock.verify(context); + } + + public void testActionLevelMultipleResultNamesAnnotationErrorInput() throws Exception { + ServletContext context = EasyMock.createStrictMock(ServletContext.class); + + // Setup some mock jsps + Set<String> resources = new HashSet<>(); + EasyMock.expect(context.getResourcePaths("/WEB-INF/location/namespace/")).andReturn(resources); + EasyMock.replay(context); + + PackageConfig packageConfig = createPackageConfigBuilder("/namespace"); + + this.conventionsService = new ConventionsServiceImpl("/WEB-INF/location"); + DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, container, "dispatcher,velocity,freemarker"); + Map<String, ResultConfig> results = builder.build(ActionLevelResultsNamesAction.class, getAnnotation(ActionLevelResultsNamesAction.class, "errorinput", Action.class), "action-level-results", packageConfig); + assertEquals(2, results.size()); + assertEquals("error", results.get("error").getName()); + assertEquals("input", results.get("input").getName()); + assertEquals(3, results.get("error").getParams().size()); + assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("error").getParams().get("location")); + assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("error").getClassName()); + assertEquals(3, results.get("input").getParams().size()); + assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("input").getParams().get("location")); + assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("input").getClassName()); + EasyMock.verify(context); + } + + public void testActionLevelMultipleResultNamesAnnotationComma() throws Exception { + ServletContext context = EasyMock.createStrictMock(ServletContext.class); + + // Setup some mock jsps + Set<String> resources = new HashSet<>(); + EasyMock.expect(context.getResourcePaths("/WEB-INF/location/namespace/")).andReturn(resources); + EasyMock.replay(context); + + PackageConfig packageConfig = createPackageConfigBuilder("/namespace"); + + this.conventionsService = new ConventionsServiceImpl("/WEB-INF/location"); + DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, container, "dispatcher,velocity,freemarker"); + Map<String, ResultConfig> results = builder.build(ActionLevelResultsNamesAction.class, getAnnotation(ActionLevelResultsNamesAction.class, "comma", Action.class), "action-level-results", packageConfig); + assertEquals(1, results.size()); + assertEquals(" , ", results.get(" , ").getName()); + assertEquals(3, results.get(" , ").getParams().size()); + assertEquals("/WEB-INF/location/namespace/error.jsp", results.get(" , ").getParams().get("location")); + assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get(" , ").getClassName()); + EasyMock.verify(context); + } + + public void testActionLevelMultipleResultNamesAnnotationNoName() throws Exception { + ServletContext context = EasyMock.createStrictMock(ServletContext.class); + + // Setup some mock jsps + Set<String> resources = new HashSet<>(); + EasyMock.expect(context.getResourcePaths("/WEB-INF/location/namespace/")).andReturn(resources); + EasyMock.replay(context); + + PackageConfig packageConfig = createPackageConfigBuilder("/namespace"); + + this.conventionsService = new ConventionsServiceImpl("/WEB-INF/location"); + DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, container, "dispatcher,velocity,freemarker"); + Map<String, ResultConfig> results = builder.build(ActionLevelResultsNamesAction.class, getAnnotation(ActionLevelResultsNamesAction.class, "noname", Action.class), "action-level-results", packageConfig); + assertEquals(1, results.size()); + assertEquals("success", results.get("success").getName()); + assertEquals(3, results.get("success").getParams().size()); + assertEquals("value", results.get("success").getParams().get("key")); + assertEquals("value1", results.get("success").getParams().get("key1")); + assertEquals("/WEB-INF/location/namespace/action-success.jsp", results.get("success").getParams().get("location")); + assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("success").getClassName()); + EasyMock.verify(context); + } + public void testClassPath() throws Exception { ServletContext context = EasyMock.createNiceMock(ServletContext.class); http://git-wip-us.apache.org/repos/asf/struts/blob/087cf610/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 61ed3eb..7e47ff6 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 @@ -291,6 +291,10 @@ public class PackageBasedActionConfigBuilderTest extends TestCase { expect(resultMapBuilder.build(OverrideResultAction.class, getAnnotation(OverrideResultAction.class, "execute", Action.class), "override-result", resultPkg)).andReturn(results); expect(resultMapBuilder.build(GlobalResultAction.class, null, "global-result", globalResultPkg)).andReturn(results); expect(resultMapBuilder.build(GlobalResultOverrideAction.class, null, "global-result-override", globalResultPkg)).andReturn(results); + expect(resultMapBuilder.build(ActionLevelResultsNamesAction.class, getAnnotation(ActionLevelResultsNamesAction.class, "execute", Action.class), "action-level-results-names", resultPkg)).andReturn(results); + expect(resultMapBuilder.build(ActionLevelResultsNamesAction.class, getAnnotation(ActionLevelResultsNamesAction.class, "errorinput", Action.class), "action-level-results-names", resultPkg)).andReturn(results); + expect(resultMapBuilder.build(ActionLevelResultsNamesAction.class, getAnnotation(ActionLevelResultsNamesAction.class, "comma", Action.class), "action-level-results-names", resultPkg)).andReturn(results); + expect(resultMapBuilder.build(ActionLevelResultsNamesAction.class, getAnnotation(ActionLevelResultsNamesAction.class, "noname", Action.class), "action-level-results-names", resultPkg)).andReturn(results); /* org.apache.struts2.convention.actions.resultpath */ expect(resultMapBuilder.build(ClassLevelResultPathAction.class, null, "class-level-result-path", resultPathPkg)).andReturn(results); @@ -565,7 +569,7 @@ public class PackageBasedActionConfigBuilderTest extends TestCase { /* org.apache.struts2.convention.actions.result */ pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.result#struts-default#/result"); assertNotNull(pkgConfig); - assertEquals(6, pkgConfig.getActionConfigs().size()); + assertEquals(7, pkgConfig.getActionConfigs().size()); verifyActionConfig(pkgConfig, "class-level-result", ClassLevelResultAction.class, "execute", pkgConfig.getName()); verifyActionConfig(pkgConfig, "class-level-results", ClassLevelResultsAction.class, "execute", pkgConfig.getName()); verifyActionConfig(pkgConfig, "action-level-result", ActionLevelResultAction.class, "execute", pkgConfig.getName()); http://git-wip-us.apache.org/repos/asf/struts/blob/087cf610/plugins/convention/src/test/java/org/apache/struts2/convention/actions/result/ActionLevelResultsNamesAction.java ---------------------------------------------------------------------- diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/actions/result/ActionLevelResultsNamesAction.java b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/result/ActionLevelResultsNamesAction.java new file mode 100644 index 0000000..8ad30f1 --- /dev/null +++ b/plugins/convention/src/test/java/org/apache/struts2/convention/actions/result/ActionLevelResultsNamesAction.java @@ -0,0 +1,61 @@ +/* + * $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.result; + +import org.apache.struts2.convention.annotation.Action; +import org.apache.struts2.convention.annotation.Result; + +/** + * <p> + * This is a test action with multiple results names. + * </p> + */ +public class ActionLevelResultsNamesAction { + @Action(results = { + @Result(name="error, input", location="error.jsp"), + @Result(name="success", location="/WEB-INF/location/namespace/action-success.jsp"), + @Result(name="failure", location="/WEB-INF/location/namespace/action-failure.jsp") + }) + public String execute() { + return null; + } + + @Action(results = { + @Result(name="error, input, ", location="error.jsp") + }) + public String errorinput() { + return null; + } + + @Action(results = { + @Result(name=" , ", location="error.jsp") + }) + public String comma() { + return null; + } + + @Action(results = { + @Result(location="/WEB-INF/location/namespace/action-success.jsp") + }) + public String noname() { + return null; + } +}
