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