Search in sources :

Example 1 with AsyncContextImpl

use of org.apache.catalina.core.AsyncContextImpl in project tomcat by apache.

the class CoyoteAdapter method asyncDispatch.

// -------------------------------------------------------- Adapter Methods
@Override
public boolean asyncDispatch(org.apache.coyote.Request req, org.apache.coyote.Response res, SocketEvent status) throws Exception {
    Request request = (Request) req.getNote(ADAPTER_NOTES);
    Response response = (Response) res.getNote(ADAPTER_NOTES);
    if (request == null) {
        throw new IllegalStateException("Dispatch may only happen on an existing request.");
    }
    boolean success = true;
    AsyncContextImpl asyncConImpl = request.getAsyncContextInternal();
    req.getRequestProcessor().setWorkerThreadName(THREAD_NAME.get());
    try {
        if (!request.isAsync()) {
            // Error or timeout
            // 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 == SocketEvent.TIMEOUT) {
            if (!asyncConImpl.timeout()) {
                asyncConImpl.setErrorState(null, false);
            }
        } else if (status == SocketEvent.ERROR) {
            // An I/O error occurred on a non-container thread which means
            // that 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);
            ClassLoader oldCL = null;
            try {
                oldCL = request.getContext().bind(false, null);
                if (req.getReadListener() != null) {
                    req.getReadListener().onError(t);
                }
                if (res.getWriteListener() != 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 == SocketEvent.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);
                    success = false;
                } finally {
                    request.getContext().unbind(false, oldCL);
                }
            } else if (readListener != null && status == SocketEvent.OPEN_READ) {
                ClassLoader oldCL = null;
                try {
                    oldCL = request.getContext().bind(false, null);
                    // 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);
                    success = false;
                } finally {
                    request.getContext().unbind(false, oldCL);
                }
            }
        }
        // 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()) {
            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.isAsync()) {
            request.finishRequest();
            response.finishResponse();
        }
        // Check to see if the processor is in an error state. If it is,
        // bail out now.
        AtomicBoolean error = new AtomicBoolean(false);
        res.action(ActionCode.IS_ERROR, error);
        if (error.get()) {
            if (request.isAsyncCompleting()) {
                // Connection will be forcibly closed which will prevent
                // completion happening at the usual point. Need to trigger
                // call to onComplete() here.
                res.action(ActionCode.ASYNC_POST_PROCESS, null);
            }
            success = false;
        }
    } catch (IOException e) {
        success = false;
    // Ignore
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        success = false;
        log.error(sm.getString("coyoteAdapter.asyncDispatch"), t);
    } finally {
        if (!success) {
            res.setStatus(500);
        }
        // Access logging
        if (!success || !request.isAsync()) {
            long time = 0;
            if (req.getStartTime() != -1) {
                time = System.currentTimeMillis() - req.getStartTime();
            }
            if (request.getMappingData().context != null) {
                request.getMappingData().context.logAccess(request, response, time, false);
            } else {
                log(req, res, time);
            }
        }
        req.getRequestProcessor().setWorkerThreadName(null);
        // Recycle the wrapper request and response
        if (!success || !request.isAsync()) {
            request.recycle();
            response.recycle();
        }
    }
    return success;
}
Also used : HttpServletResponse(javax.servlet.http.HttpServletResponse) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AsyncContextImpl(org.apache.catalina.core.AsyncContextImpl) IOException(java.io.IOException) WriteListener(javax.servlet.WriteListener) ReadListener(javax.servlet.ReadListener)

Example 2 with AsyncContextImpl

use of org.apache.catalina.core.AsyncContextImpl in project tomcat by apache.

the class Request method startAsync.

@Override
public AsyncContext startAsync(ServletRequest request, ServletResponse response) {
    if (!isAsyncSupported()) {
        throw new IllegalStateException(sm.getString("request.asyncNotSupported"));
    }
    if (asyncContext == null) {
        asyncContext = new AsyncContextImpl(this);
    }
    asyncContext.setStarted(getContext(), request, response, request == getRequest() && response == getResponse().getResponse());
    asyncContext.setTimeout(getConnector().getAsyncTimeout());
    return asyncContext;
}
Also used : AsyncContextImpl(org.apache.catalina.core.AsyncContextImpl)

Aggregations

AsyncContextImpl (org.apache.catalina.core.AsyncContextImpl)2 IOException (java.io.IOException)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 ReadListener (javax.servlet.ReadListener)1 WriteListener (javax.servlet.WriteListener)1 HttpServletResponse (javax.servlet.http.HttpServletResponse)1