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