diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java index 2ac045d45..d193c4d24 100644 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java +++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java @@ -118,6 +118,8 @@ import org.apache.struts2.conversion.StrutsTypeConverterCreator; import org.apache.struts2.conversion.StrutsTypeConverterHolder; import org.apache.struts2.dispatcher.HttpParameters; import org.apache.struts2.dispatcher.Parameter; +import org.apache.struts2.url.ParametersStringBuilder; +import org.apache.struts2.url.StrutsParametersStringBuilder; import org.apache.struts2.url.StrutsUrlDecoder; import org.apache.struts2.url.StrutsUrlEncoder; import org.apache.struts2.url.UrlDecoder; @@ -234,6 +236,7 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider .factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON) + .factory(ParametersStringBuilder.class, StrutsParametersStringBuilder.class, Scope.SINGLETON) .factory(UrlEncoder.class, StrutsUrlEncoder.class, Scope.SINGLETON) .factory(UrlDecoder.class, StrutsUrlDecoder.class, Scope.SINGLETON) ; diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java index 5dff4724c..7f6955648 100644 --- a/core/src/main/java/org/apache/struts2/StrutsConstants.java +++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java @@ -458,6 +458,7 @@ public final class StrutsConstants { /** See {@link org.apache.struts2.components.Date#setDateFormatter(DateFormatter)} */ public static final String STRUTS_DATE_FORMATTER = "struts.date.formatter"; + public static final String STRUTS_URL_PARAMETERS_STRING_BUILDER = "struts.url.parametersStringBuilder"; public static final String STRUTS_URL_ENCODER = "struts.url.encoder"; public static final String STRUTS_URL_DECODER = "struts.url.decoder"; } diff --git a/core/src/main/java/org/apache/struts2/config/StrutsBeanSelectionProvider.java b/core/src/main/java/org/apache/struts2/config/StrutsBeanSelectionProvider.java index 2e5a9315c..15b79f09b 100644 --- a/core/src/main/java/org/apache/struts2/config/StrutsBeanSelectionProvider.java +++ b/core/src/main/java/org/apache/struts2/config/StrutsBeanSelectionProvider.java @@ -66,6 +66,7 @@ import org.apache.struts2.dispatcher.DispatcherErrorHandler; import org.apache.struts2.dispatcher.StaticContentLoader; import org.apache.struts2.dispatcher.mapper.ActionMapper; import org.apache.struts2.dispatcher.multipart.MultiPartRequest; +import org.apache.struts2.url.ParametersStringBuilder; import org.apache.struts2.url.UrlDecoder; import org.apache.struts2.url.UrlEncoder; import org.apache.struts2.util.ContentTypeMatcher; @@ -431,6 +432,7 @@ public class StrutsBeanSelectionProvider extends AbstractBeanSelectionProvider { alias(ExpressionCacheFactory.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, builder, props, Scope.SINGLETON); alias(BeanInfoCacheFactory.class, StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, builder, props, Scope.SINGLETON); + alias(ParametersStringBuilder.class, StrutsConstants.STRUTS_URL_PARAMETERS_STRING_BUILDER, builder, props, Scope.SINGLETON); alias(UrlEncoder.class, StrutsConstants.STRUTS_URL_ENCODER, builder, props, Scope.SINGLETON); alias(UrlDecoder.class, StrutsConstants.STRUTS_URL_DECODER, builder, props, Scope.SINGLETON); diff --git a/core/src/main/java/org/apache/struts2/url/ParametersStringBuilder.java b/core/src/main/java/org/apache/struts2/url/ParametersStringBuilder.java new file mode 100644 index 000000000..651c46ddb --- /dev/null +++ b/core/src/main/java/org/apache/struts2/url/ParametersStringBuilder.java @@ -0,0 +1,31 @@ +/* + * 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.url; + +import java.util.Map; + +/** + * A builder used to create a proper query string out of a set of parameters + * @since Struts 6.1.0 + */ +public interface ParametersStringBuilder { + + void buildParametersString(Map params, StringBuilder link, String paramSeparator); + +} diff --git a/core/src/main/java/org/apache/struts2/url/StrutsParametersStringBuilder.java b/core/src/main/java/org/apache/struts2/url/StrutsParametersStringBuilder.java new file mode 100644 index 000000000..e6e38f451 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/url/StrutsParametersStringBuilder.java @@ -0,0 +1,91 @@ +/* + * 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.url; + +import com.opensymphony.xwork2.inject.Inject; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Map; + +public class StrutsParametersStringBuilder implements ParametersStringBuilder { + + private static final Logger LOG = LogManager.getLogger(StrutsParametersStringBuilder.class); + + private final UrlEncoder encoder; + + @Inject + public StrutsParametersStringBuilder(UrlEncoder encoder) { + this.encoder = encoder; + } + + @Override + public void buildParametersString(Map params, StringBuilder link, String paramSeparator) { + if ((params != null) && (params.size() > 0)) { + LOG.debug("Building query string out of: {} parameters", params.size()); + StringBuilder queryString = new StringBuilder(); + + // Set params + for (Map.Entry entry : params.entrySet()) { + String name = entry.getKey(); + Object value = entry.getValue(); + + if (value instanceof Iterable) { + for (Object o : (Iterable) value) { + appendParameterSubstring(queryString, paramSeparator, name, o); + } + } else if (value instanceof Object[]) { + Object[] array = (Object[]) value; + for (Object o : array) { + appendParameterSubstring(queryString, paramSeparator, name, o); + } + } else { + appendParameterSubstring(queryString, paramSeparator, name, value); + } + } + + if (queryString.length() > 0) { + if (!link.toString().contains("?")) { + link.append("?"); + } else { + link.append(paramSeparator); + } + link.append(queryString); + } + } else { + LOG.debug("Params are empty, skipping building the query string"); + } + } + + private void appendParameterSubstring(StringBuilder queryString, String paramSeparator, String name, Object value) { + if (queryString.length() > 0) { + queryString.append(paramSeparator); + } + + String encodedName = encoder.encode(name); + queryString.append(encodedName); + + queryString.append('='); + if (value != null) { + String encodedValue = encoder.encode(value.toString()); + queryString.append(encodedValue); + } + } + +} diff --git a/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java b/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java index 9f383c611..547efef11 100644 --- a/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java +++ b/core/src/main/java/org/apache/struts2/views/util/DefaultUrlHelper.java @@ -24,6 +24,7 @@ import org.apache.commons.text.StringEscapeUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.StrutsConstants; +import org.apache.struts2.url.ParametersStringBuilder; import org.apache.struts2.url.UrlDecoder; import org.apache.struts2.url.UrlEncoder; @@ -31,7 +32,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.Arrays; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -49,6 +49,7 @@ public class DefaultUrlHelper implements UrlHelper { private int httpPort = DEFAULT_HTTP_PORT; private int httpsPort = DEFAULT_HTTPS_PORT; + private ParametersStringBuilder parametersStringBuilder; private UrlEncoder encoder; private UrlDecoder decoder; @@ -72,6 +73,11 @@ public class DefaultUrlHelper implements UrlHelper { this.decoder = decoder; } + @Inject + public void setParametersStringBuilder(ParametersStringBuilder builder) { + this.parametersStringBuilder = builder; + } + public String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params) { return buildUrl(action, request, response, params, null, true, true); } @@ -170,9 +176,9 @@ public class DefaultUrlHelper implements UrlHelper { //if the action was not explicitly set grab the params from the request if (escapeAmp) { - buildParametersString(params, link, AMP, true); + parametersStringBuilder.buildParametersString(params, link, AMP); } else { - buildParametersString(params, link, "&", true); + parametersStringBuilder.buildParametersString(params, link, "&"); } String result = link.toString(); @@ -197,65 +203,35 @@ public class DefaultUrlHelper implements UrlHelper { } } + /** + * Builds parameters assigned to url - a query string + * @param params a set of params to assign + * @param link a based url + * @param paramSeparator separator used + * @deprecated since Struts 6.1.0, use {@link ParametersStringBuilder} instead + */ + @Deprecated public void buildParametersString(Map params, StringBuilder link, String paramSeparator) { - buildParametersString(params, link, paramSeparator, true); + parametersStringBuilder.buildParametersString(params, link, paramSeparator); } + /** + * Builds parameters assigned to url - a query string + * @param params a set of params to assign + * @param link a based url + * @param paramSeparator separator used + * @param encode if true, parameters will be encoded - ignored + * @deprecated since Struts 6.1.0, use {@link #buildParametersString(Map, StringBuilder, String)} + */ + @Deprecated public void buildParametersString(Map params, StringBuilder link, String paramSeparator, boolean encode) { - if ((params != null) && (params.size() > 0)) { - if (!link.toString().contains("?")) { - link.append("?"); - } else { - link.append(paramSeparator); - } - - // Set params - Iterator> iter = params.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = iter.next(); - String name = entry.getKey(); - Object value = entry.getValue(); - - if (value instanceof Iterable) { - for (Iterator iterator = ((Iterable) value).iterator(); iterator.hasNext(); ) { - Object paramValue = iterator.next(); - link.append(buildParameterSubstring(name, paramValue != null ? paramValue.toString() : StringUtils.EMPTY, encode)); - - if (iterator.hasNext()) { - link.append(paramSeparator); - } - } - } else if (value instanceof Object[]) { - Object[] array = (Object[]) value; - for (int i = 0; i < array.length; i++) { - Object paramValue = array[i]; - link.append(buildParameterSubstring(name, paramValue != null ? paramValue.toString() : StringUtils.EMPTY, encode)); - - if (i < array.length - 1) { - link.append(paramSeparator); - } - } - } else { - link.append(buildParameterSubstring(name, value != null ? value.toString() : StringUtils.EMPTY, encode)); - } - - if (iter.hasNext()) { - link.append(paramSeparator); - } - } - } + buildParametersString(params, link, paramSeparator); } protected boolean isValidScheme(String scheme) { return HTTP_PROTOCOL.equals(scheme) || HTTPS_PROTOCOL.equals(scheme); } - private String buildParameterSubstring(String name, String value, boolean encode) { - String encodedName = encode ? encoder.encode(name) : name; - String encodedValue = encode ? encoder.encode(value) : value; - return encodedName + '=' + encodedValue; - } - /** * Encodes the URL using {@link UrlEncoder#encode} with the encoding specified in the configuration. * diff --git a/core/src/main/resources/org/apache/struts2/default.properties b/core/src/main/resources/org/apache/struts2/default.properties index 07f362a7a..a57c48bea 100644 --- a/core/src/main/resources/org/apache/struts2/default.properties +++ b/core/src/main/resources/org/apache/struts2/default.properties @@ -279,6 +279,12 @@ struts.ognl.expressionMaxLength=256 ### These formatters are using a slightly different patterns, please check JavaDocs of both and more details is in WW-5016 struts.date.formatter=dateTimeFormatter +### Defines which instance of ParametersStringBuilder to use, Struts provides just one instance: +### - strutsParametersStringBuilder +### The builder is used by UrlHelp to create a proper query string out of provided parameters map +struts.url.parametersStringBuilder=strutsParametersStringBuilder + +### Defines which instances of encoder and decoder to use, Struts provides one default implementation for each struts.url.encoder=strutsUrlEncoder struts.url.decoder=strutsUrlDecoder diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml index 7980af2f2..35b5bf419 100644 --- a/core/src/main/resources/struts-default.xml +++ b/core/src/main/resources/struts-default.xml @@ -313,6 +313,8 @@ + parameters = new LinkedHashMap<>(); + parameters.put("param1", "value1"); + parameters.put("param2", "value2"); + parameters.put("param3\"", "value3"); + + StringBuilder url = new StringBuilder("http://localhost:8080/myContext/myPage.jsp?initParam=initValue"); + + builder.buildParametersString(parameters, url, UrlHelper.AMP); + + assertEquals(expectedUrl, url.toString()); + } + + @Test + public void testBuildParametersStringWithJavaScriptInjected() { + String expectedUrl = "http://localhost:8080/myContext/myPage.jsp?initParam=initValue&param1=value1&param2=value2&param3%22%3Cscript+type%3D%22text%2Fjavascript%22%3Ealert%281%29%3B%3C%2Fscript%3E=value3"; + + Map parameters = new LinkedHashMap<>(); + parameters.put("param1", "value1"); + parameters.put("param2", "value2"); + parameters.put("param3\"", "value3"); + + StringBuilder url = new StringBuilder("http://localhost:8080/myContext/myPage.jsp?initParam=initValue"); + + builder.buildParametersString(parameters, url, UrlHelper.AMP); + + assertEquals(expectedUrl, url.toString()); + } + + @Test + public void testBuildParametersStringWithEmptyListParameters() { + String expectedUrl = "https://www.nowhere.com/myworld.html"; + Map parameters = new LinkedHashMap<>(); + parameters.put("param1", new String[]{}); + parameters.put("param2", new ArrayList<>()); + StringBuilder url = new StringBuilder("https://www.nowhere.com/myworld.html"); + builder.buildParametersString(parameters, url, UrlHelper.AMP); + assertEquals(expectedUrl, url.toString()); + } + + @Test + public void testBuildParametersStringWithListParameters() { + String expectedUrl = "https://www.nowhere.com/myworld.html?param1=x¶m2=y¶m2=z"; + Map parameters = new LinkedHashMap<>(); + parameters.put("param1", new String[]{"x"}); + parameters.put("param2", new ArrayList() { + { + add("y"); + add("z"); + } + }); + StringBuilder url = new StringBuilder("https://www.nowhere.com/myworld.html"); + builder.buildParametersString(parameters, url, "&"); + assertEquals(expectedUrl, url.toString()); + } + + @Before + public void setUp() throws Exception { + builder = new StrutsParametersStringBuilder(new StrutsUrlEncoder()); + } + +} diff --git a/core/src/test/java/org/apache/struts2/url/StrutsUrlDecoderTest.java b/core/src/test/java/org/apache/struts2/url/StrutsUrlDecoderTest.java index 5dd44f897..cd52ba75b 100644 --- a/core/src/test/java/org/apache/struts2/url/StrutsUrlDecoderTest.java +++ b/core/src/test/java/org/apache/struts2/url/StrutsUrlDecoderTest.java @@ -18,6 +18,7 @@ */ package org.apache.struts2.url; +import org.apache.struts2.StrutsConstants; import org.junit.Before; import org.junit.Test; @@ -105,6 +106,13 @@ public class StrutsUrlDecoderTest { assertEquals("xxxxA", result); } + @Test + public void testDecoding() { + String result = decoder.decode("%E6%96%B0%E8%81%9E"); + + assertEquals("\u65b0\u805e", result); + } + @Before public void setUp() throws Exception { this.decoder = new StrutsUrlDecoder(); diff --git a/core/src/test/java/org/apache/struts2/url/StrutsUrlEncoderTest.java b/core/src/test/java/org/apache/struts2/url/StrutsUrlEncoderTest.java index 95aaacda6..87b5bcce9 100644 --- a/core/src/test/java/org/apache/struts2/url/StrutsUrlEncoderTest.java +++ b/core/src/test/java/org/apache/struts2/url/StrutsUrlEncoderTest.java @@ -82,6 +82,13 @@ public class StrutsUrlEncoderTest { assertEquals("%25xxxx", result); } + @Test + public void testEncoding() { + String result = encoder.encode("\u65b0\u805e"); + + assertEquals("%E6%96%B0%E8%81%9E", result); + } + @Before public void setUp() throws Exception { this.encoder = new StrutsUrlEncoder(); diff --git a/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java b/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java index 3e70e7a44..acbee3010 100644 --- a/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java +++ b/core/src/test/java/org/apache/struts2/views/util/DefaultUrlHelperTest.java @@ -18,36 +18,30 @@ */ package org.apache.struts2.views.util; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.struts2.StrutsConstants; -import org.apache.struts2.StrutsInternalTestCase; - import com.mockobjects.dynamic.Mock; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.inject.Container; import com.opensymphony.xwork2.inject.Scope.Strategy; +import org.apache.struts2.StrutsInternalTestCase; +import org.apache.struts2.url.StrutsParametersStringBuilder; import org.apache.struts2.url.StrutsUrlDecoder; import org.apache.struts2.url.StrutsUrlEncoder; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; /** * Test case for DefaultUrlHelper. - * */ public class DefaultUrlHelperTest extends StrutsInternalTestCase { - private StubContainer stubContainer; private DefaultUrlHelper urlHelper; - public void testForceAddSchemeHostAndPort() throws Exception { + public void testForceAddSchemeHostAndPort() { String expectedUrl = "http://localhost/contextPath/path1/path2/myAction.action"; Mock mockHttpServletRequest = new Mock(HttpServletRequest.class); @@ -64,7 +58,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { mockHttpServletRequest.verify(); } - public void testDoNotForceAddSchemeHostAndPort() throws Exception { + public void testDoNotForceAddSchemeHostAndPort() { String expectedUrl = "/contextPath/path1/path2/myAction.action"; Mock mockHttpServletRequest = new Mock(HttpServletRequest.class); @@ -80,7 +74,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { assertEquals(expectedUrl, result); } - public void testForceAddSchemeHostAndPortWithNonStandardPort() throws Exception { + public void testForceAddSchemeHostAndPortWithNonStandardPort() { String expectedUrl = "http://localhost:9090/contextPath/path1/path2/myAction.action"; Mock mockHttpServletRequest = new Mock(HttpServletRequest.class); @@ -97,39 +91,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { mockHttpServletRequest.verify(); } - public void testBuildParametersStringWithUrlHavingSomeExistingParameters() throws Exception { - String expectedUrl = "http://localhost:8080/myContext/myPage.jsp?initParam=initValue&param1=value1&param2=value2&param3%22%3CsCrIpT%3Ealert%281%29%3B%3C%2FsCrIpT%3E=value3"; - - Map parameters = new LinkedHashMap(); - parameters.put("param1", "value1"); - parameters.put("param2", "value2"); - parameters.put("param3\"","value3"); - - StringBuilder url = new StringBuilder("http://localhost:8080/myContext/myPage.jsp?initParam=initValue"); - - urlHelper.buildParametersString(parameters, url, UrlHelper.AMP); - - assertEquals( - expectedUrl, url.toString()); - } - - public void testBuildParametersStringWithJavaScriptInjected() throws Exception { - String expectedUrl = "http://localhost:8080/myContext/myPage.jsp?initParam=initValue&param1=value1&param2=value2&param3%22%3Cscript+type%3D%22text%2Fjavascript%22%3Ealert%281%29%3B%3C%2Fscript%3E=value3"; - - Map parameters = new LinkedHashMap(); - parameters.put("param1", "value1"); - parameters.put("param2", "value2"); - parameters.put("param3\"","value3"); - - StringBuilder url = new StringBuilder("http://localhost:8080/myContext/myPage.jsp?initParam=initValue"); - - urlHelper.buildParametersString(parameters, url, UrlHelper.AMP); - - assertEquals( - expectedUrl, url.toString()); - } - - public void testForceAddNullSchemeHostAndPort() throws Exception { + public void testForceAddNullSchemeHostAndPort() { String expectedUrl = "http://localhost/contextPath/path1/path2/myAction.action"; Mock mockHttpServletRequest = new Mock(HttpServletRequest.class); @@ -144,14 +106,14 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { expectedUrl); String result = urlHelper.buildUrl("/path1/path2/myAction.action", - (HttpServletRequest) mockHttpServletRequest.proxy(), - (HttpServletResponse) mockHttpServletResponse.proxy(), null, - null, true, true, true); + (HttpServletRequest) mockHttpServletRequest.proxy(), + (HttpServletResponse) mockHttpServletResponse.proxy(), null, + null, true, true, true); assertEquals(expectedUrl, result); mockHttpServletRequest.verify(); } - public void testForceAddNullSchemeHostAndPort2() throws Exception { + public void testForceAddNullSchemeHostAndPort2() { String expectedUrl = "http://localhost:8080/contextPath/path1/path2/myAction.action"; Mock mockHttpServletRequest = new Mock(HttpServletRequest.class); @@ -166,9 +128,9 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { expectedUrl); String result = urlHelper.buildUrl("/path1/path2/myAction.action", - (HttpServletRequest) mockHttpServletRequest.proxy(), - (HttpServletResponse) mockHttpServletResponse.proxy(), null, - null, true, true, true); + (HttpServletRequest) mockHttpServletRequest.proxy(), + (HttpServletResponse) mockHttpServletResponse.proxy(), null, + null, true, true, true); assertEquals(expectedUrl, result); mockHttpServletRequest.verify(); } @@ -184,7 +146,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { mockHttpServletResponse.expectAndReturn("encodeURL", expectedUrl, expectedUrl); String actualUrl = urlHelper.buildUrl(expectedUrl, (HttpServletRequest) mockHttpServletRequest.proxy(), - (HttpServletResponse) mockHttpServletResponse.proxy(), new HashMap()); + (HttpServletResponse) mockHttpServletResponse.proxy(), new HashMap<>()); assertEquals(expectedUrl, actualUrl); } @@ -199,7 +161,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { mockHttpServletResponse.expectAndReturn("encodeURL", expectedString, expectedString); String actionName = "my.actionName"; - TreeMap params = new TreeMap(); + TreeMap params = new TreeMap<>(); params.put("hello", "world"); params.put("foo", "bar"); @@ -218,7 +180,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { mockHttpServletResponse.expectAndReturn("encodeURL", expectedString, expectedString); String actionName = "my.actionName"; - TreeMap params = new TreeMap(); + TreeMap params = new TreeMap<>(); params.put("hello", "world"); params.put("foo", "bar"); @@ -234,7 +196,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { mockHttpServletResponse.expectAndReturn("encodeURL", expectedString, expectedString); String actionName = "my.actionName"; - TreeMap params = new TreeMap(); + TreeMap params = new TreeMap<>(); params.put("hello", new String[]{"earth", "mars"}); params.put("foo", "bar"); @@ -259,7 +221,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { mockHttpServletResponse.expectAndReturn("encodeURL", expectedString, expectedString); String actionName = "/MyAction.action"; - TreeMap params = new TreeMap(); + TreeMap params = new TreeMap<>(); params.put("hello", new String[]{"earth", "mars"}); params.put("foo", "bar"); @@ -284,7 +246,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { mockHttpServletResponse.expectAndReturn("encodeURL", expectedString, expectedString); String actionName = "/MyAction.action"; - TreeMap params = new TreeMap(); + TreeMap params = new TreeMap<>(); params.put("hello", new String[]{"earth", "mars"}); params.put("foo", "bar"); @@ -313,7 +275,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { mockHttpServletResponse.expectAndReturn("encodeURL", expectedString, expectedString); String actionName = "/MyAction.action"; - TreeMap params = new TreeMap(); + TreeMap params = new TreeMap<>(); params.put("hello", new String[]{"earth", "mars"}); params.put("foo", "bar"); @@ -342,7 +304,7 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { mockHttpServletResponse.expectAndReturn("encodeURL", expectedString, expectedString); String actionName = "/MyAction.action"; - TreeMap params = new TreeMap(); + TreeMap params = new TreeMap<>(); params.put("hello", new String[]{"earth", "mars"}); params.put("foo", "bar"); @@ -371,15 +333,15 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { mockHttpServletResponse.expectAndReturn("encodeURL", expectedString, expectedString); String actionName = "promo.html"; - Map params = new TreeMap(); + TreeMap params = new TreeMap<>(); String urlString = urlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, "https", true, true); assertEquals(expectedString, urlString); } - public void testParseQuery() throws Exception { - Map result = urlHelper.parseQueryString("aaa=aaaval&bbb=bbbval&ccc=&%3Ca%22%3E=%3Cval%3E", false); + public void testParseQuery() { + Map result = urlHelper.parseQueryString("aaa=aaaval&bbb=bbbval&ccc=&%3Ca%22%3E=%3Cval%3E", false); assertEquals(result.get("aaa"), "aaaval"); assertEquals(result.get("bbb"), "bbbval"); @@ -387,38 +349,21 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { assertEquals(result.get(""), ""); } - public void testParseEmptyQuery() throws Exception { - Map result = urlHelper.parseQueryString("", false); + public void testParseEmptyQuery() { + Map result = urlHelper.parseQueryString("", false); assertNotNull(result); assertEquals(result.size(), 0); } - public void testParseNullQuery() throws Exception { - Map result = urlHelper.parseQueryString(null, false); + public void testParseNullQuery() { + Map result = urlHelper.parseQueryString(null, false); assertNotNull(result); assertEquals(result.size(), 0); } - - public void testEncode() throws Exception { - setProp(StrutsConstants.STRUTS_I18N_ENCODING, "UTF-8"); - String result = urlHelper.encode("\u65b0\u805e"); - String expectedResult = "%E6%96%B0%E8%81%9E"; - - assertEquals(result, expectedResult); - } - - public void testDecode() throws Exception { - setProp(StrutsConstants.STRUTS_I18N_ENCODING, "UTF-8"); - String result = urlHelper.decode("%E6%96%B0%E8%81%9E"); - String expectedResult = "\u65b0\u805e"; - - assertEquals(result, expectedResult); - } - - public void testDecodeSpacesInQueryString() throws Exception { + public void testDecodeSpacesInQueryString() { Map queryParameters = urlHelper.parseQueryString("name=value+with+space", false); assertTrue(queryParameters.containsKey("name")); @@ -428,18 +373,16 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { public void setUp() throws Exception { super.setUp(); - stubContainer = new StubContainer(container); + StubContainer stubContainer = new StubContainer(container); ActionContext.getContext().withContainer(stubContainer); urlHelper = new DefaultUrlHelper(); - urlHelper.setEncoder(new StrutsUrlEncoder()); + StrutsUrlEncoder encoder = new StrutsUrlEncoder(); + urlHelper.setParametersStringBuilder(new StrutsParametersStringBuilder(encoder)); + urlHelper.setEncoder(encoder); urlHelper.setDecoder(new StrutsUrlDecoder()); } - private void setProp(String key, String val) { - stubContainer.overrides.put(key, val); - } - - class StubContainer implements Container { + static class StubContainer implements Container { Container parent; @@ -448,7 +391,9 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase { this.parent = parent; } - public Map overrides = new HashMap(); + public Map overrides = new HashMap<>(); + + @SuppressWarnings("unchecked") public T getInstance(Class type, String name) { if (String.class.isAssignableFrom(type) && overrides.containsKey(name)) { return (T) overrides.get(name); diff --git a/plugins/json/src/test/java/org/apache/struts2/json/JSONActionRedirectResultTest.java b/plugins/json/src/test/java/org/apache/struts2/json/JSONActionRedirectResultTest.java index 9e93fc5d1..268ee6087 100644 --- a/plugins/json/src/test/java/org/apache/struts2/json/JSONActionRedirectResultTest.java +++ b/plugins/json/src/test/java/org/apache/struts2/json/JSONActionRedirectResultTest.java @@ -26,6 +26,9 @@ import com.opensymphony.xwork2.util.ValueStack; import org.apache.struts2.StrutsStatics; import org.apache.struts2.dispatcher.mapper.DefaultActionMapper; import org.apache.struts2.junit.StrutsTestCase; +import org.apache.struts2.url.StrutsParametersStringBuilder; +import org.apache.struts2.url.StrutsUrlDecoder; +import org.apache.struts2.url.StrutsUrlEncoder; import org.apache.struts2.views.util.DefaultUrlHelper; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @@ -33,6 +36,9 @@ import org.springframework.mock.web.MockServletContext; public class JSONActionRedirectResultTest extends StrutsTestCase { + private DefaultActionMapper actionMapper; + private DefaultUrlHelper urlHelper; + MockActionInvocation invocation; MockHttpServletResponse response; MockServletContext servletContext; @@ -43,8 +49,8 @@ public class JSONActionRedirectResultTest extends StrutsTestCase { public void testNormalRedirect() throws Exception { JSONActionRedirectResult result = new JSONActionRedirectResult(); result.setActionName("targetAction"); - result.setActionMapper(new DefaultActionMapper()); - result.setUrlHelper(new DefaultUrlHelper()); + result.setActionMapper(actionMapper); + result.setUrlHelper(urlHelper); Object action = new Object(); stack.push(action); @@ -62,8 +68,8 @@ public class JSONActionRedirectResultTest extends StrutsTestCase { public void testJsonRedirect() throws Exception { JSONActionRedirectResult result = new JSONActionRedirectResult(); result.setActionName("targetAction"); - result.setActionMapper(new DefaultActionMapper()); - result.setUrlHelper(new DefaultUrlHelper()); + result.setActionMapper(actionMapper); + result.setUrlHelper(urlHelper); request.setParameter("struts.enableJSONValidation", "true"); request.setParameter("struts.validateOnly", "false"); @@ -82,8 +88,8 @@ public class JSONActionRedirectResultTest extends StrutsTestCase { public void testValidateOnlyFalse() throws Exception { JSONActionRedirectResult result = new JSONActionRedirectResult(); result.setActionName("targetAction"); - result.setActionMapper(new DefaultActionMapper()); - result.setUrlHelper(new DefaultUrlHelper()); + result.setActionMapper(actionMapper); + result.setUrlHelper(urlHelper); request.setParameter("struts.enableJSONValidation", "true"); request.setParameter("struts.validateOnly", "true"); @@ -118,5 +124,12 @@ public class JSONActionRedirectResultTest extends StrutsTestCase { MockActionProxy mockActionProxy = new MockActionProxy(); mockActionProxy.setConfig(new ActionConfig.Builder(null, null, null).build()); this.invocation.setProxy(mockActionProxy); + + this.actionMapper = new DefaultActionMapper(); + this.urlHelper = new DefaultUrlHelper(); + StrutsUrlEncoder encoder = new StrutsUrlEncoder(); + this.urlHelper.setParametersStringBuilder(new StrutsParametersStringBuilder(encoder)); + this.urlHelper.setEncoder(encoder); + this.urlHelper.setDecoder(new StrutsUrlDecoder()); } }