Author: markt
Date: Sat Dec 30 12:47:39 2006
New Revision: 491307

URL: http://svn.apache.org/viewvc?view=rev&rev=491307
Log:
Updated thread safety patch. I have tested this with the TCK suite and this 
patch does not cause any failures. The Admin app also now works.

Modified:
    
tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java

Modified: 
tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java
URL: 
http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java?view=diff&rev=491307&r1=491306&r2=491307
==============================================================================
--- 
tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java
 (original)
+++ 
tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java
 Sat Dec 30 12:47:39 2006
@@ -100,6 +100,48 @@
         }
     }
 
+    
+    /**
+     * Used to pass state when the request dispatcher is used. Using instance
+     * variables causes threading issues and state is too complex to pass and
+     * return single ServletRequest or ServletResponse objects.
+     */
+    private class State {
+        State(ServletRequest request, ServletResponse response,
+                boolean including) {
+            this.outerRequest = request;
+            this.outerResponse = response;
+            this.including = including;
+        }
+
+        /**
+         * The outermost request that will be passed on to the invoked servlet.
+         */
+        ServletRequest outerRequest = null;
+
+
+        /**
+         * The outermost response that will be passed on to the invoked 
servlet.
+         */
+        ServletResponse outerResponse = null;
+        
+        /**
+         * The request wrapper we have created and installed (if any).
+         */
+        ServletRequest wrapRequest = null;
+
+
+        /**
+         * The response wrapper we have created and installed (if any).
+         */
+        ServletResponse wrapResponse = null;
+        
+        /**
+         * Are we performing an include() instead of a forward()?
+         */
+        boolean including = false;
+    }
+
     // ----------------------------------------------------------- Constructors
 
 
@@ -131,7 +173,6 @@
         this.context = (Context) wrapper.getParent();
         this.requestURI = requestURI;
         this.servletPath = servletPath;
-        this.origServletPath = servletPath;
         this.pathInfo = pathInfo;
         this.queryString = queryString;
         this.name = name;
@@ -153,30 +194,12 @@
     private static Log log = LogFactory.getLog(ApplicationDispatcher.class);
 
     /**
-     * The request specified by the dispatching application.
-     */
-    private ServletRequest appRequest = null;
-
-
-    /**
-     * The response specified by the dispatching application.
-     */
-    private ServletResponse appResponse = null;
-
-
-    /**
      * The Context this RequestDispatcher is associated with.
      */
     private Context context = null;
 
 
     /**
-     * Are we performing an include() instead of a forward()?
-     */
-    private boolean including = false;
-
-
-    /**
      * Descriptive information about this implementation.
      */
     private static final String info =
@@ -190,18 +213,6 @@
 
 
     /**
-     * The outermost request that will be passed on to the invoked servlet.
-     */
-    private ServletRequest outerRequest = null;
-
-
-    /**
-     * The outermost response that will be passed on to the invoked servlet.
-     */
-    private ServletResponse outerResponse = null;
-
-
-    /**
      * The extra path information for this RequestDispatcher.
      */
     private String pathInfo = null;
@@ -218,12 +229,12 @@
      */
     private String requestURI = null;
 
+
     /**
      * The servlet path for this RequestDispatcher.
      */
     private String servletPath = null;
 
-    private String origServletPath = null;
     
     /**
      * The StringManager for this package.
@@ -246,18 +257,6 @@
     private Wrapper wrapper = null;
 
 
-    /**
-     * The request wrapper we have created and installed (if any).
-     */
-    private ServletRequest wrapRequest = null;
-
-
-    /**
-     * The response wrapper we have created and installed (if any).
-     */
-    private ServletResponse wrapResponse = null;
-
-
     // ------------------------------------------------------------- Properties
 
 
@@ -323,11 +322,11 @@
         }
 
         // Set up to handle the specified request and response
-        setup(request, response, false);
+        State state = new State(request, response, false);
         
         if (Globals.STRICT_SERVLET_COMPLIANCE) {
             // Check SRV.8.2 / SRV.14.2.5.1 compliance
-            checkSameObjects();
+            checkSameObjects(request, response);
         }
 
         // Identify the HTTP-specific request and response objects (if any)
