blob: 3ed177d85d7a4a6b621ff925a4737bf8003ebda5 [file] [log] [blame]
Jake Slack03928ae2014-05-13 18:41:56 -07001//
2// ========================================================================
3// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4// ------------------------------------------------------------------------
5// All rights reserved. This program and the accompanying materials
6// are made available under the terms of the Eclipse Public License v1.0
7// and Apache License v2.0 which accompanies this distribution.
8//
9// The Eclipse Public License is available at
10// http://www.eclipse.org/legal/epl-v10.html
11//
12// The Apache License v2.0 is available at
13// http://www.opensource.org/licenses/apache2.0.php
14//
15// You may elect to redistribute this code under either of these licenses.
16// ========================================================================
17//
18
19package org.eclipse.jetty.continuation;
20
21import java.util.ArrayList;
22import java.util.List;
23
24import javax.servlet.ServletRequest;
25import javax.servlet.ServletResponse;
26import javax.servlet.ServletResponseWrapper;
27
28import org.mortbay.log.Log;
29import org.mortbay.log.Logger;
30
31/* ------------------------------------------------------------ */
32/**
33 * This implementation of Continuation is used by {@link ContinuationSupport}
34 * when it detects that the application is deployed in a jetty-6 server.
35 * This continuation requires the {@link ContinuationFilter} to be deployed.
36 */
37public class Jetty6Continuation implements ContinuationFilter.FilteredContinuation
38{
39 private static final Logger LOG = Log.getLogger(Jetty6Continuation.class.getName());
40
41 // Exception reused for all continuations
42 // Turn on debug in ContinuationFilter to see real stack trace.
43 private final static ContinuationThrowable __exception = new ContinuationThrowable();
44
45 private final ServletRequest _request;
46 private ServletResponse _response;
47 private final org.mortbay.util.ajax.Continuation _j6Continuation;
48
49 private Throwable _retry;
50 private int _timeout;
51 private boolean _initial=true;
52 private volatile boolean _completed=false;
53 private volatile boolean _resumed=false;
54 private volatile boolean _expired=false;
55 private boolean _responseWrapped=false;
56 private List<ContinuationListener> _listeners;
57
58 public Jetty6Continuation(ServletRequest request, org.mortbay.util.ajax.Continuation continuation)
59 {
60 if (!ContinuationFilter._initialized)
61 {
62 LOG.warn("!ContinuationFilter installed",null,null);
63 throw new IllegalStateException("!ContinuationFilter installed");
64 }
65 _request=request;
66 _j6Continuation=continuation;
67 }
68
69 public void addContinuationListener(final ContinuationListener listener)
70 {
71 if (_listeners==null)
72 _listeners=new ArrayList<ContinuationListener>();
73 _listeners.add(listener);
74 }
75
76 public void complete()
77 {
78 synchronized(this)
79 {
80 if (_resumed)
81 throw new IllegalStateException();
82 _completed=true;
83 if (_j6Continuation.isPending())
84 _j6Continuation.resume();
85 }
86 }
87
88 /* ------------------------------------------------------------ */
89 /**
90 * @see org.eclipse.jetty.continuation.Continuation#getAttribute(java.lang.String)
91 */
92 public Object getAttribute(String name)
93 {
94 return _request.getAttribute(name);
95 }
96
97 /* ------------------------------------------------------------ */
98 /**
99 * @see org.eclipse.jetty.continuation.Continuation#removeAttribute(java.lang.String)
100 */
101 public void removeAttribute(String name)
102 {
103 _request.removeAttribute(name);
104 }
105
106 /* ------------------------------------------------------------ */
107 /**
108 * @see org.eclipse.jetty.continuation.Continuation#setAttribute(java.lang.String, java.lang.Object)
109 */
110 public void setAttribute(String name, Object attribute)
111 {
112 _request.setAttribute(name,attribute);
113 }
114
115 /* ------------------------------------------------------------ */
116 public ServletResponse getServletResponse()
117 {
118 return _response;
119 }
120
121 /* ------------------------------------------------------------ */
122 public boolean isExpired()
123 {
124 return _expired;
125 }
126
127 /* ------------------------------------------------------------ */
128 public boolean isInitial()
129 {
130 return _initial;
131 }
132
133 /* ------------------------------------------------------------ */
134 public boolean isResumed()
135 {
136 return _resumed;
137 }
138
139 /* ------------------------------------------------------------ */
140 public boolean isSuspended()
141 {
142 return _retry!=null;
143 }
144
145 /* ------------------------------------------------------------ */
146 public void resume()
147 {
148 synchronized(this)
149 {
150 if (_completed)
151 throw new IllegalStateException();
152 _resumed=true;
153 if (_j6Continuation.isPending())
154 _j6Continuation.resume();
155 }
156 }
157
158 /* ------------------------------------------------------------ */
159 public void setTimeout(long timeoutMs)
160 {
161 _timeout=(timeoutMs>Integer.MAX_VALUE)?Integer.MAX_VALUE:(int)timeoutMs;
162 }
163
164 /* ------------------------------------------------------------ */
165 /**
166 * @see org.eclipse.jetty.continuation.Continuation#suspend(javax.servlet.ServletResponse)
167 */
168 public void suspend(ServletResponse response)
169 {
170 try
171 {
172 _response=response;
173 _responseWrapped=_response instanceof ServletResponseWrapper;
174 _resumed=false;
175 _expired=false;
176 _completed=false;
177 _j6Continuation.suspend(_timeout);
178 }
179 catch(Throwable retry)
180 {
181 _retry=retry;
182 }
183 }
184
185 /* ------------------------------------------------------------ */
186 public void suspend()
187 {
188 try
189 {
190 _response=null;
191 _responseWrapped=false;
192 _resumed=false;
193 _expired=false;
194 _completed=false;
195 _j6Continuation.suspend(_timeout);
196 }
197 catch(Throwable retry)
198 {
199 _retry=retry;
200 }
201 }
202
203 /* ------------------------------------------------------------ */
204 public boolean isResponseWrapped()
205 {
206 return _responseWrapped;
207 }
208
209 /* ------------------------------------------------------------ */
210 /**
211 * @see org.eclipse.jetty.continuation.Continuation#undispatch()
212 */
213 public void undispatch()
214 {
215 if (isSuspended())
216 {
217 if (ContinuationFilter.__debug)
218 throw new ContinuationThrowable();
219 throw __exception;
220 }
221 throw new IllegalStateException("!suspended");
222 }
223
224 /* ------------------------------------------------------------ */
225 public boolean enter(ServletResponse response)
226 {
227 _response=response;
228 _expired=!_j6Continuation.isResumed();
229
230 if (_initial)
231 return true;
232
233 _j6Continuation.reset();
234
235 if (_expired)
236 {
237 if (_listeners!=null)
238 {
239 for (ContinuationListener l: _listeners)
240 l.onTimeout(this);
241 }
242 }
243
244 return !_completed;
245 }
246
247 /* ------------------------------------------------------------ */
248 public boolean exit()
249 {
250 _initial=false;
251
252 Throwable th=_retry;
253 _retry=null;
254 if (th instanceof Error)
255 throw (Error)th;
256 if (th instanceof RuntimeException)
257 throw (RuntimeException)th;
258
259 if (_listeners!=null)
260 {
261 for (ContinuationListener l: _listeners)
262 l.onComplete(this);
263 }
264
265 return true;
266 }
267}