throw new IllegalStateException(
"Dispatch may only happen on an existing request.");
}
boolean comet = false;
boolean success = true;
AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext();
req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
try {
if (!request.isAsync() && !comet) {
// Error or timeout - need to tell listeners the request is over
// Have to test this first since state may change while in this
// method and this is only required if entering this method in
// this state
Context ctxt = request.getMappingData().context;
if (ctxt != null) {
ctxt.fireRequestDestroyEvent(request);
}
// Lift any suspension (e.g. if sendError() was used by an async
// request) to allow the response to be written to the client
response.setSuspended(false);
}
if (status==SocketStatus.TIMEOUT) {
success = true;
if (!asyncConImpl.timeout()) {
asyncConImpl.setErrorState(null, false);
}
} else if (status==SocketStatus.ASYNC_READ_ERROR) {
// A async read error is an IO error which means the socket
// needs to be closed so set success to false to trigger a
// close
success = false;
Throwable t = (Throwable)req.getAttribute(
RequestDispatcher.ERROR_EXCEPTION);
req.getAttributes().remove(RequestDispatcher.ERROR_EXCEPTION);
ReadListener readListener = req.getReadListener();
if (readListener != null) {
ClassLoader oldCL = null;
try {
oldCL = request.getContext().bind(false, null);
readListener.onError(t);
} finally {
request.getContext().unbind(false, oldCL);
}
}
if (t != null) {
asyncConImpl.setErrorState(t, true);
}
} else if (status==SocketStatus.ASYNC_WRITE_ERROR) {
// A async write error is an IO error which means the socket
// needs to be closed so set success to false to trigger a
// close
success = false;
Throwable t = (Throwable)req.getAttribute(
RequestDispatcher.ERROR_EXCEPTION);
req.getAttributes().remove(RequestDispatcher.ERROR_EXCEPTION);
if (res.getWriteListener() != null) {
ClassLoader oldCL = null;
try {
oldCL = request.getContext().bind(false, null);
res.getWriteListener().onError(t);
} finally {
request.getContext().unbind(false, oldCL);
}
}
if (t != null) {
asyncConImpl.setErrorState(t, true);
}
}
// Check to see if non-blocking writes or reads are being used
if (!request.isAsyncDispatching() && request.isAsync()) {
WriteListener writeListener = res.getWriteListener();
ReadListener readListener = req.getReadListener();
if (writeListener != null && status == SocketStatus.OPEN_WRITE) {
ClassLoader oldCL = null;
try {
oldCL = request.getContext().bind(false, null);
res.onWritePossible();
if (request.isFinished() && req.sendAllDataReadEvent() &&
readListener != null) {
readListener.onAllDataRead();
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
writeListener.onError(t);
throw t;
} finally {
request.getContext().unbind(false, oldCL);
}
success = true;
} else if (readListener != null && status == SocketStatus.OPEN_READ) {
ClassLoader oldCL = null;
try {
oldCL = request.getContext().bind(false, null);
// If data is being read on a non-container thread a
// dispatch with status OPEN_READ will be used to get
// execution back on a container thread for the
// onAllDataRead() event. Therefore, make sure
// onDataAvailable() is not called in this case.
if (!request.isFinished()) {
readListener.onDataAvailable();
}
if (request.isFinished() && req.sendAllDataReadEvent()) {
readListener.onAllDataRead();
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
readListener.onError(t);
throw t;
} finally {
request.getContext().unbind(false, oldCL);
}
success = true;
}
}
// Has an error occurred during async processing that needs to be
// processed by the application's error page mechanism (or Tomcat's
// if the application doesn't define one)?
if (!request.isAsyncDispatching() && request.isAsync() &&
response.isErrorReportRequired()) {
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
}
if (request.isAsyncDispatching()) {
success = true;
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
Throwable t = (Throwable) request.getAttribute(
RequestDispatcher.ERROR_EXCEPTION);
if (t != null) {
asyncConImpl.setErrorState(t, true);
}
}
if (request.isComet()) {
if (!response.isClosed() && !response.isError()) {