Merge pull request #630 from apache/WW-4514-url

[WW-4514] Fixes building query string with empty parameters
This commit is contained in:
Lukasz Lenart
2022-11-06 09:50:51 +01:00
committed by GitHub
14 changed files with 341 additions and 157 deletions
@@ -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)
;
@@ -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";
}
@@ -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);
@@ -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<String, Object> params, StringBuilder link, String paramSeparator);
}
@@ -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<String, Object> 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<String, Object> 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);
}
}
}
@@ -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<String, Object> 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<String, Object> 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<String, Object> 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<Map.Entry<String, Object>> iter = params.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, Object> 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.
*
@@ -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
@@ -313,6 +313,8 @@
<bean type="com.opensymphony.xwork2.ognl.BeanInfoCacheFactory" name="struts"
class="com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory" scope="singleton"/>
<bean type="org.apache.struts2.url.ParametersStringBuilder" name="strutsParametersStringBuilder"
class="org.apache.struts2.url.StrutsParametersStringBuilder" scope="singleton"/>
<bean type="org.apache.struts2.url.UrlEncoder" name="strutsUrlEncoder"
class="org.apache.struts2.url.StrutsUrlEncoder" scope="singleton"/>
<bean type="org.apache.struts2.url.UrlDecoder" name="strutsUrlDecoder"
@@ -112,7 +112,7 @@ public class StrutsBackgroundProcessTest extends StrutsInternalTestCase {
executor.execute(bp);
}
Thread.sleep(300);
Thread.sleep(400);
for (BackgroundProcess bp : bps) {
assertTrue("Process is still active: " + bp, bp.isDone());
@@ -0,0 +1,99 @@
/*
* 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 org.apache.struts2.views.util.UrlHelper;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
public class StrutsParametersStringBuilderTest {
private ParametersStringBuilder builder;
@Test
public void testBuildParametersStringWithUrlHavingSomeExistingParameters() {
String expectedUrl = "http://localhost:8080/myContext/myPage.jsp?initParam=initValue&amp;param1=value1&amp;param2=value2&amp;param3%22%3CsCrIpT%3Ealert%281%29%3B%3C%2FsCrIpT%3E=value3";
Map<String, Object> parameters = new LinkedHashMap<>();
parameters.put("param1", "value1");
parameters.put("param2", "value2");
parameters.put("param3\"<sCrIpT>alert(1);</sCrIpT>", "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&amp;param1=value1&amp;param2=value2&amp;param3%22%3Cscript+type%3D%22text%2Fjavascript%22%3Ealert%281%29%3B%3C%2Fscript%3E=value3";
Map<String, Object> parameters = new LinkedHashMap<>();
parameters.put("param1", "value1");
parameters.put("param2", "value2");
parameters.put("param3\"<script type=\"text/javascript\">alert(1);</script>", "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<String, Object> 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&param2=y&param2=z";
Map<String, Object> parameters = new LinkedHashMap<>();
parameters.put("param1", new String[]{"x"});
parameters.put("param2", new ArrayList<String>() {
{
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());
}
}
@@ -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();
@@ -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();
@@ -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&amp;param1=value1&amp;param2=value2&amp;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\"<sCrIpT>alert(1);</sCrIpT>","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&amp;param1=value1&amp;param2=value2&amp;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\"<script type=\"text/javascript\">alert(1);</script>","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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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("<a\">"), "<val>");
}
public void testParseEmptyQuery() throws Exception {
Map result = urlHelper.parseQueryString("", false);
public void testParseEmptyQuery() {
Map<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> overrides = new HashMap<String,Object>();
public Map<String, Object> overrides = new HashMap<>();
@SuppressWarnings("unchecked")
public <T> T getInstance(Class<T> type, String name) {
if (String.class.isAssignableFrom(type) && overrides.containsKey(name)) {
return (T) overrides.get(name);
@@ -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());
}
}