Revision: 628
          http://stripes.svn.sourceforge.net/stripes/?rev=628&view=rev
Author:   bengunter
Date:     2007-11-16 22:09:40 -0800 (Fri, 16 Nov 2007)

Log Message:
-----------
STS-435: Change clean URLs not to rely on internal forwards

Must not cache the whole parameter map. During an internal forward, the 
underlying request object is replaced by a new one. Any parameters in the query 
string of the forward are then hidden because the original parameter map was 
cached by this class. Instead, I have added a Map implementation that merges 
parameter values on the fly.

Modified Paths:
--------------
    
trunk/stripes/src/net/sourceforge/stripes/controller/StripesRequestWrapper.java

Modified: 
trunk/stripes/src/net/sourceforge/stripes/controller/StripesRequestWrapper.java
===================================================================
--- 
trunk/stripes/src/net/sourceforge/stripes/controller/StripesRequestWrapper.java 
    2007-11-17 05:50:20 UTC (rev 627)
+++ 
trunk/stripes/src/net/sourceforge/stripes/controller/StripesRequestWrapper.java 
    2007-11-17 06:09:40 UTC (rev 628)
@@ -16,15 +16,17 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Set;
 
 import javax.servlet.ServletRequest;
 import javax.servlet.http.HttpServletRequest;
@@ -49,7 +51,10 @@
 
     /** The Locale that is going to be used to process the request. */
     private Locale locale;
-    
+
+    /** Flag that indicates if parameters have been initialized. */
+    private boolean parametersInitialized;
+
     /** Local copy of the parameter map, into which URI-embedded parameters 
will be merged. */
     private Map<String, String[]> parameterMap;
 
@@ -173,11 +178,35 @@
     @Override
     public Map<String, String[]> getParameterMap() {
         // lazy initialization
-        if (this.parameterMap != null)
-            return this.parameterMap;
+        if (this.parametersInitialized) {
+            if (this.parameterMap == null)
+                return super.getParameterMap();
+            else
+                return this.parameterMap;
+        }
 
+        if (isMultipart()) {
+            Map<String, String[]> params = new HashMap<String, String[]>();
+            Enumeration names = this.multipart.getParameterNames();
+
+            while (names.hasMoreElements()) {
+                String name = (String) names.nextElement();
+                params.put(name, getParameterValues(name));
+            }
+
+            this.parameterMap = mergeURIParameters(params);
+        }
+        else {
+            this.parameterMap = new MergedParameterMap(this, 
mergeURIParameters(null));
+        }
+
+        this.parametersInitialized = true;
+        return getParameterMap();
+    }
+
+    /** Merges URI-embedded parameters into an existing parameter map. */
+    protected Map<String, String[]> mergeURIParameters(Map<String, String[]> 
params) {
         UrlBinding binding = UrlBindingFactory.getInstance().getBinding(this);
-        Map<String, List<String>> params = null;
         if (binding != null && binding.getParameters().size() > 0) {
             for (UrlBindingParameter p : binding.getParameters()) {
                 String name = p.getName();
@@ -189,89 +218,26 @@
                     }
                     if (name != null && value != null) {
                         if (params == null) {
-                            params = new LinkedHashMap<String, List<String>>();
+                            params = new LinkedHashMap<String, String[]>();
                         }
-                        List<String> list = params.get(name);
-                        if (list == null) {
-                            list = new ArrayList<String>();
-                            params.put(name, list);
+                        String[] values = params.get(name);
+                        if (values == null) {
+                            values = new String[] { value };
                         }
-                        list.add(value);
+                        else {
+                            values = Arrays.copyOf(values, values.length + 1);
+                            values[values.length - 1] = value;
+                        }
+                        params.put(name, values);
                     }
                 }
             }
         }
-
-        if (params == null) {
-            // if no URI parameters then just use the parameter map from the 
wrapped request
-            this.parameterMap = 
Collections.unmodifiableMap(getParameterMapFromRequest());
-        }
-        else {
-            // merge the original request parameters with those from the URI
-            LinkedHashMap<String, String[]> merged = new LinkedHashMap<String, 
String[]>(
-                    getParameterMapFromRequest());
-            for (Entry<String, List<String>> entry : params.entrySet()) {
-                String name = entry.getKey();
-                String[] value = mergeParameters(merged.get(name), 
entry.getValue());
-                merged.put(name, value);
-            }
-            this.parameterMap = Collections.unmodifiableMap(merged);
-        }
-
-        return this.parameterMap;
+        
+        return params;
     }
