FileDocCategorySizeDatePackage
StandardHostValve.javaAPI DocApache Tomcat 6.0.1416385Fri Jul 20 04:20:30 BST 2007org.apache.catalina.core

StandardHostValve

public final class StandardHostValve extends org.apache.catalina.valves.ValveBase
Valve that implements the default basic behavior for the StandardHost container implementation.

USAGE CONSTRAINT: This implementation is likely to be useful only when processing HTTP requests.

author
Craig R. McClanahan
author
Remy Maucherat
version
$Revision: 487694 $ $Date: 2006-12-15 23:30:51 +0100 (ven., 15 déc. 2006) $

Fields Summary
private static org.apache.juli.logging.Log
log
private static final String
info
The descriptive information related to this implementation.
private static final org.apache.catalina.util.StringManager
sm
The string manager for this package.
Constructors Summary
Methods Summary
protected booleancustom(org.apache.catalina.connector.Request request, org.apache.catalina.connector.Response response, org.apache.catalina.deploy.ErrorPage errorPage)
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 true if we successfully utilized the specified error page location, or false 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


        if (container.getLogger().isDebugEnabled())
            container.getLogger().debug("Processing " + errorPage);

        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) request.getAttribute(Globals.STATUS_CODE_ATTR);
            int statusCode = statusCodeObj.intValue();
            String message =
                (String) request.getAttribute(Globals.ERROR_MESSAGE_ATTR);
            response.reset(statusCode, message);

            // Forward control to the specified location
            ServletContext servletContext =
                request.getContext().getServletContext();
            RequestDispatcher rd =
                servletContext.getRequestDispatcher(errorPage.getLocation());
            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) {

            // Report our failure to process this custom page
            container.getLogger().error("Exception Processing " + errorPage, t);
            return (false);

        }

    
public final voidevent(org.apache.catalina.connector.Request request, org.apache.catalina.connector.Response response, org.apache.catalina.CometEvent event)
Process Comet event.

param
request Request to be processed
param
response Response to be produced
param
valveContext Valve context used to forward to the next Valve
exception
IOException if an input/output error occurred
exception
ServletException if a servlet error occurred


        // Select the Context to be used for this Request
        Context context = request.getContext();

        // Bind the context CL to the current thread
        if( context.getLoader() != null ) {
            // Not started - it should check for availability first
            // This should eventually move to Engine, it's generic.
            Thread.currentThread().setContextClassLoader
                    (context.getLoader().getClassLoader());
        }

        // Ask this Context to process this request
        context.getPipeline().getFirst().event(request, response, event);

        // Access a session (if present) to update last accessed time, based on a
        // strict interpretation of the specification
        if (Globals.STRICT_SERVLET_COMPLIANCE) {
            request.getSession(false);
        }

        // Error page processing
        response.setSuspended(false);

        Throwable t = (Throwable) request.getAttribute(Globals.EXCEPTION_ATTR);

        if (t != null) {
            throwable(request, response, t);
        } else {
            status(request, response);
        }

        // Restore the context classloader
        Thread.currentThread().setContextClassLoader
            (StandardHostValve.class.getClassLoader());

    
protected static org.apache.catalina.deploy.ErrorPagefindErrorPage(org.apache.catalina.Context context, java.lang.Throwable exception)
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 null.

param
context The Context in which to search
param
exception The exception for which to find an ErrorPage


        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);

    
public java.lang.StringgetInfo()
Return descriptive information about this Valve implementation.



    // ------------------------------------------------------------- Properties


                
       

        return (info);

    
public final voidinvoke(org.apache.catalina.connector.Request request, org.apache.catalina.connector.Response response)
Select the appropriate child Context to process this request, based on the specified request URI. If no matching Context can be found, return an appropriate HTTP error.

param
request Request to be processed
param
response Response to be produced
param
valveContext Valve context used to forward to the next Valve
exception
IOException if an input/output error occurred
exception
ServletException if a servlet error occurred


        // Select the Context to be used for this Request
        Context context = request.getContext();
        if (context == null) {
            response.sendError
                (HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                 sm.getString("standardHost.noContext"));
            return;
        }

        // Bind the context CL to the current thread
        if( context.getLoader() != null ) {
            // Not started - it should check for availability first
            // This should eventually move to Engine, it's generic.
            Thread.currentThread().setContextClassLoader
                    (context.getLoader().getClassLoader());
        }

        // Ask this Context to process this request
        context.getPipeline().getFirst().invoke(request, response);

        // Access a session (if present) to update last accessed time, based on a
        // strict interpretation of the specification
        if (Globals.STRICT_SERVLET_COMPLIANCE) {
            request.getSession(false);
        }

        // Error page processing
        response.setSuspended(false);

        Throwable t = (Throwable) request.getAttribute(Globals.EXCEPTION_ATTR);

        if (t != null) {
            throwable(request, response, t);
        } else {
            status(request, response);
        }

        // Restore the context classloader
        Thread.currentThread().setContextClassLoader
            (StandardHostValve.class.getClassLoader());

    
protected voidstatus(org.apache.catalina.connector.Request request, org.apache.catalina.connector.Response 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


        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(Globals.STATUS_CODE_ATTR,
                              new Integer(statusCode));

            String message = RequestUtil.filter(response.getMessage());
            if (message == null)
                message = "";
            request.setAttribute(Globals.ERROR_MESSAGE_ATTR, message);
            request.setAttribute
                (ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
                 errorPage.getLocation());
            request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
                              new Integer(ApplicationFilterFactory.ERROR));


            Wrapper wrapper = request.getWrapper();
            if (wrapper != null)
                request.setAttribute(Globals.SERVLET_NAME_ATTR,
                                  wrapper.getName());
            request.setAttribute(Globals.EXCEPTION_PAGE_ATTR,
                                 request.getRequestURI());
            if (custom(request, response, errorPage)) {
                try {
                    response.flushBuffer();
                } catch (ClientAbortException e) {
                    // Ignore
                } catch (IOException e) {
                    container.getLogger().warn("Exception Processing " + errorPage, e);
                }
            }
        }

    
protected voidthrowable(org.apache.catalina.connector.Request request, org.apache.catalina.connector.Response response, java.lang.Throwable throwable)
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

        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,
                              new Integer(ApplicationFilterFactory.ERROR));
            request.setAttribute
                (Globals.STATUS_CODE_ATTR,
                 new Integer(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
            request.setAttribute(Globals.ERROR_MESSAGE_ATTR,
                              throwable.getMessage());
            request.setAttribute(Globals.EXCEPTION_ATTR,
                              realError);
            Wrapper wrapper = request.getWrapper();
            if (wrapper != null)
                request.setAttribute(Globals.SERVLET_NAME_ATTR,
                                  wrapper.getName());
            request.setAttribute(Globals.EXCEPTION_PAGE_ATTR,
                                 request.getRequestURI());
            request.setAttribute(Globals.EXCEPTION_TYPE_ATTR,
                              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);
        }