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