craigmcc    01/07/16 15:24:13

  Modified:    catalina/src/share/org/apache/catalina/core
                        ApplicationDispatcher.java
  Removed:     catalina/src/share/org/apache/catalina/core
                        ApplicationDispatcherContext.java
  Log:
  Modify the way that request dispatching is performed.
  
  Previously, Catalina would create request and/or response wrappers around
  the application-provided request and response objects.  However, this
  violated the application assumption that a wrapper instance created by the
  calling servlet would be the same one seen by a called servlet.
  
  Now, Catalina creates wrappers as before; however they are *inserted* into
  the request and response wrapper chains, just above the container-provided
  request and response implementation objects (or above previously inserted
  wrappers in the case of nested request dispatchers).
  
  Revision  Changes    Path
  1.20      +254 -22   
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java
  
  Index: ApplicationDispatcher.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- ApplicationDispatcher.java        2001/07/13 00:51:44     1.19
  +++ ApplicationDispatcher.java        2001/07/16 22:24:12     1.20
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java,v
 1.19 2001/07/13 00:51:44 craigmcc Exp $
  - * $Revision: 1.19 $
  - * $Date: 2001/07/13 00:51:44 $
  + * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ApplicationDispatcher.java,v
 1.20 2001/07/16 22:24:12 craigmcc Exp $
  + * $Revision: 1.20 $
  + * $Date: 2001/07/16 22:24:12 $
    *
    * ====================================================================
    *
  @@ -74,15 +74,22 @@
   import javax.servlet.ServletException;
   import javax.servlet.ServletOutputStream;
   import javax.servlet.ServletRequest;
  +import javax.servlet.ServletRequestWrapper;
   import javax.servlet.ServletResponse;
  +import javax.servlet.ServletResponseWrapper;
   import javax.servlet.UnavailableException;
   import javax.servlet.http.HttpServlet;
   import javax.servlet.http.HttpServletRequest;
  +import javax.servlet.http.HttpServletRequestWrapper;
   import javax.servlet.http.HttpServletResponse;
  +import javax.servlet.http.HttpServletResponseWrapper;
   import org.apache.catalina.Context;
   import org.apache.catalina.Globals;
   import org.apache.catalina.HttpRequest;
  +import org.apache.catalina.HttpResponse;
   import org.apache.catalina.Logger;
  +import org.apache.catalina.Request;
  +import org.apache.catalina.Response;
   import org.apache.catalina.Wrapper;
   import org.apache.catalina.util.StringManager;
   
  @@ -98,7 +105,7 @@
    * <code>javax.servlet.ServletResponseWrapper</code>.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.19 $ $Date: 2001/07/13 00:51:44 $
  + * @version $Revision: 1.20 $ $Date: 2001/07/16 22:24:12 $
    */
   
   final class ApplicationDispatcher
  @@ -191,6 +198,18 @@
   
   
       /**
  +     * 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;
  @@ -203,6 +222,12 @@
   
   
       /**
  +     * Are we performing an include() instead of a forward()?
  +     */
  +    private boolean including = false;
  +
  +
  +    /**
        * Descriptive information about this implementation.
        */
       private static final String info =
  @@ -216,6 +241,18 @@
   
   
       /**
  +     * 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;
  @@ -247,6 +284,18 @@
       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
   
   
  @@ -296,6 +345,7 @@
       private void doForward(ServletRequest request, ServletResponse response)
           throws ServletException, IOException
       {
  +
        // Reset any output that has been buffered, but keep headers/cookies
           if (response.isCommitted()) {
               if (debug >= 1)
  @@ -311,6 +361,9 @@
               throw e;
           }
   
  +        // Set up to handle the specified request and response
  +        setup(request, response, false);
  +
        // Identify the HTTP-specific request and response objects (if any)
        HttpServletRequest hrequest = null;
        if (request instanceof HttpServletRequest)
  @@ -344,7 +397,7 @@
                log(" Path Based Forward");
   
            ApplicationHttpRequest wrequest =
  -             new ApplicationHttpRequest((HttpServletRequest) request);
  +                (ApplicationHttpRequest) wrapRequest();
            StringBuffer sb = new StringBuffer();
            String contextPath = context.getPath();
            if (contextPath != null)
  @@ -361,7 +414,8 @@
                wrequest.setQueryString(queryString);
                wrequest.mergeParameters(queryString);
            }
  -            invoke(wrequest, response);
  +            invoke(outerRequest, response);
  +            unwrapRequest();
   
        }
   
  @@ -421,15 +475,13 @@
       private void doInclude(ServletRequest request, ServletResponse response)
           throws ServletException, IOException
       {
  +
  +        // Set up to handle the specified request and response
  +        setup(request, response, true);
  +
        // Create a wrapped response to use for this request
  -     ServletResponse wresponse = null;
  -     if (response instanceof HttpServletResponse) {
  -         wresponse =
  -             new ApplicationHttpResponse((HttpServletResponse) response,
  -                                         true);
  -     } else {
  -         wresponse = new ApplicationResponse(response, true);
  -     }
  +     // ServletResponse wresponse = null;
  +     ServletResponse wresponse = wrapResponse();
   
        // Handle a non-HTTP include
        if (!(request instanceof HttpServletRequest) ||
  @@ -437,7 +489,8 @@
   
            if (debug >= 1)
                log(" Non-HTTP Include");
  -            invoke(request, wresponse);
  +            invoke(request, outerResponse);
  +            unwrapResponse();
   
        }
   
  @@ -448,11 +501,13 @@
                log(" Named Dispatcher Include");
   
            ApplicationHttpRequest wrequest =
  -             new ApplicationHttpRequest((HttpServletRequest) request);
  +                (ApplicationHttpRequest) wrapRequest();
               wrequest.setAttribute(Globals.NAMED_DISPATCHER_ATTR, name);
               if (servletPath != null)
                   wrequest.setServletPath(servletPath);
  -            invoke(wrequest, wresponse);
  +            invoke(outerRequest, outerResponse);
  +            unwrapRequest();
  +            unwrapResponse();
   
        }
   
  @@ -463,7 +518,7 @@
                log(" Path Based Include");
   
            ApplicationHttpRequest wrequest =
  -             new ApplicationHttpRequest((HttpServletRequest) request);
  +                (ApplicationHttpRequest) wrapRequest();
            StringBuffer sb = new StringBuffer();
            String contextPath = context.getPath();
            if (contextPath != null)
  @@ -489,14 +544,17 @@
                                      queryString);
                wrequest.mergeParameters(queryString);
            }
  -            invoke(wrequest, wresponse);
  +            // invoke(wrequest, wresponse);
  +            invoke(outerRequest, outerResponse);
  +            unwrapRequest();
  +            unwrapResponse();
   
        }
   
       }
   
   
  -    // -------------------------------------------------------- Package Methods
  +    // -------------------------------------------------------- Private Methods
   
   
       /**
  @@ -628,7 +686,7 @@
        *
        * @param message Message to be logged
        */
  -    void log(String message) {
  +    private void log(String message) {
   
        Logger logger = context.getLogger();
        if (logger != null)
  @@ -647,7 +705,7 @@
        * @param message Message to be logged
        * @param throwable Associated exception
        */
  -    void log(String message, Throwable throwable) {
  +    private void log(String message, Throwable throwable) {
   
        Logger logger = context.getLogger();
        if (logger != null)
  @@ -658,6 +716,180 @@
                               context.getPath() + "]: " + message);
            throwable.printStackTrace(System.out);
        }
  +
  +    }
  +
  +
  +    /**
  +     * 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() {
  +
  +        if (wrapRequest == null)
  +            return;
  +
  +        ServletRequest previous = null;
  +        ServletRequest current = outerRequest;
  +        while (current != null) {
  +
  +            // If we run into the container request we are done
  +            if (current instanceof Request)
  +                break;
  +
  +            // Remove the current request if it is our wrapper
  +            if (current == wrapRequest) {
  +                ServletRequest next =
  +                  ((ServletRequestWrapper) current).getRequest();
  +                if (previous == null)
  +                    outerRequest = next;
  +                else
  +                    ((ServletRequestWrapper) previous).setRequest(next);
  +                break;
  +            }
  +
  +            // Advance to the next request in the chain
  +            previous = current;
  +            current = ((ServletRequestWrapper) current).getRequest();
  +
  +        }
  +
  +    }
  +
  +
  +    /**
  +     * Unwrap the response if we have wrapped it.
  +     */
  +    private void unwrapResponse() {
  +
  +        if (wrapResponse == null)
  +            return;
  +
  +        ServletResponse previous = null;
  +        ServletResponse current = outerResponse;
  +        while (current != null) {
  +
  +            // If we run into the container response we are done
  +            if (current instanceof Response)
  +                break;
  +
  +            // Remove the current response if it is our wrapper
  +            if (current == wrapResponse) {
  +                ServletResponse next =
  +                  ((ServletResponseWrapper) current).getResponse();
  +                if (previous == null)
  +                    outerResponse = next;
  +                else
  +                    ((ServletResponseWrapper) previous).setResponse(next);
  +                break;
  +            }
  +
  +            // Advance to the next response in the chain
  +            previous = current;
  +            current = ((ServletResponseWrapper) current).getResponse();
  +
  +        }
  +
  +    }
  +
  +
  +    /**
  +     * Create and return a request wrapper that has been inserted in the
  +     * appropriate spot in the request chain.
  +     */
  +    private ServletRequest wrapRequest() {
  +
  +        // Locate the request we should insert in front of
  +        ServletRequest previous = null;
  +        ServletRequest current = outerRequest;
  +        while (current != null) {
  +            if (!(current instanceof ServletRequestWrapper))
  +                break;
  +            if (current instanceof ApplicationHttpRequest)
  +                break;
  +            if (current instanceof ApplicationRequest)
  +                break;
  +            if (current instanceof Request)
  +                break;
  +            previous = current;
  +            current = ((ServletRequestWrapper) current).getRequest();
  +        }
  +
  +        // Instantiate a new wrapper at this point and insert it in the chain
  +        ServletRequest wrapper = null;
  +        if ((current instanceof ApplicationHttpRequest) ||
  +            (current instanceof HttpRequest) ||
  +            (current instanceof HttpServletRequest))
  +            wrapper = new ApplicationHttpRequest((HttpServletRequest) current);
  +        else
  +            wrapper = new ApplicationRequest(current);
  +        if (previous == null)
  +            outerRequest = wrapper;
  +        else
  +            ((ServletRequestWrapper) previous).setRequest(wrapper);
  +        wrapRequest = wrapper;
  +        return (wrapper);
  +
  +    }
  +
  +
  +    /**
  +     * Create and return a response wrapper that has been inserted in the
  +     * appropriate spot in the response chain.
  +     */
  +    private ServletResponse wrapResponse() {
  +
  +        // Locate the response we should insert in front of
  +        ServletResponse previous = null;
  +        ServletResponse current = outerResponse;
  +        while (current != null) {
  +            if (!(current instanceof ServletResponseWrapper))
  +                break;
  +            if (current instanceof ApplicationHttpResponse)
  +                break;
  +            if (current instanceof ApplicationResponse)
  +                break;
  +            if (current instanceof Response)
  +                break;
  +            previous = current;
  +            current = ((ServletResponseWrapper) current).getResponse();
  +        }
  +
  +        // Instantiate a new wrapper at this point and insert it in the chain
  +        ServletResponse wrapper = null;
  +        if ((current instanceof ApplicationHttpResponse) ||
  +            (current instanceof HttpResponse) ||
  +            (current instanceof HttpServletResponse))
  +            wrapper =
  +                new ApplicationHttpResponse((HttpServletResponse) current,
  +                                            including);
  +        else
  +            wrapper = new ApplicationResponse(current, including);
  +        if (previous == null)
  +            outerResponse = wrapper;
  +        else
  +            ((ServletResponseWrapper) previous).setResponse(wrapper);
  +        wrapResponse = wrapper;
  +        return (wrapper);
   
       }
   
  
  
  

Reply via email to