-    
-    /**
-     * Merges request parameter values from the original request with the 
parameters that are
-     * embedded in the URI. Either or both arguments may be empty or null.
-     * 
-     * @param request the parameters from the original request
-     * @param uri parameters extracted from the URI
-     * @return the merged parameter values
-     */
-    protected String[] mergeParameters(String[] request, List<String> uri) {
-        if (request == null || request.length == 0) {
-            if (uri == null || uri.size() == 0)
-                return null;
-            else
-                return uri.toArray(new String[uri.size()]);
-        }
-        else if (uri == null || uri.size() == 0) {
-            return request;
-        }
-        else {
-            String[] merged = new String[request.length + uri.size()];
-            System.arraycopy(merged, 0, request, 0, request.length);
-            Iterator<String> iterator = uri.iterator();
-            for (int i = request.length; iterator.hasNext(); i++) {
-                merged[i] = iterator.next();
-            }
-            return merged;
-        }
-    }
 
     /**
-     * Returns a map of parameter name and values.
-     */
-    @SuppressWarnings("unchecked")
-    protected Map<String,String[]> getParameterMapFromRequest() {
-        if (isMultipart()) {
-            Map<String,String[]> parameterMap = new HashMap<String,String[]>();
-            Enumeration names = this.multipart.getParameterNames();
-
-            while (names.hasMoreElements()) {
-                String name = (String) names.nextElement();
-                parameterMap.put(name, getParameterValues(name));
-            }
-
-            return parameterMap;
-        }
-        else {
-            return super.getParameterMap();
-        }
-    }
-
-    /**
      * Provides access to the Locale being used to process the request.
      * @return a Locale object representing the chosen locale for the request.
      * @see net.sourceforge.stripes.localization.LocalePicker
@@ -327,3 +293,155 @@
         }
     }
 }
+
+class MergedParameterMap implements Map<String, String[]> {
+    protected class Entry implements Map.Entry<String, String[]> {
+        private String key;
+
+        protected Entry(String key) {
+            this.key = key;
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        public String[] getValue() {
+            return get(key);
+        }
+
+        public String[] setValue(String[] value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            Entry that = (Entry) obj;
+            return this.key == that.key;
+        }
+
+        @Override
+        public int hashCode() {
+            return key.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return "" + key + "=" + Arrays.deepToString(getValue());
+        }
+    }
+
+    private StripesRequestWrapper request;
+    private Map<String, String[]> uriParams;
+
+    protected MergedParameterMap(StripesRequestWrapper request, Map<String, 
String[]> uriParams) {
+        this.request = request;
+        this.uriParams = uriParams;
+    }
+
+    public void clear() {
+        throw new UnsupportedOperationException();
+    }
+
+    public boolean containsKey(Object key) {
+        return getParameterMap().containsKey(key) || 
uriParams.containsKey(key);
+    }
+
+    public boolean containsValue(Object value) {
+        return getParameterMap().containsValue(value) || 
uriParams.containsValue(value);
+    }
+
+    public Set<Map.Entry<String, String[]>> entrySet() {
+        Set<Map.Entry<String, String[]>> entries = new 
LinkedHashSet<Map.Entry<String, String[]>>();
+        for (String key : keySet()) {
+            entries.add(new Entry(key));
+        }
+        return entries;
+    }
+
+    public String[] get(Object key) {
+        if (key == null)
+            return null;
+        else
+            return mergeParameters(getParameterMap().get(key), 
uriParams.get(key));
+    }
+
+    public boolean isEmpty() {
+        return getParameterMap().isEmpty() && uriParams.isEmpty();
+    }
+
+    public Set<String> keySet() {
+        Set<String> merged = new LinkedHashSet<String>();
+        merged.addAll(uriParams.keySet());
+        merged.addAll(getParameterMap().keySet());
+        return merged;
+    }
+
+    public String[] put(String key, String[] value) {
+        throw new UnsupportedOperationException();
+    }
+
+    public void putAll(Map<? extends String, ? extends String[]> m) {
+        throw new UnsupportedOperationException();
+    }
+
+    public String[] remove(Object key) {
+        throw new UnsupportedOperationException();
+    }
+
+    public int size() {
+        return keySet().size();
+    }
+
+    public Collection<String[]> values() {
+        Set<String> keys = keySet();
+        List<String[]> merged = new ArrayList<String[]>(keys.size());
+        for (String key : keys) {
+            merged.add(mergeParameters(getParameterMap().get(key), 
uriParams.get(key)));
+        }
+        return merged;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder buf = new StringBuilder("{ ");
+        for (Map.Entry<String, String[]> entry : entrySet()) {
+            buf.append(entry).append(", ");
+        }
+        if (buf.toString().endsWith(", "))
+            buf.setLength(buf.length() - 2);
+        buf.append(" }");
+        return buf.toString();
+    }
+
+    /** Get the parameter map from the request that is wrapped by the [EMAIL 
PROTECTED] StripesRequestWrapper}. */
+    @SuppressWarnings("unchecked")
+    protected Map<String, String[]> getParameterMap() {
+        return request.getRequest().getParameterMap();
+    }
+
+    /**
+     * Merges request parameter values from the original request with the 
parameters that are
+     * embedded in the URI. Either or both arguments may be empty or null.
+     * 
+     * @param requestParams the parameters from the original request
+     * @param uriParams parameters extracted from the URI
+     * @return the merged parameter values
+     */
+    protected String[] mergeParameters(String[] requestParams, String[] 
uriParams) {
+        if (requestParams == null || requestParams.length == 0) {
+            if (uriParams == null || uriParams.length == 0)
+                return null;
+            else
+                return uriParams;
+        }
+        else if (uriParams == null || uriParams.length == 0) {
+            return requestParams;
+        }
+        else {
+            String[] merged = Arrays.copyOf(uriParams, uriParams.length + 
uriParams.length);
+            System.arraycopy(requestParams, 0, merged, uriParams.length, 
requestParams.length);
+            return merged;
+        }
+    }
+}


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to