View Javadoc

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