📄 applicationdispatcher.java
字号:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestWrapper;
import javax.servlet.ServletResponse;
import javax.servlet.ServletResponseWrapper;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.InstanceEvent;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.ClientAbortException;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.RequestFacade;
import org.apache.catalina.connector.Response;
import org.apache.catalina.connector.ResponseFacade;
import org.apache.catalina.util.InstanceSupport;
import org.apache.catalina.util.StringManager;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
/**
* Standard implementation of <code>RequestDispatcher</code> that allows a
* request to be forwarded to a different resource to create the ultimate
* response, or to include the output of another resource in the response
* from this resource. This implementation allows application level servlets
* to wrap the request and/or response objects that are passed on to the
* called resource, as long as the wrapping classes extend
* <code>javax.servlet.ServletRequestWrapper</code> and
* <code>javax.servlet.ServletResponseWrapper</code>.
*
* @author Craig R. McClanahan
* @version $Revision: 505593 $ $Date: 2007-02-10 01:54:56 +0100 (sam., 10 févr. 2007) $
*/
final class ApplicationDispatcher
implements RequestDispatcher {
protected class PrivilegedForward implements PrivilegedExceptionAction {
private ServletRequest request;
private ServletResponse response;
PrivilegedForward(ServletRequest request, ServletResponse response)
{
this.request = request;
this.response = response;
}
public Object run() throws java.lang.Exception {
doForward(request,response);
return null;
}
}
protected class PrivilegedInclude implements PrivilegedExceptionAction {
private ServletRequest request;
private ServletResponse response;
PrivilegedInclude(ServletRequest request, ServletResponse response)
{
this.request = request;
this.response = response;
}
public Object run() throws ServletException, IOException {
doInclude(request,response);
return null;
}
}
/**
* Used to pass state when the request dispatcher is used. Using instance
* variables causes threading issues and state is too complex to pass and
* return single ServletRequest or ServletResponse objects.
*/
private class State {
State(ServletRequest request, ServletResponse response,
boolean including) {
this.outerRequest = request;
this.outerResponse = response;
this.including = including;
}
/**
* The outermost request that will be passed on to the invoked servlet.
*/
ServletRequest outerRequest = null;
/**
* The outermost response that will be passed on to the invoked servlet.
*/
ServletResponse outerResponse = null;
/**
* The request wrapper we have created and installed (if any).
*/
ServletRequest wrapRequest = null;
/**
* The response wrapper we have created and installed (if any).
*/
ServletResponse wrapResponse = null;
/**
* Are we performing an include() instead of a forward()?
*/
boolean including = false;
}
// ----------------------------------------------------------- Constructors
/**
* Construct a new instance of this class, configured according to the
* specified parameters. If both servletPath and pathInfo are
* <code>null</code>, it will be assumed that this RequestDispatcher
* was acquired by name, rather than by path.
*
* @param wrapper The Wrapper associated with the resource that will
* be forwarded to or included (required)
* @param requestURI The request URI to this resource (if any)
* @param servletPath The revised servlet path to this resource (if any)
* @param pathInfo The revised extra path information to this resource
* (if any)
* @param queryString Query string parameters included with this request
* (if any)
* @param name Servlet name (if a named dispatcher was created)
* else <code>null</code>
*/
public ApplicationDispatcher
(Wrapper wrapper, String requestURI, String servletPath,
String pathInfo, String queryString, String name) {
super();
// Save all of our configuration parameters
this.wrapper = wrapper;
this.context = (Context) wrapper.getParent();
this.requestURI = requestURI;
this.servletPath = servletPath;
this.pathInfo = pathInfo;
this.queryString = queryString;
this.name = name;
if (wrapper instanceof StandardWrapper)
this.support = ((StandardWrapper) wrapper).getInstanceSupport();
else
this.support = new InstanceSupport(wrapper);
if ( log.isDebugEnabled() )
log.debug("servletPath=" + this.servletPath + ", pathInfo=" +
this.pathInfo + ", queryString=" + queryString +
", name=" + this.name);
}
// ----------------------------------------------------- Instance Variables
private static Log log = LogFactory.getLog(ApplicationDispatcher.class);
/**
* The Context this RequestDispatcher is associated with.
*/
private Context context = null;
/**
* Descriptive information about this implementation.
*/
private static final String info =
"org.apache.catalina.core.ApplicationDispatcher/1.0";
/**
* The servlet name for a named dispatcher.
*/
private String name = null;
/**
* The extra path information for this RequestDispatcher.
*/
private String pathInfo = null;
/**
* The query string parameters for this RequestDispatcher.
*/
private String queryString = null;
/**
* The request URI for this RequestDispatcher.
*/
private String requestURI = null;
/**
* The servlet path for this RequestDispatcher.
*/
private String servletPath = null;
/**
* The StringManager for this package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* The InstanceSupport instance associated with our Wrapper (used to
* send "before dispatch" and "after dispatch" events.
*/
private InstanceSupport support = null;
/**
* The Wrapper associated with the resource that will be forwarded to
* or included.
*/
private Wrapper wrapper = null;
// ------------------------------------------------------------- Properties
/**
* Return the descriptive information about this implementation.
*/
public String getInfo() {
return (info);
}
// --------------------------------------------------------- Public Methods
/**
* Forward this request and response to another resource for processing.
* Any runtime exception, IOException, or ServletException thrown by the
* called servlet will be propogated to the caller.
*
* @param request The servlet request to be forwarded
* @param response The servlet response to be forwarded
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet exception occurs
*/
public void forward(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
if (Globals.IS_SECURITY_ENABLED) {
try {
PrivilegedForward dp = new PrivilegedForward(request,response);
AccessController.doPrivileged(dp);
} catch (PrivilegedActionException pe) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
throw (IOException) e;
}
} else {
doForward(request,response);
}
}
private void doForward(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
// Reset any output that has been buffered, but keep headers/cookies
if (response.isCommitted()) {
if ( log.isDebugEnabled() )
log.debug(" Forward on committed response --> ISE");
throw new IllegalStateException
(sm.getString("applicationDispatcher.forward.ise"));
}
try {
response.resetBuffer();
} catch (IllegalStateException e) {
if ( log.isDebugEnabled() )
log.debug(" Forward resetBuffer() returned ISE: " + e);
throw e;
}
// Set up to handle the specified request and response
State state = new State(request, response, false);
if (Globals.STRICT_SERVLET_COMPLIANCE) {
// Check SRV.8.2 / SRV.14.2.5.1 compliance
checkSameObjects(request, response);
}
// Identify the HTTP-specific request and response objects (if any)
HttpServletRequest hrequest = null;
if (request instanceof HttpServletRequest)
hrequest = (HttpServletRequest) request;
HttpServletResponse hresponse = null;
if (response instanceof HttpServletResponse)
hresponse = (HttpServletResponse) response;
// Handle a non-HTTP forward by passing the existing request/response
if ((hrequest == null) || (hresponse == null)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -