1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.continuation;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import javax.servlet.AsyncContext;
26 import javax.servlet.AsyncEvent;
27 import javax.servlet.AsyncListener;
28 import javax.servlet.DispatcherType;
29 import javax.servlet.ServletRequest;
30 import javax.servlet.ServletResponse;
31 import javax.servlet.ServletResponseWrapper;
32
33
34
35
36
37
38
39
40 public class Servlet3Continuation implements Continuation
41 {
42
43
44 private final static ContinuationThrowable __exception = new ContinuationThrowable();
45
46 private final ServletRequest _request;
47 private ServletResponse _response;
48 private AsyncContext _context;
49 private final List<AsyncListener> _listeners=new ArrayList<AsyncListener>();
50 private volatile boolean _initial=true;
51 private volatile boolean _resumed=false;
52 private volatile boolean _expired=false;
53 private volatile boolean _responseWrapped=false;
54
55 private long _timeoutMs=-1;
56
57
58 public Servlet3Continuation(ServletRequest request)
59 {
60 _request=request;
61
62 _listeners.add(new AsyncListener()
63 {
64 @Override
65 public void onComplete(AsyncEvent event) throws IOException
66 {
67 }
68
69 @Override
70 public void onError(AsyncEvent event) throws IOException
71 {
72 }
73
74 @Override
75 public void onStartAsync(AsyncEvent event) throws IOException
76 {
77 event.getAsyncContext().addListener(this);
78 }
79
80 @Override
81 public void onTimeout(AsyncEvent event) throws IOException
82 {
83 _initial=false;
84 event.getAsyncContext().dispatch();
85 }
86 });
87 }
88
89
90 @Override
91 public void addContinuationListener(final ContinuationListener listener)
92 {
93 AsyncListener wrapped = new AsyncListener()
94 {
95 @Override
96 public void onComplete(final AsyncEvent event) throws IOException
97 {
98 listener.onComplete(Servlet3Continuation.this);
99 }
100
101 @Override
102 public void onError(AsyncEvent event) throws IOException
103 {
104 listener.onComplete(Servlet3Continuation.this);
105 }
106
107 @Override
108 public void onStartAsync(AsyncEvent event) throws IOException
109 {
110 event.getAsyncContext().addListener(this);
111 }
112
113 @Override
114 public void onTimeout(AsyncEvent event) throws IOException
115 {
116 _expired=true;
117 listener.onTimeout(Servlet3Continuation.this);
118 }
119 };
120
121 if (_context!=null)
122 _context.addListener(wrapped);
123 else
124 _listeners.add(wrapped);
125 }
126
127
128 @Override
129 public void complete()
130 {
131 AsyncContext context=_context;
132 if (context==null)
133 throw new IllegalStateException();
134 _context.complete();
135 }
136
137
138 @Override
139 public ServletResponse getServletResponse()
140 {
141 return _response;
142 }
143
144
145 @Override
146 public boolean isExpired()
147 {
148 return _expired;
149 }
150
151
152 @Override
153 public boolean isInitial()
154 {
155 return _initial&&_request.getDispatcherType()!=DispatcherType.ASYNC;
156 }
157
158
159 @Override
160 public boolean isResumed()
161 {
162 return _resumed;
163 }
164
165
166 @Override
167 public boolean isSuspended()
168 {
169 return _request.isAsyncStarted();
170 }
171
172
173 public void keepWrappers()
174 {
175 _responseWrapped=true;
176 }
177
178
179 @Override
180 public void resume()
181 {
182 AsyncContext context=_context;
183 if (context==null)
184 throw new IllegalStateException();
185 _resumed=true;
186 _context.dispatch();
187 }
188
189
190 @Override
191 public void setTimeout(long timeoutMs)
192 {
193 _timeoutMs=timeoutMs;
194 if (_context!=null)
195 _context.setTimeout(timeoutMs);
196 }
197
198
199 @Override
200 public void suspend(ServletResponse response)
201 {
202 _response=response;
203 _responseWrapped=response instanceof ServletResponseWrapper;
204 _resumed=false;
205 _expired=false;
206 _context=_request.startAsync();
207 _context.setTimeout(_timeoutMs);
208
209 for (AsyncListener listener:_listeners)
210 _context.addListener(listener);
211 _listeners.clear();
212 }
213
214
215 @Override
216 public void suspend()
217 {
218 _resumed=false;
219 _expired=false;
220 _context=_request.startAsync();
221 _context.setTimeout(_timeoutMs);
222
223 for (AsyncListener listener:_listeners)
224 _context.addListener(listener);
225 _listeners.clear();
226 }
227
228
229 @Override
230 public boolean isResponseWrapped()
231 {
232 return _responseWrapped;
233 }
234
235
236
237
238
239 @Override
240 public Object getAttribute(String name)
241 {
242 return _request.getAttribute(name);
243 }
244
245
246
247
248
249 @Override
250 public void removeAttribute(String name)
251 {
252 _request.removeAttribute(name);
253 }
254
255
256
257
258
259 @Override
260 public void setAttribute(String name, Object attribute)
261 {
262 _request.setAttribute(name,attribute);
263 }
264
265
266
267
268
269 @Override
270 public void undispatch()
271 {
272 if (isSuspended())
273 {
274 if (ContinuationFilter.__debug)
275 throw new ContinuationThrowable();
276 throw __exception;
277 }
278 throw new IllegalStateException("!suspended");
279 }
280 }