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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]