FileDocCategorySizeDatePackage
ApplicationDispatcherForward.javaAPI DocGlassfish v2 API14785Fri May 04 22:31:54 BST 2007org.apache.catalina.core

ApplicationDispatcherForward

public class ApplicationDispatcherForward extends Object
Class responsible for processing the result of a RD.forward() invocation before committing the response. If sendError() was called during RD.forward(), an attempt is made to match the status code against the error pages of the RD's associated context, or those of the host on which the context has been deployed. The response contents are then committed, to comply with SRV.8.4 ("The Forward Method"): Before the forward method of the RequestDispatcher interface returns without exception, the response content must be sent and committed, and closed by the servlet container. If an error occurs in the target of the RequestDispatcher.forward() the exception may be propogated back through all the calling filters and servlets and eventually back to the container.

Fields Summary
private static com.sun.org.apache.commons.logging.Log
log
private static final org.apache.catalina.util.StringManager
sm
Constructors Summary
Methods Summary
static voidcommit(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, org.apache.catalina.Context context, org.apache.catalina.Wrapper wrapper)



       
                        
                        
                        
               

        CoyoteResponseFacade responseFacade = getResponseFacade(response);
        int statusCode = responseFacade.getStatus();
        Object exception = request.getAttribute(Globals.EXCEPTION_ATTR);
        String errorReportValveClass = 
            ((StandardHost)(context.getParent())).getErrorReportValveClass();

        if (errorReportValveClass != null && statusCode >= 400
                && exception == null) {
            boolean matchFound = status(request, response, responseFacade,
                                        context, wrapper, statusCode);
            if (!matchFound) {
                serveDefaultErrorPage(request, response, responseFacade,
                                      statusCode);
            }
        }

        /*
         * Commit the response only if no exception
         */
        if (statusCode < 400
                || (exception == null && errorReportValveClass != null)) {
            try {
                PrintWriter writer = response.getWriter();
                writer.flush();
                writer.close();
            } catch (IllegalStateException e) {
                try {
                    ServletOutputStream stream = response.getOutputStream();
                    stream.flush();
                    stream.close();
                } catch (IllegalStateException f) {
                    ;
                } catch (IOException f) {
                    ;
                }
            } catch (IOException e) {
                ;
            }
        }
    
private static voidcustom(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, org.apache.coyote.tomcat5.CoyoteResponseFacade responseFacade, org.apache.catalina.deploy.ErrorPage errorPage, org.apache.catalina.Context context)
Handles an HTTP status code or exception by forwarding control to the location included in the specified errorPage object.

        try {
            // Forward control to the specified error page
            if (response.isCommitted()) {
                /*
                 * If the target of the RD.forward() has called
                 * response.sendError(), the response will have been committed,
                 * and any attempt to RD.forward() the response to the error
                 * page will cause an IllegalStateException.
                 * Uncommit the response.
                 */
                resetResponse(responseFacade);
            }
            ServletContext servletContext = context.getServletContext();
            RequestDispatcher rd =
                servletContext.getRequestDispatcher(errorPage.getLocation());
            rd.forward(request, response);
        } catch (IllegalStateException ise) {
            log.warn("Exception processing " + errorPage, ise);
        } catch (Throwable t) {
            log.warn("Exception processing " + errorPage, t);
        }
    
private static org.apache.coyote.tomcat5.CoyoteResponseFacadegetResponseFacade(javax.servlet.ServletResponse response)

   
        while (response instanceof ServletResponseWrapper) {
            response = ((ServletResponseWrapper) response).getResponse();
        }

        return ((CoyoteResponseFacade) response);
    
private static voidprepareRequestForDispatch(javax.servlet.http.HttpServletRequest request, org.apache.catalina.Wrapper errorServlet, java.lang.String errorPageLocation, int errorCode, java.lang.String errorMessage)
Adds request attributes in preparation for RD.forward().

        request.setAttribute(
            ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
            Integer.valueOf(ApplicationFilterFactory.ERROR));

        request.setAttribute(
            Globals.EXCEPTION_PAGE_ATTR,
            request.getRequestURI());

        if (errorServlet != null) {
            // Save the logical name of the servlet in which the error occurred
            request.setAttribute(Globals.SERVLET_NAME_ATTR,
                                 errorServlet.getName());
        }

        request.setAttribute(
            ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
            errorPageLocation);

        request.setAttribute(Globals.STATUS_CODE_ATTR,
                             Integer.valueOf(errorCode));

        request.setAttribute(Globals.ERROR_MESSAGE_ATTR, errorMessage);
    
