1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.eclipse.jetty.continuation;
16
17 import java.util.ArrayList;
18
19 import javax.servlet.ServletRequest;
20 import javax.servlet.ServletResponse;
21 import javax.servlet.ServletResponseWrapper;
22
23
24
25
26
27
28
29
30 class FauxContinuation implements Continuation
31 {
32
33
34 private final static ContinuationThrowable __exception = new ContinuationThrowable();
35
36 private static final int __HANDLING=1;
37 private static final int __SUSPENDING=2;
38 private static final int __RESUMING=3;
39 private static final int __COMPLETING=4;
40 private static final int __SUSPENDED=5;
41 private static final int __UNSUSPENDING=6;
42 private static final int __COMPLETE=7;
43
44 private final ServletRequest _request;
45 private ServletResponse _response;
46
47 private int _state=__HANDLING;
48 private boolean _initial=true;
49 private boolean _resumed=false;
50 private boolean _timeout=false;
51 private boolean _responseWrapped=false;
52 private long _timeoutMs=30000;
53
54 private ArrayList<ContinuationListener> _listeners;
55
56 FauxContinuation(final ServletRequest request)
57 {
58 _request=request;
59 }
60
61
62 public void onComplete()
63 {
64 if (_listeners!=null)
65 for (ContinuationListener l:_listeners)
66 l.onComplete(this);
67 }
68
69
70 public void onTimeout()
71 {
72 if (_listeners!=null)
73 for (ContinuationListener l:_listeners)
74 l.onTimeout(this);
75 }
76
77
78
79
80
81 public boolean isResponseWrapped()
82 {
83 return _responseWrapped;
84 }
85
86
87 public boolean isInitial()
88 {
89 synchronized(this)
90 {
91 return _initial;
92 }
93 }
94
95
96 public boolean isResumed()
97 {
98 synchronized(this)
99 {
100 return _resumed;
101 }
102 }
103
104
105 public boolean isSuspended()
106 {
107 synchronized(this)
108 {
109 switch(_state)
110 {
111 case __HANDLING:
112 return false;
113 case __SUSPENDING:
114 case __RESUMING:
115 case __COMPLETING:
116 case __SUSPENDED:
117 return true;
118 case __UNSUSPENDING:
119 default:
120 return false;
121 }
122 }
123 }
124
125
126 public boolean isExpired()
127 {
128 synchronized(this)
129 {
130 return _timeout;
131 }
132 }
133
134
135 public void setTimeout(long timeoutMs)
136 {
137 _timeoutMs = timeoutMs;
138 }
139
140
141 public void suspend(ServletResponse response)
142 {
143 _response=response;
144 _responseWrapped=response instanceof ServletResponseWrapper;
145 suspend();
146 }
147
148
149 public void suspend()
150 {
151 synchronized (this)
152 {
153 switch(_state)
154 {
155 case __HANDLING:
156 _timeout=false;
157 _resumed=false;
158 _state=__SUSPENDING;
159 return;
160
161 case __SUSPENDING:
162 case __RESUMING:
163 return;
164
165 case __COMPLETING:
166 case __SUSPENDED:
167 case __UNSUSPENDING:
168 throw new IllegalStateException(this.getStatusString());
169
170 default:
171 throw new IllegalStateException(""+_state);
172 }
173
174 }
175 }
176
177
178
179
180
181
182 public void resume()
183 {
184 synchronized (this)
185 {
186 switch(_state)
187 {
188 case __HANDLING:
189 _resumed=true;
190 return;
191
192 case __SUSPENDING:
193 _resumed=true;
194 _state=__RESUMING;
195 return;
196
197 case __RESUMING:
198 case __COMPLETING:
199 return;
200
201 case __SUSPENDED:
202 fauxResume();
203 _resumed=true;
204 _state=__UNSUSPENDING;
205 break;
206
207 case __UNSUSPENDING:
208 _resumed=true;
209 return;
210
211 default:
212 throw new IllegalStateException(this.getStatusString());
213 }
214 }
215
216 }
217
218
219
220 public void complete()
221 {
222
223 synchronized (this)
224 {
225 switch(_state)
226 {
227 case __HANDLING:
228 throw new IllegalStateException(this.getStatusString());
229
230 case __SUSPENDING:
231 _state=__COMPLETING;
232 break;
233
234 case __RESUMING:
235 break;
236
237 case __COMPLETING:
238 return;
239
240 case __SUSPENDED:
241 _state=__COMPLETING;
242 fauxResume();
243 break;
244
245 case __UNSUSPENDING:
246 return;
247
248 default:
249 throw new IllegalStateException(this.getStatusString());
250 }
251 }
252
253 }
254
255
256
257
258
259 public ServletResponse getServletResponse()
260 {
261 return _response;
262 }
263
264
265
266 void handling()
267 {
268 synchronized (this)
269 {
270 _responseWrapped=false;
271 switch(_state)
272 {
273 case __HANDLING:
274 throw new IllegalStateException(this.getStatusString());
275
276 case __SUSPENDING:
277 case __RESUMING:
278 throw new IllegalStateException(this.getStatusString());
279
280 case __COMPLETING:
281 return;
282
283 case __SUSPENDED:
284 fauxResume();
285 case __UNSUSPENDING:
286 _state=__HANDLING;
287 return;
288
289 default:
290 throw new IllegalStateException(""+_state);
291 }
292
293 }
294 }
295
296
297
298
299
300 public boolean handleSuspension()
301 {
302 synchronized (this)
303 {
304 switch(_state)
305 {
306 case __HANDLING:
307 _state=__COMPLETE;
308 return true;
309
310 case __SUSPENDING:
311 _initial=false;
312 _state=__SUSPENDED;
313 fauxSuspend();
314 if (_state==__SUSPENDED || _state==__COMPLETING)
315 return true;
316
317 _initial=false;
318 _state=__HANDLING;
319 return false;
320
321 case __RESUMING:
322 _initial=false;
323 _state=__HANDLING;
324 return false;
325
326 case __COMPLETING:
327 _initial=false;
328 _state=__COMPLETE;
329 return true;
330
331 case __SUSPENDED:
332 case __UNSUSPENDING:
333 default:
334 throw new IllegalStateException(this.getStatusString());
335 }
336 }
337 }
338
339
340 protected void expire()
341 {
342
343
344 synchronized (this)
345 {
346 _timeout=true;
347 }
348
349 onTimeout();
350
351 synchronized (this)
352 {
353 switch(_state)
354 {
355 case __HANDLING:
356 return;
357
358 case __SUSPENDING:
359 _timeout=true;
360 _state=__RESUMING;
361 fauxResume();
362 return;
363
364 case __RESUMING:
365 return;
366
367 case __COMPLETING:
368 return;
369
370 case __SUSPENDED:
371 _timeout=true;
372 _state=__UNSUSPENDING;
373 break;
374
375 case __UNSUSPENDING:
376 _timeout=true;
377 return;
378
379 default:
380 throw new IllegalStateException(this.getStatusString());
381 }
382 }
383 }
384
385 private void fauxSuspend()
386 {
387 long expire_at = System.currentTimeMillis()+_timeoutMs;
388 long wait=_timeoutMs;
389 while (_timeoutMs>0 && wait>0)
390 {
391 try
392 {
393 this.wait(wait);
394 }
395 catch (InterruptedException e)
396 {
397 break;
398 }
399 wait=expire_at-System.currentTimeMillis();
400 }
401
402 if (_timeoutMs>0 && wait<=0)
403 expire();
404 }
405
406 private void fauxResume()
407 {
408 _timeoutMs=0;
409 this.notifyAll();
410 }
411
412 public String toString()
413 {
414 return getStatusString();
415 }
416
417 String getStatusString()
418 {
419 synchronized (this)
420 {
421 return
422 ((_state==__HANDLING)?"HANDLING":
423 (_state==__SUSPENDING)?"SUSPENDING":
424 (_state==__SUSPENDED)?"SUSPENDED":
425 (_state==__RESUMING)?"RESUMING":
426 (_state==__UNSUSPENDING)?"UNSUSPENDING":
427 (_state==__COMPLETING)?"COMPLETING":
428 ("???"+_state))+
429 (_initial?",initial":"")+
430 (_resumed?",resumed":"")+
431 (_timeout?",timeout":"");
432 }
433 }
434
435
436 public void addContinuationListener(ContinuationListener listener)
437 {
438 if (_listeners==null)
439 _listeners=new ArrayList<ContinuationListener>();
440 _listeners.add(listener);
441
442 }
443
444
445
446
447
448 public Object getAttribute(String name)
449 {
450 return _request.getAttribute(name);
451 }
452
453
454
455
456
457 public void removeAttribute(String name)
458 {
459 _request.removeAttribute(name);
460 }
461
462
463
464
465
466 public void setAttribute(String name, Object attribute)
467 {
468 _request.setAttribute(name,attribute);
469 }
470
471
472
473
474
475 public void undispatch()
476 {
477 if (isSuspended())
478 {
479 if (ContinuationFilter.__debug)
480 throw new ContinuationThrowable();
481 throw __exception;
482 }
483 throw new IllegalStateException("!suspended");
484
485 }
486 }