craigmcc    01/07/16 17:14:17

  Modified:    catalina/src/share/org/apache/catalina/servlets
                        InvokerServlet.java LocalStrings.properties
  Added:       catalina/src/share/org/apache/catalina/servlets
                        InvokerHttpRequest.java
  Log:
  Modify the way that the invoker servlet works.
  
  Previously, the invoker servlet would dynamically create a new Wrapper
  (and associated servlet mapping) on the first request to a particular
  servlet, and then do a RequestDispatcher.forward() to utilize the new
  Wrapper immediately.  This causes problems, though, when the invoker is
  itself included via a RequestDispatcher -- the semantics of
  RequestDispatcher.forward() say that the response is closed after the
  forwarded-to servlet returns, so that any output subsequently added by the
  including servlet would be ignored.
  
  Now, the invoker servlet will still create a new Wrapper and mapping as it
  did before (these are used on all subsequent requests to the same
  servlet).  However, instead of calling RequestDispatcher.forward(), a new
  servlet instance is allocated, invoked, and deallocated directly.
  
  PR: Bugzilla #1902
  Submitted by: Jason Hunter <[EMAIL PROTECTED]>
  
  Revision  Changes    Path
  1.6       +85 -51    
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/InvokerServlet.java
  
  Index: InvokerServlet.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/InvokerServlet.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- InvokerServlet.java       2001/05/16 17:56:46     1.5
  +++ InvokerServlet.java       2001/07/17 00:14:17     1.6
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/InvokerServlet.java,v
 1.5 2001/05/16 17:56:46 remm Exp $
  - * $Revision: 1.5 $
  - * $Date: 2001/05/16 17:56:46 $
  + * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/InvokerServlet.java,v
 1.6 2001/07/17 00:14:17 craigmcc Exp $
  + * $Revision: 1.6 $
  + * $Date: 2001/07/17 00:14:17 $
    *
    * ====================================================================
    *
  @@ -86,7 +86,7 @@
    * in the web application deployment descriptor.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.5 $ $Date: 2001/05/16 17:56:46 $
  + * @version $Revision: 1.6 $ $Date: 2001/07/17 00:14:17 $
    */
   
   public final class InvokerServlet
  @@ -367,58 +367,92 @@
                   }
               }
   
  -            // Ensure that we can actually allocate and release an instance
  -            try {
  -                Servlet instance = wrapper.allocate();
  -                wrapper.deallocate(instance);
  -            } catch (ServletException e) {
  -                log("serveRequest.load", e);
  -                context.removeServletMapping(pattern);
  -                context.removeChild(wrapper);
  -                Throwable rootCause = e.getRootCause();
  -                if (rootCause == null)
  -                    rootCause = e;
  -                if (included)
  -                    throw new ServletException
  -                        (sm.getString("invokerServlet.cannotLoad",
  -                                      inRequestURI), rootCause);
  -                if ((rootCause != null) &&
  -                    (rootCause instanceof ClassNotFoundException)) {
  -                    response.sendError(HttpServletResponse.SC_NOT_FOUND,
  -                                       inRequestURI);
  -                } else {
  -                    response.sendError
  -                        (HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
  -                         inRequestURI);
  -                }
  -                return;
  -            } catch (Throwable t) {
  -                log("serveRequest.load", t);
  -                context.removeServletMapping(pattern);
  -                context.removeChild(wrapper);
  -                if (included)
  -                    throw new ServletException
  -                        (sm.getString("invokerServlet.cannotLoad",
  -                                      inRequestURI), t);
  -                response.sendError
  -                    (HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
  -                     inRequestURI);
  -                return;
  -            }
  -
        }
   
  -     // Pass this request on to the identified or newly created wrapper
  +        // Create a request wrapper to pass on to the invoked servlet
  +        InvokerHttpRequest wrequest =
  +            new InvokerHttpRequest(request);
        StringBuffer sb = new StringBuffer(inServletPath);
        sb.append("/");
        sb.append(servletClass);
  -     sb.append(pathInfo);
  -     String dispatcherPath = sb.toString();
  -     if (debug >= 1)
  -         log("serveRequest:  Forwarding to '" + dispatcherPath + "'");
  -     RequestDispatcher rd =
  -         getServletContext().getRequestDispatcher(dispatcherPath);
  -     rd.forward(request, response);
  +        wrequest.setServletPath(sb.toString());
  +        if ((pathInfo == null) || (pathInfo.length() < 1))
  +            wrequest.setPathInfo(null);
  +        else
  +            wrequest.setPathInfo(pathInfo);
  +        wrequest.setQueryString(request.getQueryString());
  +
  +        // Allocate a servlet instance to perform this request
  +        Servlet instance = null;
  +        try {
  +            instance = wrapper.allocate();
  +        } catch (ServletException e) {
  +            log(sm.getString("invokerServlet.allocate", inRequestURI), e);
  +            context.removeServletMapping(pattern);
  +            context.removeChild(wrapper);
  +            Throwable rootCause = e.getRootCause();
  +            if (rootCause == null)
  +                rootCause = e;
  +            if (rootCause instanceof ClassNotFoundException) {
  +                response.sendError(HttpServletResponse.SC_NOT_FOUND,
  +                                   inRequestURI);
  +                return;
  +            } else if (rootCause instanceof IOException) {
  +                throw (IOException) rootCause;
  +            } else if (rootCause instanceof RuntimeException) {
  +                throw (RuntimeException) rootCause;
  +            } else if (rootCause instanceof ServletException) {
  +                throw (ServletException) rootCause;
  +            } else {
  +                throw new ServletException
  +                    (sm.getString("invokerServlet.allocate", inRequestURI),
  +                     rootCause);
  +            }
  +        } catch (Throwable e) {
  +            log(sm.getString("invokerServlet.allocate", inRequestURI), e);
  +            context.removeServletMapping(pattern);
  +            context.removeChild(wrapper);
  +            throw new ServletException
  +                (sm.getString("invokerServlet.allocate", inRequestURI), e);
  +        }
  +
  +        // Invoke the service() method of the allocated servlet
  +        try {
  +            instance.service(wrequest, response);
  +        } catch (IOException e) {
  +            try {
  +                wrapper.deallocate(instance);
  +            } catch (Throwable f) {
  +                ;
  +            }
  +            throw e;
  +        } catch (ServletException e) {
  +            try {
  +                wrapper.deallocate(instance);
  +            } catch (Throwable f) {
  +                ;
  +            }
  +            throw e;
  +        } catch (RuntimeException e) {
  +            try {
  +                wrapper.deallocate(instance);
  +            } catch (Throwable f) {
  +                ;
  +            }
  +            throw e;
  +        }
  +
  +        // Deallocate the allocated servlet instance
  +        try {
  +            wrapper.deallocate(instance);
  +        } catch (ServletException e) {
  +            log(sm.getString("invokerServlet.deallocate", inRequestURI), e);
  +            throw e;
  +        } catch (Throwable e) {
  +            log(sm.getString("invokerServlet.deallocate", inRequestURI), e);
  +            throw new ServletException
  +                (sm.getString("invokerServlet.deallocate", inRequestURI), e);
  +        }
   
       }
   
  
  
  
  1.8       +2 -0      
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/LocalStrings.properties,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- LocalStrings.properties   2001/05/14 00:02:32     1.7
  +++ LocalStrings.properties   2001/07/17 00:14:17     1.8
  @@ -2,7 +2,9 @@
   defaultservlet.upto=Up to:
   defaultservlet.subdirectories=Subdirectories:
   defaultservlet.files=Files:
  +invokerServlet.allocate=Cannot allocate servlet instance for path {0}
   invokerServlet.cannotCreate=Cannot create servlet wrapper for path {0}
  +invokerServlet.deallocate=Cannot deallocate servlet instance for path {0}
   invokerServlet.invalidPath=No servlet name or class was specified in path {0}
   invokerServlet.notNamed=Cannot call invoker servlet with a named dispatcher
   invokerServlet.noWrapper=Container has not called setWrapper() for this servlet
  
  
  
  1.1                  
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/InvokerHttpRequest.java
  
  Index: InvokerHttpRequest.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/InvokerHttpRequest.java,v
 1.1 2001/07/17 00:14:16 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2001/07/17 00:14:16 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  
  package org.apache.catalina.servlets;
  
  
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.Enumeration;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletRequestWrapper;
  import org.apache.catalina.Globals;
  import org.apache.catalina.HttpRequest;
  import org.apache.catalina.connector.HttpRequestFacade;
  import org.apache.catalina.util.Enumerator;
  import org.apache.catalina.util.RequestUtil;
  import org.apache.catalina.util.StringManager;
  
  
  /**
   * Wrapper around a <code>javax.servlet.http.HttpServletRequest</code>
   * utilized when <code>InvokerServlet</code> processes the initial request
   * for an invoked servlet.  Subsequent requests will be mapped directly
   * to the servlet, because a new servlet mapping will have been created.
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2001/07/17 00:14:16 $
   */
  
  class InvokerHttpRequest extends HttpServletRequestWrapper {
  
  
      // ----------------------------------------------------------- Constructors
  
  
      /**
       * Construct a new wrapped request around the specified servlet request.
       *
       * @param request The servlet request being wrapped
       */
      public InvokerHttpRequest(HttpServletRequest request) {
  
        super(request);
          this.contextPath = request.getContextPath();
          this.pathInfo = request.getPathInfo();
          this.queryString = request.getQueryString();
          this.requestURI = request.getRequestURI();
          this.servletPath = request.getServletPath();
  
      }
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * The context path for this request.
       */
      protected String contextPath = null;
  
  
      /**
       * Descriptive information about this implementation.
       */
      protected static final String info =
          "org.apache.catalina.servlets.InvokerHttpRequest/1.0";
  
  
      /**
       * The path information for this request.
       */
      protected String pathInfo = null;
  
  
      /**
       * The query string for this request.
       */
      protected String queryString = null;
  
  
      /**
       * The request URI for this request.
       */
      protected String requestURI = null;
  
  
      /**
       * The servlet path for this request.
       */
      protected String servletPath = null;
  
  
      /**
       * The string manager for this package.
       */
      protected static StringManager sm =
        StringManager.getManager(Constants.Package);
  
  
      // --------------------------------------------- HttpServletRequest Methods
  
  
      /**
       * Override the <code>getContextPath()</code> method of the wrapped
       * request.
       */
      public String getContextPath() {
  
        return (this.contextPath);
  
      }
  
  
      /**
       * Override the <code>getPathInfo()</code> method of the wrapped request.
       */
      public String getPathInfo() {
  
        return (this.pathInfo);
  
      }
  
  
      /**
       * Override the <code>getQueryString()</code> method of the wrapped
       * request.
       */
      public String getQueryString() {
  
        return (this.queryString);
  
      }
  
  
      /**
       * Override the <code>getRequestURI()</code> method of the wrapped
       * request.
       */
      public String getRequestURI() {
  
        return (this.requestURI);
  
      }
  
  
      /**
       * Override the <code>getServletPath()</code> method of the wrapped
       * request.
       */
      public String getServletPath() {
  
        return (this.servletPath);
  
      }
  
  
      // -------------------------------------------------------- Package Methods
  
  
  
      /**
       * Return descriptive information about this implementation.
       */
      public String getInfo() {
  
          return (this.info);
  
      }
  
  
      /**
       * Set the context path for this request.
       *
       * @param contextPath The new context path
       */
      void setContextPath(String contextPath) {
  
        this.contextPath = contextPath;
  
      }
  
  
      /**
       * Set the path information for this request.
       *
       * @param pathInfo The new path info
       */
      void setPathInfo(String pathInfo) {
  
        this.pathInfo = pathInfo;
  
      }
  
  
      /**
       * Set the query string for this request.
       *
       * @param queryString The new query string
       */
      void setQueryString(String queryString) {
  
        this.queryString = queryString;
  
      }
  
  
      /**
       * Set the request URI for this request.
       *
       * @param requestURI The new request URI
       */
      void setRequestURI(String requestURI) {
  
        this.requestURI = requestURI;
  
      }
  
  
      /**
       * Set the servlet path for this request.
       *
       * @param servletPath The new servlet path
       */
      void setServletPath(String servletPath) {
  
        this.servletPath = servletPath;
  
      }
  
  
  }
  
  
  

Reply via email to