remm        01/09/26 10:45:52

  Modified:    catalina/src/share/org/apache/catalina/valves
                        ErrorDispatcherValve.java
  Log:
  - Error report and dispatching refactoring.
  - The error page dispatching code is now located in this valve.
  
  Revision  Changes    Path
  1.2       +218 -20   
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/valves/ErrorDispatcherValve.java
  
  Index: ErrorDispatcherValve.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/valves/ErrorDispatcherValve.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ErrorDispatcherValve.java 2001/09/25 22:11:49     1.1
  +++ ErrorDispatcherValve.java 2001/09/26 17:45:52     1.2
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/valves/ErrorDispatcherValve.java,v
 1.1 2001/09/25 22:11:49 remm Exp $
  - * $Revision: 1.1 $
  - * $Date: 2001/09/25 22:11:49 $
  + * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/valves/ErrorDispatcherValve.java,v
 1.2 2001/09/26 17:45:52 remm Exp $
  + * $Revision: 1.2 $
  + * $Date: 2001/09/26 17:45:52 $
    *
    * ====================================================================
    *
  @@ -69,6 +69,8 @@
   import java.util.ArrayList;
   import java.util.Enumeration;
   import java.util.Iterator;
  +import javax.servlet.RequestDispatcher;
  +import javax.servlet.ServletContext;
   import javax.servlet.ServletException;
   import javax.servlet.ServletRequest;
   import javax.servlet.ServletResponse;
  @@ -77,6 +79,7 @@
   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;
  @@ -84,7 +87,9 @@
   import org.apache.catalina.Response;
   import org.apache.catalina.Valve;
   import org.apache.catalina.ValveContext;
  -import org.apache.catalina.connector.HttpResponseWrapper;
  +import org.apache.catalina.Wrapper;
  +import org.apache.catalina.deploy.ErrorPage;
  +import org.apache.catalina.util.RequestUtil;
   import org.apache.catalina.util.StringManager;
   
   
  @@ -99,7 +104,7 @@
    *
    * @author Remy Maucherat
    * @author Craig R. McClanahan
  - * @version $Revision: 1.1 $ $Date: 2001/09/25 22:11:49 $
  + * @version $Revision: 1.2 $ $Date: 2001/09/26 17:45:52 $
    */
   
   public class ErrorDispatcherValve
  @@ -110,9 +115,15 @@
   
   
       /**
  +     * The debugging detail level for this component.
  +     */
  +    protected int debug = 0;
  +
  +
  +    /**
        * The descriptive information related to this implementation.
        */
  -    private static final String info =
  +    protected static final String info =
           "org.apache.catalina.valves.ErrorDispatcherValve/1.0";
   
   
  @@ -155,23 +166,17 @@
                          ValveContext context)
           throws IOException, ServletException {
   
  -        // Skip logging for non-HTTP requests and responses
  -        if (!(request instanceof HttpRequest) ||
  -            !(response instanceof HttpResponse)) {
  -            context.invokeNext(request, response);
  -            return;
  -        }
  -        HttpRequest hrequest = (HttpRequest) request;
  -        HttpResponse hresponse = (HttpResponse) response;
  -        HttpServletRequest hreq =
  -            (HttpServletRequest) hrequest.getRequest();
  -        HttpServletResponse hres =
  -            (HttpServletResponse) hresponse.getResponse();
  -
           // Perform the request
           context.invokeNext(request, response);
  +
  +        ServletRequest sreq = request.getRequest();
  +        Throwable t = (Throwable) sreq.getAttribute(Globals.EXCEPTION_ATTR);
   
  -        Context mappedContext = request.getContext();
  +        if (t != null) {
  +            throwable(request, response, t);
  +        } else {
  +            status(request, response);
  +        }
   
       }
   
  @@ -190,6 +195,199 @@
   
   
       // ------------------------------------------------------ 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();
  +
  +        Throwable realError = throwable;
  +        ErrorPage errorPage = findErrorPage(context, realError);
  +        if ((errorPage == null) && (realError instanceof ServletException)) {
  +            realError = ((ServletException) realError).getRootCause();
  +            if (realError != null)
  +                errorPage = findErrorPage(context, realError);
  +            else
  +                realError = throwable;
  +        }
  +
  +        if (errorPage != null) {
  +            ServletRequest sreq = request.getRequest();
  +            ServletResponse sresp = response.getResponse();
  +            sreq.setAttribute(Globals.ERROR_MESSAGE_ATTR,
  +                              throwable.getMessage());
  +            sreq.setAttribute(Globals.EXCEPTION_ATTR,
  +                              throwable);
  +            Wrapper wrapper = request.getWrapper();
  +            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,
  +                              throwable.getClass());
  +            if (custom(request, response, errorPage)) {
  +                try {
  +                    sresp.flushBuffer();
  +                } catch (IOException e) {
  +                    log("Exception Processing " + errorPage, e);
  +                }
  +            }
  +        }
  +
  +    }
  +
  +
  +    /**
  +     * 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();
  +        ErrorPage errorPage = context.findErrorPage(statusCode);
  +        if (errorPage != null) {
  +            ServletRequest sreq = request.getRequest();
  +            ServletResponse sresp = response.getResponse();
  +            sreq.setAttribute(Globals.STATUS_CODE_ATTR,
  +                              new Integer(statusCode));
  +            sreq.setAttribute(Globals.ERROR_MESSAGE_ATTR,
  +                              message);
  +            Wrapper wrapper = request.getWrapper();
  +            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();
  +
  +        try {
  +
  +            // Reset the response if possible (else IllegalStateException)
  +            hres.reset();
  +
  +            // Forward control to the specified location
  +            ServletContext servletContext =
  +                request.getContext().getServletContext();
  +            RequestDispatcher rd =
  +                servletContext.getRequestDispatcher(errorPage.getLocation());
  +            rd.forward(hreq, hres);
  +
  +            // 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);
  +
  +        }
  +
  +    }
   
   
       /**
  
  
  

Reply via email to