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