@@ -344,7 +343,7 @@
             if ( log.isDebugEnabled() )
                 log.debug(" Non-HTTP Forward");
             
-            processRequest(hrequest,hresponse);
+            processRequest(hrequest,hresponse,state);
 
         }
 
@@ -355,17 +354,17 @@
                 log.debug(" Named Dispatcher Forward");
             
             ApplicationHttpRequest wrequest =
-                (ApplicationHttpRequest) wrapRequest();
+                (ApplicationHttpRequest) wrapRequest(state);
             wrequest.setRequestURI(hrequest.getRequestURI());
             wrequest.setContextPath(hrequest.getContextPath());
             wrequest.setServletPath(hrequest.getServletPath());
             wrequest.setPathInfo(hrequest.getPathInfo());
             wrequest.setQueryString(hrequest.getQueryString());
 
-            processRequest(request,response);
+            processRequest(request,response,state);
 
             wrequest.recycle();
-            unwrapRequest();
+            unwrapRequest(state);
 
         }
 
@@ -376,7 +375,7 @@
                 log.debug(" Path Based Forward");
 
             ApplicationHttpRequest wrequest =
-                (ApplicationHttpRequest) wrapRequest();
+                (ApplicationHttpRequest) wrapRequest(state);
             String contextPath = context.getPath();
 
             if (hrequest.getAttribute(Globals.FORWARD_REQUEST_URI_ATTR) == 
null) {
@@ -401,10 +400,10 @@
                 wrequest.setQueryParams(queryString);
             }
 
-            processRequest(request,response);
+            processRequest(request,response,state);
 
             wrequest.recycle();
-            unwrapRequest();
+            unwrapRequest(state);
 
         }
 
@@ -453,22 +452,23 @@
      * @exception ServletException if a servlet error occurs
      */
     private void processRequest(ServletRequest request, 
-                                ServletResponse response)
+                                ServletResponse response,
+                                State state)
         throws IOException, ServletException {
                 
         Integer disInt = (Integer) request.getAttribute
             (ApplicationFilterFactory.DISPATCHER_TYPE_ATTR);
         if (disInt != null) {
             if (disInt.intValue() != ApplicationFilterFactory.ERROR) {
-                outerRequest.setAttribute
+                state.outerRequest.setAttribute
                     (ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
-                     origServletPath);
-                outerRequest.setAttribute
+                     servletPath);
+                state.outerRequest.setAttribute
                     (ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
                      new Integer(ApplicationFilterFactory.FORWARD));
-                invoke(outerRequest, response);
+                invoke(state.outerRequest, response, state);
             } else {
-                invoke(outerRequest, response);
+                invoke(state.outerRequest, response, state);
             }
         }
 
@@ -510,16 +510,16 @@
         throws ServletException, IOException
     {
         // Set up to handle the specified request and response
-        setup(request, response, true);
+        State state = new State(request, response, true);
 
         if (Globals.STRICT_SERVLET_COMPLIANCE) {
             // Check SRV.8.2 / SRV.14.2.5.1 compliance
-            checkSameObjects();
+            checkSameObjects(request, response);
         }
         
         // Create a wrapped response to use for this request
         // ServletResponse wresponse = null;
-        wrapResponse();
+        wrapResponse(state);
 
         // Handle a non-HTTP include
         if (!(request instanceof HttpServletRequest) ||
@@ -527,10 +527,13 @@
 
             if ( log.isDebugEnabled() )
                 log.debug(" Non-HTTP Include");
-            request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
-                                             new 
Integer(ApplicationFilterFactory.INCLUDE));
-            
request.setAttribute(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR, 
origServletPath);
-            invoke(request, outerResponse);
+            request.setAttribute(
+                    ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
+                    new Integer(ApplicationFilterFactory.INCLUDE));
+            request.setAttribute(
+                    ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
+                    servletPath);
+            invoke(request, state.outerResponse, state);
         }
 
         // Handle an HTTP named dispatcher include
@@ -540,14 +543,17 @@
                 log.debug(" Named Dispatcher Include");
 
             ApplicationHttpRequest wrequest =
