Author: jholmes Date: Tue Jul 24 11:15:13 2007 New Revision: 559146 URL: http://svn.apache.org/viewvc?view=rev&rev=559146 Log: WW-1938 Bug with multiple s:param tags inside s:url tag
Modified: struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Component.java struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/URL.java struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/URLTag.java struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java struts/struts2/branches/STRUTS_2_0_X/core/src/site/resources/tags/url.html struts/struts2/branches/STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java struts/struts2/branches/STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/util/UrlHelperTest.java Modified: struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Component.java URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Component.java?view=diff&rev=559146&r1=559145&r2=559146 ============================================================================== --- struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Component.java (original) +++ struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Component.java Tue Jul 24 11:15:13 2007 @@ -338,12 +338,13 @@ */ protected String determineActionURL(String action, String namespace, String method, HttpServletRequest req, HttpServletResponse res, Map parameters, String scheme, - boolean includeContext, boolean encodeResult) { + boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort, + boolean escapeAmp) { String finalAction = findString(action); String finalNamespace = determineNamespace(namespace, getStack(), req); ActionMapping mapping = new ActionMapping(finalAction, finalNamespace, method, parameters); String uri = actionMapper.getUriFromActionMapping(mapping); - return UrlHelper.buildUrl(uri, req, res, parameters, scheme, includeContext, encodeResult); + return UrlHelper.buildUrl(uri, req, res, parameters, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, escapeAmp); } /** Modified: struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/URL.java URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/URL.java?view=diff&rev=559146&r1=559145&r2=559146 ============================================================================== --- struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/URL.java (original) +++ struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/URL.java Tue Jul 24 11:15:13 2007 @@ -53,6 +53,12 @@ * additional request parameters.</p> * * <b>NOTE:</b> + * <p>By default request parameters will be separated using escaped ampersands (i.e., &amp;). + * This is necessary for XHTML compliance, however, when using the URL generated by this tag + * with the <s:property> tag, the <b>escapeAmp</b> attribute should be used to disable + * ampersand escaping.</p> + * + * <b>NOTE:</b> * <p>When includeParams is 'all' or 'get', the parameter defined in param tag will take * precedence and will not be overriden if they exists in the parameter submitted. For * example, in Example 3 below, if there is a id parameter in the url where the page this @@ -68,16 +74,20 @@ * <ul> * <li>action (String) - (value or action choose either one, if both exist value takes precedence) action's name (alias) <li> * <li>value (String) - (value or action choose either one, if both exist value takes precedence) the url itself</li> - * <li>scheme (String) - http scheme (http, https) default to the scheme this request is in</li> + * <li>scheme (String) - http scheme (http, https) defaults to the scheme this request is in</li> * <li>namespace - action's namespace</li> - * <li>method (String) - action's method, default to execute() </li> - * <li>encode (Boolean) - url encode the generated url. Default is true</li> - * <li>includeParams (String) - The includeParams attribute may have the value 'none', 'get' or 'all'. Default is 'get'. + * <li>method (String) - action's method name, defaults to 'execute'</li> + * <li>encode (Boolean) - url encode the generated url. Defaults to 'true'.</li> + * <li>includeParams (String) - The includeParams attribute may have the value 'none', 'get' or 'all'. Defaults to 'get'. * none - include no parameters in the URL * get - include only GET parameters in the URL (default) * all - include both GET and POST parameters in the URL * </li> - * <li>includeContext (Boolean) - determine wheather to include the web app context path. Default is true.</li> + * <li>includeContext (Boolean) - Specifies whether to include the web app context path. Defaults to 'true'.</li> + * <li>escapeAmp (Boolean) - Specifies whether to escape ampersand (&) to (&amp;) or not. Defaults to 'true'.</li> + * <li>portletMode (String) - The resulting portlet mode.</li> + * <li>windowState (String) - The resulting portlet window state.</li> + * <li>portletUrlType (String) - Specifies if this should be a portlet render or action URL.</li> * </ul> * * <!-- END SNIPPET: params --> @@ -135,6 +145,7 @@ protected String method; protected boolean encode = true; protected boolean includeContext = true; + protected boolean escapeAmp = true; protected String portletMode; protected String windowState; protected String portletUrlType; @@ -240,7 +251,7 @@ result = PortletUrlHelper.buildUrl(action, namespace, parameters, portletUrlType, portletMode, windowState); } else { - result = determineActionURL(action, namespace, method, req, res, parameters, scheme, includeContext, encode); + result = determineActionURL(action, namespace, method, req, res, parameters, scheme, includeContext, encode, false, escapeAmp); } } else { if(Dispatcher.getInstance().isPortletSupportActive() && PortletActionContext.isPortletRequest()) { @@ -254,7 +265,7 @@ if (_value != null && _value.indexOf("?") > 0) { _value = _value.substring(0, _value.indexOf("?")); } - result = UrlHelper.buildUrl(_value, req, res, parameters, scheme, includeContext, encode); + result = UrlHelper.buildUrl(_value, req, res, parameters, scheme, includeContext, encode, false, escapeAmp); } } if ( anchor != null && anchor.length() > 0 ) { @@ -336,6 +347,11 @@ @StrutsTagAttribute(description="The anchor for this URL") public void setAnchor(String anchor) { this.anchor = anchor; + } + + @StrutsTagAttribute(description="Specifies whether to escape ampersand (&) to (&amp;) or not", type="Boolean", defaultValue="true") + public void setEscapeAmp(boolean escapeAmp) { + this.escapeAmp = escapeAmp; } Modified: struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/URLTag.java URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/URLTag.java?view=diff&rev=559146&r1=559145&r2=559146 ============================================================================== --- struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/URLTag.java (original) +++ struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/URLTag.java Tue Jul 24 11:15:13 2007 @@ -44,6 +44,7 @@ protected String method; protected String encode; protected String includeContext; + protected String escapeAmp; protected String portletMode; protected String windowState; protected String portletUrlType; @@ -74,6 +75,9 @@ if (includeContext != null) { url.setIncludeContext(Boolean.valueOf(includeContext).booleanValue()); } + if (escapeAmp != null) { + url.setEscapeAmp(Boolean.valueOf(escapeAmp).booleanValue()); + } } public void setEncode(String encode) { @@ -82,6 +86,10 @@ public void setIncludeContext(String includeContext) { this.includeContext = includeContext; + } + + public void setEscapeAmp(String escapeAmp) { + this.escapeAmp = escapeAmp; } public void setIncludeParams(String name) { Modified: struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java?view=diff&rev=559146&r1=559145&r2=559146 ============================================================================== --- struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java (original) +++ struts/struts2/branches/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java Tue Jul 24 11:15:13 2007 @@ -91,6 +91,10 @@ } public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort) { + return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, true); + } + + public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort, boolean escapeAmp) { StringBuffer link = new StringBuffer(); boolean changedScheme = false; @@ -169,7 +173,11 @@ } //if the action was not explicitly set grab the params from the request - buildParametersString(params, link); + if (escapeAmp) { + buildParametersString(params, link); + } else { + buildParametersString(params, link, "&"); + } String result; Modified: struts/struts2/branches/STRUTS_2_0_X/core/src/site/resources/tags/url.html URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_2_0_X/core/src/site/resources/tags/url.html?view=diff&rev=559146&r1=559145&r2=559146 ============================================================================== --- struts/struts2/branches/STRUTS_2_0_X/core/src/site/resources/tags/url.html (original) +++ struts/struts2/branches/STRUTS_2_0_X/core/src/site/resources/tags/url.html Tue Jul 24 11:15:13 2007 @@ -52,6 +52,14 @@ <td align="left" valign="top">Whether to encode parameters</td> </tr> <tr> + <td align="left" valign="top">escapeAmp</td> + <td align="left" valign="top">false</td> + <td align="left" valign="top">true</td> + <td align="left" valign="top">true</td> + <td align="left" valign="top">Boolean</td> + <td align="left" valign="top">Specifies whether to escape ampersand (&) to (&amp;) or not</td> + </tr> + <tr> <td align="left" valign="top">id</td> <td align="left" valign="top">false</td> <td align="left" valign="top"></td> Modified: struts/struts2/branches/STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java?view=diff&rev=559146&r1=559145&r2=559146 ============================================================================== --- struts/struts2/branches/STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java (original) +++ struts/struts2/branches/STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java Tue Jul 24 11:15:13 2007 @@ -348,6 +348,19 @@ assertEquals("/team.action?section=team&company=acme+inc", writer.toString()); } + public void testRequestURIActionIncludeGetDoNotEscapeAmp() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setAction("team"); + tag.setIncludeParams("get"); + tag.setEscapeAmp("false"); + tag.doStartTag(); + tag.doEndTag(); + + assertEquals("/team.action?section=team&company=acme+inc", writer.toString()); + } + public void testRequestURINoActionIncludeNone() throws Exception { request.setRequestURI("/public/about"); request.setQueryString("section=team&company=acme inc"); Modified: struts/struts2/branches/STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/util/UrlHelperTest.java URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/util/UrlHelperTest.java?view=diff&rev=559146&r1=559145&r2=559146 ============================================================================== --- struts/struts2/branches/STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/util/UrlHelperTest.java (original) +++ struts/struts2/branches/STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/util/UrlHelperTest.java Tue Jul 24 11:15:13 2007 @@ -144,6 +144,22 @@ assertEquals(expectedString, urlString); } + public void testBuildUrlCorrectlyAddsDoNotEscapeAmp() { + String expectedString = "my.actionName?foo=bar&hello=world"; + Mock mockHttpServletRequest = new Mock(HttpServletRequest.class); + mockHttpServletRequest.expectAndReturn("getScheme", "http"); + Mock mockHttpServletResponse = new Mock(HttpServletResponse.class); + mockHttpServletResponse.expectAndReturn("encodeURL", expectedString, expectedString); + + String actionName = "my.actionName"; + TreeMap params = new TreeMap(); + params.put("hello", "world"); + params.put("foo", "bar"); + + String urlString = UrlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, null, true, true, false, false); + assertEquals(expectedString, urlString); + } + public void testBuildUrlWithStringArray() { String expectedString = "my.actionName?foo=bar&hello=earth&hello=mars"; Mock mockHttpServletRequest = new Mock(HttpServletRequest.class);