ApplicationDispatcherForwardpublic 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 |
Methods Summary |
---|
static void | commit(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 void | custom(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.CoyoteResponseFacade | getResponseFacade(javax.servlet.ServletResponse response)
while (response instanceof ServletResponseWrapper) {
response = ((ServletResponseWrapper) response).getResponse();
}
return ((CoyoteResponseFacade) response);
| private static void | prepareRequestForDispatch(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 void | resetResponse(org.apache.coyote.tomcat5.CoyoteResponseFacade responseFacade)
responseFacade.setSuspended(false);
responseFacade.setAppCommitted(false);
| private static void | serveDefaultErrorPage(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 void | serveErrorPage(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 boolean | status(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;
|
|