-                (ApplicationHttpRequest) wrapRequest();
+                (ApplicationHttpRequest) wrapRequest(state);
             wrequest.setAttribute(Globals.NAMED_DISPATCHER_ATTR, name);
             if (servletPath != null)
                 wrequest.setServletPath(servletPath);
-            
wrequest.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
-                                             new 
Integer(ApplicationFilterFactory.INCLUDE));
-            
wrequest.setAttribute(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR, 
origServletPath);
-            invoke(outerRequest, outerResponse);
+            wrequest.setAttribute(
+                    ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
+                    new Integer(ApplicationFilterFactory.INCLUDE));
+            wrequest.setAttribute(
+                    ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
+                    servletPath);
+            invoke(state.outerRequest, state.outerResponse, state);
 
             wrequest.recycle();
         }
@@ -559,7 +565,7 @@
                 log.debug(" Path Based Include");
 
             ApplicationHttpRequest wrequest =
-                (ApplicationHttpRequest) wrapRequest();
+                (ApplicationHttpRequest) wrapRequest(state);
             String contextPath = context.getPath();
             if (requestURI != null)
                 wrequest.setAttribute(Globals.INCLUDE_REQUEST_URI_ATTR,
@@ -579,10 +585,13 @@
                 wrequest.setQueryParams(queryString);
             }
             
-            
wrequest.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
-                                             new 
Integer(ApplicationFilterFactory.INCLUDE));
-            
wrequest.setAttribute(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR, 
origServletPath);
-            invoke(outerRequest, outerResponse);
+            wrequest.setAttribute(
+                    ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
+                    new Integer(ApplicationFilterFactory.INCLUDE));
+            wrequest.setAttribute(
+                    ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
+                    servletPath);
+            invoke(state.outerRequest, state.outerResponse, state);
 
             wrequest.recycle();
         }
@@ -608,8 +617,8 @@
      * @exception IOException if an input/output error occurs
      * @exception ServletException if a servlet error occurs
      */
