You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by re...@apache.org on 2007/11/30 00:27:02 UTC

svn commit: r599629 - /cocoon/trunk/core/cocoon-servlet-service/cocoon-servlet-service-impl/src/main/java/org/apache/cocoon/servletservice/util/BlockCallHttpServletRequest.java

Author: reinhard
Date: Thu Nov 29 15:26:52 2007
New Revision: 599629

URL: http://svn.apache.org/viewvc?rev=599629&view=rev
Log:
use Rice' implementation instead (COCOON-1943)
(though I'm still curious why traversing the call frame is necessary)

Modified:
    cocoon/trunk/core/cocoon-servlet-service/cocoon-servlet-service-impl/src/main/java/org/apache/cocoon/servletservice/util/BlockCallHttpServletRequest.java

Modified: cocoon/trunk/core/cocoon-servlet-service/cocoon-servlet-service-impl/src/main/java/org/apache/cocoon/servletservice/util/BlockCallHttpServletRequest.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-servlet-service/cocoon-servlet-service-impl/src/main/java/org/apache/cocoon/servletservice/util/BlockCallHttpServletRequest.java?rev=599629&r1=599628&r2=599629&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-servlet-service/cocoon-servlet-service-impl/src/main/java/org/apache/cocoon/servletservice/util/BlockCallHttpServletRequest.java (original)
+++ cocoon/trunk/core/cocoon-servlet-service/cocoon-servlet-service-impl/src/main/java/org/apache/cocoon/servletservice/util/BlockCallHttpServletRequest.java Thu Nov 29 15:26:52 2007
@@ -16,6 +16,9 @@
  */
 package org.apache.cocoon.servletservice.util;
 
+import org.apache.cocoon.callstack.CallFrame;
+import org.apache.cocoon.callstack.CallStack;
+import org.apache.cocoon.callstack.environment.CallFrameHelper;
 import org.apache.commons.collections.iterators.IteratorEnumeration;
 
 import javax.servlet.RequestDispatcher;
@@ -29,6 +32,7 @@
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Serializable;
 import java.io.UnsupportedEncodingException;
 import java.io.InputStreamReader;
 import java.io.Reader;
@@ -36,11 +40,18 @@
 import java.security.Principal;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.StringTokenizer;
 
 /**
  * Create a HttpServletRequest from an URL, that is used while calling e.g. a
@@ -63,10 +74,10 @@
     private final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z", Locale.US);
 
     /**
-     * The <code>parent</code> holds reference to the request object that
-     * makes a servlet call.
+     * The <code>parentRequest</code> holds reference to the request object
+     * that makes a servlet call.
      */
-    private HttpServletRequest parent;
+    private HttpServletRequest parentRequest;
 
     /**
      * Block call request URI
@@ -82,7 +93,7 @@
     /**
      * Request headers map
      */
-    private final Map headers;
+    private final Headers headers;
 
     /**
      * Request character encoding.
@@ -102,7 +113,9 @@
     /**
      * Request attributes map.
      */
-    private final Map attributes;
+    private final Attributes attributes;
+
+    private Parameters parameters;
 
     /**
      * @param uri
@@ -111,48 +124,14 @@
      *            reference to the request object that makes a servlet call
      */
     public BlockCallHttpServletRequest(URI uri, HttpServletRequest parentRequest) {
-        this.parent = parentRequest;
+        this.parentRequest = parentRequest;
         this.uri = uri;
-        this.headers = createRequestHeaderMap(parentRequest);
+        this.headers = new Headers();
         this.method = "GET";
         this.contentLength = -1;
         this.content = NullServletInputStream.INSTANCE;
-        this.attributes = createRequestAttributesMap(parentRequest);
-    }
-
-    /**
-     * Create a new {@link Map} that contains all request attributes. A sub
-     * request can't pass parameters to the parent request, however, it can
-     * modify parameter values.
-     *
-     * TODO Is there any way to prevent sub request from altering parent
-     * attributes?
-     */
-    private Map createRequestAttributesMap(HttpServletRequest req) {
-        Map attributes = new HashMap();
-        if (req != null) {
-            Enumeration parentAttributes = req.getAttributeNames();
-            while (parentAttributes.hasMoreElements()) {
-                String attr = (String) parentAttributes.nextElement();
-                attributes.put(attr, req.getAttribute(attr));
-            }
-        }
-        return attributes;
-    }
-
-    /**
-     * Create a new {@link Map} that contains all headers.
-     */
-    private Map createRequestHeaderMap(HttpServletRequest req) {
-        Map headers = new HashMap();
-        if (req != null) {
-            Enumeration parentHeaders = req.getHeaderNames();
-            while (parentHeaders.hasMoreElements()) {
-                String header = (String) parentHeaders.nextElement();
-                headers.put(header, req.getHeader(header));
-            }
-        }
-        return headers;
+        this.attributes = new Attributes();
+        this.parameters = new Parameters();
     }
 
     /*
@@ -191,8 +170,7 @@
      * @see javax.servlet.ServletRequest#getServerName()
      */
     public String getServerName() {
-        // TODO implement this
-        return "";
+        return this.parentRequest.getServerName();
     }
 
     /*
@@ -201,8 +179,7 @@
      * @see javax.servlet.ServletRequest#getServerPort()
      */
     public int getServerPort() {
-        // TODO implement this
-        return 80;
+        return this.parentRequest.getServerPort();
     }
 
     /*
@@ -211,7 +188,7 @@
      * @see javax.servlet.http.HttpServletRequest#getContextPath()
      */
     public String getContextPath() {
-        return parent.getContextPath();
+        return parentRequest.getContextPath();
     }
 
     /*
@@ -281,7 +258,7 @@
      * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String)
      */
     public String getHeader(String name) {
-        return (String) this.headers.get(name);
+        return (String) this.headers.getValue(name);
     }
 
     /*
@@ -290,11 +267,11 @@
      * @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String)
      */
     public Enumeration getHeaders(String name) {
-        return new IteratorEnumeration(headers.values().iterator());
+        return this.headers.getNames();
     }
 
     public void setHeader(String name, String value) {
-        headers.put(name, value);
+        this.headers.setValue(name, value);
     }
 
     /*
@@ -343,7 +320,7 @@
      * @see javax.servlet.http.HttpServletRequest#getHeaderNames()
      */
     public Enumeration getHeaderNames() {
-        return new IteratorEnumeration(headers.keySet().iterator());
+        return this.headers.getNames();
     }
 
     //
@@ -356,7 +333,7 @@
      * @see javax.servlet.ServletRequest#getParameter(java.lang.String)
      */
     public String getParameter(String name) {
-        return this.parent.getParameter(name);
+        return (String) this.parameters.getValue(name);
     }
 
     /*
@@ -365,7 +342,7 @@
      * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
      */
     public String[] getParameterValues(String name) {
-        return this.parent.getParameterValues(name);
+        return this.parameters.getValues(name);
     }
 
     /*
@@ -374,7 +351,7 @@
      * @see javax.servlet.ServletRequest#getParameterNames()
      */
     public Enumeration getParameterNames() {
-        return this.parent.getParameterNames();
+        return this.parameters.getNames();
     }
 
     /*
@@ -383,7 +360,7 @@
      * @see javax.servlet.ServletRequest#getParameterMap()
      */
     public Map getParameterMap() {
-        return this.parent.getParameterMap();
+        return this.parameters.getValues();
     }
 
     //
@@ -482,7 +459,7 @@
      * @see javax.servlet.ServletRequest#getAttribute(java.lang.String)
      */
     public Object getAttribute(String name) {
-        return this.attributes.get(name);
+        return this.attributes.getValue(name);
     }
 
     /*
@@ -491,7 +468,7 @@
      * @see javax.servlet.ServletRequest#getAttributeNames()
      */
     public Enumeration getAttributeNames() {
-        return new IteratorEnumeration(this.attributes.keySet().iterator());
+        return this.attributes.getNames();
     }
 
     /*
@@ -502,9 +479,9 @@
      */
     public void setAttribute(String name, Object value) {
         if (value != null) {
-            this.attributes.put(name, value);
+            this.attributes.setValue(name, value);
         } else {
-            removeAttribute(name);
+            this.removeAttribute(name);
         }
     }
 
@@ -532,7 +509,7 @@
      * @see javax.servlet.http.HttpServletRequest#getCookies()
      */
     public Cookie[] getCookies() {
-        return this.parent.getCookies();
+        return this.parentRequest.getCookies();
     }
 
     /*
@@ -541,7 +518,7 @@
      * @see javax.servlet.ServletRequest#getLocale()
      */
     public Locale getLocale() {
-        return this.parent.getLocale();
+        return this.parentRequest.getLocale();
     }
 
     /*
@@ -550,7 +527,7 @@
      * @see javax.servlet.ServletRequest#getLocales()
      */
     public Enumeration getLocales() {
-        return this.parent.getLocales();
+        return this.parentRequest.getLocales();
     }
 
     /**
@@ -567,7 +544,7 @@
      * @see javax.servlet.ServletRequest#getRemoteAddr()
      */
     public String getRemoteAddr() {
-        return this.parent.getRemoteAddr();
+        return this.parentRequest.getRemoteAddr();
     }
 
     /*
@@ -576,7 +553,7 @@
      * @see javax.servlet.ServletRequest#getRemoteHost()
      */
     public String getRemoteHost() {
-        return this.parent.getRemoteHost();
+        return this.parentRequest.getRemoteHost();
     }
 
     /*
@@ -794,7 +771,7 @@
      */
     public boolean isSecure() {
         // TODO Auto-generated method stub
-        return this.parent.isSecure();
+        return this.parentRequest.isSecure();
     }
 
     /*
@@ -809,11 +786,11 @@
     }
 
     public String getLocalAddr() {
-        return this.parent.getLocalAddr();
+        return this.parentRequest.getLocalAddr();
     }
 
     public String getLocalName() {
-        return this.parent.getLocalName();
+        return this.parentRequest.getLocalName();
     }
 
     /*
@@ -831,4 +808,232 @@
         // TODO Auto-generated method stub
         return 0;
     }
+
+    private abstract static class Values implements Serializable {
+
+        /** The parameter names are the keys and the value is a List object */
+        Map values = new HashMap();
+
+        /**
+         * Construct a new object from a queryString
+         */
+        public Values() {
+        }
+
+        protected void setValue(String name, Object value) {
+            List list;
+            if (this.values.containsKey(name)) {
+                list = (List) values.get(name);
+            } else {
+                list = new ArrayList();
+                this.values.put(name, list);
+            }
+            list.add(value);
+        }
+
+        public Object getValue(String name) {
+            if (this.values.containsKey(name)) {
+                return ((List) values.get(name)).get(0);
+            }
+
+            return getValueOfCaller(name);
+        }
+
+        protected abstract Object getValueOfCaller(String name);
+
+        public Enumeration getNames() {
+            Set names = new HashSet();
+            for (int i = 0; i < CallStack.size(); i++) {
+                CallFrame frame = CallStack.frameAt(i);
+                HttpServletRequest request = (HttpServletRequest) frame.getAttribute(CallFrameHelper.REQUEST_OBJECT);
+                if (request instanceof BlockCallHttpServletRequest) {
+                    names.addAll(this.values.keySet());
+                } else {
+                    for (Enumeration enumeration = request.getParameterNames(); enumeration.hasMoreElements();) {
+                        names.add(enumeration.nextElement());
+                    }
+                }
+                if (request.equals(this.getRequest())) {
+                    break;
+                }
+            }
+
+            return new EnumerationFromIterator(names.iterator());
+        }
+
+        public Map getValues() {
+            Map result = new HashMap();
+            for (int i = 0; i < CallStack.size(); i++) {
+                CallFrame frame = CallStack.frameAt(i);
+                HttpServletRequest request = (HttpServletRequest) frame.getAttribute(CallFrameHelper.REQUEST_OBJECT);
+                if (request instanceof BlockCallHttpServletRequest)
+                    result.putAll(this.values);
+                else {
+                    result.putAll(request.getParameterMap());
+                }
+                if (request.equals(this.getRequest()))
+                    break;
+            }
+
+            return result;
+        }
+
+        protected abstract BlockCallHttpServletRequest getRequest();
+
+        // protected abstract Map getValues(HttpServletRequest request);
+
+        final class EnumerationFromIterator implements Enumeration {
+
+            private Iterator iterator;
+
+            EnumerationFromIterator(Iterator iter) {
+                this.iterator = iter;
+            }
+
+            public boolean hasMoreElements() {
+                return iterator.hasNext();
+            }
+
+            public Object nextElement() {
+                return iterator.next();
+            }
+        }
+
+    }
+
+    private class Parameters extends Values {
+
+        public Parameters() {
+            if (this.getRequest().uri.getQuery() != null) {
+                StringTokenizer st = new StringTokenizer(this.getRequest().uri.getQuery(), "&");
+                while (st.hasMoreTokens()) {
+                    String pair = st.nextToken();
+                    int pos = pair.indexOf('=');
+                    if (pos != -1) {
+                        this.setValue(this.parseName(pair.substring(0, pos)), this.parseName(pair.substring(pos + 1,
+                                        pair.length())));
+                    }
+                }
+            }
+        }
+
+        private String parseName(String s) {
+            StringBuffer sb = new StringBuffer();
+            for (int i = 0; i < s.length(); i++) {
+                char c = s.charAt(i);
+                switch (c) {
+                case '+':
+                    sb.append(' ');
+                    break;
+                case '%':
+                    try {
+                        if (s.charAt(i + 1) == 'u') {
+                            // working with multi-byte symbols in format %uXXXX
+                            sb.append((char) Integer.parseInt(s.substring(i + 2, i + 6), 16));
+                            i += 5; // 4 digits and 1 symbol u
+                        } else {
+                            // working with single-byte symbols in format %YY
+                            sb.append((char) Integer.parseInt(s.substring(i + 1, i + 3), 16));
+                            i += 2;
+                        }
+                    } catch (NumberFormatException e) {
+                        throw new IllegalArgumentException();
+                    } catch (StringIndexOutOfBoundsException e) {
+                        String rest = s.substring(i);
+                        sb.append(rest);
+                        if (rest.length() == 2)
+                            i++;
+                    }
+
+                    break;
+                default:
+                    sb.append(c);
+                    break;
+                }
+            }
+            return sb.toString();
+        }
+
+        public String[] getValues(String name) {
+            List list = (List) this.values.get(name);
+            if (list == null)
+                return null;
+
+            String[] result = new String[list.size()];
+            for (int i = 0; i < list.size(); i++) {
+                result[i] = (String) list.get(i);
+            }
+            return result;
+        }
+
+        protected BlockCallHttpServletRequest getRequest() {
+            return BlockCallHttpServletRequest.this;
+        }
+
+        protected Object getValueOfCaller(String name) {
+            return this.getRequest().parentRequest.getParameter(name);
+        }
+    }
+
+    private class Headers extends Values {
+        public Object getValueOfCaller(String name) {
+            return this.getRequest().parentRequest.getHeader(name);
+        }
+
+        public Enumeration getValues(String name) {
+            List list = (List) this.values.get(name);
+            if (list == null) {
+                return new Enumeration() {
+
+                    public boolean hasMoreElements() {
+                        return false;
+                    }
+
+                    public Object nextElement() {
+                        throw new NoSuchElementException();
+                    }
+
+                };
+            }
+
+            return new IteratorEnumeration(list.iterator());
+        }
+
+        protected BlockCallHttpServletRequest getRequest() {
+            return BlockCallHttpServletRequest.this;
+        }
+    }
+
+    private class Attributes extends Values {
+
+        public Object getValue(String name) {
+            if (values.containsKey(name)) {
+                return values.get(name);
+            }
+
+            return getValueOfCaller(name);
+        }
+
+        public Object getValueOfCaller(String name) {
+            return this.getRequest().parentRequest.getAttribute(name);
+        }
+
+        protected void setValue(String name, Object value) {
+            this.values.put(name, value);
+        }
+
+        public void remove(String name) {
+            if (this.values.containsKey(name)) {
+                this.values.remove(name);
+            } else {
+                this.getRequest().parentRequest.removeAttribute(name);
+            }
+        }
+
+        protected BlockCallHttpServletRequest getRequest() {
+            return BlockCallHttpServletRequest.this;
+        }
+
+    }
+
 }