Author: tmjee
Date: Thu Aug 31 07:34:32 2006
New Revision: 438940

URL: http://svn.apache.org/viewvc?rev=438940&view=rev
Log:
WW-1426
  - URL Tag cause duplicates query string


Modified:
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/URL.java
    
struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java
    
struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java
    
struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/util/UrlHelperTest.java

Modified: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/URL.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/URL.java?rev=438940&r1=438939&r2=438940&view=diff
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/URL.java 
(original)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/URL.java 
Thu Aug 31 07:34:32 2006
@@ -33,7 +33,9 @@
 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 @@
             }
 
             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 @@
     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 @@
                 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 @@
 
     /**
      * 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();
             

Modified: 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java?rev=438940&r1=438939&r2=438940&view=diff
==============================================================================
--- 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java
 (original)
+++ 
struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java
 Thu Aug 31 07:34:32 2006
@@ -267,18 +267,20 @@
        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);
+                               }
                        }
                }
        }

Modified: 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java?rev=438940&r1=438939&r2=438940&view=diff
==============================================================================
--- 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java
 (original)
+++ 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java
 Thu Aug 31 07:34:32 2006
@@ -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 @@
 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");

Modified: 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/util/UrlHelperTest.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/util/UrlHelperTest.java?rev=438940&r1=438939&r2=438940&view=diff
==============================================================================
--- 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/util/UrlHelperTest.java
 (original)
+++ 
struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/util/UrlHelperTest.java
 Thu Aug 31 07:34:32 2006
@@ -25,6 +25,7 @@
 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;
@@ -280,6 +281,21 @@
        assertEquals(result.get("bbb"), "bbbval");
        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);


Reply via email to