View Javadoc

1   package org.eclipse.jetty.continuation;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   import javax.servlet.ServletRequest;
6   import javax.servlet.ServletResponse;
7   import javax.servlet.ServletResponseWrapper;
8   
9   
10  
11  /* ------------------------------------------------------------ */
12  /**
13   * This implementation of Continuation is used by {@link ContinuationSupport}
14   * when it detects that the application is deployed in a jetty-6 server.
15   * This continuation requires the {@link ContinuationFilter} to be deployed.
16   */
17  public class Jetty6Continuation implements ContinuationFilter.FilteredContinuation
18  {
19      // Exception reused for all continuations
20      // Turn on debug in ContinuationFilter to see real stack trace.
21      private final static ContinuationThrowable __exception = new ContinuationThrowable();
22      
23      private final ServletRequest _request;
24      private ServletResponse _response;
25      private final org.mortbay.util.ajax.Continuation _j6Continuation;
26  
27      private Throwable _retry;
28      private int _timeout;
29      private boolean _initial=true;
30      private volatile boolean _completed=false;
31      private volatile boolean _resumed=false;
32      private volatile boolean _expired=false;
33      private boolean _responseWrapped=false;
34      private List<ContinuationListener> _listeners;
35  
36      public Jetty6Continuation(ServletRequest request, org.mortbay.util.ajax.Continuation continuation)
37      {
38          _request=request;
39          _j6Continuation=continuation;
40      }
41  
42      public void addContinuationListener(final ContinuationListener listener)
43      {
44          if (_listeners==null)
45              _listeners=new ArrayList<ContinuationListener>();
46          _listeners.add(listener);
47      }
48  
49      public void complete()
50      {
51          synchronized(this)
52          {
53              if (_resumed)
54                  throw new IllegalStateException();
55              _completed=true;
56              if (_j6Continuation.isPending())
57                  _j6Continuation.resume();
58          }
59      }
60      
61      /* ------------------------------------------------------------ */
62      /**
63       * @see org.eclipse.jetty.continuation.Continuation#getAttribute(java.lang.String)
64       */
65      public Object getAttribute(String name)
66      {
67          return _request.getAttribute(name);
68      }
69  
70      /* ------------------------------------------------------------ */
71      /**
72       * @see org.eclipse.jetty.continuation.Continuation#removeAttribute(java.lang.String)
73       */
74      public void removeAttribute(String name)
75      {
76          _request.removeAttribute(name);
77      }
78  
79      /* ------------------------------------------------------------ */
80      /**
81       * @see org.eclipse.jetty.continuation.Continuation#setAttribute(java.lang.String, java.lang.Object)
82       */
83      public void setAttribute(String name, Object attribute)
84      {
85          _request.setAttribute(name,attribute);
86      }
87  
88      /* ------------------------------------------------------------ */
89      public ServletResponse getServletResponse()
90      {
91          return _response;
92      }
93  
94      /* ------------------------------------------------------------ */
95      public boolean isExpired()
96      {
97          return _expired;
98      }
99  
100     /* ------------------------------------------------------------ */
101     public boolean isInitial()
102     {
103         return _initial;
104     }
105 
106     /* ------------------------------------------------------------ */
107     public boolean isResumed()
108     {
109         return _resumed;
110     }
111 
112     /* ------------------------------------------------------------ */
113     public boolean isSuspended()
114     {
115         return _retry!=null;
116     }
117 
118     /* ------------------------------------------------------------ */
119     public void resume()
120     {
121         synchronized(this)
122         {
123             if (_completed)
124                 throw new IllegalStateException();
125             _resumed=true;
126             if (_j6Continuation.isPending())
127                 _j6Continuation.resume();
128         }
129     }
130 
131     /* ------------------------------------------------------------ */
132     public void setTimeout(long timeoutMs)
133     {
134         _timeout=(timeoutMs>Integer.MAX_VALUE)?Integer.MAX_VALUE:(int)timeoutMs;
135     }
136 
137     /* ------------------------------------------------------------ */
138     /**
139      * @see org.eclipse.jetty.continuation.Continuation#suspend(javax.servlet.ServletResponse)
140      */
141     public void suspend(ServletResponse response)
142     {
143         try
144         {
145             _response=response;
146             _responseWrapped=_response instanceof ServletResponseWrapper;
147             _resumed=false;
148             _expired=false;
149             _completed=false;
150             _j6Continuation.suspend(_timeout);
151         }
152         catch(Throwable retry)
153         {
154             _retry=retry;
155         }
156     }
157 
158     /* ------------------------------------------------------------ */
159     public void suspend()
160     {
161         try
162         {
163             _response=null;
164             _responseWrapped=false;
165             _resumed=false;
166             _expired=false;
167             _completed=false;
168             _j6Continuation.suspend(_timeout);
169         }
170         catch(Throwable retry)
171         {
172             _retry=retry;
173         }
174     }
175 
176     /* ------------------------------------------------------------ */
177     public boolean isResponseWrapped()
178     {
179         return _responseWrapped;
180     }
181 
182     /* ------------------------------------------------------------ */
183     /**
184      * @see org.eclipse.jetty.continuation.Continuation#undispatch()
185      */
186     public void undispatch()
187     {
188         if (isSuspended())
189         {
190             if (ContinuationFilter.__debug)
191                 throw new ContinuationThrowable();
192             throw __exception;
193         }
194         throw new IllegalStateException("!suspended");
195     }
196 
197     /* ------------------------------------------------------------ */
198     public boolean enter(ServletResponse response)
199     {
200         _response=response;
201         _expired=!_j6Continuation.isResumed();
202 
203         if (_initial)
204             return true;
205 
206         _j6Continuation.reset();
207 
208         if (_expired)
209         {
210             if (_listeners!=null)
211             {
212                 for (ContinuationListener l: _listeners)
213                     l.onTimeout(this);
214             }
215 
216             return !_completed;
217         }
218 
219         return true;
220     }
221 
222     /* ------------------------------------------------------------ */
223     public boolean exit()
224     {
225         _initial=false;
226 
227         Throwable th=_retry;
228         _retry=null;
229         if (th instanceof ThreadDeath)
230             throw (ThreadDeath)th;
231         if (th instanceof Error)
232             throw (Error)th;
233         if (th instanceof RuntimeException)
234             throw (RuntimeException)th;
235 
236         if (_listeners!=null)
237         {
238             for (ContinuationListener l: _listeners)
239                 l.onComplete(this);
240         }
241         
242         return true;
243     }
244 }