You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2011/09/02 12:45:26 UTC

svn commit: r1164469 - in /tomcat/trunk/java/org/apache/catalina/core: StandardContextValve.java StandardHostValve.java

Author: markt
Date: Fri Sep  2 10:45:26 2011
New Revision: 1164469

URL: http://svn.apache.org/viewvc?rev=1164469&view=rev
Log:
Fix a regression with the fix for 51653 that broke custom error page handling for error status codes return by the authenticators.
This moves error page handling back to the host valve and also moves request listener handling to the host valve. This ensures that everything at a context level happens inside the listeners and that custom error pages are available for all context errors.

Modified:
    tomcat/trunk/java/org/apache/catalina/core/StandardContextValve.java
    tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContextValve.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContextValve.java?rev=1164469&r1=1164468&r2=1164469&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContextValve.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContextValve.java Fri Sep  2 10:45:26 2011
@@ -21,24 +21,16 @@ package org.apache.catalina.core;
 
 import java.io.IOException;
 
-import javax.servlet.DispatcherType;
 import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.catalina.Container;
-import org.apache.catalina.Context;
 import org.apache.catalina.Wrapper;
 import org.apache.catalina.comet.CometEvent;
-import org.apache.catalina.connector.ClientAbortException;
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.connector.Response;
-import org.apache.catalina.deploy.ErrorPage;
 import org.apache.catalina.valves.ValveBase;
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.buf.MessageBytes;
 
 /**
@@ -54,8 +46,6 @@ import org.apache.tomcat.util.buf.Messag
 
 final class StandardContextValve extends ValveBase {
     
-    private static final Log log = LogFactory.getLog(StandardHostValve.class);
-
     //------------------------------------------------------ Constructor
     public StandardContextValve() {
         super(true);
@@ -124,7 +114,7 @@ final class StandardContextValve extends
                 || (requestPathMB.equalsIgnoreCase("/META-INF"))
                 || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
                 || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
-            error(request, response, HttpServletResponse.SC_NOT_FOUND);
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
             return;
         }
 
@@ -151,13 +141,13 @@ final class StandardContextValve extends
         // Select the Wrapper to be used for this Request
         Wrapper wrapper = request.getWrapper();
         if (wrapper == null) {
-            error(request, response, HttpServletResponse.SC_NOT_FOUND);
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
             return;
         } else if (wrapper.isUnavailable()) {
             // May be as a result of a reload, try and find the new wrapper
             wrapper = (Wrapper) container.findChild(wrapper.getName());
             if (wrapper == null) {
-                error(request, response, HttpServletResponse.SC_NOT_FOUND);
+                response.sendError(HttpServletResponse.SC_NOT_FOUND);
                 return;
             }
         }
@@ -169,47 +159,14 @@ final class StandardContextValve extends
             container.getLogger().error(sm.getString(
                     "standardContextValve.acknowledgeException"), ioe);
             request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
-            error(request, response,
-                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
             return;
         }
         
-        // Don't fire listeners during async processing
-        // If a request init listener throws an exception, the request is
-        // aborted
-        boolean asyncAtStart = request.isAsync(); 
-        if (asyncAtStart || context.fireRequestInitEvent(request)) {
-            if (request.isAsyncSupported()) {
-                request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
-            }
-            wrapper.getPipeline().getFirst().invoke(request, response);
-
-            // If the request was async at the start and an error occurred then
-            // the async error handling will kick-in and that will fire the
-            // request destroyed event *after* the error handling has taken
-            // place
-            if (!(request.isAsync() || (asyncAtStart && request.getAttribute(
-                        RequestDispatcher.ERROR_EXCEPTION) != null))) {
-                // Protect against NPEs if context was destroyed during a long
-                // running request.
-                StandardContext c = context;
-                if (c != null && c.getState().isAvailable()) {
-                    // Error page processing
-                    response.setSuspended(false);
-
-                    Throwable t = (Throwable) request.getAttribute(
-                            RequestDispatcher.ERROR_EXCEPTION);
-
-                    if (t != null) {
-                        throwable(request, response, t);
-                    } else {
-                        status(request, response);
-                    }
-
-                    context.fireRequestDestroyEvent(request);
-                }
-            }
+        if (request.isAsyncSupported()) {
+            request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
         }
+        wrapper.getPipeline().getFirst().invoke(request, response);
     }
 
 
@@ -233,273 +190,5 @@ final class StandardContextValve extends
         Wrapper wrapper = request.getWrapper();
 
         wrapper.getPipeline().getFirst().event(request, response, event);
-            
-        // Error page processing
-        response.setSuspended(false);
-
-        Throwable t = (Throwable) request.getAttribute(
-                RequestDispatcher.ERROR_EXCEPTION);
-
-        if (t != null) {
-            throwable(request, response, t);
-        } else {
-            status(request, response);
-        }
-    }
-
-
-    // -------------------------------------------------------- Private Methods
-
-
-    /**
-     * Report an error for the specified resource.
-     *
-     * @param response The response we are creating
-     */
-    private void error(Request request, Response response, int status) {
-
-        context.fireRequestInitEvent(request);
-        
-        try {
-            response.sendError(status);
-        } catch (IllegalStateException e) {
-            // Ignore
-        } catch (IOException e) {
-            // Ignore
-        }
-
-        response.setSuspended(false);
-        status(request, response);
-        
-        context.fireRequestDestroyEvent(request);
-    }
-
-
-    /**
-     * 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
-     */
-    private void status(Request request, Response response) {
-
-        int statusCode = response.getStatus();
-
-        // Handle a custom error page for this status code
-        Context context = request.getContext();
-        if (context == null)
-            return;
-
-        /* Only look for error pages when isError() is set.
-         * isError() is set when response.sendError() is invoked. This
-         * allows custom error pages without relying on default from
-         * web.xml.
-         */
-        if (!response.isError())
-            return;
-
-        ErrorPage errorPage = context.findErrorPage(statusCode);
-        if (errorPage != null) {
-            response.setAppCommitted(false);
-            request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE,
-                              Integer.valueOf(statusCode));
-
-            String message = response.getMessage();
-            if (message == null)
-                message = "";
-            request.setAttribute(RequestDispatcher.ERROR_MESSAGE, message);
-            request.setAttribute
-                (ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
-                 errorPage.getLocation());
-            request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
-                              DispatcherType.ERROR);
-
-
-            Wrapper wrapper = request.getWrapper();
-            if (wrapper != null)
-                request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME,
-                                  wrapper.getName());
-            request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI,
-                                 request.getRequestURI());
-            if (custom(request, response, errorPage)) {
-                try {
-                    response.flushBuffer();
-                } catch (ClientAbortException e) {
-                    // Ignore
-                } catch (IOException e) {
-                    container.getLogger().warn("Exception Processing " + errorPage, e);
-                }
-            }
-        }
-    }
-
-    
-    /**
-     * 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 throwable The exception that occurred (which possibly wraps
-     *  a root cause exception
-     */
-    private 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 ) {
-            if (log.isDebugEnabled()) {
-                log.debug
-                    (sm.getString("standardHost.clientAbort",
-                        realError.getCause().getMessage()));
-            }
-            return;
-        }
-
-        ErrorPage errorPage = findErrorPage(context, throwable);
-        if ((errorPage == null) && (realError != throwable)) {
-            errorPage = findErrorPage(context, realError);
-        }
-
-        if (errorPage != null) {
-            response.setAppCommitted(false);
-            request.setAttribute
-                (ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
-                 errorPage.getLocation());
-            request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
-                              DispatcherType.ERROR);
-            request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE,
-                    new Integer(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
-            request.setAttribute(RequestDispatcher.ERROR_MESSAGE,
-                              throwable.getMessage());
-            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,
-                              realError);
-            Wrapper wrapper = request.getWrapper();
-            if (wrapper != null)
-                request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME,
-                                  wrapper.getName());
-            request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI,
-                                 request.getRequestURI());
-            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,
-                              realError.getClass());
-            if (custom(request, response, errorPage)) {
-                try {
-                    response.flushBuffer();
-                } catch (IOException e) {
-                    container.getLogger().warn("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.
-            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-            // The response is an error
-            response.setError();
-
-            status(request, response);
-        }
-    }
-
-
-    /**
-     * 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
-     */
-    private boolean custom(Request request, Response response,
-                             ErrorPage errorPage) {
-
-        if (container.getLogger().isDebugEnabled())
-            container.getLogger().debug("Processing " + errorPage);
-
-        request.setPathInfo(errorPage.getLocation());
-
-        try {
-            // Forward control to the specified location
-            ServletContext servletContext =
-                request.getContext().getServletContext();
-            RequestDispatcher rd =
-                servletContext.getRequestDispatcher(errorPage.getLocation());
-
-            if (response.isCommitted()) {
-                // Response is committed - including the error page is the
-                // best we can do 
-                rd.include(request.getRequest(), response.getResponse());
-            } else {
-                // Reset the response (keeping the real error code and message)
-                response.resetBuffer(true);
-
-                rd.forward(request.getRequest(), response.getResponse());
-
-                // 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) {
-            ExceptionUtils.handleThrowable(t);
-            // Report our failure to process this custom page
-            container.getLogger().error("Exception Processing " + errorPage, t);
-            return (false);
-
-        }
-    }
-
-    
-    /**
-     * 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
-     */
-    private static ErrorPage findErrorPage
-        (Context context, Throwable exception) {
-
-        if (exception == null)
-            return (null);
-        Class<?> clazz = exception.getClass();
-        String name = clazz.getName();
-        while (!Object.class.equals(clazz)) {
-            ErrorPage errorPage = context.findErrorPage(name);
-            if (errorPage != null)
-                return (errorPage);
-            clazz = clazz.getSuperclass();
-            if (clazz == null)
-                break;
-            name = clazz.getName();
-        }
-        return (null);
-
     }
 }

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java?rev=1164469&r1=1164468&r2=1164469&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardHostValve.java Fri Sep  2 10:45:26 2011
@@ -23,15 +23,24 @@ import java.io.IOException;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
+import javax.servlet.DispatcherType;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.catalina.Context;
 import org.apache.catalina.Globals;
+import org.apache.catalina.Wrapper;
 import org.apache.catalina.comet.CometEvent;
+import org.apache.catalina.connector.ClientAbortException;
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.connector.Response;
+import org.apache.catalina.deploy.ErrorPage;
 import org.apache.catalina.valves.ValveBase;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.res.StringManager;
 
 
@@ -49,6 +58,8 @@ import org.apache.tomcat.util.res.String
 
 final class StandardHostValve extends ValveBase {
 
+    private static final Log log = LogFactory.getLog(StandardHostValve.class);
+
     protected static final boolean STRICT_SERVLET_COMPLIANCE;
 
     protected static final boolean ACCESS_SESSION;
@@ -146,9 +157,40 @@ final class StandardHostValve extends Va
             request.setAsyncSupported(context.getPipeline().isAsyncSupported());
         }
 
-
-        // Ask this Context to process this request
-        context.getPipeline().getFirst().invoke(request, response);
+        // Don't fire listeners during async processing
+        // If a request init listener throws an exception, the request is
+        // aborted
+        boolean asyncAtStart = request.isAsync(); 
+        if (asyncAtStart || context.fireRequestInitEvent(request)) {
+
+            // Ask this Context to process this request
+            context.getPipeline().getFirst().invoke(request, response);
+    
+            // If the request was async at the start and an error occurred then
+            // the async error handling will kick-in and that will fire the
+            // request destroyed event *after* the error handling has taken
+            // place
+            if (!(request.isAsync() || (asyncAtStart && request.getAttribute(
+                        RequestDispatcher.ERROR_EXCEPTION) != null))) {
+                // Protect against NPEs if context was destroyed during a long
+                // running request.
+                if (context.getState().isAvailable()) {
+                    // Error page processing
+                    response.setSuspended(false);
+    
+                    Throwable t = (Throwable) request.getAttribute(
+                            RequestDispatcher.ERROR_EXCEPTION);
+    
+                    if (t != null) {
+                        throwable(request, response, t);
+                    } else {
+                        status(request, response);
+                    }
+    
+                    context.fireRequestDestroyEvent(request);
+                }
+            }
+        }
 
         // Access a session (if present) to update last accessed time, based on a
         // strict interpretation of the specification
@@ -165,7 +207,6 @@ final class StandardHostValve extends Va
             Thread.currentThread().setContextClassLoader
                     (StandardHostValve.class.getClassLoader());
         }
