Mercurial Hosting > luan
comparison src/org/eclipse/jetty/continuation/Continuation.java @ 802:3428c60d7cfc
replace jetty jars with source
| author | Franklin Schmidt <fschmidt@gmail.com> |
|---|---|
| date | Wed, 07 Sep 2016 21:15:48 -0600 |
| parents | |
| children | 1fc8ee20cb18 |
comparison
equal
deleted
inserted
replaced
| 801:6a21393191c1 | 802:3428c60d7cfc |
|---|---|
| 1 // | |
| 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 | |
| 19 package org.eclipse.jetty.continuation; | |
| 20 | |
| 21 import javax.servlet.Filter; | |
| 22 import javax.servlet.FilterChain; | |
| 23 import javax.servlet.Servlet; | |
| 24 import javax.servlet.ServletRequest; | |
| 25 import javax.servlet.ServletResponse; | |
| 26 import javax.servlet.ServletResponseWrapper; | |
| 27 | |
| 28 /* ------------------------------------------------------------ */ | |
| 29 /** | |
| 30 * Continuation. | |
| 31 * | |
| 32 * A continuation is a mechanism by which a HTTP Request can be suspended and | |
| 33 * restarted after a timeout or an asynchronous event has occurred. | |
| 34 * <p> | |
| 35 * The continuation mechanism is a portable mechanism that will work | |
| 36 * asynchronously without additional configuration of all jetty-7, | |
| 37 * jetty-8 and Servlet 3.0 containers. With the addition of | |
| 38 * the {@link ContinuationFilter}, the mechanism will also work | |
| 39 * asynchronously on jetty-6 and non-asynchronously on any | |
| 40 * servlet 2.5 container. | |
| 41 * <p> | |
| 42 * The Continuation API is a simplification of the richer async API | |
| 43 * provided by the servlet-3.0 and an enhancement of the continuation | |
| 44 * API that was introduced with jetty-6. | |
| 45 * </p> | |
| 46 * <h1>Continuation Usage</h1> | |
| 47 * <p> | |
| 48 * A continuation object is obtained for a request by calling the | |
| 49 * factory method {@link ContinuationSupport#getContinuation(ServletRequest)}. | |
| 50 * The continuation type returned will depend on the servlet container | |
| 51 * being used. | |
| 52 * </p> | |
| 53 * <p> | |
| 54 * There are two distinct style of operation of the continuation API. | |
| 55 * </p> | |
| 56 * <h3>Suspend/Resume Usage</h3> | |
| 57 * <p>The suspend/resume style is used when a servlet and/or | |
| 58 * filter is used to generate the response after a asynchronous wait that is | |
| 59 * terminated by an asynchronous handler. | |
| 60 * </p> | |
| 61 * <pre> | |
| 62 * <b>Filter/Servlet:</b> | |
| 63 * // if we need to get asynchronous results | |
| 64 * Object results = request.getAttribute("results); | |
| 65 * if (results==null) | |
| 66 * { | |
| 67 * Continuation continuation = ContinuationSupport.getContinuation(request); | |
| 68 * continuation.suspend(); | |
| 69 * myAsyncHandler.register(continuation); | |
| 70 * return; // or continuation.undispatch(); | |
| 71 * } | |
| 72 * | |
| 73 * async wait ... | |
| 74 * | |
| 75 * <b>Async Handler:</b> | |
| 76 * // when the waited for event happens | |
| 77 * continuation.setAttribute("results",event); | |
| 78 * continuation.resume(); | |
| 79 * | |
| 80 * <b>Filter/Servlet:</b> | |
| 81 * // when the request is redispatched | |
| 82 * if (results==null) | |
| 83 * { | |
| 84 * ... // see above | |
| 85 * } | |
| 86 * else | |
| 87 * { | |
| 88 * response.getOutputStream().write(process(results)); | |
| 89 * } | |
| 90 * </pre> | |
| 91 * <h3>Suspend/Complete Usage</h3> | |
| 92 * <p> | |
| 93 * The suspend/complete style is used when an asynchronous handler is used to | |
| 94 * generate the response: | |
| 95 * </p> | |
| 96 * <pre> | |
| 97 * <b>Filter/Servlet:</b> | |
| 98 * // when we want to enter asynchronous mode | |
| 99 * Continuation continuation = ContinuationSupport.getContinuation(request); | |
| 100 * continuation.suspend(response); // response may be wrapped | |
| 101 * myAsyncHandler.register(continuation); | |
| 102 * return; // or continuation.undispatch(); | |
| 103 * | |
| 104 * <b>Wrapping Filter:</b> | |
| 105 * // any filter that had wrapped the response should be implemented like: | |
| 106 * try | |
| 107 * { | |
| 108 * chain.doFilter(request,wrappedResponse); | |
| 109 * } | |
| 110 * finally | |
| 111 * { | |
| 112 * if (!continuation.isResponseWrapped()) | |
| 113 * wrappedResponse.finish() | |
| 114 * else | |
| 115 * continuation.addContinuationListener(myCompleteListener) | |
| 116 * } | |
| 117 * | |
| 118 * async wait ... | |
| 119 * | |
| 120 * <b>Async Handler:</b> | |
| 121 * // when the async event happens | |
| 122 * continuation.getServletResponse().getOutputStream().write(process(event)); | |
| 123 * continuation.complete() | |
| 124 * </pre> | |
| 125 * | |
| 126 * <h1>Continuation Timeout</h1> | |
| 127 * <p> | |
| 128 * If a continuation is suspended, but neither {@link #complete()} or {@link #resume()} is | |
| 129 * called during the period set by {@link #setTimeout(long)}, then the continuation will | |
| 130 * expire and {@link #isExpired()} will return true. | |
| 131 * </p> | |
| 132 * <p> | |
| 133 * When a continuation expires, the {@link ContinuationListener#onTimeout(Continuation)} | |
| 134 * method is called on any {@link ContinuationListener} that has been registered via the | |
| 135 * {@link #addContinuationListener(ContinuationListener)} method. The onTimeout handlers | |
| 136 * may write a response and call {@link #complete()}. If {@link #complete()} is not called, | |
| 137 * then the container will redispatch the request as if {@link #resume()} had been called, | |
| 138 * except that {@link #isExpired()} will be true and {@link #isResumed()} will be false. | |
| 139 * </p> | |
| 140 * | |
| 141 * @see ContinuationSupport | |
| 142 * @see ContinuationListener | |
| 143 * | |
| 144 */ | |
| 145 public interface Continuation | |
| 146 { | |
| 147 public final static String ATTRIBUTE = "org.eclipse.jetty.continuation"; | |
| 148 | |
| 149 /* ------------------------------------------------------------ */ | |
| 150 /** | |
| 151 * Set the continuation timeout. | |
| 152 * | |
| 153 * @param timeoutMs | |
| 154 * The time in milliseconds to wait before expiring this | |
| 155 * continuation after a call to {@link #suspend()} or {@link #suspend(ServletResponse)}. | |
| 156 * A timeout of <=0 means the continuation will never expire. | |
| 157 */ | |
| 158 void setTimeout(long timeoutMs); | |
| 159 | |
| 160 /* ------------------------------------------------------------ */ | |
| 161 /** | |
| 162 * Suspend the processing of the request and associated | |
| 163 * {@link ServletResponse}. | |
| 164 * | |
| 165 * <p> | |
| 166 * After this method has been called, the lifecycle of the request will be | |
| 167 * extended beyond the return to the container from the | |
| 168 * {@link Servlet#service(ServletRequest, ServletResponse)} method and | |
| 169 * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)} | |
| 170 * calls. When a suspended request is returned to the container after | |
| 171 * a dispatch, then the container will not commit the associated response | |
| 172 * (unless an exception other than {@link ContinuationThrowable} is thrown). | |
| 173 * </p> | |
| 174 * | |
| 175 * <p> | |
| 176 * When the thread calling the filter chain and/or servlet has returned to | |
| 177 * the container with a suspended request, the thread is freed for other | |
| 178 * tasks and the request is held until either: | |
| 179 * <ul> | |
| 180 * <li>a call to {@link #resume()}.</li> | |
| 181 * <li>a call to {@link #complete()}.</li> | |
| 182 * <li>the timeout expires.</li> | |
| 183 * </ul> | |
| 184 * <p> | |
| 185 * Typically suspend with no arguments is uses when a call to {@link #resume()} | |
| 186 * is expected. If a call to {@link #complete()} is expected, then the | |
| 187 * {@link #suspend(ServletResponse)} method should be used instead of this method. | |
| 188 * </p> | |
| 189 * | |
| 190 * @exception IllegalStateException | |
| 191 * If the request cannot be suspended | |
| 192 */ | |
| 193 void suspend(); | |
| 194 | |
| 195 | |
| 196 /* ------------------------------------------------------------ */ | |
| 197 /** | |
| 198 * Suspend the processing of the request and associated | |
| 199 * {@link ServletResponse}. | |
| 200 * | |
| 201 * <p> | |
| 202 * After this method has been called, the lifecycle of the request will be | |
| 203 * extended beyond the return to the container from the | |
| 204 * {@link Servlet#service(ServletRequest, ServletResponse)} method and | |
| 205 * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)} | |
| 206 * calls. When a suspended request is returned to the container after | |
| 207 * a dispatch, then the container will not commit the associated response | |
| 208 * (unless an exception other than {@link ContinuationThrowable} is thrown). | |
| 209 * </p> | |
| 210 * <p> | |
| 211 * When the thread calling the filter chain and/or servlet has returned to | |
| 212 * the container with a suspended request, the thread is freed for other | |
| 213 * tasks and the request is held until either: | |
| 214 * <ul> | |
| 215 * <li>a call to {@link #resume()}.</li> | |
| 216 * <li>a call to {@link #complete()}.</li> | |
| 217 * <li>the timeout expires.</li> | |
| 218 * </ul> | |
| 219 * <p> | |
| 220 * Typically suspend with a response argument is uses when a call to {@link #complete()} | |
| 221 * is expected. If a call to {@link #resume()} is expected, then the | |
| 222 * {@link #suspend()} method should be used instead of this method. | |
| 223 * </p> | |
| 224 * <p> | |
| 225 * Filters that may wrap the response object should check {@link #isResponseWrapped()} | |
| 226 * to decide if they should destroy/finish the wrapper. If {@link #isResponseWrapped()} | |
| 227 * returns true, then the wrapped request has been passed to the asynchronous | |
| 228 * handler and the wrapper should not be destroyed/finished until after a call to | |
| 229 * {@link #complete()} (potentially using a {@link ContinuationListener#onComplete(Continuation)} | |
| 230 * listener). | |
| 231 * | |
| 232 * @param response The response to return via a call to {@link #getServletResponse()} | |
| 233 * @exception IllegalStateException | |
| 234 * If the request cannot be suspended | |
| 235 */ | |
| 236 void suspend(ServletResponse response); | |
| 237 | |
| 238 /* ------------------------------------------------------------ */ | |
| 239 /** | |
| 240 * Resume a suspended request. | |
| 241 * | |
| 242 * <p> | |
| 243 * This method can be called by any thread that has been passed a reference | |
| 244 * to a continuation. When called the request is redispatched to the | |
| 245 * normal filter chain and servlet processing with {@link #isInitial()} false. | |
| 246 * </p> | |
| 247 * <p> | |
| 248 * If resume is called before a suspended request is returned to the | |
| 249 * container (ie the thread that called {@link #suspend()} is still | |
| 250 * within the filter chain and/or servlet service method), then the resume | |
| 251 * does not take effect until the call to the filter chain and/or servlet | |
| 252 * returns to the container. In this case both {@link #isSuspended()} and | |
| 253 * {@link #isResumed()} return true. Multiple calls to resume are ignored. | |
| 254 * </p> | |
| 255 * <p> | |
| 256 * Typically resume() is used after a call to {@link #suspend()} with | |
| 257 * no arguments. The dispatch after a resume call will use the original | |
| 258 * request and response objects, even if {@link #suspend(ServletResponse)} | |
| 259 * had been passed a wrapped response. | |
| 260 * </p> | |
| 261 * | |
| 262 * @see #suspend() | |
| 263 * @exception IllegalStateException if the request is not suspended. | |
| 264 * | |
| 265 */ | |
| 266 void resume(); | |
| 267 | |
| 268 /* ------------------------------------------------------------ */ | |
| 269 /** | |
| 270 * Complete a suspended request. | |
| 271 * | |
| 272 * <p> | |
| 273 * This method can be called by any thread that has been passed a reference | |
| 274 * to a suspended request. When a request is completed, the associated | |
| 275 * response object committed and flushed. The request is not redispatched. | |
| 276 * </p> | |
| 277 * | |
| 278 * <p> | |
| 279 * If complete is called before a suspended request is returned to the | |
| 280 * container (ie the thread that called {@link #suspend()} is still | |
| 281 * within the filter chain and/or servlet service method), then the complete | |
| 282 * does not take effect until the call to the filter chain and/or servlet | |
| 283 * returns to the container. In this case both {@link #isSuspended()} and | |
| 284 * {@link #isResumed()} return true. | |
| 285 * </p> | |
| 286 * | |
| 287 * <p> | |
| 288 * Typically resume() is used after a call to {@link #suspend(ServletResponse)} with | |
| 289 * a possibly wrapped response. The async handler should use the response | |
| 290 * provided by {@link #getServletResponse()} to write the response before | |
| 291 * calling {@link #complete()}. If the request was suspended with a | |
| 292 * call to {@link #suspend()} then no response object will be available via | |
| 293 * {@link #getServletResponse()}. | |
| 294 * </p> | |
| 295 * | |
| 296 * <p> | |
| 297 * Once complete has been called and any thread calling the filter chain | |
| 298 * and/or servlet chain has returned to the container, the request lifecycle | |
| 299 * is complete. The container is able to recycle request objects, so it is | |
| 300 * not valid hold a request or continuation reference after the end of the | |
| 301 * life cycle. | |
| 302 * | |
| 303 * @see #suspend() | |
| 304 * @exception IllegalStateException | |
| 305 * if the request is not suspended. | |
| 306 * | |
| 307 */ | |
| 308 void complete(); | |
| 309 | |
| 310 /* ------------------------------------------------------------ */ | |
| 311 /** | |
| 312 * @return true after {@link #suspend()} has been called and before the | |
| 313 * request has been redispatched due to being resumed, completed or | |
| 314 * timed out. | |
| 315 */ | |
| 316 boolean isSuspended(); | |
| 317 | |
| 318 /* ------------------------------------------------------------ */ | |
| 319 /** | |
| 320 * @return true if the request has been redispatched by a call to | |
| 321 * {@link #resume()}. Returns false after any subsequent call to | |
| 322 * suspend | |
| 323 */ | |
| 324 boolean isResumed(); | |
| 325 | |
| 326 /* ------------------------------------------------------------ */ | |
| 327 /** | |
| 328 * @return true after a request has been redispatched as the result of a | |
| 329 * timeout. Returns false after any subsequent call to suspend. | |
| 330 */ | |
| 331 boolean isExpired(); | |
| 332 | |
| 333 /* ------------------------------------------------------------ */ | |
| 334 /** | |
| 335 * @return true while the request is within the initial dispatch to the | |
| 336 * filter chain and/or servlet. Will return false once the calling | |
| 337 * thread has returned to the container after suspend has been | |
| 338 * called and during any subsequent redispatch. | |
| 339 */ | |
| 340 boolean isInitial(); | |
| 341 | |
| 342 /* ------------------------------------------------------------ */ | |
| 343 /** | |
| 344 * Is the suspended response wrapped. | |
| 345 * <p> | |
| 346 * Filters that wrap the response object should check this method to | |
| 347 * determine if they should destroy/finish the wrapped response. If | |
| 348 * the request was suspended with a call to {@link #suspend(ServletResponse)} | |
| 349 * that passed the wrapped response, then the filter should register | |
| 350 * a {@link ContinuationListener} to destroy/finish the wrapped response | |
| 351 * during a call to {@link ContinuationListener#onComplete(Continuation)}. | |
| 352 * @return True if {@link #suspend(ServletResponse)} has been passed a | |
| 353 * {@link ServletResponseWrapper} instance. | |
| 354 */ | |
| 355 boolean isResponseWrapped(); | |
| 356 | |
| 357 | |
| 358 /* ------------------------------------------------------------ */ | |
| 359 /** | |
| 360 * Get the suspended response. | |
| 361 * @return the {@link ServletResponse} passed to {@link #suspend(ServletResponse)}. | |
| 362 */ | |
| 363 ServletResponse getServletResponse(); | |
| 364 | |
| 365 /* ------------------------------------------------------------ */ | |
| 366 /** | |
| 367 * Add a ContinuationListener. | |
| 368 * | |
| 369 * @param listener | |
| 370 */ | |
| 371 void addContinuationListener(ContinuationListener listener); | |
| 372 | |
| 373 /* ------------------------------------------------------------ */ | |
| 374 /** Set a request attribute. | |
| 375 * This method is a convenience method to call the {@link ServletRequest#setAttribute(String, Object)} | |
| 376 * method on the associated request object. | |
| 377 * This is a thread safe call and may be called by any thread. | |
| 378 * @param name the attribute name | |
| 379 * @param attribute the attribute value | |
| 380 */ | |
| 381 public void setAttribute(String name, Object attribute); | |
| 382 | |
| 383 /* ------------------------------------------------------------ */ | |
| 384 /** Get a request attribute. | |
| 385 * This method is a convenience method to call the {@link ServletRequest#getAttribute(String)} | |
| 386 * method on the associated request object. | |
| 387 * This is a thread safe call and may be called by any thread. | |
| 388 * @param name the attribute name | |
| 389 * @return the attribute value | |
| 390 */ | |
| 391 public Object getAttribute(String name); | |
| 392 | |
| 393 /* ------------------------------------------------------------ */ | |
| 394 /** Remove a request attribute. | |
| 395 * This method is a convenience method to call the {@link ServletRequest#removeAttribute(String)} | |
| 396 * method on the associated request object. | |
| 397 * This is a thread safe call and may be called by any thread. | |
| 398 * @param name the attribute name | |
| 399 */ | |
| 400 public void removeAttribute(String name); | |
| 401 | |
| 402 /* ------------------------------------------------------------ */ | |
| 403 /** | |
| 404 * Undispatch the request. | |
| 405 * <p> | |
| 406 * This method can be called on a suspended continuation in order | |
| 407 * to exit the dispatch to the filter/servlet by throwing a {@link ContinuationThrowable} | |
| 408 * which is caught either by the container or the {@link ContinuationFilter}. | |
| 409 * This is an alternative to simply returning from the dispatch in the case | |
| 410 * where filters in the filter chain may not be prepared to handle a suspended | |
| 411 * request. | |
| 412 * </p> | |
| 413 * This method should only be used as a last resort and a normal return is a prefereable | |
| 414 * solution if filters can be updated to handle that case. | |
| 415 * | |
| 416 * @throws ContinuationThrowable thrown if the request is suspended. The instance of the | |
| 417 * exception may be reused on subsequent calls, so the stack frame may not be accurate. | |
| 418 */ | |
| 419 public void undispatch() throws ContinuationThrowable; | |
| 420 } |
