Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   //
   //  ========================================================================
   //  Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
   //  ------------------------------------------------------------------------
   //  All rights reserved. This program and the accompanying materials
   //  are made available under the terms of the Eclipse Public License v1.0
   //  and Apache License v2.0 which accompanies this distribution.
   //
   //      The Eclipse Public License is available at
  //      http://www.eclipse.org/legal/epl-v10.html
  //
  //      The Apache License v2.0 is available at
  //      http://www.opensource.org/licenses/apache2.0.php
  //
  //  You may elect to redistribute this code under either of these licenses.
  //  ========================================================================
  //
  
  package org.eclipse.jetty.server;
  
  
  import java.util.List;
  
  
  
  /* ------------------------------------------------------------ */
Implementation of Continuation and AsyncContext interfaces
  
  public class AsyncContinuation implements AsyncContextContinuation
  {
      private static final Logger LOG = Log.getLogger(AsyncContinuation.class);
  
      private final static long DEFAULT_TIMEOUT=30000L;
      
      private final static ContinuationThrowable __exception = new ContinuationThrowable();
      
      // STATES:
      //               handling()    suspend()     unhandle()    resume()       complete()  doComplete()
      //                             startAsync()                dispatch()   
      // IDLE          DISPATCHED      
      // DISPATCHED                  ASYNCSTARTED  UNCOMPLETED
      // ASYNCSTARTED                              ASYNCWAIT     REDISPATCHING  COMPLETING
      // REDISPATCHING                             REDISPATCHED  
      // ASYNCWAIT                                               REDISPATCH     COMPLETING
      // REDISPATCH    REDISPATCHED
      // REDISPATCHED                ASYNCSTARTED  UNCOMPLETED
      // COMPLETING    UNCOMPLETED                 UNCOMPLETED
      // UNCOMPLETED                                                                        COMPLETED
      // COMPLETED
      private static final int __IDLE=0;         // Idle request
      private static final int __DISPATCHED=1;   // Request dispatched to filter/servlet
      private static final int __ASYNCSTARTED=2; // Suspend called, but not yet returned to container
      private static final int __REDISPATCHING=3;// resumed while dispatched
      private static final int __ASYNCWAIT=4;    // Suspended and parked
      private static final int __REDISPATCH=5;   // Has been scheduled
      private static final int __REDISPATCHED=6; // Request redispatched to filter/servlet
      private static final int __COMPLETING=7;   // complete while dispatched
      private static final int __UNCOMPLETED=8;  // Request is completable
      private static final int __COMPLETED=9;    // Request is complete
      
      /* ------------------------------------------------------------ */
      protected AbstractHttpConnection _connection;
      private List<AsyncListener_lastAsyncListeners;
      private List<AsyncListener_asyncListeners;
  
      /* ------------------------------------------------------------ */
      private int _state;
      private boolean _initial;
      private boolean _resumed;
      private boolean _expired;
      private volatile boolean _responseWrapped;
      private long _timeoutMs=;
      private AsyncEventState _event;
      private volatile long _expireAt;    
      private volatile boolean _continuation;
      
     /* ------------------------------------------------------------ */
     protected AsyncContinuation()
     {
         =;
         =true;
     }
 
     /* ------------------------------------------------------------ */
     protected void setConnection(final AbstractHttpConnection connection)
     {
         synchronized(this)
         {
             =connection;
         }
     }
 
     /* ------------------------------------------------------------ */
     public void addListener(AsyncListener listener)
     {
         synchronized(this)
         {
             if (==null)
                 =new ArrayList<AsyncListener>();
             .add(listener);
         }
     }
 
     /* ------------------------------------------------------------ */
     public void addListener(AsyncListener listener,ServletRequest requestServletResponse response)
     {
         synchronized(this)
         {
             // TODO handle the request/response ???
             if (==null)
                 =new ArrayList<AsyncListener>();
             .add(listener);
         }
     }
 
     /* ------------------------------------------------------------ */
     public void addContinuationListener(ContinuationListener listener)
     {
         synchronized(this)
         {
             if (==null)
                 =new ArrayList<ContinuationListener>();
             .add(listener);
         }
     }
 
     /* ------------------------------------------------------------ */
     public void setTimeout(long ms)
     {
         synchronized(this)
         {
             =ms;
         }
     } 
 
     /* ------------------------------------------------------------ */
     public long getTimeout()
     {
         synchronized(this)
         {
             return ;
         }
     } 
 
     /* ------------------------------------------------------------ */
     {
         synchronized(this)
         {
             return ;
         }
     } 
    
     /* ------------------------------------------------------------ */
    

See also:
org.eclipse.jetty.continuation.Continuation.keepWrappers()
 
 
     /* ------------------------------------------------------------ */
    
 
     public boolean isResponseWrapped()
     {
         return ;
     }
 
     /* ------------------------------------------------------------ */
     /* (non-Javadoc)
      * @see javax.servlet.ServletRequest#isInitial()
      */
     public boolean isInitial()
     {
         synchronized(this)
         {
             return ;
         }
     }
     
     /* ------------------------------------------------------------ */
     /* (non-Javadoc)
      * @see javax.servlet.ServletRequest#isSuspended()
      */
     public boolean isSuspended()
     {
         synchronized(this)
         {
             switch()
             {
                 case :
                 case :
                 case :
                 case :
                     return true;
                     
                 default:
                     return false;   
             }
         }
     }
     
     /* ------------------------------------------------------------ */
     public boolean isSuspending()
     {
         synchronized(this)
         {
             switch()
             {
                 case :
                 case :
                     return true;
                     
                 default:
                     return false;   
             }
         }
     }
     
     /* ------------------------------------------------------------ */
     public boolean isDispatchable()
     {
         synchronized(this)
         {
             switch()
             {
                 case :
                 case :
                 case :
                 case :
                     return true;
                     
                 default:
                     return false;   
             }
         }
     }
 
     /* ------------------------------------------------------------ */
     @Override
     public String toString()
     {
         synchronized (this)
         {
             return super.toString()+"@"+getStatusString();
         }
     }
 
     /* ------------------------------------------------------------ */
     public String getStatusString()
     {
         synchronized (this)
         {
             return
             ((==)?"IDLE":
                 (==)?"DISPATCHED":
                     (==)?"ASYNCSTARTED":
                         (==)?"ASYNCWAIT":
                             (==)?"REDISPATCHING":
                                 (==)?"REDISPATCH":
                                     (==)?"REDISPATCHED":
                                         (==)?"COMPLETING":
                                             (==)?"UNCOMPLETED":
                                                 (==)?"COMPLETE":
                                                     ("UNKNOWN?"+))+
             (?",initial":"")+
             (?",resumed":"")+
             (?",expired":"");
         }
     }
 
     /* ------------------------------------------------------------ */
    

Returns:
false if the handling of the request should not proceed
 
     protected boolean handling()
     {
         synchronized (this)
         {
             =false;
             =false;
             
             switch()
             {
                 case :
                     =true;
                     =;
                     if (!=null)
                         .clear();
                     if (!=null)
                         .clear();
                     else
                     {
                         =;
                         =null;
                     }
                     return true;
                     
                 case :
                     =;
                     return false;
 
                 case :
                     return false;
                     
                 case :
                     =;
                     return true;
 
                 default:
                     throw new IllegalStateException(this.getStatusString());
             }
         }
     }
 
     /* ------------------------------------------------------------ */
     /* (non-Javadoc)
      * @see javax.servlet.ServletRequest#suspend(long)
      */
     private void doSuspend(final ServletContext context,
             final ServletRequest request,
             final ServletResponse response)
     {
         synchronized (this)
         {
             switch()
             {
                 case :
                 case :
                     =false;
                     =false;
 
                     if (==null || request!=.getSuppliedRequest() || response != .getSuppliedResponse() || context != .getServletContext())
                         =new AsyncEventState(context,request,response);
                     else
                     {
                         .=null;
                         .=null;
                     }
                     =;
                     List<AsyncListenerrecycle=;
                     =;
                     =recycle;
                     if (!=null)
                         .clear();
                     break;
 
                 default:
                     throw new IllegalStateException(this.getStatusString());
             }
         }
         
         if (!=null)
         {
             for (AsyncListener listener : )
             {
                 try
                 {
                     listener.onStartAsync();
                 }
                 catch(Exception e)
                 {
                     .warn(e);
                 }
             }
         }
     }
 
     /* ------------------------------------------------------------ */
    
Signal that the HttpConnection has finished handling the request. For blocking connectors, this call may block if the request has been suspended (startAsync called).

Returns:
true if handling is complete, false if the request should be handled again (eg because of a resume that happened before unhandle was called)
 
     protected boolean unhandle()
     {
         synchronized (this)
         {
             switch()
             {
                 case :
                 case :
                     =;
                     return true;
 
                 case :
                     throw new IllegalStateException(this.getStatusString());
 
                 case :
                     =false;
                     =;
                     scheduleTimeout(); // could block and change state.
                     if (==)
                         return true;
                     else if (==)
                     {
                         =;
                         return true;
                     }         
                     =false;
                     =;
                     return false
 
                 case :
                     =false;
                     =;
                     return false
 
                 case :
                     =false;
                     =;
                     return true;
 
                 default:
                     throw new IllegalStateException(this.getStatusString());
             }
         }
     }
 
     /* ------------------------------------------------------------ */
     public void dispatch()
     {
         boolean dispatch=false;
         synchronized (this)
         {
             switch()
             {
                 case :
                     =;
                     =true;
                     return;
 
                 case :
                     dispatch=!;
                     =;
                     =true;
                     break;
                     
                 case :
                     return;
                     
                 default:
                     throw new IllegalStateException(this.getStatusString());
             }
         }
         
         if (dispatch)
         {
             cancelTimeout();
             scheduleDispatch();
         }
     }
 
     /* ------------------------------------------------------------ */
     protected void expired()
     {
         final List<ContinuationListenercListeners;
         final List<AsyncListeneraListeners;
         synchronized (this)
         {
             switch()
             {
                 case :
                 case :
                     cListeners=;
                     aListeners=;
                     break;
                 default:
                     cListeners=null;
                     aListeners=null;
                     return;
             }
             =true;
         }
         
         if (aListeners!=null)
         {
             for (AsyncListener listener : aListeners)
             {
                 try
                 {
                     listener.onTimeout();
                 }
                 catch(Exception e)
                 {
                     .warn(e);
                 }
             }
         }
         if (cListeners!=null)
         {
             for (ContinuationListener listener : cListeners)
             {
                 try
                 {
                     listener.onTimeout(this);
                 }
                 catch(Exception e)
                 {
                     .warn(e);
                 }
             }
         }
             
            
         
         synchronized (this)
         {
             switch()
             {
                 case :
                 case :
                     if (
                         dispatch();
                    else
                         // TODO maybe error dispatch?
                         complete();
             }
         }
 
         scheduleDispatch();
     }
     
     /* ------------------------------------------------------------ */
     /* (non-Javadoc)
      * @see javax.servlet.ServletRequest#complete()
      */
     public void complete()
     {
         // just like resume, except don't set _resumed=true;
         boolean dispatch=false;
         synchronized (this)
         {
             switch()
             {
                 case :
                 case :
                     throw new IllegalStateException(this.getStatusString());
 
                 case :
                     =;
                     return;
                     
                 case :
                     =;
                     dispatch=!;
                     break;
                     
                 default:
                     throw new IllegalStateException(this.getStatusString());
             }
         }
         
         if (dispatch)
         {
             cancelTimeout();
             scheduleDispatch();
         }
     }
 
     /* ------------------------------------------------------------ */
     @Override
     public <T extends AsyncListener> T createListener(Class<T> clazzthrows ServletException 
     {
         try
         {
             // TODO inject
             return clazz.newInstance();
         }
         catch(Exception e)
         {
             throw new ServletException(e);
         }
     }
 
 
     /* ------------------------------------------------------------ */
     /* (non-Javadoc)
      * @see javax.servlet.ServletRequest#complete()
      */
     protected void doComplete(Throwable ex)
     {
         final List<ContinuationListenercListeners;
         final List<AsyncListeneraListeners;
         synchronized (this)
         {
             switch()
             {
                 case :
                     =;
                     cListeners=;
                     aListeners=;
                     break;
                     
                 default:
                     cListeners=null;
                     aListeners=null;
                     throw new IllegalStateException(this.getStatusString());
             }
         }
         
         if (aListeners!=null)
         {
             for (AsyncListener listener : aListeners)
             {
                 try
                 {
                     if (ex!=null)
                     {
                         .getSuppliedRequest().setAttribute(.,ex);
                         .getSuppliedRequest().setAttribute(.,ex.getMessage());
                         listener.onError();
                     }
                     else
                         listener.onComplete();
                 }
                 catch(Exception e)
                 {
                     .warn(e);
                 }
             }
         }
         if (cListeners!=null)
         {
             for (ContinuationListener listener : cListeners)
             {
                 try
                 {
                     listener.onComplete(this);
                 }
                 catch(Exception e)
                 {
                     .warn(e);
                 }
             }
         }
     }
 
     /* ------------------------------------------------------------ */
     protected void recycle()
     {
         synchronized (this)
         {
             switch()
             {
                 case :
                 case :
                     throw new IllegalStateException(getStatusString());
                 default:
                     =;
             }
              = true;
             =false;
             =false;
             =false;
             cancelTimeout();
             =;
             =null;
         }
     }    
     
     /* ------------------------------------------------------------ */
     public void cancel()
     {
         synchronized (this)
         {
             cancelTimeout();
             =null;
         }
     }
 
     /* ------------------------------------------------------------ */
     protected void scheduleDispatch()
     {
         EndPoint endp=.getEndPoint();
         if (!endp.isBlocking())
         {
             ((AsyncEndPoint)endp).asyncDispatch();
         }
     }
 
     /* ------------------------------------------------------------ */
     protected void scheduleTimeout()
     {
         EndPoint endp=.getEndPoint();
         if (>0)
         {
             if (endp.isBlocking())
             {
                 synchronized(this)
                 {
                      = System.currentTimeMillis()+;
                     long wait=;
                     while (>0 && wait>0 && .getServer().isRunning())
                     {
                         try
                         {
                             this.wait(wait);
                         }
                         catch (InterruptedException e)
                         {
                             .ignore(e);
                         }
                         wait=-System.currentTimeMillis();
                     }
 
                     if (>0 && wait<=0 && .getServer().isRunning())
                     {
                         expired();
                     }
                 }            
             }
             else
             {
                 ((AsyncEndPoint)endp).scheduleTimeout(.,);
             }
         }
     }
 
     /* ------------------------------------------------------------ */
     protected void cancelTimeout()
     {
         EndPoint endp=.getEndPoint();
         if (endp.isBlocking())
         {
             synchronized(this)
             {
                 =0;
                 this.notifyAll();
             }
         }
         else 
         {
             final AsyncEventState event=;
             if (event!=null)
             {
                 ((AsyncEndPoint)endp).cancelTimeout(event._timeout);
             }
         }
     }
 
     /* ------------------------------------------------------------ */
     public boolean isCompleting()
     {
         synchronized (this)
         {
             return ==;
         }
     }
     
     /* ------------------------------------------------------------ */
     boolean isUncompleted()
     {
         synchronized (this)
         {
             return ==;
         }
     } 
     
     /* ------------------------------------------------------------ */
     public boolean isComplete()
     {
         synchronized (this)
         {
             return ==;
         }
     }
 
 
     /* ------------------------------------------------------------ */
     public boolean isAsyncStarted()
     {
         synchronized (this)
         {
             switch()
             {
                 case :
                 case :
                 case :
                 case :
                     return true;
 
                 default:
                     return false;
             }
         }
     }
 
 
     /* ------------------------------------------------------------ */
     public boolean isAsync()
     {
         synchronized (this)
         {
             switch()
             {
                 case :
                 case :
                 case :
                 case :
                     return false;
 
                 default:
                     return true;
             }
         }
     }
 
     /* ------------------------------------------------------------ */
     public void dispatch(ServletContext contextString path)
     {
         .=context;
         .=path;
         dispatch();
     }
 
     /* ------------------------------------------------------------ */
     public void dispatch(String path)
     {
         .=path;
         dispatch();
     }
 
     /* ------------------------------------------------------------ */
     public Request getBaseRequest()
     {
         return .getRequest();
     }
     
     /* ------------------------------------------------------------ */
     public ServletRequest getRequest()
     {
         if (!=null)
             return .getSuppliedRequest();
         return .getRequest();
     }
 
     /* ------------------------------------------------------------ */
     public ServletResponse getResponse()
     {
         if ( && !=null && .getSuppliedResponse()!=null)
             return .getSuppliedResponse();
         return .getResponse();
     }
 
     /* ------------------------------------------------------------ */
     public void start(final Runnable run)
     {
         final AsyncEventState event=;
         if (event!=null)
         {
             .getServer().getThreadPool().dispatch(new Runnable()
             {
                 public void run()
                 {
                     ((Context)event.getServletContext()).getContextHandler().handle(run);
                 }
             });
         }
     }
 
     /* ------------------------------------------------------------ */
     public boolean hasOriginalRequestAndResponse()
     {
         synchronized (this)
         {
             return (!=null && .getSuppliedRequest()==. && .getSuppliedResponse()==.);
         }
     }
 
     /* ------------------------------------------------------------ */
     {
         final AsyncEventState event=;
         if (event!=null)
             return ((Context)event.getServletContext()).getContextHandler();
         return null;
     }
 
 
     /* ------------------------------------------------------------ */
    
 
     public boolean isResumed()
     {
         synchronized (this)
         {
             return ;
         }
     }
     /* ------------------------------------------------------------ */
    
 
     public boolean isExpired()
     {
         synchronized (this)
         {
             return ;
         }
     }
 
     /* ------------------------------------------------------------ */
    
 
     public void resume()
     {
         dispatch();
     }
     
 
 
     /* ------------------------------------------------------------ */
     protected void suspend(final ServletContext context,
             final ServletRequest request,
             final ServletResponse response)
     {
         synchronized (this)
         {
             =!(response instanceof Response);
             doSuspend(context,request,response);
             if (request instanceof HttpServletRequest)
             {
                 . = URIUtil.addPaths(((HttpServletRequest)request).getServletPath(),((HttpServletRequest)request).getPathInfo());
             }
         }
     }
 
     
     /* ------------------------------------------------------------ */
    
 
     public void suspend(ServletResponse response)
     {
         =true;
         =!(response instanceof Response);
     }
 
     /* ------------------------------------------------------------ */
    
 
     public void suspend()
     {
         =false;
         =true;
     }
 
     /* ------------------------------------------------------------ */
    
 
     {
         if ( && !=null && .getSuppliedResponse()!=null)
             return .getSuppliedResponse();
         return .getResponse();
     }
 
     /* ------------------------------------------------------------ */
    
 
     public Object getAttribute(String name)
     {
         return .getRequest().getAttribute(name);
     }
 
     /* ------------------------------------------------------------ */
    
    public void removeAttribute(String name)
    {
        .getRequest().removeAttribute(name);
    }
    /* ------------------------------------------------------------ */
    
    public void setAttribute(String nameObject attribute)
    {
        .getRequest().setAttribute(name,attribute);
    }
    /* ------------------------------------------------------------ */
    
    public void undispatch()
    {
        if (isSuspended())
        {
            if (.isDebugEnabled())
                throw new ContinuationThrowable();
            else
                throw ;
        }
        throw new IllegalStateException("!suspended");
    }
    /* ------------------------------------------------------------ */
    /* ------------------------------------------------------------ */
    public class AsyncTimeout extends Timeout.Task implements Runnable
    {
            @Override
            public void expired()
            {
                AsyncContinuation.this.expired();
            }
            @Override
            public void run()
            {
                AsyncContinuation.this.expired();
            }
    }
    /* ------------------------------------------------------------ */
    /* ------------------------------------------------------------ */
    public class AsyncEventState extends AsyncEvent
    {
        private final ServletContext _suspendedContext;
        private ServletContext _dispatchContext;
        private String _pathInContext;
        private Timeout.Task _timeout=  new AsyncTimeout();
        
        public AsyncEventState(ServletContext contextServletRequest requestServletResponse response)
        {
            super(AsyncContinuation.thisrequest,response);
            =context;
            // Get the base request So we can remember the initial paths
            Request r=.getRequest();
            // If we haven't been async dispatched before
            if (r.getAttribute(.)==null)
            {
                // We are setting these attributes during startAsync, when the spec implies that 
                // they are only available after a call to AsyncContext.dispatch(...);
                
                // have we been forwarded before?
                String uri=(String)r.getAttribute(.);
                if (uri!=null)
                {
                    r.setAttribute(.,uri);
                }
                else
                {
                    r.setAttribute(.,r.getRequestURI());
                    r.setAttribute(.,r.getContextPath());
                    r.setAttribute(.,r.getServletPath());
                    r.setAttribute(.,r.getPathInfo());
                    r.setAttribute(.,r.getQueryString());
                }
            }
        }
        
        public ServletContext getSuspendedContext()
        {
            return ;
        }
        
        public ServletContext getDispatchContext()
        {
            return ;
        }
        
        public ServletContext getServletContext()
        {
            return ==null?:;
        }
        
        /* ------------------------------------------------------------ */
        

Returns:
The path in the context
        public String getPath()
        {
            return ;
        }
    }