- URL Tag cause duplicates query string



git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@438940 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Toby Jee
2006-08-31 14:34:32 +00:00
parent ad4b4c218a
commit f40e13a076
4 changed files with 231 additions and 21 deletions
@@ -33,7 +33,9 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpUtils;
import java.io.IOException;
import java.io.Writer;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
/**
@@ -157,9 +159,10 @@ public class URL extends Component {
}
if (NONE.equalsIgnoreCase(includeParams)) {
mergeRequestParameters(value, parameters, Collections.EMPTY_MAP);
ActionContext.getContext().put(XWorkContinuationConfig.CONTINUE_KEY, null);
} else if (ALL.equalsIgnoreCase(includeParams)) {
mergeRequestParameters(parameters, req.getParameterMap());
mergeRequestParameters(value, parameters, req.getParameterMap());
// for ALL also include GET parameters
includeGetParameters();
@@ -179,10 +182,7 @@ public class URL extends Component {
private void includeGetParameters() {
if(!(Dispatcher.getInstance().isPortletSupportActive() && PortletActionContext.isPortletRequest())) {
String query = extractQueryString();
if (query != null) {
//mergeRequestParameters(parameters, HttpUtils.parseQueryString(query));
mergeRequestParameters(parameters, UrlHelper.parseQueryString(query));
}
mergeRequestParameters(value, parameters, UrlHelper.parseQueryString(query));
}
}
@@ -221,7 +221,14 @@ public class URL extends Component {
result = PortletUrlHelper.buildResourceUrl(value, parameters);
}
else {
result = UrlHelper.buildUrl(value, req, res, parameters, scheme, includeContext, encode);
String _value = value;
// We don't include the request parameters cause they would have been
// prioritised before this [in start(Writer) method]
if (_value != null && _value.indexOf("?") > 0) {
_value = _value.substring(0, _value.indexOf("?"));
}
result = UrlHelper.buildUrl(_value, req, res, parameters, scheme, includeContext, encode);
}
}
if ( anchor != null && anchor.length() > 0 ) {
@@ -345,13 +352,52 @@ public class URL extends Component {
/**
* Merge request parameters into current parameters. If a parameter is
* already present, than the request parameter will not override its value.
* already present, than the request parameter in the current request and value atrribute
* will not override its value.
*
* The priority is as follows:-
* <ul>
* <li>parameter from the current request (least priority)</li>
* <li>parameter form the value attribute (more priority)</li>
* <li>parameter from the param tag (most priority)</li>
* </ul>
*
* @param value the value attribute (url to be generated by this component)
* @param parameters component parameters
* @param contextParameters request parameters
*/
protected void mergeRequestParameters(Map parameters, Map contextParameters){
for (Iterator iterator = contextParameters.entrySet().iterator(); iterator.hasNext();) {
protected void mergeRequestParameters(String value, Map parameters, Map contextParameters){
Map mergedParams = new LinkedHashMap(contextParameters);
// Merge contextParameters (from current request) with parameters specified in value attribute
// eg. value="someAction.action?id=someId&venue=someVenue"
// where the parameters specified in value attribute takes priority.
if (value != null && value.trim().length() > 0 && value.indexOf("?") > 0) {
mergedParams = new LinkedHashMap();
String queryString = value.substring(value.indexOf("?")+1);
mergedParams = UrlHelper.parseQueryString(queryString);
for (Iterator iterator = contextParameters.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
Object key = entry.getKey();
if (!mergedParams.containsKey(key)) {
mergedParams.put(key, entry.getValue());
}
}
}
// Merge parameters specified in value attribute
// eg. value="someAction.action?id=someId&venue=someVenue"
// with parameters specified though param tag
// eg. <param name="id" value="%{'someId'}" />
// where parameters specified through param tag takes priority.
for (Iterator iterator = mergedParams.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
Object key = entry.getKey();
@@ -267,18 +267,20 @@ public class UrlHelper {
if (queryString != null) {
String[] params = queryString.split("&");
for (int a=0; a< params.length; a++) {
String[] tmpParams = params[a].split("=");
String paramName = null;
String paramValue = "";
if (tmpParams.length > 0) {
paramName = tmpParams[0];
}
if (tmpParams.length > 1) {
paramValue = tmpParams[1];
}
if (paramName != null) {
String translatedParamValue = translateAndDecode(paramValue);
queryParams.put(paramName, translatedParamValue);
if (params[a].trim().length() > 0) {
String[] tmpParams = params[a].split("=");
String paramName = null;
String paramValue = "";
if (tmpParams.length > 0) {
paramName = tmpParams[0];
}
if (tmpParams.length > 1) {
paramValue = tmpParams[1];
}
if (paramName != null) {
String translatedParamValue = translateAndDecode(paramValue);
queryParams.put(paramName, translatedParamValue);
}
}
}
}
@@ -18,6 +18,7 @@
package org.apache.struts2.views.jsp;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.jsp.JspWriter;
@@ -35,6 +36,151 @@ import com.opensymphony.xwork2.util.OgnlValueStack;
public class URLTagTest extends AbstractUITagTest {
private URLTag tag;
/**
* To test priority of parameter passed in to url component though
* various way
* - current request url
* - tag's value attribute
* - tag's nested param tag
*
* id1
* ===
* - found in current request url
* - found in tag's value attribute
* - found in tag's param tag
* CONCLUSION: tag's param tag takes precedence (paramId1)
*
* id2
* ===
* - found in current request url
* - found in tag's value attribute
* CONCLUSION: tag's value attribute take precedence (tagId2)
*
* urlParam1
* =========
* - found in current request url
* CONCLUSION: param in current request url will be used (urlValue1)
*
* urlParam2
* =========
* - found in current request url
* CONCLUSION: param in current request url will be used. (urlValue2)
*
* tagId
* =====
* - found in tag's value attribute
* CONCLUSION: param in tag's value attribute wil; be used. (tagValue)
*
* param1
* ======
* - found in nested param tag
* CONCLUSION: param in nested param tag will be used. (param1value)
*
* param2
* ======
* - found in nested param tag
* CONCLUSION: param in nested param tag will be used. (param2value)
*/
public void testParametersPriority() throws Exception {
request.setQueryString("id1=urlId1&id2=urlId2&urlParam1=urlValue1&urlParam2=urlValue2");
tag.setValue("testAction.action?id1=tagId1&id2=tagId2&tagId=tagValue");
ParamTag param1 = new ParamTag();
param1.setPageContext(pageContext);
param1.setName("param1");
param1.setValue("%{'param1value'}");
ParamTag param2 = new ParamTag();
param2.setPageContext(pageContext);
param2.setName("param2");
param2.setValue("%{'param2value'}");
ParamTag param3 = new ParamTag();
param3.setPageContext(pageContext);
param3.setName("id1");
param3.setValue("%{'paramId1'}");
tag.doStartTag();
param1.doStartTag();
param1.doEndTag();
param2.doStartTag();
param2.doEndTag();
param3.doStartTag();
param3.doEndTag();
URL url = (URL) tag.getComponent();
Map parameters = url.getParameters();
assertNotNull(parameters);
assertEquals(parameters.size(), 7);
assertEquals(parameters.get("id1"), "paramId1");
assertEquals(parameters.get("id2"), "tagId2");
assertEquals(parameters.get("urlParam1"), "urlValue1");
assertEquals(parameters.get("urlParam2"), "urlValue2");
assertEquals(parameters.get("tagId"), "tagValue");
assertEquals(parameters.get("param1"), "param1value");
assertEquals(parameters.get("param2"), "param2value");
}
/**
* To test priority of parameter passed in to url component though
* various way, with includeParams="NONE"
* - current request url
* - tag's value attribute
* - tag's nested param tag
*
* In this case only parameters from the tag itself is taken into account.
* Those from request will not count, only those in tag's value attribute
* and nested param tag.
*
* @throws Exception
*/
public void testParametersPriorityWithIncludeParamsAsNONE() throws Exception {
request.setQueryString("id1=urlId1&id2=urlId2&urlParam1=urlValue1&urlParam2=urlValue2");
tag.setValue("testAction.action?id1=tagId1&id2=tagId2&tagId=tagValue");
tag.setIncludeParams("NONE");
ParamTag param1 = new ParamTag();
param1.setPageContext(pageContext);
param1.setName("param1");
param1.setValue("%{'param1value'}");
ParamTag param2 = new ParamTag();
param2.setPageContext(pageContext);
param2.setName("param2");
param2.setValue("%{'param2value'}");
ParamTag param3 = new ParamTag();
param3.setPageContext(pageContext);
param3.setName("id1");
param3.setValue("%{'paramId1'}");
tag.doStartTag();
param1.doStartTag();
param1.doEndTag();
param2.doStartTag();
param2.doEndTag();
param3.doStartTag();
param3.doEndTag();
URL url = (URL) tag.getComponent();
Map parameters = url.getParameters();
assertEquals(parameters.size(), 5);
assertEquals(parameters.get("id1"), "paramId1");
assertEquals(parameters.get("id2"), "tagId2");
assertEquals(parameters.get("tagId"), "tagValue");
assertEquals(parameters.get("param1"), "param1value");
assertEquals(parameters.get("param2"), "param2value");
}
public void testIncludeParamsDefaultToGET() throws Exception {
request.setQueryString("one=oneVal&two=twoVal&three=threeVal");
@@ -25,6 +25,7 @@ import org.apache.struts2.config.Settings;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
@@ -281,6 +282,21 @@ public class UrlHelperTest extends StrutsTestCase {
assertEquals(result.get("ccc"), "");
}
public void testParseEmptyQuery() throws Exception {
Map result = UrlHelper.parseQueryString("");
assertNotNull(result);
assertEquals(result.size(), 0);
}
public void testParseNullQuery() throws Exception {
Map result = UrlHelper.parseQueryString(null);
assertNotNull(result);
assertEquals(result.size(), 0);
}
public void testTranslateAndEncode() throws Exception {
String defaultI18nEncoding = Settings.get(StrutsConstants.STRUTS_I18N_ENCODING);
try {