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, AsyncListener
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<ContinuationListener> _listeners=new ArrayList<ContinuationListener>();
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
63
64 @Override
65 public void addContinuationListener(final ContinuationListener listener)
66 {
67 _listeners.add(listener);
68 }
69
70
71 @Override
72 public void complete()
73 {
74 AsyncContext context=_context;
75 if (context==null)
76 throw new IllegalStateException();
77 _context.complete();
78 }
79
80
81 @Override
82 public ServletResponse getServletResponse()
83 {
84 return _response;
85 }
86
87
88 @Override
89 public boolean isExpired()
90 {
91 return _expired;
92 }
93
94
95 @Override
96 public boolean isInitial()
97 {
98 return _initial&&_request.getDispatcherType()!=DispatcherType.ASYNC;
99 }
100
101
102 @Override
103 public boolean isResumed()
104 {
105 return _resumed;
106 }
107
108
109 @Override
110 public boolean isSuspended()
111 {
112 if (_request.isAsyncStarted())
113 return true;
114 try
115 {
116 return _request.getAsyncContext()!=null;
117 }
118 catch(IllegalStateException e)
119 {
120
121 }
122 return false;
123 }
124
125
126 public void keepWrappers()
127 {
128 _responseWrapped=true;
129 }
130
131
132 @Override
133 public void resume()
134 {
135 AsyncContext context=_context;
136 if (context==null)
137 throw new IllegalStateException();
138 _resumed=true;
139 _context.dispatch();
140 }
141
142
143 @Override
144 public void setTimeout(long timeoutMs)
145 {
146 _timeoutMs=timeoutMs;
147 if (_context!=null)
148 _context.setTimeout(timeoutMs);
149 }
150
151
152 @Override
153 public void suspend(ServletResponse response)
154 {
155 _response=response;
156 _responseWrapped=response instanceof ServletResponseWrapper;
157 _resumed=false;
158 _expired=false;
159 _context=_request.startAsync();
160 _context.setTimeout(_timeoutMs);
161 _context.addListener(this);
162 }
163
164
165 @Override
166 public void suspend()
167 {
168 _resumed=false;
169 _expired=false;
170 _context=_request.startAsync();
171 _context.setTimeout(_timeoutMs);
172 _context.addListener(this);
173 }
174
175
176 @Override
177 public boolean isResponseWrapped()
178 {
179 return _responseWrapped;
180 }
181
182
183
184
185
186 @Override
187 public Object getAttribute(String name)
188 {
189 return _request.getAttribute(name);
190 }
191
192
193
194
195
196 @Override
197 public void removeAttribute(String name)
198 {
199 _request.removeAttribute(name);
200 }
201
202
203
204
205
206 @Override
207 public void setAttribute(String name, Object attribute)
208 {
209 _request.setAttribute(name,attribute);
210 }
211
212
213
214
215
216 @Override
217 public void undispatch()
218 {
219 if (isSuspended())
220 {
221 if (ContinuationFilter.__debug)
222 throw new ContinuationThrowable();
223 throw __exception;
224 }
225 throw new IllegalStateException("!suspended");
226 }
227
228
229
230 @Override
231 public void onComplete(AsyncEvent event) throws IOException
232 {
233 for (ContinuationListener listener:_listeners)
234 listener.onComplete(this);
235 }
236
237
238 @Override
239 public void onError(AsyncEvent event) throws IOException
240 {
241 }
242
243
244 @Override
245 public void onStartAsync(AsyncEvent event) throws IOException
246 {
247 _initial=false;
248 }
249
250
251 @Override
252 public void onTimeout(AsyncEvent event) throws IOException
253 {
254 _initial=false;
255 _expired=true;
256 for (ContinuationListener listener:_listeners)
257 listener.onTimeout(this);
258 if (event.getSuppliedRequest().isAsyncStarted())
259 event.getAsyncContext().dispatch();
260 }
261 }