-
     }
 
 
@@ -197,6 +238,19 @@ final class StandardHostValve extends Va
         // Ask this Context to process this request
         context.getPipeline().getFirst().event(request, response, event);
 
+        
+        // Error page processing
+        response.setSuspended(false);
+
+        Throwable t = (Throwable) request.getAttribute(
+                RequestDispatcher.ERROR_EXCEPTION);
+
+        if (t != null) {
+            throwable(request, response, t);
+        } else {
+            status(request, response);
+        }
+
         // Access a session (if present) to update last accessed time, based on a
         // strict interpretation of the specification
         if (ACCESS_SESSION) {
@@ -210,6 +264,237 @@ final class StandardHostValve extends Va
     }
 
 
+    // -------------------------------------------------------- Private Methods
+
+    /**
+     * 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
+     */
+    private void status(Request request, Response response) {
+
+        int statusCode = response.getStatus();
+
+        // Handle a custom error page for this status code
+        Context context = request.getContext();
+        if (context == null)
+            return;
+
+        /* Only look for error pages when isError() is set.
+         * isError() is set when response.sendError() is invoked. This
+         * allows custom error pages without relying on default from
+         * web.xml.
+         */
+        if (!response.isError())
+            return;
+
+        ErrorPage errorPage = context.findErrorPage(statusCode);
+        if (errorPage != null) {
+            response.setAppCommitted(false);
+            request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE,
+                              Integer.valueOf(statusCode));
+
+            String message = response.getMessage();
+            if (message == null)
+                message = "";
+            request.setAttribute(RequestDispatcher.ERROR_MESSAGE, message);
+            request.setAttribute
+                (ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
+                 errorPage.getLocation());
+            request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
+                              DispatcherType.ERROR);
+
+
+            Wrapper wrapper = request.getWrapper();
+            if (wrapper != null)
+                request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME,
+                                  wrapper.getName());
+            request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI,
+                                 request.getRequestURI());
+            if (custom(request, response, errorPage)) {
+                try {
+                    response.flushBuffer();
+                } catch (ClientAbortException e) {
+                    // Ignore
+                } catch (IOException e) {
+                    container.getLogger().warn("Exception Processing " + errorPage, e);
+                }
+            }
+        }
+    }
+
+
+    /**
+     * 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 throwable The exception that occurred (which possibly wraps
+     *  a root cause exception
+     */
+    private 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 ) {
+            if (log.isDebugEnabled()) {
+                log.debug
+                    (sm.getString("standardHost.clientAbort",
+                        realError.getCause().getMessage()));
+            }
+            return;
+        }
+
+        ErrorPage errorPage = findErrorPage(context, throwable);
+        if ((errorPage == null) && (realError != throwable)) {
+            errorPage = findErrorPage(context, realError);
+        }
+
+        if (errorPage != null) {
+            response.setAppCommitted(false);
+            request.setAttribute
+                (ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
+                 errorPage.getLocation());
+            request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
+                              DispatcherType.ERROR);
+            request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE,
+                    new Integer(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
+            request.setAttribute(RequestDispatcher.ERROR_MESSAGE,
+                              throwable.getMessage());
+            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,
+                              realError);
+            Wrapper wrapper = request.getWrapper();
+            if (wrapper != null)
+                request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME,
+                                  wrapper.getName());
+            request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI,
+                                 request.getRequestURI());
+            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,
+                              realError.getClass());
+            if (custom(request, response, errorPage)) {
+                try {
+                    response.flushBuffer();
+                } catch (IOException e) {
+                    container.getLogger().warn("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.
+            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            // The response is an error
+            response.setError();
+
+            status(request, response);
+        }
+    }
+
+
+    /**
+     * 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
+     */
+    private boolean custom(Request request, Response response,
+                             ErrorPage errorPage) {
+
+        if (container.getLogger().isDebugEnabled())
+            container.getLogger().debug("Processing " + errorPage);
+
+        request.setPathInfo(errorPage.getLocation());
+
+        try {
+            // Forward control to the specified location
+            ServletContext servletContext =
+                request.getContext().getServletContext();
+            RequestDispatcher rd =
+                servletContext.getRequestDispatcher(errorPage.getLocation());
+
+            if (response.isCommitted()) {
+                // Response is committed - including the error page is the
+                // best we can do 
+                rd.include(request.getRequest(), response.getResponse());
+            } else {
+                // Reset the response (keeping the real error code and message)
+                response.resetBuffer(true);
+
+                rd.forward(request.getRequest(), response.getResponse());
+
+                // 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) {
+            ExceptionUtils.handleThrowable(t);
+            // Report our failure to process this custom page
+            container.getLogger().error("Exception Processing " + errorPage, t);
+            return (false);
+
+        }
+    }
+
+
+    /**
+     * 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
+     */
+    private static ErrorPage findErrorPage
+        (Context context, Throwable exception) {
+
+        if (exception == null)
+            return (null);
+        Class<?> clazz = exception.getClass();
+        String name = clazz.getName();
+        while (!Object.class.equals(clazz)) {
+            ErrorPage errorPage = context.findErrorPage(name);
+            if (errorPage != null)
+                return (errorPage);
+            clazz = clazz.getSuperclass();
+            if (clazz == null)
+                break;
+            name = clazz.getName();
+        }
+        return (null);
+
+    }
+
+
     private static class PrivilegedSetTccl implements PrivilegedAction<Void> {
 
         private ClassLoader cl;



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