-    private void invoke(ServletRequest request, ServletResponse response)
-            throws IOException, ServletException {
+    private void invoke(ServletRequest request, ServletResponse response,
+            State state) throws IOException, ServletException {
 
         // Checking to see if the context classloader is the current context
         // classloader. If it's not, we're saving it, and setting the context
@@ -757,8 +766,8 @@
         
         // Unwrap request/response if needed
         // See Bugzilla 30949
-        unwrapRequest();
-        unwrapResponse();
+        unwrapRequest(state);
+        unwrapResponse(state);
 
         // Rethrow an exception if one was thrown by the invoked servlet
         if (ioException != null)
@@ -772,35 +781,15 @@
 
 
     /**
-     * Set up to handle the specified request and response
-     *
-     * @param request The servlet request specified by the caller
-     * @param response The servlet response specified by the caller
-     * @param including Are we performing an include() as opposed to
-     *  a forward()?
-     */
-    private void setup(ServletRequest request, ServletResponse response,
-                       boolean including) {
-
-        this.appRequest = request;
-        this.appResponse = response;
-        this.outerRequest = request;
-        this.outerResponse = response;
-        this.including = including;
-
-    }
-
-
-    /**
      * Unwrap the request if we have wrapped it.
      */
-    private void unwrapRequest() {
+    private void unwrapRequest(State state) {
 
-        if (wrapRequest == null)
+        if (state.wrapRequest == null)
             return;
 
         ServletRequest previous = null;
-        ServletRequest current = outerRequest;
+        ServletRequest current = state.outerRequest;
         while (current != null) {
 
             // If we run into the container request we are done
@@ -809,11 +798,11 @@
                 break;
 
             // Remove the current request if it is our wrapper
-            if (current == wrapRequest) {
+            if (current == state.wrapRequest) {
                 ServletRequest next =
                   ((ServletRequestWrapper) current).getRequest();
                 if (previous == null)
-                    outerRequest = next;
+                    state.outerRequest = next;
                 else
                     ((ServletRequestWrapper) previous).setRequest(next);
                 break;
@@ -831,13 +820,13 @@
     /**
      * Unwrap the response if we have wrapped it.
      */
-    private void unwrapResponse() {
+    private void unwrapResponse(State state) {
 
-        if (wrapResponse == null)
+        if (state.wrapResponse == null)
             return;
 
         ServletResponse previous = null;
-        ServletResponse current = outerResponse;
+        ServletResponse current = state.outerResponse;
         while (current != null) {
 
             // If we run into the container response we are done
@@ -846,11 +835,11 @@
                 break;
 
             // Remove the current response if it is our wrapper
-            if (current == wrapResponse) {
+            if (current == state.wrapResponse) {
                 ServletResponse next =
                   ((ServletResponseWrapper) current).getResponse();
                 if (previous == null)
-                    outerResponse = next;
+                    state.outerResponse = next;
                 else
                     ((ServletResponseWrapper) previous).setResponse(next);
                 break;
@@ -869,11 +858,11 @@
      * Create and return a request wrapper that has been inserted in the
      * appropriate spot in the request chain.
      */
-    private ServletRequest wrapRequest() {
+    private ServletRequest wrapRequest(State state) {
 
         // Locate the request we should insert in front of
         ServletRequest previous = null;
-        ServletRequest current = outerRequest;
+        ServletRequest current = state.outerRequest;
         while (current != null) {
             if ("org.apache.catalina.servlets.InvokerHttpRequest".
                 equals(current.getClass().getName()))
@@ -898,11 +887,11 @@
             // Compute a crossContext flag
             HttpServletRequest hcurrent = (HttpServletRequest) current;
             boolean crossContext = false;
-            if ((outerRequest instanceof ApplicationHttpRequest) ||
-                (outerRequest instanceof Request) ||
-                (outerRequest instanceof HttpServletRequest)) {
+            if ((state.outerRequest instanceof ApplicationHttpRequest) ||
+                (state.outerRequest instanceof Request) ||
+                (state.outerRequest instanceof HttpServletRequest)) {
                 HttpServletRequest houterRequest = 
-                    (HttpServletRequest) outerRequest;
+                    (HttpServletRequest) state.outerRequest;
                 Object contextPath = houterRequest.getAttribute
                     (Globals.INCLUDE_CONTEXT_PATH_ATTR);
                 if (contextPath == null) {
@@ -917,10 +906,10 @@
             wrapper = new ApplicationRequest(current);
         }
         if (previous == null)
-            outerRequest = wrapper;
+            state.outerRequest = wrapper;
         else
             ((ServletRequestWrapper) previous).setRequest(wrapper);
-        wrapRequest = wrapper;
+        state.wrapRequest = wrapper;
         return (wrapper);
 
     }
@@ -930,11 +919,11 @@
      * Create and return a response wrapper that has been inserted in the
      * appropriate spot in the response chain.
      */
-    private ServletResponse wrapResponse() {
+    private ServletResponse wrapResponse(State state) {
 
         // Locate the response we should insert in front of
         ServletResponse previous = null;
-        ServletResponse current = outerResponse;
+        ServletResponse current = state.outerResponse;
         while (current != null) {
             if (!(current instanceof ServletResponseWrapper))
                 break;
@@ -955,20 +944,21 @@
             (current instanceof HttpServletResponse))
             wrapper =
                 new ApplicationHttpResponse((HttpServletResponse) current,
-                                            including);
+                        state.including);
         else
-            wrapper = new ApplicationResponse(current, including);
+            wrapper = new ApplicationResponse(current, state.including);
         if (previous == null)
-            outerResponse = wrapper;
+            state.outerResponse = wrapper;
         else
             ((ServletResponseWrapper) previous).setResponse(wrapper);
-        wrapResponse = wrapper;
+        state.wrapResponse = wrapper;
         return (wrapper);
 
     }
 
 
-    private void checkSameObjects() throws ServletException {
+    private void checkSameObjects(ServletRequest appRequest,
+            ServletResponse appResponse) throws ServletException {
         ServletRequest originalRequest =
             ApplicationFilterChain.getLastServicedRequest();
         ServletResponse originalResponse =



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to