You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2003/07/19 16:30:07 UTC

cvs commit: jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/valves LocalStrings.properties mbeans-descriptors.xml ErrorDispatcherValve.java

remm        2003/07/19 07:30:07

  Modified:    catalina/src/share/org/apache/catalina/core
                        LocalStrings.properties StandardHost.java
                        StandardHostValve.java StandardServer.java
               catalina/src/share/org/apache/catalina/valves
                        LocalStrings.properties mbeans-descriptors.xml
  Removed:     catalina/src/share/org/apache/catalina/valves
                        ErrorDispatcherValve.java
  Log:
  - Merge ErrorDispacherValve functionality back into StadardHostValve, and
    remove associated hacks from StandardServer and StandardHost.
  
  Revision  Changes    Path
  1.8       +1 -0      jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/LocalStrings.properties,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- LocalStrings.properties	24 Jun 2003 22:37:33 -0000	1.7
  +++ LocalStrings.properties	19 Jul 2003 14:30:07 -0000	1.8
  @@ -93,6 +93,7 @@
   standardHost.accessBase=Cannot access document base directory {0}
   standardHost.alreadyStarted=Host has already been started
   standardHost.appBase=Application base directory {0} does not exist
  +standardHost.clientAbort=Remote Client Aborted Request, IOException: {0}
   standardHost.configRequired=URL to configuration file is required
   standardHost.configNotAllowed=Use of configuration file is not allowed
   standardHost.installBase=Only web applications in the Host web application directory can be installed
  
  
  
  1.19      +1 -5      jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardHost.java
  
  Index: StandardHost.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardHost.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- StandardHost.java	21 Jun 2003 20:00:22 -0000	1.18
  +++ StandardHost.java	19 Jul 2003 14:30:07 -0000	1.19
  @@ -75,7 +75,6 @@
   import org.apache.catalina.LifecycleException;
   import org.apache.catalina.Valve;
   import org.apache.catalina.Realm;
  -import org.apache.catalina.valves.ErrorDispatcherValve;
   import org.apache.catalina.valves.ValveBase;
   import org.apache.commons.modeler.Registry;
   
  @@ -788,9 +787,6 @@
                        errorReportValveClass));
               }
           }
  -
  -        // Set dispatcher valve
  -        addValve(new ErrorDispatcherValve());
   
           super.start();
   
  
  
  
  1.7       +317 -4    jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardHostValve.java
  
  Index: StandardHostValve.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardHostValve.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- StandardHostValve.java	18 Jul 2003 18:49:28 -0000	1.6
  +++ StandardHostValve.java	19 Jul 2003 14:30:07 -0000	1.7
  @@ -66,16 +66,28 @@
   
   
   import java.io.IOException;
  +import javax.servlet.RequestDispatcher;
  +import javax.servlet.ServletContext;
   import javax.servlet.ServletException;
  +import javax.servlet.ServletRequest;
  +import javax.servlet.ServletResponse;
   import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpServletResponse;
   import org.apache.catalina.Container;
   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.Manager;
   import org.apache.catalina.Request;
   import org.apache.catalina.Response;
   import org.apache.catalina.Session;
   import org.apache.catalina.ValveContext;
  +import org.apache.catalina.Wrapper;
  +import org.apache.catalina.connector.ClientAbortException;
  +import org.apache.catalina.deploy.ErrorPage;
  +import org.apache.catalina.util.RequestUtil;
   import org.apache.catalina.util.StringManager;
   import org.apache.catalina.valves.ValveBase;
   
  @@ -176,6 +188,307 @@
           // Ask this Context to process this request
           context.getPipeline().invoke(request, response);
   
  +        // Error page processing
  +        response.setSuspended(false);
  +
  +        Throwable t = (Throwable) hreq.getAttribute(Globals.EXCEPTION_ATTR);
  +
  +        if (t != null) {
  +            throwable(request, response, t);
  +        } else {
  +            status(request, response);
  +        }
  +
  +    }
  +
  +
  +    // ------------------------------------------------------ Protected Methods
  +
  +
  +    /**
  +     * Handle the specified Throwable encountered while processing
  +     * the specified Request to produce the specified Response.  Any
  +     * exceptions that occur during generation of the exception report are
  +     * logged and swallowed.
  +     *
  +     * @param request The request being processed
  +     * @param response The response being generated
  +     * @param exception The exception that occurred (which possibly wraps
  +     *  a root cause exception
  +     */
  +    protected void throwable(Request request, Response response,
  +                             Throwable throwable) {
  +        Context context = request.getContext();
  +        if (context == null)
  +            return;
  +        
  +        Throwable realError = throwable;
  +        
  +        if (realError instanceof ServletException) {
  +            realError = ((ServletException) realError).getRootCause();
  +            if (realError == null) {
  +                realError = throwable;
  +            }
  +        } 
  +
  +        // If this is an aborted request from a client just log it and return
  +        if (realError instanceof ClientAbortException ) {
  +            log(sm.getString(
  +                "errorDispatcherValve.clientAbort",
  +                ((ClientAbortException)realError).getThrowable().getMessage()));
  +            return;
  +        }
  +
  +        ErrorPage errorPage = findErrorPage(context, realError);
  +
  +        if (errorPage != null) {
  +            response.setAppCommitted(false);
  +            ServletRequest sreq = request.getRequest();
  +            ServletResponse sresp = response.getResponse();
  +            sreq.setAttribute
  +                (ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
  +                 errorPage.getLocation());
  +            sreq.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
  +                              new Integer(ApplicationFilterFactory.ERROR));
  +            sreq.setAttribute
  +                (Globals.STATUS_CODE_ATTR,
  +                 new Integer(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
  +            sreq.setAttribute(Globals.ERROR_MESSAGE_ATTR,
  +                              throwable.getMessage());
  +            sreq.setAttribute(Globals.EXCEPTION_ATTR,
  +                              realError);
  +            Wrapper wrapper = request.getWrapper();
  +            if (wrapper != null)
  +                sreq.setAttribute(Globals.SERVLET_NAME_ATTR,
  +                                  wrapper.getName());
  +            if (sreq instanceof HttpServletRequest)
  +                sreq.setAttribute(Globals.EXCEPTION_PAGE_ATTR,
  +                                  ((HttpServletRequest) sreq).getRequestURI());
  +            sreq.setAttribute(Globals.EXCEPTION_TYPE_ATTR,
  +                              realError.getClass());
  +            if (custom(request, response, errorPage)) {
  +                try {
  +                    sresp.flushBuffer();
  +                } catch (IOException e) {
  +                    log("Exception Processing " + errorPage, e);
  +                }
  +            }
  +        } else {
  +            // A custom error-page has not been defined for the exception
  +            // that was thrown during request processing. Check if an
  +            // error-page for error code 500 was specified and if so, 
  +            // send that page back as the response.
  +            ServletResponse sresp = (ServletResponse) response;
  +            if (sresp instanceof HttpServletResponse) {
  +                ((HttpServletResponse) sresp).setStatus(
  +                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
  +                // The response is an error
  +                response.setError();
  +
  +                status(request, response);
  +            }
  +        }
  +            
  +
  +    }
  +
  +
  +    /**
  +     * Handle the HTTP status code (and corresponding message) generated
  +     * while processing the specified Request to produce the specified
  +     * Response.  Any exceptions that occur during generation of the error
  +     * report are logged and swallowed.
  +     *
  +     * @param request The request being processed
  +     * @param response The response being generated
  +     */
  +    protected void status(Request request, Response response) {
  +
  +        // Do nothing on non-HTTP responses
  +        if (!(response instanceof HttpResponse))
  +            return;
  +        HttpResponse hresponse = (HttpResponse) response;
  +        if (!(response.getResponse() instanceof HttpServletResponse))
  +            return;
  +        int statusCode = hresponse.getStatus();
  +        String message = RequestUtil.filter(hresponse.getMessage());
  +        if (message == null)
  +            message = "";
  +
  +        // Handle a custom error page for this status code
  +        Context context = request.getContext();
  +        if (context == null)
  +            return;
  +
  +        ErrorPage errorPage = context.findErrorPage(statusCode);
  +        if (errorPage != null) {
  +            response.setAppCommitted(false);
  +            ServletRequest sreq = request.getRequest();
  +            ServletResponse sresp = response.getResponse();
  +            sreq.setAttribute(Globals.STATUS_CODE_ATTR,
  +                              new Integer(statusCode));
  +            sreq.setAttribute(Globals.ERROR_MESSAGE_ATTR, message);
  +            sreq.setAttribute
  +                (ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
  +                 errorPage.getLocation());
  +            sreq.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
  +                              new Integer(ApplicationFilterFactory.ERROR));
  +            
  +             
  +            Wrapper wrapper = request.getWrapper();
  +            if (wrapper != null)
  +                sreq.setAttribute(Globals.SERVLET_NAME_ATTR,
  +                                  wrapper.getName());
  +            if (sreq instanceof HttpServletRequest)
  +                sreq.setAttribute(Globals.EXCEPTION_PAGE_ATTR,
  +                                  ((HttpServletRequest) sreq).getRequestURI());
  +            if (custom(request, response, errorPage)) {
  +                try {
  +                    sresp.flushBuffer();
  +                } catch (IOException e) {
  +                    log("Exception Processing " + errorPage, e);
  +                }
  +            }
  +        }
  +
       }
  +
  +
  +    /**
  +     * Find and return the ErrorPage instance for the specified exception's
  +     * class, or an ErrorPage instance for the closest superclass for which
  +     * there is such a definition.  If no associated ErrorPage instance is
  +     * found, return <code>null</code>.
  +     *
  +     * @param context The Context in which to search
  +     * @param exception The exception for which to find an ErrorPage
  +     */
  +    protected static ErrorPage findErrorPage
  +        (Context context, Throwable exception) {
  +
  +        if (exception == null)
  +            return (null);
  +        Class clazz = exception.getClass();
  +        String name = clazz.getName();
  +        while (!"java.lang.Object".equals(clazz)) {
  +            ErrorPage errorPage = context.findErrorPage(name);
  +            if (errorPage != null)
  +                return (errorPage);
  +            clazz = clazz.getSuperclass();
  +            if (clazz == null)
  +                break;
  +            name = clazz.getName();
  +        }
  +        return (null);
  +
  +    }
  +
  +
  +    /**
  +     * Handle an HTTP status code or Java exception by forwarding control
  +     * to the location included in the specified errorPage object.  It is
  +     * assumed that the caller has already recorded any request attributes
  +     * that are to be forwarded to this page.  Return <code>true</code> if
  +     * we successfully utilized the specified error page location, or
  +     * <code>false</code> if the default error report should be rendered.
  +     *
  +     * @param request The request being processed
  +     * @param response The response being generated
  +     * @param errorPage The errorPage directive we are obeying
  +     */
  +    protected boolean custom(Request request, Response response,
  +                             ErrorPage errorPage) {
  +
  +        if (debug >= 1)
  +            log("Processing " + errorPage);
  +
  +        // Validate our current environment
  +        if (!(request instanceof HttpRequest)) {
  +            if (debug >= 1)
  +                log(" Not processing an HTTP request --> default handling");
  +            return (false);     // NOTE - Nothing we can do generically
  +        }
  +        HttpServletRequest hreq =
  +            (HttpServletRequest) request.getRequest();
  +        if (!(response instanceof HttpResponse)) {
  +            if (debug >= 1)
  +                log("Not processing an HTTP response --> default handling");
  +            return (false);     // NOTE - Nothing we can do generically
  +        }
  +        HttpServletResponse hres =
  +            (HttpServletResponse) response.getResponse();
  +        
  +        ((HttpRequest) request).setPathInfo(errorPage.getLocation());
  +
  +        try {
  +
  +            // Reset the response if possible (else IllegalStateException)
  +            //hres.reset();
  +            // Reset the response (keeping the real error code and message)
  +            Integer statusCodeObj =
  +                (Integer) hreq.getAttribute(Globals.STATUS_CODE_ATTR);
  +            int statusCode = statusCodeObj.intValue();
  +            String message = 
  +                (String) hreq.getAttribute(Globals.ERROR_MESSAGE_ATTR);
  +            ((HttpResponse) response).reset(statusCode, message);
  +
  +            // Forward control to the specified location
  +            ServletContext servletContext =
  +                request.getContext().getServletContext();
  +            RequestDispatcher rd =
  +                servletContext.getRequestDispatcher(errorPage.getLocation());
  +            rd.forward(hreq, hres);
  +
  +            // If we forward, the response is suspended again
  +            response.setSuspended(false);
  +
  +            // Indicate that we have successfully processed this custom page
  +            return (true);
  +
  +        } catch (Throwable t) {
  +
  +            // Report our failure to process this custom page
  +            log("Exception Processing " + errorPage, t);
  +            return (false);
  +
  +        }
  +
  +    }
  +
  +
  +    /**
  +     * Log a message on the Logger associated with our Container (if any).
  +     *
  +     * @param message Message to be logged
  +     */
  +    protected void log(String message) {
  +
  +        Logger logger = container.getLogger();
  +        if (logger != null)
  +            logger.log(this.toString() + ": " + message);
  +        else
  +            System.out.println(this.toString() + ": " + message);
  +
  +    }
  +
  +
  +    /**
  +     * Log a message on the Logger associated with our Container (if any).
  +     *
  +     * @param message Message to be logged
  +     * @param throwable Associated exception
  +     */
  +    protected void log(String message, Throwable throwable) {
  +
  +        Logger logger = container.getLogger();
  +        if (logger != null)
  +            logger.log(this.toString() + ": " + message, throwable);
  +        else {
  +            System.out.println(this.toString() + ": " + message);
  +            throwable.printStackTrace(System.out);
  +        }
  +
  +    }
  +
   
   }
  
  
  
  1.18      +4 -5      jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardServer.java
  
  Index: StandardServer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardServer.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- StandardServer.java	22 May 2003 23:04:18 -0000	1.17
  +++ StandardServer.java	19 Jul 2003 14:30:07 -0000	1.18
  @@ -210,7 +210,6 @@
           "org.apache.catalina.startup.EngineConfig",
           "org.apache.catalina.startup.HostConfig",
           "org.apache.catalina.valves.CertificatesValve",
  -        "org.apache.catalina.valves.ErrorDispatcherValve",
           "org.apache.catalina.valves.ErrorReportValve",
           "org.apache.catalina.valves.RequestListenerValve",
       };
  
  
  
  1.5       +0 -3      jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/valves/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/valves/LocalStrings.properties,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- LocalStrings.properties	19 Jul 2003 10:14:17 -0000	1.4
  +++ LocalStrings.properties	19 Jul 2003 14:30:07 -0000	1.5
  @@ -10,9 +10,6 @@
   requestListenerValve.requestDestroy=Exception sending request destroyed lifecycle event to listener instance of class {0}
   valveBase.noNext=Configuration error: No 'next' valve configured
   
  -# Error Dispatcher valve
  -errorDispatcherValve.clientAbort=Remote Client Aborted Request, IOException: {0}
  -
   # Error report valve
   errorReportValve.errorReport=Error report
   errorReportValve.statusHeader=HTTP Status {0} - {1}
  
  
  
  1.5       +0 -22     jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/valves/mbeans-descriptors.xml
  
  Index: mbeans-descriptors.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/valves/mbeans-descriptors.xml,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- mbeans-descriptors.xml	11 Jun 2003 03:10:01 -0000	1.4
  +++ mbeans-descriptors.xml	19 Jul 2003 14:30:07 -0000	1.5
  @@ -76,28 +76,6 @@
   
     </mbean>
   
  -  <mbean name="ErrorDispatcherValve"
  -         description="Implementation of a Valve that handles the error
  -         dispatch"
  -         domain="Catalina"
  -         group="Valve"
  -         type="org.apache.catalina.valves.ErrorDispatcherValve">
  -
  -    <attribute name="className"
  -               description="Fully qualified class name of the managed object"
  -               type="java.lang.String"
  -               writeable="false"/>
  -
  -    <attribute name="containerName"
  -               description="Object name of the container"
  -               type="javax.management.ObjectName"/>
  -
  -    <attribute name="debug"
  -               description="The debugging detail level for this component"
  -               type="int"/>
  -
  -  </mbean>
  -
     <mbean name="ExtendedAccessLogValve"
            description="Valve that generates a web server access log"
            domain="Catalina"
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org