com.caucho.server.webapp.RequestDispatcherImpl Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.server.webapp;
import com.caucho.server.dispatch.Invocation;
import com.caucho.server.http.AbstractHttpResponse;
import com.caucho.server.http.AbstractResponseStream;
import com.caucho.server.http.CauchoRequest;
import com.caucho.server.http.CauchoResponse;
import com.caucho.server.http.HttpServletRequestImpl;
import com.caucho.server.http.HttpServletResponseImpl;
import com.caucho.util.L10N;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.logging.Logger;
public class RequestDispatcherImpl implements RequestDispatcher {
private final static Logger log
= Logger.getLogger(RequestDispatcherImpl.class.getName());
private static final L10N L = new L10N(RequestDispatcherImpl.class);
static final int MAX_DEPTH = 64;
// WebApp the request dispatcher was called from
private WebApp _webApp;
private Invocation _includeInvocation;
private Invocation _forwardInvocation;
private Invocation _errorInvocation;
private Invocation _dispatchInvocation;
private Invocation _requestInvocation;
private Invocation _asyncInvocation;
private boolean _isLogin;
RequestDispatcherImpl(Invocation includeInvocation,
Invocation forwardInvocation,
Invocation errorInvocation,
Invocation dispatchInvocation,
Invocation requestInvocation,
WebApp webApp)
{
_includeInvocation = includeInvocation;
_forwardInvocation = forwardInvocation;
_errorInvocation = errorInvocation;
_dispatchInvocation = dispatchInvocation;
_requestInvocation = requestInvocation;
_webApp = webApp;
}
public void setLogin(boolean isLogin)
{
_isLogin = isLogin;
}
public boolean isModified()
{
return _includeInvocation.isModified();
}
public Invocation getAsyncInvocation()
{
if (_asyncInvocation == null) {
Invocation invocation = new Invocation();
invocation.copyFrom(_dispatchInvocation);
FilterChain chain = invocation.getFilterChain();
chain = new ResumeFilterChain(chain, invocation.getWebApp());
invocation.setFilterChain(chain);
_asyncInvocation = invocation;
}
return _asyncInvocation;
}
@Override
public void forward(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
forward(request, response,
null, _forwardInvocation, DispatcherType.FORWARD);
}
public void dispatchResume(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
// server/1lb1
dispatchResume((HttpServletRequest) request, (HttpServletResponse) response,
getAsyncInvocation());
}
public void error(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
forward(request, response, "error", _errorInvocation, DispatcherType.ERROR);
}
public void dispatch(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
if (request.getServletContext() instanceof UnknownWebApp) {
_requestInvocation.getFilterChain().doFilter(request, response);
}
else {
forward(request, response,
"error", _dispatchInvocation, DispatcherType.REQUEST);
}
}
/**
* Forwards the request to the servlet named by the request dispatcher.
*
* @param topRequest the servlet request.
* @param topResponse the servlet response.
* @param method special to tell if from error.
*/
public void forward(ServletRequest topRequest, ServletResponse topResponse,
String method, Invocation invocation,
DispatcherType type)
throws ServletException, IOException
{
CauchoResponse cauchoRes = null;
boolean allowForward = false;
if (_webApp != null)
allowForward = _webApp.isAllowForwardAfterFlush();
if (topResponse instanceof CauchoResponse) {
cauchoRes = (CauchoResponse) topResponse;
cauchoRes.setForwardEnclosed(! allowForward);
}
// jsp/15m8
if (topResponse.isCommitted() && method == null && ! allowForward) {
IllegalStateException exn;
exn = new IllegalStateException(L.l("forward() not allowed after buffer has committed."));
if (cauchoRes == null || ! cauchoRes.hasError()) {
if (cauchoRes != null)
cauchoRes.setHasError(true);
throw exn;
}
_webApp.log(exn.getMessage(), exn);
return;
} else if ("error".equals(method) || (method == null)) {
// server/10yg
// } else if ("error".equals(method) || (method == null && ! allowForward)) {
topResponse.resetBuffer();
if (cauchoRes != null) {
// server/10yh
// ServletResponse resp = cauchoRes.getResponse();
ServletResponse resp = cauchoRes;
while (resp != null) {
if (allowForward && resp instanceof IncludeResponse) {
// server/10yh
break;
}
else if (resp instanceof CauchoResponse) {
CauchoResponse cr = (CauchoResponse) resp;
cr.resetBuffer();
resp = cr.getResponse();
} else {
resp.resetBuffer();
resp = null;
}
}
}
}
HttpServletRequest parentReq;
ServletRequestWrapper reqWrapper = null;
if (topRequest instanceof ServletRequestWrapper) {
// reqWrapper = (ServletRequestWrapper) req;
ServletRequest request = topRequest; // reqWrapper.getRequest();
while (request instanceof ServletRequestWrapper) {
reqWrapper = (ServletRequestWrapper) request;
request = ((ServletRequestWrapper) request).getRequest();
}
parentReq = (HttpServletRequest) request;
} else if (topRequest instanceof HttpServletRequest) {
parentReq = (HttpServletRequest) topRequest;
} else {
throw new IllegalStateException(L.l(
"expected instance of ServletRequest at `{0}'", topRequest));
}
HttpServletResponse parentRes;
ServletResponseWrapper resWrapper = null;
if (topResponse instanceof ServletResponseWrapper) {
ServletResponse response = topResponse;
while (response instanceof ServletResponseWrapper) {
resWrapper = (ServletResponseWrapper) response;
response = ((ServletResponseWrapper) response).getResponse();
}
parentRes = (HttpServletResponse) response;
} else if (topResponse instanceof HttpServletResponse) {
parentRes = (HttpServletResponse) topResponse;
} else {
throw new IllegalStateException(L.l(
"expected instance of ServletResponse at `{0}'", topResponse));
}
ForwardRequest subRequest;
if (_isLogin)
subRequest = new LoginRequest(parentReq, parentRes, invocation);
else if (type == DispatcherType.ERROR)
subRequest = new ErrorRequest(parentReq, parentRes, invocation);
else if (type == DispatcherType.REQUEST)
subRequest = new DispatchRequest(parentReq, parentRes, invocation);
else
subRequest = new ForwardRequest(parentReq, parentRes, invocation);
// server/10ye
if (subRequest.getRequestDepth(0) > MAX_DEPTH)
throw new ServletException(L.l("too many servlet forwards `{0}'", parentReq.getServletPath()));
ForwardResponse subResponse = subRequest.getResponse();
if (reqWrapper != null) {
reqWrapper.setRequest(subRequest);
}
else {
topRequest = subRequest;
}
if (resWrapper != null) {
resWrapper.setResponse(subResponse);
}
else {
topResponse = subResponse;
}
boolean isValid = false;
subRequest.startRequest();
Thread thread = Thread.currentThread();
ClassLoader loader = thread.getContextClassLoader();
try {
// server/1s30
if (_webApp != null)
thread.setContextClassLoader(_webApp.getClassLoader());
invocation.service(topRequest, topResponse);
isValid = true;
} finally {
if (reqWrapper != null)
reqWrapper.setRequest(parentReq);
if (resWrapper != null)
resWrapper.setResponse(parentRes);
subRequest.finishRequest(isValid);
// server/106r, ioc/0310
if (isValid) {
finishResponse(topResponse);
}
thread.setContextClassLoader(loader);
}
}
private void finishResponse(ServletResponse res)
throws ServletException, IOException
{
if (_webApp.isAllowForwardAfterFlush()) {
//
} else {
if (res instanceof CauchoResponse) {
CauchoResponse cauchoResponse = (CauchoResponse) res;
cauchoResponse.close();
ServletResponse resp = cauchoResponse.getResponse();
while(resp != null) {
if (resp instanceof CauchoResponse) {
CauchoResponse cr = (CauchoResponse)resp;
cr.close();
resp = cr.getResponse();
} else {
resp = null;
}
}
} else {
try {
OutputStream os = res.getOutputStream();
os.close();
} catch (Exception e) {
}
try {
PrintWriter out = res.getWriter();
out.close();
} catch (Exception e) {
}
}
}
}
public void include(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
include(request, response, null);
}
/**
* Include a request into the current page.
*/
public void include(ServletRequest topRequest, ServletResponse topResponse,
String method)
throws ServletException, IOException
{
Invocation invocation = _includeInvocation;
HttpServletRequest parentReq;
ServletRequestWrapper reqWrapper = null;
if (topRequest instanceof ServletRequestWrapper) {
ServletRequest request = topRequest;
while (request instanceof ServletRequestWrapper) {
reqWrapper = (ServletRequestWrapper) request;
request = ((ServletRequestWrapper) request).getRequest();
}
parentReq = (HttpServletRequest) request;
} else if (topRequest instanceof HttpServletRequest) {
parentReq = (HttpServletRequest) topRequest;
} else {
throw new IllegalStateException(L.l(
"expected instance of ServletRequestWrapper at `{0}'", topResponse));
}
HttpServletResponse parentRes;
ServletResponseWrapper resWrapper = null;
if (topResponse instanceof ServletResponseWrapper) {
ServletResponse response = topResponse;
while (response instanceof ServletResponseWrapper) {
resWrapper = (ServletResponseWrapper) response;
response = ((ServletResponseWrapper) response).getResponse();
}
parentRes = (HttpServletResponse) response;
} else if (topResponse instanceof HttpServletResponse) {
parentRes = (HttpServletResponse) topResponse;
} else {
throw new IllegalStateException(L.l(
"expected instance of ServletResponse at '{0}'", topResponse));
}
IncludeRequest subRequest
= new IncludeRequest(parentReq, parentRes, invocation);
// server/10yf, jsp/15di
if (subRequest.getRequestDepth(0) > MAX_DEPTH)
throw new ServletException(L.l("too many servlet includes '{0}'", parentReq.getServletPath()));
IncludeResponse subResponse = subRequest.getResponse();
if (reqWrapper != null) {
reqWrapper.setRequest(subRequest);
}
else {
topRequest = subRequest;
}
if (resWrapper != null) {
resWrapper.setResponse(subResponse);
}
else {
topResponse = subResponse;
}
// jsp/15lf, jsp/17eg - XXX: integrated with ResponseStream?
// res.flushBuffer();
subRequest.startRequest();
try {
invocation.service(topRequest, topResponse);
} finally {
if (reqWrapper != null)
reqWrapper.setRequest(parentReq);
if (resWrapper != null)
resWrapper.setResponse(parentRes);
subRequest.finishRequest();
}
}
/**
* Dispatch the async resume request to the servlet
* named by the request dispatcher.
*
* @param request the servlet request.
* @param response the servlet response.
* @param invocation current invocation
*/
public void dispatchResume(HttpServletRequest request,
HttpServletResponse response,
Invocation invocation)
throws ServletException, IOException
{
HttpServletRequestWrapper parentRequest = null;
HttpServletRequestImpl bottomRequest = null;
HttpServletResponseImpl bottomResponse = null;
HttpServletRequest req = request;
while (req != null && req instanceof HttpServletRequestWrapper) {
parentRequest = (HttpServletRequestWrapper) req;
req = (HttpServletRequest) parentRequest.getRequest();
}
if (! (req instanceof HttpServletRequestImpl)) {
throw new IllegalStateException(L.l("Wrapped async requests must use HttpServletRequestWrapper around the original request"));
}
bottomRequest = (HttpServletRequestImpl) req;
HttpServletResponse res = response;
while (res != null && res instanceof HttpServletResponseWrapper) {
HttpServletResponseWrapper parentResponse
= (HttpServletResponseWrapper) res;
res = (HttpServletResponse) parentResponse.getResponse();
}
if (! (res instanceof HttpServletResponseImpl)) {
throw new IllegalStateException(L.l("Wrapped async requests must use HttpServletRequestWrapper around the original request"));
}
bottomResponse = (HttpServletResponseImpl) res;
AsyncRequest asyncRequest
= new AsyncRequest(bottomRequest, bottomResponse, invocation);
if (parentRequest != null) {
parentRequest.setRequest(asyncRequest);
}
else {
request = asyncRequest;
}
Thread thread = Thread.currentThread();
ClassLoader oldLoader = thread.getContextClassLoader();
try {
invocation.service(request, response);
} finally {
// subRequest.finishRequest();
thread.setContextClassLoader(oldLoader);
}
}
@Override
public String toString()
{
return (getClass().getSimpleName()
+ "[" + _dispatchInvocation.getRawURI() + "]");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy