103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.server;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.AsyncContext;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.AsyncEvent;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.AsyncListener;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.RequestDispatcher;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletException;
2603928aee4356845252ac6b662d5c72c29903813eJake Slack
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.ArrayList;
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.List;
2903928aee4356845252ac6b662d5c72c29903813eJake Slack
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletContext;
3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletRequest;
3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletResponse;
3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletRequest;
3403928aee4356845252ac6b662d5c72c29903813eJake Slack
3503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.continuation.Continuation;
3603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.continuation.ContinuationThrowable;
3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.continuation.ContinuationListener;
3803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.AsyncEndPoint;
3903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.EndPoint;
4003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.handler.ContextHandler;
4103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.handler.ContextHandler.Context;
4203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.URIUtil;
4303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
4403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
4503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.thread.Timeout;
4603928aee4356845252ac6b662d5c72c29903813eJake Slack
4703928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
4803928aee4356845252ac6b662d5c72c29903813eJake Slack/** Implementation of Continuation and AsyncContext interfaces
4903928aee4356845252ac6b662d5c72c29903813eJake Slack *
5003928aee4356845252ac6b662d5c72c29903813eJake Slack */
5103928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class AsyncContinuation implements AsyncContext, Continuation
5203928aee4356845252ac6b662d5c72c29903813eJake Slack{
5303928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(AsyncContinuation.class);
5403928aee4356845252ac6b662d5c72c29903813eJake Slack
5503928aee4356845252ac6b662d5c72c29903813eJake Slack    private final static long DEFAULT_TIMEOUT=30000L;
5603928aee4356845252ac6b662d5c72c29903813eJake Slack
5703928aee4356845252ac6b662d5c72c29903813eJake Slack    private final static ContinuationThrowable __exception = new ContinuationThrowable();
5803928aee4356845252ac6b662d5c72c29903813eJake Slack
5903928aee4356845252ac6b662d5c72c29903813eJake Slack    // STATES:
6003928aee4356845252ac6b662d5c72c29903813eJake Slack    //               handling()    suspend()     unhandle()    resume()       complete()  doComplete()
6103928aee4356845252ac6b662d5c72c29903813eJake Slack    //                             startAsync()                dispatch()
6203928aee4356845252ac6b662d5c72c29903813eJake Slack    // IDLE          DISPATCHED
6303928aee4356845252ac6b662d5c72c29903813eJake Slack    // DISPATCHED                  ASYNCSTARTED  UNCOMPLETED
6403928aee4356845252ac6b662d5c72c29903813eJake Slack    // ASYNCSTARTED                              ASYNCWAIT     REDISPATCHING  COMPLETING
6503928aee4356845252ac6b662d5c72c29903813eJake Slack    // REDISPATCHING                             REDISPATCHED
6603928aee4356845252ac6b662d5c72c29903813eJake Slack    // ASYNCWAIT                                               REDISPATCH     COMPLETING
6703928aee4356845252ac6b662d5c72c29903813eJake Slack    // REDISPATCH    REDISPATCHED
6803928aee4356845252ac6b662d5c72c29903813eJake Slack    // REDISPATCHED                ASYNCSTARTED  UNCOMPLETED
6903928aee4356845252ac6b662d5c72c29903813eJake Slack    // COMPLETING    UNCOMPLETED                 UNCOMPLETED
7003928aee4356845252ac6b662d5c72c29903813eJake Slack    // UNCOMPLETED                                                                        COMPLETED
7103928aee4356845252ac6b662d5c72c29903813eJake Slack    // COMPLETED
7203928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int __IDLE=0;         // Idle request
7303928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int __DISPATCHED=1;   // Request dispatched to filter/servlet
7403928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int __ASYNCSTARTED=2; // Suspend called, but not yet returned to container
7503928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int __REDISPATCHING=3;// resumed while dispatched
7603928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int __ASYNCWAIT=4;    // Suspended and parked
7703928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int __REDISPATCH=5;   // Has been scheduled
7803928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int __REDISPATCHED=6; // Request redispatched to filter/servlet
7903928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int __COMPLETING=7;   // complete while dispatched
8003928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int __UNCOMPLETED=8;  // Request is completable
8103928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int __COMPLETED=9;    // Request is complete
8203928aee4356845252ac6b662d5c72c29903813eJake Slack
8303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
8403928aee4356845252ac6b662d5c72c29903813eJake Slack    protected AbstractHttpConnection _connection;
8503928aee4356845252ac6b662d5c72c29903813eJake Slack    private List<AsyncListener> _lastAsyncListeners;
8603928aee4356845252ac6b662d5c72c29903813eJake Slack    private List<AsyncListener> _asyncListeners;
8703928aee4356845252ac6b662d5c72c29903813eJake Slack    private List<ContinuationListener> _continuationListeners;
8803928aee4356845252ac6b662d5c72c29903813eJake Slack
8903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
9003928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _state;
9103928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _initial;
9203928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _resumed;
9303928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _expired;
9403928aee4356845252ac6b662d5c72c29903813eJake Slack    private volatile boolean _responseWrapped;
9503928aee4356845252ac6b662d5c72c29903813eJake Slack    private long _timeoutMs=DEFAULT_TIMEOUT;
9603928aee4356845252ac6b662d5c72c29903813eJake Slack    private AsyncEventState _event;
9703928aee4356845252ac6b662d5c72c29903813eJake Slack    private volatile long _expireAt;
9803928aee4356845252ac6b662d5c72c29903813eJake Slack    private volatile boolean _continuation;
9903928aee4356845252ac6b662d5c72c29903813eJake Slack
10003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
10103928aee4356845252ac6b662d5c72c29903813eJake Slack    protected AsyncContinuation()
10203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
10303928aee4356845252ac6b662d5c72c29903813eJake Slack        _state=__IDLE;
10403928aee4356845252ac6b662d5c72c29903813eJake Slack        _initial=true;
10503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
10603928aee4356845252ac6b662d5c72c29903813eJake Slack
10703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
10803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void setConnection(final AbstractHttpConnection connection)
10903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
11103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
11203928aee4356845252ac6b662d5c72c29903813eJake Slack            _connection=connection;
11303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
11403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11503928aee4356845252ac6b662d5c72c29903813eJake Slack
11603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addListener(AsyncListener listener)
11803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11903928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
12003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
12103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_asyncListeners==null)
12203928aee4356845252ac6b662d5c72c29903813eJake Slack                _asyncListeners=new ArrayList<AsyncListener>();
12303928aee4356845252ac6b662d5c72c29903813eJake Slack            _asyncListeners.add(listener);
12403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
12503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
12603928aee4356845252ac6b662d5c72c29903813eJake Slack
12703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
12803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addListener(AsyncListener listener,ServletRequest request, ServletResponse response)
12903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
13103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
13203928aee4356845252ac6b662d5c72c29903813eJake Slack            // TODO handle the request/response ???
13303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_asyncListeners==null)
13403928aee4356845252ac6b662d5c72c29903813eJake Slack                _asyncListeners=new ArrayList<AsyncListener>();
13503928aee4356845252ac6b662d5c72c29903813eJake Slack            _asyncListeners.add(listener);
13603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
13703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
13803928aee4356845252ac6b662d5c72c29903813eJake Slack
13903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
14003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addContinuationListener(ContinuationListener listener)
14103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
14203928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
14303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
14403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_continuationListeners==null)
14503928aee4356845252ac6b662d5c72c29903813eJake Slack                _continuationListeners=new ArrayList<ContinuationListener>();
14603928aee4356845252ac6b662d5c72c29903813eJake Slack            _continuationListeners.add(listener);
14703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
14803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
14903928aee4356845252ac6b662d5c72c29903813eJake Slack
15003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
15103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setTimeout(long ms)
15203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
15303928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
15403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
15503928aee4356845252ac6b662d5c72c29903813eJake Slack            _timeoutMs=ms;
15603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
15703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
15803928aee4356845252ac6b662d5c72c29903813eJake Slack
15903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
16003928aee4356845252ac6b662d5c72c29903813eJake Slack    public long getTimeout()
16103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
16203928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
16303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
16403928aee4356845252ac6b662d5c72c29903813eJake Slack            return _timeoutMs;
16503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
16603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
16703928aee4356845252ac6b662d5c72c29903813eJake Slack
16803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
16903928aee4356845252ac6b662d5c72c29903813eJake Slack    public AsyncEventState getAsyncEventState()
17003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
17103928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
17203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
17303928aee4356845252ac6b662d5c72c29903813eJake Slack            return _event;
17403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
17503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
17603928aee4356845252ac6b662d5c72c29903813eJake Slack
17703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
17803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
17903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.continuation.Continuation#keepWrappers()
18003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
18103928aee4356845252ac6b662d5c72c29903813eJake Slack
18203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
18303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
18403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.continuation.Continuation#isResponseWrapped()
18503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
18603928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isResponseWrapped()
18703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
18803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _responseWrapped;
18903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
19003928aee4356845252ac6b662d5c72c29903813eJake Slack
19103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
19203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* (non-Javadoc)
19303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletRequest#isInitial()
19403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
19503928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isInitial()
19603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
19703928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
19803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
19903928aee4356845252ac6b662d5c72c29903813eJake Slack            return _initial;
20003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
20103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
20203928aee4356845252ac6b662d5c72c29903813eJake Slack
20303928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isContinuation()
20403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
20503928aee4356845252ac6b662d5c72c29903813eJake Slack        return _continuation;
20603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
20703928aee4356845252ac6b662d5c72c29903813eJake Slack
20803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
20903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* (non-Javadoc)
21003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletRequest#isSuspended()
21103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
21203928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isSuspended()
21303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
21403928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
21503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
21603928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
21703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
21803928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCSTARTED:
21903928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCHING:
22003928aee4356845252ac6b662d5c72c29903813eJake Slack                case __COMPLETING:
22103928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCWAIT:
22203928aee4356845252ac6b662d5c72c29903813eJake Slack                    return true;
22303928aee4356845252ac6b662d5c72c29903813eJake Slack
22403928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
22503928aee4356845252ac6b662d5c72c29903813eJake Slack                    return false;
22603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
22703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
22803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
22903928aee4356845252ac6b662d5c72c29903813eJake Slack
23003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
23103928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isSuspending()
23203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
23303928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
23403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
23503928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
23603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
23703928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCSTARTED:
23803928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCWAIT:
23903928aee4356845252ac6b662d5c72c29903813eJake Slack                    return true;
24003928aee4356845252ac6b662d5c72c29903813eJake Slack
24103928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
24203928aee4356845252ac6b662d5c72c29903813eJake Slack                    return false;
24303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
24403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
24503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
24603928aee4356845252ac6b662d5c72c29903813eJake Slack
24703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
24803928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isDispatchable()
24903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
25003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
25103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
25203928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
25303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
25403928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCH:
25503928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCHED:
25603928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCHING:
25703928aee4356845252ac6b662d5c72c29903813eJake Slack                case __COMPLETING:
25803928aee4356845252ac6b662d5c72c29903813eJake Slack                    return true;
25903928aee4356845252ac6b662d5c72c29903813eJake Slack
26003928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
26103928aee4356845252ac6b662d5c72c29903813eJake Slack                    return false;
26203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
26303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
26403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
26503928aee4356845252ac6b662d5c72c29903813eJake Slack
26603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
26703928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
26803928aee4356845252ac6b662d5c72c29903813eJake Slack    public String toString()
26903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
27003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
27103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
27203928aee4356845252ac6b662d5c72c29903813eJake Slack            return super.toString()+"@"+getStatusString();
27303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
27403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
27503928aee4356845252ac6b662d5c72c29903813eJake Slack
27603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
27703928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getStatusString()
27803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
27903928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
28003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
28103928aee4356845252ac6b662d5c72c29903813eJake Slack            return
28203928aee4356845252ac6b662d5c72c29903813eJake Slack            ((_state==__IDLE)?"IDLE":
28303928aee4356845252ac6b662d5c72c29903813eJake Slack                (_state==__DISPATCHED)?"DISPATCHED":
28403928aee4356845252ac6b662d5c72c29903813eJake Slack                    (_state==__ASYNCSTARTED)?"ASYNCSTARTED":
28503928aee4356845252ac6b662d5c72c29903813eJake Slack                        (_state==__ASYNCWAIT)?"ASYNCWAIT":
28603928aee4356845252ac6b662d5c72c29903813eJake Slack                            (_state==__REDISPATCHING)?"REDISPATCHING":
28703928aee4356845252ac6b662d5c72c29903813eJake Slack                                (_state==__REDISPATCH)?"REDISPATCH":
28803928aee4356845252ac6b662d5c72c29903813eJake Slack                                    (_state==__REDISPATCHED)?"REDISPATCHED":
28903928aee4356845252ac6b662d5c72c29903813eJake Slack                                        (_state==__COMPLETING)?"COMPLETING":
29003928aee4356845252ac6b662d5c72c29903813eJake Slack                                            (_state==__UNCOMPLETED)?"UNCOMPLETED":
29103928aee4356845252ac6b662d5c72c29903813eJake Slack                                                (_state==__COMPLETED)?"COMPLETE":
29203928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    ("UNKNOWN?"+_state))+
29303928aee4356845252ac6b662d5c72c29903813eJake Slack            (_initial?",initial":"")+
29403928aee4356845252ac6b662d5c72c29903813eJake Slack            (_resumed?",resumed":"")+
29503928aee4356845252ac6b662d5c72c29903813eJake Slack            (_expired?",expired":"");
29603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
29703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
29803928aee4356845252ac6b662d5c72c29903813eJake Slack
29903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
30003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
30103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return false if the handling of the request should not proceed
30203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
30303928aee4356845252ac6b662d5c72c29903813eJake Slack    protected boolean handling()
30403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
30503928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
30603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
30703928aee4356845252ac6b662d5c72c29903813eJake Slack            _continuation=false;
30803928aee4356845252ac6b662d5c72c29903813eJake Slack
30903928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
31003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
31103928aee4356845252ac6b662d5c72c29903813eJake Slack                case __IDLE:
31203928aee4356845252ac6b662d5c72c29903813eJake Slack                    _initial=true;
31303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__DISPATCHED;
31403928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_lastAsyncListeners!=null)
31503928aee4356845252ac6b662d5c72c29903813eJake Slack                        _lastAsyncListeners.clear();
31603928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_asyncListeners!=null)
31703928aee4356845252ac6b662d5c72c29903813eJake Slack                        _asyncListeners.clear();
31803928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
31903928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
32003928aee4356845252ac6b662d5c72c29903813eJake Slack                        _asyncListeners=_lastAsyncListeners;
32103928aee4356845252ac6b662d5c72c29903813eJake Slack                        _lastAsyncListeners=null;
32203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
32303928aee4356845252ac6b662d5c72c29903813eJake Slack                    return true;
32403928aee4356845252ac6b662d5c72c29903813eJake Slack
32503928aee4356845252ac6b662d5c72c29903813eJake Slack                case __COMPLETING:
32603928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__UNCOMPLETED;
32703928aee4356845252ac6b662d5c72c29903813eJake Slack                    return false;
32803928aee4356845252ac6b662d5c72c29903813eJake Slack
32903928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCWAIT:
33003928aee4356845252ac6b662d5c72c29903813eJake Slack                    return false;
33103928aee4356845252ac6b662d5c72c29903813eJake Slack
33203928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCH:
33303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__REDISPATCHED;
33403928aee4356845252ac6b662d5c72c29903813eJake Slack                    return true;
33503928aee4356845252ac6b662d5c72c29903813eJake Slack
33603928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
33703928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException(this.getStatusString());
33803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
33903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
34003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
34103928aee4356845252ac6b662d5c72c29903813eJake Slack
34203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
34303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* (non-Javadoc)
34403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletRequest#suspend(long)
34503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
34603928aee4356845252ac6b662d5c72c29903813eJake Slack    private void doSuspend(final ServletContext context,
34703928aee4356845252ac6b662d5c72c29903813eJake Slack            final ServletRequest request,
34803928aee4356845252ac6b662d5c72c29903813eJake Slack            final ServletResponse response)
34903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
35003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
35103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
35203928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
35303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
35403928aee4356845252ac6b662d5c72c29903813eJake Slack                case __DISPATCHED:
35503928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCHED:
35603928aee4356845252ac6b662d5c72c29903813eJake Slack                    _resumed=false;
35703928aee4356845252ac6b662d5c72c29903813eJake Slack                    _expired=false;
35803928aee4356845252ac6b662d5c72c29903813eJake Slack
35903928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_event==null || request!=_event.getSuppliedRequest() || response != _event.getSuppliedResponse() || context != _event.getServletContext())
36003928aee4356845252ac6b662d5c72c29903813eJake Slack                        _event=new AsyncEventState(context,request,response);
36103928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
36203928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
36303928aee4356845252ac6b662d5c72c29903813eJake Slack                        _event._dispatchContext=null;
36403928aee4356845252ac6b662d5c72c29903813eJake Slack                        _event._pathInContext=null;
36503928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
36603928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__ASYNCSTARTED;
36703928aee4356845252ac6b662d5c72c29903813eJake Slack                    List<AsyncListener> recycle=_lastAsyncListeners;
36803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _lastAsyncListeners=_asyncListeners;
36903928aee4356845252ac6b662d5c72c29903813eJake Slack                    _asyncListeners=recycle;
37003928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_asyncListeners!=null)
37103928aee4356845252ac6b662d5c72c29903813eJake Slack                        _asyncListeners.clear();
37203928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
37303928aee4356845252ac6b662d5c72c29903813eJake Slack
37403928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
37503928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException(this.getStatusString());
37603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
37703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
37803928aee4356845252ac6b662d5c72c29903813eJake Slack
37903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_lastAsyncListeners!=null)
38003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
38103928aee4356845252ac6b662d5c72c29903813eJake Slack            for (AsyncListener listener : _lastAsyncListeners)
38203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
38303928aee4356845252ac6b662d5c72c29903813eJake Slack                try
38403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
38503928aee4356845252ac6b662d5c72c29903813eJake Slack                    listener.onStartAsync(_event);
38603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
38703928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(Exception e)
38803928aee4356845252ac6b662d5c72c29903813eJake Slack                {
38903928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.warn(e);
39003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
39103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
39203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
39303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
39403928aee4356845252ac6b662d5c72c29903813eJake Slack
39503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
39603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
39703928aee4356845252ac6b662d5c72c29903813eJake Slack     * Signal that the HttpConnection has finished handling the request.
39803928aee4356845252ac6b662d5c72c29903813eJake Slack     * For blocking connectors, this call may block if the request has
39903928aee4356845252ac6b662d5c72c29903813eJake Slack     * been suspended (startAsync called).
40003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return true if handling is complete, false if the request should
40103928aee4356845252ac6b662d5c72c29903813eJake Slack     * be handled again (eg because of a resume that happened before unhandle was called)
40203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
40303928aee4356845252ac6b662d5c72c29903813eJake Slack    protected boolean unhandle()
40403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
40503928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
40603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
40703928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
40803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
40903928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCHED:
41003928aee4356845252ac6b662d5c72c29903813eJake Slack                case __DISPATCHED:
41103928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__UNCOMPLETED;
41203928aee4356845252ac6b662d5c72c29903813eJake Slack                    return true;
41303928aee4356845252ac6b662d5c72c29903813eJake Slack
41403928aee4356845252ac6b662d5c72c29903813eJake Slack                case __IDLE:
41503928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException(this.getStatusString());
41603928aee4356845252ac6b662d5c72c29903813eJake Slack
41703928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCSTARTED:
41803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _initial=false;
41903928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__ASYNCWAIT;
42003928aee4356845252ac6b662d5c72c29903813eJake Slack                    scheduleTimeout(); // could block and change state.
42103928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_state==__ASYNCWAIT)
42203928aee4356845252ac6b662d5c72c29903813eJake Slack                        return true;
42303928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if (_state==__COMPLETING)
42403928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
42503928aee4356845252ac6b662d5c72c29903813eJake Slack                        _state=__UNCOMPLETED;
42603928aee4356845252ac6b662d5c72c29903813eJake Slack                        return true;
42703928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
42803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _initial=false;
42903928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__REDISPATCHED;
43003928aee4356845252ac6b662d5c72c29903813eJake Slack                    return false;
43103928aee4356845252ac6b662d5c72c29903813eJake Slack
43203928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCHING:
43303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _initial=false;
43403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__REDISPATCHED;
43503928aee4356845252ac6b662d5c72c29903813eJake Slack                    return false;
43603928aee4356845252ac6b662d5c72c29903813eJake Slack
43703928aee4356845252ac6b662d5c72c29903813eJake Slack                case __COMPLETING:
43803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _initial=false;
43903928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__UNCOMPLETED;
44003928aee4356845252ac6b662d5c72c29903813eJake Slack                    return true;
44103928aee4356845252ac6b662d5c72c29903813eJake Slack
44203928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
44303928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException(this.getStatusString());
44403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
44503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
44603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
44703928aee4356845252ac6b662d5c72c29903813eJake Slack
44803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
44903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void dispatch()
45003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
45103928aee4356845252ac6b662d5c72c29903813eJake Slack        boolean dispatch=false;
45203928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
45303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
45403928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
45503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
45603928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCSTARTED:
45703928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__REDISPATCHING;
45803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _resumed=true;
45903928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
46003928aee4356845252ac6b662d5c72c29903813eJake Slack
46103928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCWAIT:
46203928aee4356845252ac6b662d5c72c29903813eJake Slack                    dispatch=!_expired;
46303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__REDISPATCH;
46403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _resumed=true;
46503928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
46603928aee4356845252ac6b662d5c72c29903813eJake Slack
46703928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCH:
46803928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
46903928aee4356845252ac6b662d5c72c29903813eJake Slack
47003928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
47103928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException(this.getStatusString());
47203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
47303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
47403928aee4356845252ac6b662d5c72c29903813eJake Slack
47503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (dispatch)
47603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
47703928aee4356845252ac6b662d5c72c29903813eJake Slack            cancelTimeout();
47803928aee4356845252ac6b662d5c72c29903813eJake Slack            scheduleDispatch();
47903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
48003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
48103928aee4356845252ac6b662d5c72c29903813eJake Slack
48203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
48303928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void expired()
48403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
48503928aee4356845252ac6b662d5c72c29903813eJake Slack        final List<ContinuationListener> cListeners;
48603928aee4356845252ac6b662d5c72c29903813eJake Slack        final List<AsyncListener> aListeners;
48703928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
48803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
48903928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
49003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
49103928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCSTARTED:
49203928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCWAIT:
49303928aee4356845252ac6b662d5c72c29903813eJake Slack                    cListeners=_continuationListeners;
49403928aee4356845252ac6b662d5c72c29903813eJake Slack                    aListeners=_asyncListeners;
49503928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
49603928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
49703928aee4356845252ac6b662d5c72c29903813eJake Slack                    cListeners=null;
49803928aee4356845252ac6b662d5c72c29903813eJake Slack                    aListeners=null;
49903928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
50003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
50103928aee4356845252ac6b662d5c72c29903813eJake Slack            _expired=true;
50203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
50303928aee4356845252ac6b662d5c72c29903813eJake Slack
50403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (aListeners!=null)
50503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
50603928aee4356845252ac6b662d5c72c29903813eJake Slack            for (AsyncListener listener : aListeners)
50703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
50803928aee4356845252ac6b662d5c72c29903813eJake Slack                try
50903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
51003928aee4356845252ac6b662d5c72c29903813eJake Slack                    listener.onTimeout(_event);
51103928aee4356845252ac6b662d5c72c29903813eJake Slack                }
51203928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(Exception e)
51303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
51403928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.debug(e);
51503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _connection.getRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION,e);
51603928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
51703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
51803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
51903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
52003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (cListeners!=null)
52103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
52203928aee4356845252ac6b662d5c72c29903813eJake Slack            for (ContinuationListener listener : cListeners)
52303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
52403928aee4356845252ac6b662d5c72c29903813eJake Slack                try
52503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
52603928aee4356845252ac6b662d5c72c29903813eJake Slack                    listener.onTimeout(this);
52703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
52803928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(Exception e)
52903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
53003928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.warn(e);
53103928aee4356845252ac6b662d5c72c29903813eJake Slack                }
53203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
53303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
53403928aee4356845252ac6b662d5c72c29903813eJake Slack
53503928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
53603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
53703928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
53803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
53903928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCSTARTED:
54003928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCWAIT:
54103928aee4356845252ac6b662d5c72c29903813eJake Slack                    dispatch();
54203928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
54303928aee4356845252ac6b662d5c72c29903813eJake Slack
54403928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
54503928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (!_continuation)
54603928aee4356845252ac6b662d5c72c29903813eJake Slack                        _expired=false;
54703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
54803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
54903928aee4356845252ac6b662d5c72c29903813eJake Slack
55003928aee4356845252ac6b662d5c72c29903813eJake Slack        scheduleDispatch();
55103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
55203928aee4356845252ac6b662d5c72c29903813eJake Slack
55303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
55403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* (non-Javadoc)
55503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletRequest#complete()
55603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
55703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void complete()
55803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
55903928aee4356845252ac6b662d5c72c29903813eJake Slack        // just like resume, except don't set _resumed=true;
56003928aee4356845252ac6b662d5c72c29903813eJake Slack        boolean dispatch=false;
56103928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
56203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
56303928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
56403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
56503928aee4356845252ac6b662d5c72c29903813eJake Slack                case __DISPATCHED:
56603928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCHED:
56703928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException(this.getStatusString());
56803928aee4356845252ac6b662d5c72c29903813eJake Slack
56903928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCSTARTED:
57003928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__COMPLETING;
57103928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
57203928aee4356845252ac6b662d5c72c29903813eJake Slack
57303928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCWAIT:
57403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__COMPLETING;
57503928aee4356845252ac6b662d5c72c29903813eJake Slack                    dispatch=!_expired;
57603928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
57703928aee4356845252ac6b662d5c72c29903813eJake Slack
57803928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
57903928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException(this.getStatusString());
58003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
58103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
58203928aee4356845252ac6b662d5c72c29903813eJake Slack
58303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (dispatch)
58403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
58503928aee4356845252ac6b662d5c72c29903813eJake Slack            cancelTimeout();
58603928aee4356845252ac6b662d5c72c29903813eJake Slack            scheduleDispatch();
58703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
58803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
58903928aee4356845252ac6b662d5c72c29903813eJake Slack
59003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
59103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* (non-Javadoc)
59203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletRequest#complete()
59303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
59403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void errorComplete()
59503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
59603928aee4356845252ac6b662d5c72c29903813eJake Slack        // just like complete except can overrule a prior dispatch call;
59703928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
59803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
59903928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
60003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
60103928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCHING:
60203928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCSTARTED:
60303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__COMPLETING;
60403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _resumed=false;
60503928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
60603928aee4356845252ac6b662d5c72c29903813eJake Slack
60703928aee4356845252ac6b662d5c72c29903813eJake Slack                case __COMPLETING:
60803928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
60903928aee4356845252ac6b662d5c72c29903813eJake Slack
61003928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
61103928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException(this.getStatusString());
61203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
61303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
61403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
61503928aee4356845252ac6b662d5c72c29903813eJake Slack
61603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
61703928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
61803928aee4356845252ac6b662d5c72c29903813eJake Slack    public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException
61903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
62003928aee4356845252ac6b662d5c72c29903813eJake Slack        try
62103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
62203928aee4356845252ac6b662d5c72c29903813eJake Slack            // TODO inject
62303928aee4356845252ac6b662d5c72c29903813eJake Slack            return clazz.newInstance();
62403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
62503928aee4356845252ac6b662d5c72c29903813eJake Slack        catch(Exception e)
62603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
62703928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new ServletException(e);
62803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
62903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
63003928aee4356845252ac6b662d5c72c29903813eJake Slack
63103928aee4356845252ac6b662d5c72c29903813eJake Slack
63203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
63303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* (non-Javadoc)
63403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletRequest#complete()
63503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
63603928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void doComplete(Throwable ex)
63703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
63803928aee4356845252ac6b662d5c72c29903813eJake Slack        final List<ContinuationListener> cListeners;
63903928aee4356845252ac6b662d5c72c29903813eJake Slack        final List<AsyncListener> aListeners;
64003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
64103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
64203928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
64303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
64403928aee4356845252ac6b662d5c72c29903813eJake Slack                case __UNCOMPLETED:
64503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__COMPLETED;
64603928aee4356845252ac6b662d5c72c29903813eJake Slack                    cListeners=_continuationListeners;
64703928aee4356845252ac6b662d5c72c29903813eJake Slack                    aListeners=_asyncListeners;
64803928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
64903928aee4356845252ac6b662d5c72c29903813eJake Slack
65003928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
65103928aee4356845252ac6b662d5c72c29903813eJake Slack                    cListeners=null;
65203928aee4356845252ac6b662d5c72c29903813eJake Slack                    aListeners=null;
65303928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException(this.getStatusString());
65403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
65503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
65603928aee4356845252ac6b662d5c72c29903813eJake Slack
65703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (aListeners!=null)
65803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
65903928aee4356845252ac6b662d5c72c29903813eJake Slack            for (AsyncListener listener : aListeners)
66003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
66103928aee4356845252ac6b662d5c72c29903813eJake Slack                try
66203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
66303928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (ex!=null)
66403928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
66503928aee4356845252ac6b662d5c72c29903813eJake Slack                        _event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION,ex);
66603928aee4356845252ac6b662d5c72c29903813eJake Slack                        _event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_MESSAGE,ex.getMessage());
66703928aee4356845252ac6b662d5c72c29903813eJake Slack                        listener.onError(_event);
66803928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
66903928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
67003928aee4356845252ac6b662d5c72c29903813eJake Slack                        listener.onComplete(_event);
67103928aee4356845252ac6b662d5c72c29903813eJake Slack                }
67203928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(Exception e)
67303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
67403928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.warn(e);
67503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
67603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
67703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
67803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (cListeners!=null)
67903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
68003928aee4356845252ac6b662d5c72c29903813eJake Slack            for (ContinuationListener listener : cListeners)
68103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
68203928aee4356845252ac6b662d5c72c29903813eJake Slack                try
68303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
68403928aee4356845252ac6b662d5c72c29903813eJake Slack                    listener.onComplete(this);
68503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
68603928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(Exception e)
68703928aee4356845252ac6b662d5c72c29903813eJake Slack                {
68803928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.warn(e);
68903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
69003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
69103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
69203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
69303928aee4356845252ac6b662d5c72c29903813eJake Slack
69403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
69503928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void recycle()
69603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
69703928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
69803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
69903928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
70003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
70103928aee4356845252ac6b662d5c72c29903813eJake Slack                case __DISPATCHED:
70203928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCHED:
70303928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException(getStatusString());
70403928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
70503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=__IDLE;
70603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
70703928aee4356845252ac6b662d5c72c29903813eJake Slack            _initial = true;
70803928aee4356845252ac6b662d5c72c29903813eJake Slack            _resumed=false;
70903928aee4356845252ac6b662d5c72c29903813eJake Slack            _expired=false;
71003928aee4356845252ac6b662d5c72c29903813eJake Slack            _responseWrapped=false;
71103928aee4356845252ac6b662d5c72c29903813eJake Slack            cancelTimeout();
71203928aee4356845252ac6b662d5c72c29903813eJake Slack            _timeoutMs=DEFAULT_TIMEOUT;
71303928aee4356845252ac6b662d5c72c29903813eJake Slack            _continuationListeners=null;
71403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
71503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
71603928aee4356845252ac6b662d5c72c29903813eJake Slack
71703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
71803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void cancel()
71903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
72003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
72103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
72203928aee4356845252ac6b662d5c72c29903813eJake Slack            cancelTimeout();
72303928aee4356845252ac6b662d5c72c29903813eJake Slack            _continuationListeners=null;
72403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
72503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
72603928aee4356845252ac6b662d5c72c29903813eJake Slack
72703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
72803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void scheduleDispatch()
72903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
73003928aee4356845252ac6b662d5c72c29903813eJake Slack        EndPoint endp=_connection.getEndPoint();
73103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!endp.isBlocking())
73203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
73303928aee4356845252ac6b662d5c72c29903813eJake Slack            ((AsyncEndPoint)endp).asyncDispatch();
73403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
73503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
73603928aee4356845252ac6b662d5c72c29903813eJake Slack
73703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
73803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void scheduleTimeout()
73903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
74003928aee4356845252ac6b662d5c72c29903813eJake Slack        EndPoint endp=_connection.getEndPoint();
74103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_timeoutMs>0)
74203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
74303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (endp.isBlocking())
74403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
74503928aee4356845252ac6b662d5c72c29903813eJake Slack                synchronized(this)
74603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
74703928aee4356845252ac6b662d5c72c29903813eJake Slack                    _expireAt = System.currentTimeMillis()+_timeoutMs;
74803928aee4356845252ac6b662d5c72c29903813eJake Slack                    long wait=_timeoutMs;
74903928aee4356845252ac6b662d5c72c29903813eJake Slack                    while (_expireAt>0 && wait>0 && _connection.getServer().isRunning())
75003928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
75103928aee4356845252ac6b662d5c72c29903813eJake Slack                        try
75203928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
75303928aee4356845252ac6b662d5c72c29903813eJake Slack                            this.wait(wait);
75403928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
75503928aee4356845252ac6b662d5c72c29903813eJake Slack                        catch (InterruptedException e)
75603928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
75703928aee4356845252ac6b662d5c72c29903813eJake Slack                            LOG.ignore(e);
75803928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
75903928aee4356845252ac6b662d5c72c29903813eJake Slack                        wait=_expireAt-System.currentTimeMillis();
76003928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
76103928aee4356845252ac6b662d5c72c29903813eJake Slack
76203928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_expireAt>0 && wait<=0 && _connection.getServer().isRunning())
76303928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
76403928aee4356845252ac6b662d5c72c29903813eJake Slack                        expired();
76503928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
76603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
76703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
76803928aee4356845252ac6b662d5c72c29903813eJake Slack            else
76903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
77003928aee4356845252ac6b662d5c72c29903813eJake Slack                ((AsyncEndPoint)endp).scheduleTimeout(_event._timeout,_timeoutMs);
77103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
77203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
77303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
77403928aee4356845252ac6b662d5c72c29903813eJake Slack
77503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
77603928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void cancelTimeout()
77703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
77803928aee4356845252ac6b662d5c72c29903813eJake Slack        EndPoint endp=_connection.getEndPoint();
77903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (endp.isBlocking())
78003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
78103928aee4356845252ac6b662d5c72c29903813eJake Slack            synchronized(this)
78203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
78303928aee4356845252ac6b662d5c72c29903813eJake Slack                _expireAt=0;
78403928aee4356845252ac6b662d5c72c29903813eJake Slack                this.notifyAll();
78503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
78603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
78703928aee4356845252ac6b662d5c72c29903813eJake Slack        else
78803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
78903928aee4356845252ac6b662d5c72c29903813eJake Slack            final AsyncEventState event=_event;
79003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (event!=null)
79103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
79203928aee4356845252ac6b662d5c72c29903813eJake Slack                ((AsyncEndPoint)endp).cancelTimeout(event._timeout);
79303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
79403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
79503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
79603928aee4356845252ac6b662d5c72c29903813eJake Slack
79703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
79803928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isCompleting()
79903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
80003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
80103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
80203928aee4356845252ac6b662d5c72c29903813eJake Slack            return _state==__COMPLETING;
80303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
80403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
80503928aee4356845252ac6b662d5c72c29903813eJake Slack
80603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
80703928aee4356845252ac6b662d5c72c29903813eJake Slack    boolean isUncompleted()
80803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
80903928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
81003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
81103928aee4356845252ac6b662d5c72c29903813eJake Slack            return _state==__UNCOMPLETED;
81203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
81303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
81403928aee4356845252ac6b662d5c72c29903813eJake Slack
81503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
81603928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isComplete()
81703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
81803928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
81903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
82003928aee4356845252ac6b662d5c72c29903813eJake Slack            return _state==__COMPLETED;
82103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
82203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
82303928aee4356845252ac6b662d5c72c29903813eJake Slack
82403928aee4356845252ac6b662d5c72c29903813eJake Slack
82503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
82603928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isAsyncStarted()
82703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
82803928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
82903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
83003928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
83103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
83203928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCSTARTED:
83303928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCHING:
83403928aee4356845252ac6b662d5c72c29903813eJake Slack                case __REDISPATCH:
83503928aee4356845252ac6b662d5c72c29903813eJake Slack                case __ASYNCWAIT:
83603928aee4356845252ac6b662d5c72c29903813eJake Slack                    return true;
83703928aee4356845252ac6b662d5c72c29903813eJake Slack
83803928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
83903928aee4356845252ac6b662d5c72c29903813eJake Slack                    return false;
84003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
84103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
84203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
84303928aee4356845252ac6b662d5c72c29903813eJake Slack
84403928aee4356845252ac6b662d5c72c29903813eJake Slack
84503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
84603928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isAsync()
84703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
84803928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
84903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
85003928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
85103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
85203928aee4356845252ac6b662d5c72c29903813eJake Slack                case __IDLE:
85303928aee4356845252ac6b662d5c72c29903813eJake Slack                case __DISPATCHED:
85403928aee4356845252ac6b662d5c72c29903813eJake Slack                case __UNCOMPLETED:
85503928aee4356845252ac6b662d5c72c29903813eJake Slack                case __COMPLETED:
85603928aee4356845252ac6b662d5c72c29903813eJake Slack                    return false;
85703928aee4356845252ac6b662d5c72c29903813eJake Slack
85803928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
85903928aee4356845252ac6b662d5c72c29903813eJake Slack                    return true;
86003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
86103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
86203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
86303928aee4356845252ac6b662d5c72c29903813eJake Slack
86403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
86503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void dispatch(ServletContext context, String path)
86603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
86703928aee4356845252ac6b662d5c72c29903813eJake Slack        _event._dispatchContext=context;
86803928aee4356845252ac6b662d5c72c29903813eJake Slack        _event.setPath(path);
86903928aee4356845252ac6b662d5c72c29903813eJake Slack        dispatch();
87003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
87103928aee4356845252ac6b662d5c72c29903813eJake Slack
87203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
87303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void dispatch(String path)
87403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
87503928aee4356845252ac6b662d5c72c29903813eJake Slack        _event.setPath(path);
87603928aee4356845252ac6b662d5c72c29903813eJake Slack        dispatch();
87703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
87803928aee4356845252ac6b662d5c72c29903813eJake Slack
87903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
88003928aee4356845252ac6b662d5c72c29903813eJake Slack    public Request getBaseRequest()
88103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
88203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _connection.getRequest();
88303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
88403928aee4356845252ac6b662d5c72c29903813eJake Slack
88503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
88603928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletRequest getRequest()
88703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
88803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_event!=null)
88903928aee4356845252ac6b662d5c72c29903813eJake Slack            return _event.getSuppliedRequest();
89003928aee4356845252ac6b662d5c72c29903813eJake Slack        return _connection.getRequest();
89103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
89203928aee4356845252ac6b662d5c72c29903813eJake Slack
89303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
89403928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletResponse getResponse()
89503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
89603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_responseWrapped && _event!=null && _event.getSuppliedResponse()!=null)
89703928aee4356845252ac6b662d5c72c29903813eJake Slack            return _event.getSuppliedResponse();
89803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _connection.getResponse();
89903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
90003928aee4356845252ac6b662d5c72c29903813eJake Slack
90103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
90203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void start(final Runnable run)
90303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
90403928aee4356845252ac6b662d5c72c29903813eJake Slack        final AsyncEventState event=_event;
90503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (event!=null)
90603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
90703928aee4356845252ac6b662d5c72c29903813eJake Slack            _connection.getServer().getThreadPool().dispatch(new Runnable()
90803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
90903928aee4356845252ac6b662d5c72c29903813eJake Slack                public void run()
91003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
91103928aee4356845252ac6b662d5c72c29903813eJake Slack                    ((Context)event.getServletContext()).getContextHandler().handle(run);
91203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
91303928aee4356845252ac6b662d5c72c29903813eJake Slack            });
91403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
91503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
91603928aee4356845252ac6b662d5c72c29903813eJake Slack
91703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
91803928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean hasOriginalRequestAndResponse()
91903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
92003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
92103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
92203928aee4356845252ac6b662d5c72c29903813eJake Slack            return (_event!=null && _event.getSuppliedRequest()==_connection._request && _event.getSuppliedResponse()==_connection._response);
92303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
92403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
92503928aee4356845252ac6b662d5c72c29903813eJake Slack
92603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
92703928aee4356845252ac6b662d5c72c29903813eJake Slack    public ContextHandler getContextHandler()
92803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
92903928aee4356845252ac6b662d5c72c29903813eJake Slack        final AsyncEventState event=_event;
93003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (event!=null)
93103928aee4356845252ac6b662d5c72c29903813eJake Slack            return ((Context)event.getServletContext()).getContextHandler();
93203928aee4356845252ac6b662d5c72c29903813eJake Slack        return null;
93303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
93403928aee4356845252ac6b662d5c72c29903813eJake Slack
93503928aee4356845252ac6b662d5c72c29903813eJake Slack
93603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
93703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
93803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see Continuation#isResumed()
93903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
94003928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isResumed()
94103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
94203928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
94303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
94403928aee4356845252ac6b662d5c72c29903813eJake Slack            return _resumed;
94503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
94603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
94703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
94803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
94903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see Continuation#isExpired()
95003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
95103928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isExpired()
95203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
95303928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
95403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
95503928aee4356845252ac6b662d5c72c29903813eJake Slack            return _expired;
95603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
95703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
95803928aee4356845252ac6b662d5c72c29903813eJake Slack
95903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
96003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
96103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see Continuation#resume()
96203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
96303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void resume()
96403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
96503928aee4356845252ac6b662d5c72c29903813eJake Slack        dispatch();
96603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
96703928aee4356845252ac6b662d5c72c29903813eJake Slack
96803928aee4356845252ac6b662d5c72c29903813eJake Slack
96903928aee4356845252ac6b662d5c72c29903813eJake Slack
97003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
97103928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void startAsync(final ServletContext context,
97203928aee4356845252ac6b662d5c72c29903813eJake Slack            final ServletRequest request,
97303928aee4356845252ac6b662d5c72c29903813eJake Slack            final ServletResponse response)
97403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
97503928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
97603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
97703928aee4356845252ac6b662d5c72c29903813eJake Slack            _responseWrapped=!(response instanceof Response);
97803928aee4356845252ac6b662d5c72c29903813eJake Slack            doSuspend(context,request,response);
97903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (request instanceof HttpServletRequest)
98003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
98103928aee4356845252ac6b662d5c72c29903813eJake Slack                _event._pathInContext = URIUtil.addPaths(((HttpServletRequest)request).getServletPath(),((HttpServletRequest)request).getPathInfo());
98203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
98303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
98403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
98503928aee4356845252ac6b662d5c72c29903813eJake Slack
98603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
98703928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void startAsync()
98803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
98903928aee4356845252ac6b662d5c72c29903813eJake Slack        _responseWrapped=false;
99003928aee4356845252ac6b662d5c72c29903813eJake Slack        _continuation=false;
99103928aee4356845252ac6b662d5c72c29903813eJake Slack        doSuspend(_connection.getRequest().getServletContext(),_connection.getRequest(),_connection.getResponse());
99203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
99303928aee4356845252ac6b662d5c72c29903813eJake Slack
99403928aee4356845252ac6b662d5c72c29903813eJake Slack
99503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
99603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
99703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see Continuation#suspend()
99803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
99903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void suspend(ServletResponse response)
100003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
100103928aee4356845252ac6b662d5c72c29903813eJake Slack        _continuation=true;
100203928aee4356845252ac6b662d5c72c29903813eJake Slack        _responseWrapped=!(response instanceof Response);
100303928aee4356845252ac6b662d5c72c29903813eJake Slack        doSuspend(_connection.getRequest().getServletContext(),_connection.getRequest(),response);
100403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
100503928aee4356845252ac6b662d5c72c29903813eJake Slack
100603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
100703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
100803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see Continuation#suspend()
100903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
101003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void suspend()
101103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
101203928aee4356845252ac6b662d5c72c29903813eJake Slack        _responseWrapped=false;
101303928aee4356845252ac6b662d5c72c29903813eJake Slack        _continuation=true;
101403928aee4356845252ac6b662d5c72c29903813eJake Slack        doSuspend(_connection.getRequest().getServletContext(),_connection.getRequest(),_connection.getResponse());
101503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
101603928aee4356845252ac6b662d5c72c29903813eJake Slack
101703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
101803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
101903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.continuation.Continuation#getServletResponse()
102003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
102103928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletResponse getServletResponse()
102203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
102303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_responseWrapped && _event!=null && _event.getSuppliedResponse()!=null)
102403928aee4356845252ac6b662d5c72c29903813eJake Slack            return _event.getSuppliedResponse();
102503928aee4356845252ac6b662d5c72c29903813eJake Slack        return _connection.getResponse();
102603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
102703928aee4356845252ac6b662d5c72c29903813eJake Slack
102803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
102903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
103003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.continuation.Continuation#getAttribute(java.lang.String)
103103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
103203928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object getAttribute(String name)
103303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
103403928aee4356845252ac6b662d5c72c29903813eJake Slack        return _connection.getRequest().getAttribute(name);
103503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
103603928aee4356845252ac6b662d5c72c29903813eJake Slack
103703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
103803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
103903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.continuation.Continuation#removeAttribute(java.lang.String)
104003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
104103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void removeAttribute(String name)
104203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
104303928aee4356845252ac6b662d5c72c29903813eJake Slack        _connection.getRequest().removeAttribute(name);
104403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
104503928aee4356845252ac6b662d5c72c29903813eJake Slack
104603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
104703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
104803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.continuation.Continuation#setAttribute(java.lang.String, java.lang.Object)
104903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
105003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setAttribute(String name, Object attribute)
105103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
105203928aee4356845252ac6b662d5c72c29903813eJake Slack        _connection.getRequest().setAttribute(name,attribute);
105303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
105403928aee4356845252ac6b662d5c72c29903813eJake Slack
105503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
105603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
105703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.continuation.Continuation#undispatch()
105803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
105903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void undispatch()
106003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
106103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (isSuspended())
106203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
106303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LOG.isDebugEnabled())
106403928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new ContinuationThrowable();
106503928aee4356845252ac6b662d5c72c29903813eJake Slack            else
106603928aee4356845252ac6b662d5c72c29903813eJake Slack                throw __exception;
106703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
106803928aee4356845252ac6b662d5c72c29903813eJake Slack        throw new IllegalStateException("!suspended");
106903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
107003928aee4356845252ac6b662d5c72c29903813eJake Slack
107103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
107203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
107303928aee4356845252ac6b662d5c72c29903813eJake Slack    public class AsyncTimeout extends Timeout.Task implements Runnable
107403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
107503928aee4356845252ac6b662d5c72c29903813eJake Slack            @Override
107603928aee4356845252ac6b662d5c72c29903813eJake Slack            public void expired()
107703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
107803928aee4356845252ac6b662d5c72c29903813eJake Slack                AsyncContinuation.this.expired();
107903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
108003928aee4356845252ac6b662d5c72c29903813eJake Slack
108103928aee4356845252ac6b662d5c72c29903813eJake Slack            @Override
108203928aee4356845252ac6b662d5c72c29903813eJake Slack            public void run()
108303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
108403928aee4356845252ac6b662d5c72c29903813eJake Slack                AsyncContinuation.this.expired();
108503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
108603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
108703928aee4356845252ac6b662d5c72c29903813eJake Slack
108803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
108903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
109003928aee4356845252ac6b662d5c72c29903813eJake Slack    public class AsyncEventState extends AsyncEvent
109103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
109203928aee4356845252ac6b662d5c72c29903813eJake Slack        private final ServletContext _suspendedContext;
109303928aee4356845252ac6b662d5c72c29903813eJake Slack        private ServletContext _dispatchContext;
109403928aee4356845252ac6b662d5c72c29903813eJake Slack        private String _pathInContext;
109503928aee4356845252ac6b662d5c72c29903813eJake Slack        private Timeout.Task _timeout=  new AsyncTimeout();
109603928aee4356845252ac6b662d5c72c29903813eJake Slack
109703928aee4356845252ac6b662d5c72c29903813eJake Slack        public AsyncEventState(ServletContext context, ServletRequest request, ServletResponse response)
109803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
109903928aee4356845252ac6b662d5c72c29903813eJake Slack            super(AsyncContinuation.this, request,response);
110003928aee4356845252ac6b662d5c72c29903813eJake Slack            _suspendedContext=context;
110103928aee4356845252ac6b662d5c72c29903813eJake Slack            // Get the base request So we can remember the initial paths
110203928aee4356845252ac6b662d5c72c29903813eJake Slack            Request r=_connection.getRequest();
110303928aee4356845252ac6b662d5c72c29903813eJake Slack
110403928aee4356845252ac6b662d5c72c29903813eJake Slack            // If we haven't been async dispatched before
110503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (r.getAttribute(AsyncContext.ASYNC_REQUEST_URI)==null)
110603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
110703928aee4356845252ac6b662d5c72c29903813eJake Slack                // We are setting these attributes during startAsync, when the spec implies that
110803928aee4356845252ac6b662d5c72c29903813eJake Slack                // they are only available after a call to AsyncContext.dispatch(...);
110903928aee4356845252ac6b662d5c72c29903813eJake Slack
111003928aee4356845252ac6b662d5c72c29903813eJake Slack                // have we been forwarded before?
111103928aee4356845252ac6b662d5c72c29903813eJake Slack                String uri=(String)r.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
111203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (uri!=null)
111303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
111403928aee4356845252ac6b662d5c72c29903813eJake Slack                    r.setAttribute(AsyncContext.ASYNC_REQUEST_URI,uri);
111503928aee4356845252ac6b662d5c72c29903813eJake Slack                    r.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH,r.getAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH));
111603928aee4356845252ac6b662d5c72c29903813eJake Slack                    r.setAttribute(AsyncContext.ASYNC_SERVLET_PATH,r.getAttribute(RequestDispatcher.FORWARD_SERVLET_PATH));
111703928aee4356845252ac6b662d5c72c29903813eJake Slack                    r.setAttribute(AsyncContext.ASYNC_PATH_INFO,r.getAttribute(RequestDispatcher.FORWARD_PATH_INFO));
111803928aee4356845252ac6b662d5c72c29903813eJake Slack                    r.setAttribute(AsyncContext.ASYNC_QUERY_STRING,r.getAttribute(RequestDispatcher.FORWARD_QUERY_STRING));
111903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
112003928aee4356845252ac6b662d5c72c29903813eJake Slack                else
112103928aee4356845252ac6b662d5c72c29903813eJake Slack                {
112203928aee4356845252ac6b662d5c72c29903813eJake Slack                    r.setAttribute(AsyncContext.ASYNC_REQUEST_URI,r.getRequestURI());
112303928aee4356845252ac6b662d5c72c29903813eJake Slack                    r.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH,r.getContextPath());
112403928aee4356845252ac6b662d5c72c29903813eJake Slack                    r.setAttribute(AsyncContext.ASYNC_SERVLET_PATH,r.getServletPath());
112503928aee4356845252ac6b662d5c72c29903813eJake Slack                    r.setAttribute(AsyncContext.ASYNC_PATH_INFO,r.getPathInfo());
112603928aee4356845252ac6b662d5c72c29903813eJake Slack                    r.setAttribute(AsyncContext.ASYNC_QUERY_STRING,r.getQueryString());
112703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
112803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
112903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
113003928aee4356845252ac6b662d5c72c29903813eJake Slack
113103928aee4356845252ac6b662d5c72c29903813eJake Slack        public ServletContext getSuspendedContext()
113203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
113303928aee4356845252ac6b662d5c72c29903813eJake Slack            return _suspendedContext;
113403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
113503928aee4356845252ac6b662d5c72c29903813eJake Slack
113603928aee4356845252ac6b662d5c72c29903813eJake Slack        public ServletContext getDispatchContext()
113703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
113803928aee4356845252ac6b662d5c72c29903813eJake Slack            return _dispatchContext;
113903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
114003928aee4356845252ac6b662d5c72c29903813eJake Slack
114103928aee4356845252ac6b662d5c72c29903813eJake Slack        public ServletContext getServletContext()
114203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
114303928aee4356845252ac6b662d5c72c29903813eJake Slack            return _dispatchContext==null?_suspendedContext:_dispatchContext;
114403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
114503928aee4356845252ac6b662d5c72c29903813eJake Slack
114603928aee4356845252ac6b662d5c72c29903813eJake Slack        public void setPath(String path)
114703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
114803928aee4356845252ac6b662d5c72c29903813eJake Slack            _pathInContext=path;
114903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
115003928aee4356845252ac6b662d5c72c29903813eJake Slack
115103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
115203928aee4356845252ac6b662d5c72c29903813eJake Slack        /**
115303928aee4356845252ac6b662d5c72c29903813eJake Slack         * @return The path in the context
115403928aee4356845252ac6b662d5c72c29903813eJake Slack         */
115503928aee4356845252ac6b662d5c72c29903813eJake Slack        public String getPath()
115603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
115703928aee4356845252ac6b662d5c72c29903813eJake Slack            return _pathInContext;
115803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
115903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
116003928aee4356845252ac6b662d5c72c29903813eJake Slack}
1161