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