private static voidresetResponse(org.apache.coyote.tomcat5.CoyoteResponseFacade responseFacade)

        responseFacade.setSuspended(false);
        responseFacade.setAppCommitted(false);
    
private static voidserveDefaultErrorPage(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, org.apache.coyote.tomcat5.CoyoteResponseFacade responseFacade, int statusCode)
Renders the default error page.


        // Do nothing on a 1xx, 2xx and 3xx status
        if (response.isCommitted() || statusCode < 400
                || responseFacade.getContentCount() > 0) {
            return;
        }

        String message = RequestUtil.filter(responseFacade.getMessage());
        if (message == null) {
            message = "";
        }

        // Do nothing if there is no report for the specified status code
        String report = null;
        try {
            report = sm.getString("http." + statusCode, message);
        } catch (Throwable t) {
            ;
        }
        if (report == null) {
            return;
        }

        String responseContents =
            ErrorReportValve.makeErrorPage(statusCode, message, null, null,
                                           report, response);
        // START SJSAS 6412710
        response.setLocale(sm.getResourceBundleLocale(response.getLocale()));
        // END SJSAS 6412710

        try {
            response.setContentType("text/html");
            response.getWriter().write(responseContents);
        } catch (Throwable t) {
            log.warn("Exception sending default error page", t);
        }
    
private static voidserveErrorPage(javax.servlet.http.HttpServletResponse response, org.apache.catalina.deploy.ErrorPage errorPage, int statusCode)
Copies the contents of the given error page to the response.


        ServletOutputStream ostream = null;
        PrintWriter writer = null;
        FileReader reader = null;
        BufferedInputStream istream = null;
        IOException ioe = null;

        String message = errorPage.getReason();
        if (message != null && !response.isCommitted()) {
            response.reset();
            response.setStatus(statusCode, message);
        }
         
        try {
            ostream = response.getOutputStream();
        } catch (IllegalStateException e) {
            // If it fails, we try to get a Writer instead if we're
            // trying to serve a text file
            writer = response.getWriter();
        }

        if (writer != null) {
            reader = new FileReader(errorPage.getLocation());
            ioe = ResponseUtil.copy(reader, writer);
            try {
                reader.close();
            } catch (Throwable t) {
                ;
            }
        } else {
            istream = new BufferedInputStream(
                new FileInputStream(errorPage.getLocation()));
            ioe = ResponseUtil.copy(istream, ostream);
            try {
                istream.close();
            } catch (Throwable t) {
                ;
            }
        }

        // Rethrow any exception that may have occurred
        if (ioe != null) {
            throw ioe;
        }
    
private static booleanstatus(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, org.apache.coyote.tomcat5.CoyoteResponseFacade responseFacade, org.apache.catalina.Context context, org.apache.catalina.Wrapper wrapper, int statusCode)


        /*
         * Attempt error-page mapping only if response.sendError(), as
         * opposed to response.setStatus(), was called.
         */
        if (!responseFacade.isError()) {
            return false;
        }

        boolean matchFound = false;

        ErrorPage errorPage = context.findErrorPage(statusCode);
        if (errorPage != null) {

            matchFound = true;

            // Prevent infinite loop
            String requestPath = (String) request.getAttribute(
                ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR);
            if (requestPath == null
                    || !requestPath.equals(errorPage.getLocation())) {
                String message = RequestUtil.filter(responseFacade.getMessage());
                if (message == null) {
                    message = "";
                }
                prepareRequestForDispatch(request,
                                          wrapper,
                                          errorPage.getLocation(),
                                          statusCode,
                                          message);
                custom(request, response, responseFacade, errorPage, context);
            }
        } else {
            errorPage = ((StandardHost) context.getParent()).findErrorPage(
                                            statusCode);
            if (errorPage != null) {
                matchFound = true;
                try {
                    serveErrorPage(response, errorPage, statusCode);
                } catch (Exception e) {
                    log.warn("Exception processing " + errorPage, e);
                }
            }
        }

        return matchFound;