mirror of
https://github.com/jetty/jetty.project.git
synced 2025-02-28 19:09:10 +00:00
Issue #1676 Removed deprecated module jetty-continuations
This commit is contained in:
parent
748d582994
commit
79cafb37a0
@ -57,8 +57,6 @@
|
|||||||
<includes>**/*</includes>
|
<includes>**/*</includes>
|
||||||
<excludes>
|
<excludes>
|
||||||
META-INF/**,
|
META-INF/**,
|
||||||
**/Servlet3Continuation*,
|
|
||||||
**/Jetty6Continuation*,
|
|
||||||
**/AppContextLeakPreventer*.java,
|
**/AppContextLeakPreventer*.java,
|
||||||
**/AWTLeakPreventer*.java,
|
**/AWTLeakPreventer*.java,
|
||||||
**/IntrospectorCleaner*.java,
|
**/IntrospectorCleaner*.java,
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<classifier>sources</classifier>
|
<classifier>sources</classifier>
|
||||||
<includes>**/*</includes>
|
<includes>**/*</includes>
|
||||||
<excludes>META-INF/**,**/Servlet3Continuation*,**/Jetty6Continuation*</excludes>
|
<excludes>META-INF/**</excludes>
|
||||||
<includeGroupIds>org.eclipse.jetty,org.eclipse.jetty.websocket</includeGroupIds>
|
<includeGroupIds>org.eclipse.jetty,org.eclipse.jetty.websocket</includeGroupIds>
|
||||||
<excludeArtifactIds>javax</excludeArtifactIds>
|
<excludeArtifactIds>javax</excludeArtifactIds>
|
||||||
<excludeGroupIds>javax,org.eclipse.jetty.orbit,org.mortbay.jetty.alpn</excludeGroupIds>
|
<excludeGroupIds>javax,org.eclipse.jetty.orbit,org.mortbay.jetty.alpn</excludeGroupIds>
|
||||||
|
@ -156,11 +156,6 @@
|
|||||||
<artifactId>jetty-client</artifactId>
|
<artifactId>jetty-client</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-continuation</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-deploy</artifactId>
|
<artifactId>jetty-deploy</artifactId>
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
|
||||||
<parent>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-project</artifactId>
|
|
||||||
<version>10.0.0-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>jetty-continuation</artifactId>
|
|
||||||
<name>Jetty :: Continuation</name>
|
|
||||||
<description>Asynchronous API</description>
|
|
||||||
<url>http://www.eclipse.org/jetty</url>
|
|
||||||
<properties>
|
|
||||||
<bundle-symbolic-name>${project.groupId}.continuation</bundle-symbolic-name>
|
|
||||||
</properties>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>findbugs-maven-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<onlyAnalyze>org.eclipse.jetty.continuation.*</onlyAnalyze>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.servlet</groupId>
|
|
||||||
<artifactId>javax.servlet-api</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
@ -1,419 +0,0 @@
|
|||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.continuation;
|
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
import javax.servlet.ServletResponseWrapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Continuation.
|
|
||||||
* <p>
|
|
||||||
* A continuation is a mechanism by which a HTTP Request can be suspended and
|
|
||||||
* restarted after a timeout or an asynchronous event has occurred.
|
|
||||||
* <p>
|
|
||||||
* The continuation mechanism is a portable mechanism that will work
|
|
||||||
* asynchronously without additional configuration of all jetty-7,
|
|
||||||
* jetty-8 and Servlet 3.0 containers. With the addition of
|
|
||||||
* the {@link ContinuationFilter}, the mechanism will also work
|
|
||||||
* asynchronously on jetty-6 and non-asynchronously on any
|
|
||||||
* servlet 2.5 container.
|
|
||||||
* <p>
|
|
||||||
* The Continuation API is a simplification of the richer async API
|
|
||||||
* provided by the servlet-3.0 and an enhancement of the continuation
|
|
||||||
* API that was introduced with jetty-6.
|
|
||||||
* </p>
|
|
||||||
* <h1>Continuation Usage</h1>
|
|
||||||
* <p>
|
|
||||||
* A continuation object is obtained for a request by calling the
|
|
||||||
* factory method {@link ContinuationSupport#getContinuation(ServletRequest)}.
|
|
||||||
* The continuation type returned will depend on the servlet container
|
|
||||||
* being used.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* There are two distinct style of operation of the continuation API.
|
|
||||||
* </p>
|
|
||||||
* <h1>Suspend/Resume Usage</h1>
|
|
||||||
* <p>The suspend/resume style is used when a servlet and/or
|
|
||||||
* filter is used to generate the response after a asynchronous wait that is
|
|
||||||
* terminated by an asynchronous handler.
|
|
||||||
* </p>
|
|
||||||
* <pre>
|
|
||||||
* <b>Filter/Servlet:</b>
|
|
||||||
* // if we need to get asynchronous results
|
|
||||||
* Object results = request.getAttribute("results);
|
|
||||||
* if (results==null)
|
|
||||||
* {
|
|
||||||
* Continuation continuation = ContinuationSupport.getContinuation(request);
|
|
||||||
* continuation.suspend();
|
|
||||||
* myAsyncHandler.register(continuation);
|
|
||||||
* return; // or continuation.undispatch();
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* async wait ...
|
|
||||||
*
|
|
||||||
* <b>Async Handler:</b>
|
|
||||||
* // when the waited for event happens
|
|
||||||
* continuation.setAttribute("results",event);
|
|
||||||
* continuation.resume();
|
|
||||||
*
|
|
||||||
* <b>Filter/Servlet:</b>
|
|
||||||
* // when the request is redispatched
|
|
||||||
* if (results==null)
|
|
||||||
* {
|
|
||||||
* ... // see above
|
|
||||||
* }
|
|
||||||
* else
|
|
||||||
* {
|
|
||||||
* response.getOutputStream().write(process(results));
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
* <h1>Suspend/Complete Usage</h1>
|
|
||||||
* <p>
|
|
||||||
* The suspend/complete style is used when an asynchronous handler is used to
|
|
||||||
* generate the response:
|
|
||||||
* </p>
|
|
||||||
* <pre>
|
|
||||||
* <b>Filter/Servlet:</b>
|
|
||||||
* // when we want to enter asynchronous mode
|
|
||||||
* Continuation continuation = ContinuationSupport.getContinuation(request);
|
|
||||||
* continuation.suspend(response); // response may be wrapped
|
|
||||||
* myAsyncHandler.register(continuation);
|
|
||||||
* return; // or continuation.undispatch();
|
|
||||||
*
|
|
||||||
* <b>Wrapping Filter:</b>
|
|
||||||
* // any filter that had wrapped the response should be implemented like:
|
|
||||||
* try
|
|
||||||
* {
|
|
||||||
* chain.doFilter(request,wrappedResponse);
|
|
||||||
* }
|
|
||||||
* finally
|
|
||||||
* {
|
|
||||||
* if (!continuation.isResponseWrapped())
|
|
||||||
* wrappedResponse.finish()
|
|
||||||
* else
|
|
||||||
* continuation.addContinuationListener(myCompleteListener)
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* async wait ...
|
|
||||||
*
|
|
||||||
* <b>Async Handler:</b>
|
|
||||||
* // when the async event happens
|
|
||||||
* continuation.getServletResponse().getOutputStream().write(process(event));
|
|
||||||
* continuation.complete()
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* <h1>Continuation Timeout</h1>
|
|
||||||
* <p>
|
|
||||||
* If a continuation is suspended, but neither {@link #complete()} or {@link #resume()} is
|
|
||||||
* called during the period set by {@link #setTimeout(long)}, then the continuation will
|
|
||||||
* expire and {@link #isExpired()} will return true.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* When a continuation expires, the {@link ContinuationListener#onTimeout(Continuation)}
|
|
||||||
* method is called on any {@link ContinuationListener} that has been registered via the
|
|
||||||
* {@link #addContinuationListener(ContinuationListener)} method. The onTimeout handlers
|
|
||||||
* may write a response and call {@link #complete()}. If {@link #complete()} is not called,
|
|
||||||
* then the container will redispatch the request as if {@link #resume()} had been called,
|
|
||||||
* except that {@link #isExpired()} will be true and {@link #isResumed()} will be false.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @see ContinuationSupport
|
|
||||||
* @see ContinuationListener
|
|
||||||
*
|
|
||||||
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public interface Continuation
|
|
||||||
{
|
|
||||||
public final static String ATTRIBUTE = "org.eclipse.jetty.continuation";
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Set the continuation timeout.
|
|
||||||
*
|
|
||||||
* @param timeoutMs
|
|
||||||
* The time in milliseconds to wait before expiring this
|
|
||||||
* continuation after a call to {@link #suspend()} or {@link #suspend(ServletResponse)}.
|
|
||||||
* A timeout of <=0 means the continuation will never expire.
|
|
||||||
*/
|
|
||||||
void setTimeout(long timeoutMs);
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Suspend the processing of the request and associated
|
|
||||||
* {@link ServletResponse}.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* After this method has been called, the lifecycle of the request will be
|
|
||||||
* extended beyond the return to the container from the
|
|
||||||
* {@link javax.servlet.Servlet#service(ServletRequest, ServletResponse)} method and
|
|
||||||
* {@link javax.servlet.Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}
|
|
||||||
* calls. When a suspended request is returned to the container after
|
|
||||||
* a dispatch, then the container will not commit the associated response
|
|
||||||
* (unless an exception other than {@link ContinuationThrowable} is thrown).
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* When the thread calling the filter chain and/or servlet has returned to
|
|
||||||
* the container with a suspended request, the thread is freed for other
|
|
||||||
* tasks and the request is held until either:
|
|
||||||
* <ul>
|
|
||||||
* <li>a call to {@link #resume()}.</li>
|
|
||||||
* <li>a call to {@link #complete()}.</li>
|
|
||||||
* <li>the timeout expires.</li>
|
|
||||||
* </ul>
|
|
||||||
* <p>
|
|
||||||
* Typically suspend with no arguments is uses when a call to {@link #resume()}
|
|
||||||
* is expected. If a call to {@link #complete()} is expected, then the
|
|
||||||
* {@link #suspend(ServletResponse)} method should be used instead of this method.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @exception IllegalStateException
|
|
||||||
* If the request cannot be suspended
|
|
||||||
*/
|
|
||||||
void suspend();
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Suspend the processing of the request and associated
|
|
||||||
* {@link ServletResponse}.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* After this method has been called, the lifecycle of the request will be
|
|
||||||
* extended beyond the return to the container from the
|
|
||||||
* {@link javax.servlet.Servlet#service(ServletRequest, ServletResponse)} method and
|
|
||||||
* {@link javax.servlet.Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}
|
|
||||||
* calls. When a suspended request is returned to the container after
|
|
||||||
* a dispatch, then the container will not commit the associated response
|
|
||||||
* (unless an exception other than {@link ContinuationThrowable} is thrown).
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* When the thread calling the filter chain and/or servlet has returned to
|
|
||||||
* the container with a suspended request, the thread is freed for other
|
|
||||||
* tasks and the request is held until either:
|
|
||||||
* <ul>
|
|
||||||
* <li>a call to {@link #resume()}.</li>
|
|
||||||
* <li>a call to {@link #complete()}.</li>
|
|
||||||
* <li>the timeout expires.</li>
|
|
||||||
* </ul>
|
|
||||||
* <p>
|
|
||||||
* Typically suspend with a response argument is uses when a call to {@link #complete()}
|
|
||||||
* is expected. If a call to {@link #resume()} is expected, then the
|
|
||||||
* {@link #suspend()} method should be used instead of this method.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Filters that may wrap the response object should check {@link #isResponseWrapped()}
|
|
||||||
* to decide if they should destroy/finish the wrapper. If {@link #isResponseWrapped()}
|
|
||||||
* returns true, then the wrapped request has been passed to the asynchronous
|
|
||||||
* handler and the wrapper should not be destroyed/finished until after a call to
|
|
||||||
* {@link #complete()} (potentially using a {@link ContinuationListener#onComplete(Continuation)}
|
|
||||||
* listener).
|
|
||||||
*
|
|
||||||
* @param response The response to return via a call to {@link #getServletResponse()}
|
|
||||||
* @exception IllegalStateException
|
|
||||||
* If the request cannot be suspended
|
|
||||||
*/
|
|
||||||
void suspend(ServletResponse response);
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Resume a suspended request.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This method can be called by any thread that has been passed a reference
|
|
||||||
* to a continuation. When called the request is redispatched to the
|
|
||||||
* normal filter chain and servlet processing with {@link #isInitial()} false.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* If resume is called before a suspended request is returned to the
|
|
||||||
* container (ie the thread that called {@link #suspend()} is still
|
|
||||||
* within the filter chain and/or servlet service method), then the resume
|
|
||||||
* does not take effect until the call to the filter chain and/or servlet
|
|
||||||
* returns to the container. In this case both {@link #isSuspended()} and
|
|
||||||
* {@link #isResumed()} return true. Multiple calls to resume are ignored.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Typically resume() is used after a call to {@link #suspend()} with
|
|
||||||
* no arguments. The dispatch after a resume call will use the original
|
|
||||||
* request and response objects, even if {@link #suspend(ServletResponse)}
|
|
||||||
* had been passed a wrapped response.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @see #suspend()
|
|
||||||
* @exception IllegalStateException if the request is not suspended.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void resume();
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Complete a suspended request.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This method can be called by any thread that has been passed a reference
|
|
||||||
* to a suspended request. When a request is completed, the associated
|
|
||||||
* response object committed and flushed. The request is not redispatched.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* If complete is called before a suspended request is returned to the
|
|
||||||
* container (ie the thread that called {@link #suspend()} is still
|
|
||||||
* within the filter chain and/or servlet service method), then the complete
|
|
||||||
* does not take effect until the call to the filter chain and/or servlet
|
|
||||||
* returns to the container. In this case both {@link #isSuspended()} and
|
|
||||||
* {@link #isResumed()} return true.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Typically resume() is used after a call to {@link #suspend(ServletResponse)} with
|
|
||||||
* a possibly wrapped response. The async handler should use the response
|
|
||||||
* provided by {@link #getServletResponse()} to write the response before
|
|
||||||
* calling {@link #complete()}. If the request was suspended with a
|
|
||||||
* call to {@link #suspend()} then no response object will be available via
|
|
||||||
* {@link #getServletResponse()}.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Once complete has been called and any thread calling the filter chain
|
|
||||||
* and/or servlet chain has returned to the container, the request lifecycle
|
|
||||||
* is complete. The container is able to recycle request objects, so it is
|
|
||||||
* not valid hold a request or continuation reference after the end of the
|
|
||||||
* life cycle.
|
|
||||||
*
|
|
||||||
* @see #suspend()
|
|
||||||
* @exception IllegalStateException
|
|
||||||
* if the request is not suspended.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void complete();
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @return true after {@link #suspend()} has been called and before the
|
|
||||||
* request has been redispatched due to being resumed, completed or
|
|
||||||
* timed out.
|
|
||||||
*/
|
|
||||||
boolean isSuspended();
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @return true if the request has been redispatched by a call to
|
|
||||||
* {@link #resume()}. Returns false after any subsequent call to
|
|
||||||
* suspend
|
|
||||||
*/
|
|
||||||
boolean isResumed();
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @return true after a request has been redispatched as the result of a
|
|
||||||
* timeout. Returns false after any subsequent call to suspend.
|
|
||||||
*/
|
|
||||||
boolean isExpired();
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @return true while the request is within the initial dispatch to the
|
|
||||||
* filter chain and/or servlet. Will return false once the calling
|
|
||||||
* thread has returned to the container after suspend has been
|
|
||||||
* called and during any subsequent redispatch.
|
|
||||||
*/
|
|
||||||
boolean isInitial();
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Is the suspended response wrapped.
|
|
||||||
* <p>
|
|
||||||
* Filters that wrap the response object should check this method to
|
|
||||||
* determine if they should destroy/finish the wrapped response. If
|
|
||||||
* the request was suspended with a call to {@link #suspend(ServletResponse)}
|
|
||||||
* that passed the wrapped response, then the filter should register
|
|
||||||
* a {@link ContinuationListener} to destroy/finish the wrapped response
|
|
||||||
* during a call to {@link ContinuationListener#onComplete(Continuation)}.
|
|
||||||
* @return True if {@link #suspend(ServletResponse)} has been passed a
|
|
||||||
* {@link ServletResponseWrapper} instance.
|
|
||||||
*/
|
|
||||||
boolean isResponseWrapped();
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Get the suspended response.
|
|
||||||
* @return the {@link ServletResponse} passed to {@link #suspend(ServletResponse)}.
|
|
||||||
*/
|
|
||||||
ServletResponse getServletResponse();
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Add a ContinuationListener.
|
|
||||||
*
|
|
||||||
* @param listener the listener
|
|
||||||
*/
|
|
||||||
void addContinuationListener(ContinuationListener listener);
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/** Set a request attribute.
|
|
||||||
* This method is a convenience method to call the {@link ServletRequest#setAttribute(String, Object)}
|
|
||||||
* method on the associated request object.
|
|
||||||
* This is a thread safe call and may be called by any thread.
|
|
||||||
* @param name the attribute name
|
|
||||||
* @param attribute the attribute value
|
|
||||||
*/
|
|
||||||
public void setAttribute(String name, Object attribute);
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/** Get a request attribute.
|
|
||||||
* This method is a convenience method to call the {@link ServletRequest#getAttribute(String)}
|
|
||||||
* method on the associated request object.
|
|
||||||
* This is a thread safe call and may be called by any thread.
|
|
||||||
* @param name the attribute name
|
|
||||||
* @return the attribute value
|
|
||||||
*/
|
|
||||||
public Object getAttribute(String name);
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/** Remove a request attribute.
|
|
||||||
* This method is a convenience method to call the {@link ServletRequest#removeAttribute(String)}
|
|
||||||
* method on the associated request object.
|
|
||||||
* This is a thread safe call and may be called by any thread.
|
|
||||||
* @param name the attribute name
|
|
||||||
*/
|
|
||||||
public void removeAttribute(String name);
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Undispatch the request.
|
|
||||||
* <p>
|
|
||||||
* This method can be called on a suspended continuation in order
|
|
||||||
* to exit the dispatch to the filter/servlet by throwing a {@link ContinuationThrowable}
|
|
||||||
* which is caught either by the container or the {@link ContinuationFilter}.
|
|
||||||
* This is an alternative to simply returning from the dispatch in the case
|
|
||||||
* where filters in the filter chain may not be prepared to handle a suspended
|
|
||||||
* request.
|
|
||||||
* </p>
|
|
||||||
* This method should only be used as a last resort and a normal return is a prefereable
|
|
||||||
* solution if filters can be updated to handle that case.
|
|
||||||
*
|
|
||||||
* @throws ContinuationThrowable thrown if the request is suspended. The instance of the
|
|
||||||
* exception may be reused on subsequent calls, so the stack frame may not be accurate.
|
|
||||||
*/
|
|
||||||
public void undispatch() throws ContinuationThrowable;
|
|
||||||
}
|
|
@ -1,167 +0,0 @@
|
|||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.continuation;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
|
||||||
import javax.servlet.FilterChain;
|
|
||||||
import javax.servlet.FilterConfig;
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* <p>ContinuationFilter must be applied to servlet paths that make use of
|
|
||||||
* the asynchronous features provided by {@link Continuation} APIs, but that
|
|
||||||
* are deployed in servlet containers that are a
|
|
||||||
* compliant Servlet 3.0 container.</p>
|
|
||||||
* <p>The following init parameters may be used to configure the filter (these are mostly for testing):</p>
|
|
||||||
* <dl>
|
|
||||||
* <dt>debug</dt><dd>Boolean controlling debug output</dd>
|
|
||||||
* <dt>faux</dt><dd>Boolean to force use of faux continuations</dd>
|
|
||||||
* </dl>
|
|
||||||
* <p>If the servlet container is not Jetty 7+ nor a Servlet 3
|
|
||||||
* container, then "faux" continuations will be used.</p>
|
|
||||||
* <p>Faux continuations will just put the thread that called {@link Continuation#suspend()}
|
|
||||||
* in wait, and will notify that thread when {@link Continuation#resume()} or
|
|
||||||
* {@link Continuation#complete()} is called.</p>
|
|
||||||
* <p>Faux continuations are not threadless continuations (they are "faux" - fake - for this reason)
|
|
||||||
* and as such they will scale less than proper continuations.</p>
|
|
||||||
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class ContinuationFilter implements Filter
|
|
||||||
{
|
|
||||||
static boolean _initialized;
|
|
||||||
static boolean __debug; // shared debug status
|
|
||||||
private boolean _faux;
|
|
||||||
private boolean _filtered;
|
|
||||||
ServletContext _context;
|
|
||||||
private boolean _debug;
|
|
||||||
|
|
||||||
public void init(FilterConfig filterConfig) throws ServletException
|
|
||||||
{
|
|
||||||
filterConfig.getServletContext().log("WARNING: " + this.getClass().getName() + " is now DEPRECATED, use Servlet 3.0 AsyncContext instead.");
|
|
||||||
boolean jetty_7_or_greater="org.eclipse.jetty.servlet".equals(filterConfig.getClass().getPackage().getName());
|
|
||||||
_context = filterConfig.getServletContext();
|
|
||||||
|
|
||||||
String param=filterConfig.getInitParameter("debug");
|
|
||||||
_debug=param!=null&&Boolean.parseBoolean(param);
|
|
||||||
if (_debug)
|
|
||||||
__debug=true;
|
|
||||||
|
|
||||||
param=filterConfig.getInitParameter("partial");
|
|
||||||
param=filterConfig.getInitParameter("faux");
|
|
||||||
if (param!=null)
|
|
||||||
_faux=Boolean.parseBoolean(param);
|
|
||||||
else
|
|
||||||
_faux=!(jetty_7_or_greater || _context.getMajorVersion()>=3);
|
|
||||||
|
|
||||||
_filtered=_faux;
|
|
||||||
if (_debug)
|
|
||||||
_context.log("ContinuationFilter "+
|
|
||||||
" jetty="+jetty_7_or_greater+
|
|
||||||
" faux="+_faux+
|
|
||||||
" filtered="+_filtered+
|
|
||||||
" servlet3="+ContinuationSupport.__servlet3);
|
|
||||||
_initialized=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
|
|
||||||
{
|
|
||||||
if (_filtered)
|
|
||||||
{
|
|
||||||
Continuation c = (Continuation) request.getAttribute(Continuation.ATTRIBUTE);
|
|
||||||
FilteredContinuation fc;
|
|
||||||
if (_faux && (c==null || !(c instanceof FauxContinuation)))
|
|
||||||
{
|
|
||||||
fc = new FauxContinuation(request);
|
|
||||||
request.setAttribute(Continuation.ATTRIBUTE,fc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fc=(FilteredContinuation)c;
|
|
||||||
|
|
||||||
boolean complete=false;
|
|
||||||
while (!complete)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (fc==null || (fc).enter(response))
|
|
||||||
chain.doFilter(request,response);
|
|
||||||
}
|
|
||||||
catch (ContinuationThrowable e)
|
|
||||||
{
|
|
||||||
debug("faux",e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (fc==null)
|
|
||||||
fc = (FilteredContinuation) request.getAttribute(Continuation.ATTRIBUTE);
|
|
||||||
|
|
||||||
complete=fc==null || (fc).exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
chain.doFilter(request,response);
|
|
||||||
}
|
|
||||||
catch (ContinuationThrowable e)
|
|
||||||
{
|
|
||||||
debug("caught",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void debug(String string)
|
|
||||||
{
|
|
||||||
if (_debug)
|
|
||||||
{
|
|
||||||
_context.log(string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void debug(String string, Throwable th)
|
|
||||||
{
|
|
||||||
if (_debug)
|
|
||||||
{
|
|
||||||
if (th instanceof ContinuationThrowable)
|
|
||||||
_context.log(string+":"+th);
|
|
||||||
else
|
|
||||||
_context.log(string,th);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void destroy()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface FilteredContinuation extends Continuation
|
|
||||||
{
|
|
||||||
boolean enter(ServletResponse response);
|
|
||||||
boolean exit();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.continuation;
|
|
||||||
|
|
||||||
import java.util.EventListener;
|
|
||||||
|
|
||||||
import javax.servlet.ServletRequestListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Continuation Listener
|
|
||||||
* <p>
|
|
||||||
* A ContinuationListener may be registered with a call to
|
|
||||||
* {@link Continuation#addContinuationListener(ContinuationListener)}.
|
|
||||||
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public interface ContinuationListener extends EventListener
|
|
||||||
{
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Called when a continuation life cycle is complete and after
|
|
||||||
* any calls to {@link ServletRequestListener#requestDestroyed(javax.servlet.ServletRequestEvent)}
|
|
||||||
* The response may still be written to during the call.
|
|
||||||
*
|
|
||||||
* @param continuation the continuation
|
|
||||||
*/
|
|
||||||
public void onComplete(Continuation continuation);
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Called when a suspended continuation has timed out.
|
|
||||||
* The response may be written to and the methods
|
|
||||||
* {@link Continuation#resume()} or {@link Continuation#complete()}
|
|
||||||
* may be called by a onTimeout implementation,
|
|
||||||
* @param continuation the continuation
|
|
||||||
*/
|
|
||||||
public void onTimeout(Continuation continuation);
|
|
||||||
|
|
||||||
}
|
|
@ -1,125 +0,0 @@
|
|||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.continuation;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletRequestWrapper;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ContinuationSupport.
|
|
||||||
*
|
|
||||||
* Factory class for accessing Continuation instances, which with either be
|
|
||||||
* a servlet 3.0 or a faux continuation.
|
|
||||||
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class ContinuationSupport
|
|
||||||
{
|
|
||||||
static final boolean __servlet3;
|
|
||||||
static final Class<?> __waitingContinuation;
|
|
||||||
static final Constructor<? extends Continuation> __newServlet3Continuation;
|
|
||||||
static
|
|
||||||
{
|
|
||||||
boolean servlet3Support=false;
|
|
||||||
Constructor<? extends Continuation>s3cc=null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
boolean servlet3=ServletRequest.class.getMethod("startAsync")!=null;
|
|
||||||
if (servlet3)
|
|
||||||
{
|
|
||||||
Class<? extends Continuation> s3c = ContinuationSupport.class.getClassLoader().loadClass("org.eclipse.jetty.continuation.Servlet3Continuation").asSubclass(Continuation.class);
|
|
||||||
s3cc=s3c.getConstructor(ServletRequest.class);
|
|
||||||
servlet3Support=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
__servlet3=servlet3Support;
|
|
||||||
__newServlet3Continuation=s3cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Class<?> waiting=null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
waiting=ContinuationSupport.class.getClassLoader().loadClass("org.mortbay.util.ajax.WaitingContinuation");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
__waitingContinuation=waiting;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Get a Continuation. The type of the Continuation returned may
|
|
||||||
* vary depending on the container in which the application is
|
|
||||||
* deployed. It may be an implementation native to the container (eg
|
|
||||||
* org.eclipse.jetty.server.AsyncContinuation) or one of the utility
|
|
||||||
* implementations provided such as an internal <code>FauxContinuation</code>
|
|
||||||
* or a real implementation like {@link org.eclipse.jetty.continuation.Servlet3Continuation}.
|
|
||||||
* @param request The request
|
|
||||||
* @return a Continuation instance
|
|
||||||
*/
|
|
||||||
public static Continuation getContinuation(ServletRequest request)
|
|
||||||
{
|
|
||||||
Continuation continuation = (Continuation) request.getAttribute(Continuation.ATTRIBUTE);
|
|
||||||
if (continuation!=null)
|
|
||||||
return continuation;
|
|
||||||
|
|
||||||
while (request instanceof ServletRequestWrapper)
|
|
||||||
request=((ServletRequestWrapper)request).getRequest();
|
|
||||||
|
|
||||||
if (__servlet3 )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
continuation=__newServlet3Continuation.newInstance(request);
|
|
||||||
request.setAttribute(Continuation.ATTRIBUTE,continuation);
|
|
||||||
return continuation;
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalStateException("!(Jetty || Servlet 3.0 || ContinuationFilter)");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @param request the servlet request
|
|
||||||
* @param response the servlet response
|
|
||||||
* @deprecated use {@link #getContinuation(ServletRequest)}
|
|
||||||
* @return the continuation
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static Continuation getContinuation(final ServletRequest request, final ServletResponse response)
|
|
||||||
{
|
|
||||||
return getContinuation(request);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
package org.eclipse.jetty.continuation;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/** ContinuationThrowable
|
|
||||||
* <p>
|
|
||||||
* A ContinuationThrowable is throw by {@link Continuation#undispatch()}
|
|
||||||
* in order to exit the dispatch to a Filter or Servlet. Use of
|
|
||||||
* ContinuationThrowable is discouraged and it is preferable to
|
|
||||||
* allow return to be used. ContinuationThrowables should only be
|
|
||||||
* used when there is a Filter/Servlet which cannot be modified
|
|
||||||
* to avoid committing a response when {@link Continuation#isSuspended()}
|
|
||||||
* is true.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* ContinuationThrowable instances are often reused so that the
|
|
||||||
* stack trace may be entirely unrelated to the calling stack.
|
|
||||||
* A real stack trace may be obtained by enabling debug.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* ContinuationThrowable extends Error as this is more likely
|
|
||||||
* to be uncaught (or rethrown) by a Filter/Servlet. A ContinuationThrowable
|
|
||||||
* does not represent and error condition.
|
|
||||||
* </p>
|
|
||||||
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class ContinuationThrowable extends Error
|
|
||||||
{
|
|
||||||
public ContinuationThrowable()
|
|
||||||
{
|
|
||||||
super(null, null, false, false);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,531 +0,0 @@
|
|||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
package org.eclipse.jetty.continuation;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
import javax.servlet.ServletResponseWrapper;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.continuation.ContinuationFilter.FilteredContinuation;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* A blocking implementation of Continuation.
|
|
||||||
* This implementation of Continuation is used by the {@link ContinuationFilter}
|
|
||||||
* when there are is no native or asynchronous continuation type available.
|
|
||||||
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
class FauxContinuation implements FilteredContinuation
|
|
||||||
{
|
|
||||||
// common exception used for all continuations.
|
|
||||||
// Turn on debug in ContinuationFilter to see real stack trace.
|
|
||||||
private final static ContinuationThrowable __exception = new ContinuationThrowable();
|
|
||||||
|
|
||||||
private static final int __HANDLING=1; // Request dispatched to filter/servlet
|
|
||||||
private static final int __SUSPENDING=2; // Suspend called, but not yet returned to container
|
|
||||||
private static final int __RESUMING=3; // resumed while suspending
|
|
||||||
private static final int __COMPLETING=4; // resumed while suspending or suspended
|
|
||||||
private static final int __SUSPENDED=5; // Suspended and parked
|
|
||||||
private static final int __UNSUSPENDING=6;
|
|
||||||
private static final int __COMPLETE=7;
|
|
||||||
|
|
||||||
private final ServletRequest _request;
|
|
||||||
private ServletResponse _response;
|
|
||||||
|
|
||||||
private int _state=__HANDLING;
|
|
||||||
private boolean _initial=true;
|
|
||||||
private boolean _resumed=false;
|
|
||||||
private boolean _timeout=false;
|
|
||||||
private boolean _responseWrapped=false;
|
|
||||||
private long _timeoutMs=30000;
|
|
||||||
|
|
||||||
private ArrayList<ContinuationListener> _listeners;
|
|
||||||
|
|
||||||
FauxContinuation(final ServletRequest request)
|
|
||||||
{
|
|
||||||
_request=request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void onComplete()
|
|
||||||
{
|
|
||||||
if (_listeners!=null)
|
|
||||||
for (ContinuationListener l:_listeners)
|
|
||||||
l.onComplete(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void onTimeout()
|
|
||||||
{
|
|
||||||
if (_listeners!=null)
|
|
||||||
for (ContinuationListener l:_listeners)
|
|
||||||
l.onTimeout(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.continuation.Continuation#isResponseWrapped()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isResponseWrapped()
|
|
||||||
{
|
|
||||||
return _responseWrapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public boolean isInitial()
|
|
||||||
{
|
|
||||||
synchronized(this)
|
|
||||||
{
|
|
||||||
return _initial;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public boolean isResumed()
|
|
||||||
{
|
|
||||||
synchronized(this)
|
|
||||||
{
|
|
||||||
return _resumed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public boolean isSuspended()
|
|
||||||
{
|
|
||||||
synchronized(this)
|
|
||||||
{
|
|
||||||
switch(_state)
|
|
||||||
{
|
|
||||||
case __HANDLING:
|
|
||||||
return false;
|
|
||||||
case __SUSPENDING:
|
|
||||||
case __RESUMING:
|
|
||||||
case __COMPLETING:
|
|
||||||
case __SUSPENDED:
|
|
||||||
return true;
|
|
||||||
case __UNSUSPENDING:
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public boolean isExpired()
|
|
||||||
{
|
|
||||||
synchronized(this)
|
|
||||||
{
|
|
||||||
return _timeout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void setTimeout(long timeoutMs)
|
|
||||||
{
|
|
||||||
_timeoutMs = timeoutMs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void suspend(ServletResponse response)
|
|
||||||
{
|
|
||||||
_response=response;
|
|
||||||
_responseWrapped=response instanceof ServletResponseWrapper;
|
|
||||||
suspend();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void suspend()
|
|
||||||
{
|
|
||||||
synchronized (this)
|
|
||||||
{
|
|
||||||
switch(_state)
|
|
||||||
{
|
|
||||||
case __HANDLING:
|
|
||||||
_timeout=false;
|
|
||||||
_resumed=false;
|
|
||||||
_state=__SUSPENDING;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case __SUSPENDING:
|
|
||||||
case __RESUMING:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case __COMPLETING:
|
|
||||||
case __SUSPENDED:
|
|
||||||
case __UNSUSPENDING:
|
|
||||||
throw new IllegalStateException(this.getStatusString());
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException(""+_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.mortbay.jetty.Suspendor#resume()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void resume()
|
|
||||||
{
|
|
||||||
synchronized (this)
|
|
||||||
{
|
|
||||||
switch(_state)
|
|
||||||
{
|
|
||||||
case __HANDLING:
|
|
||||||
_resumed=true;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case __SUSPENDING:
|
|
||||||
_resumed=true;
|
|
||||||
_state=__RESUMING;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case __RESUMING:
|
|
||||||
case __COMPLETING:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case __SUSPENDED:
|
|
||||||
fauxResume();
|
|
||||||
_resumed=true;
|
|
||||||
_state=__UNSUSPENDING;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case __UNSUSPENDING:
|
|
||||||
_resumed=true;
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException(this.getStatusString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void complete()
|
|
||||||
{
|
|
||||||
// just like resume, except don't set _resumed=true;
|
|
||||||
synchronized (this)
|
|
||||||
{
|
|
||||||
switch(_state)
|
|
||||||
{
|
|
||||||
case __HANDLING:
|
|
||||||
throw new IllegalStateException(this.getStatusString());
|
|
||||||
|
|
||||||
case __SUSPENDING:
|
|
||||||
_state=__COMPLETING;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case __RESUMING:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case __COMPLETING:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case __SUSPENDED:
|
|
||||||
_state=__COMPLETING;
|
|
||||||
fauxResume();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case __UNSUSPENDING:
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException(this.getStatusString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.continuation.Continuation#getServletResponse()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean enter(ServletResponse response)
|
|
||||||
{
|
|
||||||
_response=response;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.continuation.Continuation#getServletResponse()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public ServletResponse getServletResponse()
|
|
||||||
{
|
|
||||||
return _response;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
void handling()
|
|
||||||
{
|
|
||||||
synchronized (this)
|
|
||||||
{
|
|
||||||
_responseWrapped=false;
|
|
||||||
switch(_state)
|
|
||||||
{
|
|
||||||
case __HANDLING:
|
|
||||||
throw new IllegalStateException(this.getStatusString());
|
|
||||||
|
|
||||||
case __SUSPENDING:
|
|
||||||
case __RESUMING:
|
|
||||||
throw new IllegalStateException(this.getStatusString());
|
|
||||||
|
|
||||||
case __COMPLETING:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case __SUSPENDED:
|
|
||||||
fauxResume();
|
|
||||||
_state=__HANDLING;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case __UNSUSPENDING:
|
|
||||||
_state=__HANDLING;
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException(""+_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @return true if handling is complete
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean exit()
|
|
||||||
{
|
|
||||||
synchronized (this)
|
|
||||||
{
|
|
||||||
switch(_state)
|
|
||||||
{
|
|
||||||
case __HANDLING:
|
|
||||||
_state=__COMPLETE;
|
|
||||||
onComplete();
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case __SUSPENDING:
|
|
||||||
_initial=false;
|
|
||||||
_state=__SUSPENDED;
|
|
||||||
fauxSuspend(); // could block and change state.
|
|
||||||
if (_state==__SUSPENDED || _state==__COMPLETING)
|
|
||||||
{
|
|
||||||
onComplete();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_initial=false;
|
|
||||||
_state=__HANDLING;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case __RESUMING:
|
|
||||||
_initial=false;
|
|
||||||
_state=__HANDLING;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case __COMPLETING:
|
|
||||||
_initial=false;
|
|
||||||
_state=__COMPLETE;
|
|
||||||
onComplete();
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case __SUSPENDED:
|
|
||||||
case __UNSUSPENDING:
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException(this.getStatusString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
protected void expire()
|
|
||||||
{
|
|
||||||
// just like resume, except don't set _resumed=true;
|
|
||||||
|
|
||||||
synchronized (this)
|
|
||||||
{
|
|
||||||
_timeout=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
onTimeout();
|
|
||||||
|
|
||||||
synchronized (this)
|
|
||||||
{
|
|
||||||
switch(_state)
|
|
||||||
{
|
|
||||||
case __HANDLING:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case __SUSPENDING:
|
|
||||||
_timeout=true;
|
|
||||||
_state=__RESUMING;
|
|
||||||
fauxResume();
|
|
||||||
return;
|
|
||||||
|
|
||||||
case __RESUMING:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case __COMPLETING:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case __SUSPENDED:
|
|
||||||
_timeout=true;
|
|
||||||
_state=__UNSUSPENDING;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case __UNSUSPENDING:
|
|
||||||
_timeout=true;
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException(this.getStatusString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fauxSuspend()
|
|
||||||
{
|
|
||||||
long expire_at = System.currentTimeMillis()+_timeoutMs;
|
|
||||||
long wait=_timeoutMs;
|
|
||||||
while (_timeoutMs>0 && wait>0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.wait(wait);
|
|
||||||
}
|
|
||||||
catch (InterruptedException e)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wait=expire_at-System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_timeoutMs>0 && wait<=0)
|
|
||||||
expire();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fauxResume()
|
|
||||||
{
|
|
||||||
_timeoutMs=0;
|
|
||||||
this.notifyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return getStatusString();
|
|
||||||
}
|
|
||||||
|
|
||||||
String getStatusString()
|
|
||||||
{
|
|
||||||
synchronized (this)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
((_state==__HANDLING)?"HANDLING":
|
|
||||||
(_state==__SUSPENDING)?"SUSPENDING":
|
|
||||||
(_state==__SUSPENDED)?"SUSPENDED":
|
|
||||||
(_state==__RESUMING)?"RESUMING":
|
|
||||||
(_state==__UNSUSPENDING)?"UNSUSPENDING":
|
|
||||||
(_state==__COMPLETING)?"COMPLETING":
|
|
||||||
("???"+_state))+
|
|
||||||
(_initial?",initial":"")+
|
|
||||||
(_resumed?",resumed":"")+
|
|
||||||
(_timeout?",timeout":"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addContinuationListener(ContinuationListener listener)
|
|
||||||
{
|
|
||||||
if (_listeners==null)
|
|
||||||
_listeners=new ArrayList<ContinuationListener>();
|
|
||||||
_listeners.add(listener);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.continuation.Continuation#getAttribute(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object getAttribute(String name)
|
|
||||||
{
|
|
||||||
return _request.getAttribute(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.continuation.Continuation#removeAttribute(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void removeAttribute(String name)
|
|
||||||
{
|
|
||||||
_request.removeAttribute(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.continuation.Continuation#setAttribute(java.lang.String, java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setAttribute(String name, Object attribute)
|
|
||||||
{
|
|
||||||
_request.setAttribute(name,attribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.continuation.Continuation#undispatch()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void undispatch()
|
|
||||||
{
|
|
||||||
if (isSuspended())
|
|
||||||
{
|
|
||||||
if (ContinuationFilter.__debug)
|
|
||||||
throw new ContinuationThrowable();
|
|
||||||
throw __exception;
|
|
||||||
}
|
|
||||||
throw new IllegalStateException("!suspended");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,262 +0,0 @@
|
|||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.continuation;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.servlet.AsyncContext;
|
|
||||||
import javax.servlet.AsyncEvent;
|
|
||||||
import javax.servlet.AsyncListener;
|
|
||||||
import javax.servlet.DispatcherType;
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
import javax.servlet.ServletResponseWrapper;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* This implementation of Continuation is used by {@link ContinuationSupport}
|
|
||||||
* when it detects that the application has been deployed in a Servlet 3
|
|
||||||
* server.
|
|
||||||
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class Servlet3Continuation implements Continuation, AsyncListener
|
|
||||||
{
|
|
||||||
// Exception reused for all continuations
|
|
||||||
// Turn on debug in ContinuationFilter to see real stack trace.
|
|
||||||
private final static ContinuationThrowable __exception = new ContinuationThrowable();
|
|
||||||
|
|
||||||
private final ServletRequest _request;
|
|
||||||
private ServletResponse _response;
|
|
||||||
private AsyncContext _context;
|
|
||||||
private final List<ContinuationListener> _listeners=new ArrayList<ContinuationListener>();
|
|
||||||
private volatile boolean _initial=true;
|
|
||||||
private volatile boolean _resumed=false;
|
|
||||||
private volatile boolean _expired=false;
|
|
||||||
private volatile boolean _responseWrapped=false;
|
|
||||||
|
|
||||||
private long _timeoutMs=-1;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Servlet3Continuation(ServletRequest request)
|
|
||||||
{
|
|
||||||
_request=request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void addContinuationListener(final ContinuationListener listener)
|
|
||||||
{
|
|
||||||
_listeners.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void complete()
|
|
||||||
{
|
|
||||||
AsyncContext context=_context;
|
|
||||||
if (context==null)
|
|
||||||
throw new IllegalStateException();
|
|
||||||
_context.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public ServletResponse getServletResponse()
|
|
||||||
{
|
|
||||||
return _response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public boolean isExpired()
|
|
||||||
{
|
|
||||||
return _expired;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public boolean isInitial()
|
|
||||||
{
|
|
||||||
return _initial&&_request.getDispatcherType()!=DispatcherType.ASYNC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public boolean isResumed()
|
|
||||||
{
|
|
||||||
return _resumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public boolean isSuspended()
|
|
||||||
{
|
|
||||||
if (_request.isAsyncStarted())
|
|
||||||
return true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return _request.getAsyncContext()!=null;
|
|
||||||
}
|
|
||||||
catch(IllegalStateException e)
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void keepWrappers()
|
|
||||||
{
|
|
||||||
_responseWrapped=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void resume()
|
|
||||||
{
|
|
||||||
AsyncContext context=_context;
|
|
||||||
if (context==null)
|
|
||||||
throw new IllegalStateException();
|
|
||||||
_resumed=true;
|
|
||||||
_context.dispatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void setTimeout(long timeoutMs)
|
|
||||||
{
|
|
||||||
_timeoutMs=timeoutMs;
|
|
||||||
if (_context!=null)
|
|
||||||
_context.setTimeout(timeoutMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void suspend(ServletResponse response)
|
|
||||||
{
|
|
||||||
_response=response;
|
|
||||||
_responseWrapped=response instanceof ServletResponseWrapper;
|
|
||||||
_resumed=false;
|
|
||||||
_expired=false;
|
|
||||||
_context=_request.startAsync();
|
|
||||||
_context.setTimeout(_timeoutMs);
|
|
||||||
_context.addListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void suspend()
|
|
||||||
{
|
|
||||||
_resumed=false;
|
|
||||||
_expired=false;
|
|
||||||
_context=_request.startAsync();
|
|
||||||
_context.setTimeout(_timeoutMs);
|
|
||||||
_context.addListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public boolean isResponseWrapped()
|
|
||||||
{
|
|
||||||
return _responseWrapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.continuation.Continuation#getAttribute(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object getAttribute(String name)
|
|
||||||
{
|
|
||||||
return _request.getAttribute(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.continuation.Continuation#removeAttribute(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void removeAttribute(String name)
|
|
||||||
{
|
|
||||||
_request.removeAttribute(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.continuation.Continuation#setAttribute(java.lang.String, java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setAttribute(String name, Object attribute)
|
|
||||||
{
|
|
||||||
_request.setAttribute(name,attribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.continuation.Continuation#undispatch()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void undispatch()
|
|
||||||
{
|
|
||||||
if (isSuspended())
|
|
||||||
{
|
|
||||||
_initial=false;
|
|
||||||
if (ContinuationFilter.__debug)
|
|
||||||
throw new ContinuationThrowable();
|
|
||||||
throw __exception;
|
|
||||||
}
|
|
||||||
throw new IllegalStateException("!suspended");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void onComplete(AsyncEvent event) throws IOException
|
|
||||||
{
|
|
||||||
for (ContinuationListener listener:_listeners)
|
|
||||||
listener.onComplete(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void onError(AsyncEvent event) throws IOException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void onStartAsync(AsyncEvent event) throws IOException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void onTimeout(AsyncEvent event) throws IOException
|
|
||||||
{
|
|
||||||
_expired=true;
|
|
||||||
for (ContinuationListener listener:_listeners)
|
|
||||||
listener.onTimeout(this);
|
|
||||||
if (event.getSuppliedRequest().isAsyncStarted())
|
|
||||||
event.getAsyncContext().dispatch();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jetty Continuation : <em>DEPRECATED: use Servlet 3.0 {@link javax.servlet.AsyncContext} instead</em>
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
package org.eclipse.jetty.continuation;
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
|||||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||||
|
|
||||||
<Array id="serverClasses" type="java.lang.String">
|
<Array id="serverClasses" type="java.lang.String">
|
||||||
<Item>-org.eclipse.jetty.continuation.</Item>
|
|
||||||
<Item>-org.eclipse.jetty.jndi.</Item>
|
<Item>-org.eclipse.jetty.jndi.</Item>
|
||||||
<Item>-org.eclipse.jetty.plus.jaas.</Item>
|
<Item>-org.eclipse.jetty.plus.jaas.</Item>
|
||||||
<Item>-org.eclipse.jetty.websocket.</Item>
|
<Item>-org.eclipse.jetty.websocket.</Item>
|
||||||
@ -19,7 +18,6 @@
|
|||||||
<Item>org.xml.</Item>
|
<Item>org.xml.</Item>
|
||||||
<Item>org.w3c.</Item>
|
<Item>org.w3c.</Item>
|
||||||
<Item>org.apache.commons.logging</Item>
|
<Item>org.apache.commons.logging</Item>
|
||||||
<Item>org.eclipse.jetty.continuation</Item>
|
|
||||||
<Item>org.eclipse.jetty.plus.jaas.</Item>
|
<Item>org.eclipse.jetty.plus.jaas.</Item>
|
||||||
<Item>org.eclipse.jetty.websocket</Item>
|
<Item>org.eclipse.jetty.websocket</Item>
|
||||||
<Item>org.eclipse.jetty.servlet.DefaultServlet</Item>
|
<Item>org.eclipse.jetty.servlet.DefaultServlet</Item>
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
</Call>
|
</Call>
|
||||||
|
|
||||||
<!-- Array id="serverClasses" type="java.lang.String">
|
<!-- Array id="serverClasses" type="java.lang.String">
|
||||||
<Item>-org.eclipse.jetty.continuation.</Item>
|
|
||||||
<Item>-org.eclipse.jetty.jndi.</Item>
|
<Item>-org.eclipse.jetty.jndi.</Item>
|
||||||
<Item>-org.eclipse.jetty.plus.jaas.</Item>
|
<Item>-org.eclipse.jetty.plus.jaas.</Item>
|
||||||
<Item>-org.eclipse.jetty.websocket.</Item>
|
<Item>-org.eclipse.jetty.websocket.</Item>
|
||||||
@ -22,7 +21,6 @@
|
|||||||
<Item>org.xml.</Item>
|
<Item>org.xml.</Item>
|
||||||
<Item>org.w3c.</Item>
|
<Item>org.w3c.</Item>
|
||||||
<Item>org.apache.commons.logging</Item>
|
<Item>org.apache.commons.logging</Item>
|
||||||
<Item>org.eclipse.jetty.continuation</Item>
|
|
||||||
<Item>org.eclipse.jetty.plus.jaas.</Item>
|
<Item>org.eclipse.jetty.plus.jaas.</Item>
|
||||||
<Item>org.eclipse.jetty.websocket</Item>
|
<Item>org.eclipse.jetty.websocket</Item>
|
||||||
<Item>org.eclipse.jetty.servlet.DefaultServlet</Item>
|
<Item>org.eclipse.jetty.servlet.DefaultServlet</Item>
|
||||||
|
@ -350,7 +350,7 @@
|
|||||||
<arguments>
|
<arguments>
|
||||||
<argument>jetty.home=${assembly-directory}</argument>
|
<argument>jetty.home=${assembly-directory}</argument>
|
||||||
<argument>jetty.base=${assembly-directory}/demo-base</argument>
|
<argument>jetty.base=${assembly-directory}/demo-base</argument>
|
||||||
<argument>--add-to-startd=server,continuation,deploy,websocket,ext,resources,client,annotations,jndi,servlets,jsp,jstl,http,https,test-keystore</argument>
|
<argument>--add-to-startd=server,deploy,websocket,ext,resources,client,annotations,jndi,servlets,jsp,jstl,http,https,test-keystore</argument>
|
||||||
</arguments>
|
</arguments>
|
||||||
</configuration>
|
</configuration>
|
||||||
<goals>
|
<goals>
|
||||||
|
@ -450,11 +450,6 @@
|
|||||||
<artifactId>jetty-client</artifactId>
|
<artifactId>jetty-client</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-continuation</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-proxy</artifactId>
|
<artifactId>jetty-proxy</artifactId>
|
||||||
|
@ -104,11 +104,6 @@
|
|||||||
<artifactId>jetty-annotations</artifactId>
|
<artifactId>jetty-annotations</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-continuation</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-websocket</artifactId>
|
<artifactId>jetty-websocket</artifactId>
|
||||||
|
@ -32,10 +32,6 @@
|
|||||||
<!-- =========================================================== -->
|
<!-- =========================================================== -->
|
||||||
<!-- One of each type! -->
|
<!-- One of each type! -->
|
||||||
<!-- =========================================================== -->
|
<!-- =========================================================== -->
|
||||||
|
|
||||||
<!-- Use this connector for many frequently idle connections
|
|
||||||
and for threadless continuations.
|
|
||||||
-->
|
|
||||||
<Call name="addConnector">
|
<Call name="addConnector">
|
||||||
<Arg>
|
<Arg>
|
||||||
<New class="org.eclipse.jetty.server.ServerConnector">
|
<New class="org.eclipse.jetty.server.ServerConnector">
|
||||||
|
@ -1367,7 +1367,6 @@ public class ServletHandler extends ScopedHandler
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PathMappings<ServletHolder> pm = new PathMappings<>();
|
PathMappings<ServletHolder> pm = new PathMappings<>();
|
||||||
Map<String,ServletMapping> servletPathMappings = new HashMap<>();
|
|
||||||
|
|
||||||
//create a map of paths to set of ServletMappings that define that mapping
|
//create a map of paths to set of ServletMappings that define that mapping
|
||||||
HashMap<String, List<ServletMapping>> sms = new HashMap<>();
|
HashMap<String, List<ServletMapping>> sms = new HashMap<>();
|
||||||
@ -1445,7 +1444,6 @@ public class ServletHandler extends ScopedHandler
|
|||||||
finalMapping.getServletName(),
|
finalMapping.getServletName(),
|
||||||
_servletNameMap.get(finalMapping.getServletName()).getSource());
|
_servletNameMap.get(finalMapping.getServletName()).getSource());
|
||||||
|
|
||||||
servletPathMappings.put(pathSpec, finalMapping);
|
|
||||||
pm.put(new ServletPathSpec(pathSpec),_servletNameMap.get(finalMapping.getServletName()));
|
pm.put(new ServletPathSpec(pathSpec),_servletNameMap.get(finalMapping.getServletName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,11 +25,6 @@
|
|||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-continuation</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-http</artifactId>
|
<artifactId>jetty-http</artifactId>
|
||||||
|
1
pom.xml
1
pom.xml
@ -51,7 +51,6 @@
|
|||||||
<module>jetty-io</module>
|
<module>jetty-io</module>
|
||||||
<module>jetty-http</module>
|
<module>jetty-http</module>
|
||||||
<module>jetty-http2</module>
|
<module>jetty-http2</module>
|
||||||
<module>jetty-continuation</module>
|
|
||||||
<module>jetty-server</module>
|
<module>jetty-server</module>
|
||||||
<module>jetty-xml</module>
|
<module>jetty-xml</module>
|
||||||
<module>jetty-security</module>
|
<module>jetty-security</module>
|
||||||
|
@ -53,7 +53,6 @@
|
|||||||
<modules>
|
<modules>
|
||||||
<module>test-webapps</module>
|
<module>test-webapps</module>
|
||||||
<module>test-sessions</module>
|
<module>test-sessions</module>
|
||||||
<module>test-continuation</module>
|
|
||||||
<module>test-loginservice</module>
|
<module>test-loginservice</module>
|
||||||
<module>test-integration</module>
|
<module>test-integration</module>
|
||||||
<module>test-quickstart</module>
|
<module>test-quickstart</module>
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
|
||||||
<parent>
|
|
||||||
<groupId>org.eclipse.jetty.tests</groupId>
|
|
||||||
<artifactId>tests-parent</artifactId>
|
|
||||||
<version>10.0.0-SNAPSHOT</version>
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>test-continuation</artifactId>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
<name>Test :: Continuation</name>
|
|
||||||
<description>Asynchronous API</description>
|
|
||||||
<properties>
|
|
||||||
<bundle-symbolic-name>${project.groupId}.continuation</bundle-symbolic-name>
|
|
||||||
</properties>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-deploy-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<!-- DO NOT DEPLOY (or Release) -->
|
|
||||||
<skip>true</skip>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-servlet</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-continuation</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
|
||||||
<artifactId>jetty-test-helper</artifactId>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
@ -1,666 +0,0 @@
|
|||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.continuation;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServlet;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Handler;
|
|
||||||
import org.eclipse.jetty.server.Request;
|
|
||||||
import org.eclipse.jetty.server.RequestLog;
|
|
||||||
import org.eclipse.jetty.server.Response;
|
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.server.ServerConnector;
|
|
||||||
import org.eclipse.jetty.server.handler.RequestLogHandler;
|
|
||||||
import org.eclipse.jetty.server.handler.StatisticsHandler;
|
|
||||||
import org.eclipse.jetty.servlet.FilterHolder;
|
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
|
||||||
import org.eclipse.jetty.util.IO;
|
|
||||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
import org.junit.runners.Parameterized.Parameter;
|
|
||||||
import org.junit.runners.Parameterized.Parameters;
|
|
||||||
|
|
||||||
@RunWith(Parameterized.class)
|
|
||||||
public class ContinuationsTest
|
|
||||||
{
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public static class SneakyList extends ArrayList<String> {
|
|
||||||
@Override
|
|
||||||
public boolean add(String e)
|
|
||||||
{
|
|
||||||
// System.err.printf("add(%s)%n",e);
|
|
||||||
return super.add(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Parameters(name="{0}")
|
|
||||||
public static List<Object[]> data()
|
|
||||||
{
|
|
||||||
List<Object[]> setup = new ArrayList<>();
|
|
||||||
|
|
||||||
// Servlet3 / AsyncContext Setup
|
|
||||||
{
|
|
||||||
String description = "Servlet 3 Setup";
|
|
||||||
Class<? extends Continuation> expectedImplClass = Servlet3Continuation.class;
|
|
||||||
List<String> log = new ArrayList<>();
|
|
||||||
RequestLogHandler servlet3Setup = new RequestLogHandler();
|
|
||||||
servlet3Setup.setRequestLog(new Log(log));
|
|
||||||
|
|
||||||
ServletContextHandler servletContext = new ServletContextHandler();
|
|
||||||
servlet3Setup.setHandler(servletContext);
|
|
||||||
|
|
||||||
ServletHandler servletHandler=servletContext.getServletHandler();
|
|
||||||
List<String> history = new SneakyList();
|
|
||||||
Listener listener = new Listener(history);
|
|
||||||
ServletHolder holder=new ServletHolder(new SuspendServlet(history, listener));
|
|
||||||
holder.setAsyncSupported(true);
|
|
||||||
servletHandler.addServletWithMapping(holder, "/");
|
|
||||||
setup.add(new Object[]{description,servlet3Setup,history,listener,expectedImplClass,log});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Faux Continuations Setup
|
|
||||||
{
|
|
||||||
String description = "Faux Setup";
|
|
||||||
Class<? extends Continuation> expectedImplClass = FauxContinuation.class;
|
|
||||||
|
|
||||||
// no log for this setup
|
|
||||||
List<String> log = null;
|
|
||||||
|
|
||||||
ServletContextHandler fauxSetup = new ServletContextHandler();
|
|
||||||
ServletHandler servletHandler=fauxSetup.getServletHandler();
|
|
||||||
List<String> history = new SneakyList();
|
|
||||||
Listener listener = new Listener(history);
|
|
||||||
ServletHolder holder=new ServletHolder(new SuspendServlet(history, listener));
|
|
||||||
servletHandler.addServletWithMapping(holder,"/");
|
|
||||||
|
|
||||||
FilterHolder filter= servletHandler.addFilterWithMapping(ContinuationFilter.class,"/*",null);
|
|
||||||
filter.setInitParameter("debug","true");
|
|
||||||
filter.setInitParameter("faux","true");
|
|
||||||
setup.add(new Object[]{description,fauxSetup,history,listener,expectedImplClass,log});
|
|
||||||
}
|
|
||||||
|
|
||||||
return setup;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Parameter(0)
|
|
||||||
public String setupDescription;
|
|
||||||
|
|
||||||
@Parameter(1)
|
|
||||||
public Handler setupHandler;
|
|
||||||
|
|
||||||
@Parameter(2)
|
|
||||||
public List<String> history;
|
|
||||||
|
|
||||||
@Parameter(3)
|
|
||||||
public Listener listener;
|
|
||||||
|
|
||||||
@Parameter(4)
|
|
||||||
public Class<? extends Continuation> expectedImplClass;
|
|
||||||
|
|
||||||
@Parameter(5)
|
|
||||||
public List<String> log;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNormal() throws Exception
|
|
||||||
{
|
|
||||||
String response = process(null, null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("NORMAL"));
|
|
||||||
assertThat(history, hasItem(expectedImplClass.getName()));
|
|
||||||
assertThat(history, not(hasItem("onTimeout")));
|
|
||||||
assertThat(history, not(hasItem("onComplete")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSleep() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("sleep=200", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("SLEPT"));
|
|
||||||
assertThat(history, not(hasItem("onTimeout")));
|
|
||||||
assertThat(history, not(hasItem("onComplete")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspend() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=200", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("TIMEOUT"));
|
|
||||||
assertThat(history, hasItem("onTimeout"));
|
|
||||||
assertThat(history, hasItem("onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendWaitResume() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=200&resume=10", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("RESUMED"));
|
|
||||||
assertThat(history, not(hasItem("onTimeout")));
|
|
||||||
assertThat(history, hasItem("onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendResume() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=200&resume=0", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("RESUMED"));
|
|
||||||
assertThat(history, not(hasItem("onTimeout")));
|
|
||||||
assertThat(history, hasItem("onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendWaitComplete() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=200&complete=50", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("COMPLETED"));
|
|
||||||
assertThat(history, hasItem("initial"));
|
|
||||||
assertThat(history, not(hasItem("!initial")));
|
|
||||||
assertThat(history, not(hasItem("onTimeout")));
|
|
||||||
assertThat(history, hasItem("onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendComplete() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=200&complete=0", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("COMPLETED"));
|
|
||||||
assertThat(history, hasItem("initial"));
|
|
||||||
assertThat(history, not(hasItem("!initial")));
|
|
||||||
assertThat(history, not(hasItem("onTimeout")));
|
|
||||||
assertThat(history, hasItem("onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendWaitResumeSuspendWaitResume() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=1000&resume=10&suspend2=1000&resume2=10", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("RESUMED"));
|
|
||||||
assertEquals(2, count(history, "suspend"));
|
|
||||||
assertEquals(2, count(history, "resume"));
|
|
||||||
assertEquals(0, count(history, "onTimeout"));
|
|
||||||
assertEquals(1, count(history, "onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendWaitResumeSuspendComplete() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=1000&resume=10&suspend2=1000&complete2=10", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("COMPLETED"));
|
|
||||||
assertEquals(2, count(history, "suspend"));
|
|
||||||
assertEquals(1, count(history, "resume"));
|
|
||||||
assertEquals(0, count(history, "onTimeout"));
|
|
||||||
assertEquals(1, count(history, "onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendWaitResumeSuspend() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=1000&resume=10&suspend2=10", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("TIMEOUT"));
|
|
||||||
assertEquals(2, count(history, "suspend"));
|
|
||||||
assertEquals(1, count(history, "resume"));
|
|
||||||
assertEquals(1, count(history, "onTimeout"));
|
|
||||||
assertEquals(1, count(history, "onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendTimeoutSuspendResume() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=10&suspend2=1000&resume2=10", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("RESUMED"));
|
|
||||||
assertEquals(2, count(history, "suspend"));
|
|
||||||
assertEquals(1, count(history, "resume"));
|
|
||||||
assertEquals(1, count(history, "onTimeout"));
|
|
||||||
assertEquals(1, count(history, "onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendTimeoutSuspendComplete() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=10&suspend2=1000&complete2=10", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("COMPLETED"));
|
|
||||||
assertEquals(2, count(history, "suspend"));
|
|
||||||
assertEquals(0, count(history, "resume"));
|
|
||||||
assertEquals(1, count(history, "onTimeout"));
|
|
||||||
assertEquals(1, count(history, "onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendTimeoutSuspend() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=10&suspend2=10", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("TIMEOUT"));
|
|
||||||
assertEquals(2, count(history, "suspend"));
|
|
||||||
assertEquals(0, count(history, "resume"));
|
|
||||||
assertEquals(2, count(history, "onTimeout"));
|
|
||||||
assertEquals(1, count(history, "onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendThrowResume() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=200&resume=10&undispatch=true", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("RESUMED"));
|
|
||||||
assertThat(history, not(hasItem("onTimeout")));
|
|
||||||
assertThat(history, hasItem("onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendResumeThrow() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=200&resume=0&undispatch=true", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("RESUMED"));
|
|
||||||
assertThat(history, not(hasItem("onTimeout")));
|
|
||||||
assertThat(history, hasItem("onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendThrowComplete() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=200&complete=10&undispatch=true", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("COMPLETED"));
|
|
||||||
assertThat(history, not(hasItem("onTimeout")));
|
|
||||||
assertThat(history, hasItem("onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuspendCompleteThrow() throws Exception
|
|
||||||
{
|
|
||||||
String response = process("suspend=200&complete=0&undispatch=true", null);
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, containsString("COMPLETED"));
|
|
||||||
assertThat(history, not(hasItem("onTimeout")));
|
|
||||||
assertThat(history, hasItem("onComplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private long count(List<String> history, String value)
|
|
||||||
{
|
|
||||||
return history.stream()
|
|
||||||
.filter(value::equals)
|
|
||||||
.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String process(String query, String content) throws Exception
|
|
||||||
{
|
|
||||||
Server server = new Server();
|
|
||||||
server.setStopTimeout(20000);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ServerConnector connector = new ServerConnector(server);
|
|
||||||
server.addConnector(connector);
|
|
||||||
if(log != null)
|
|
||||||
{
|
|
||||||
log.clear();
|
|
||||||
}
|
|
||||||
history.clear();
|
|
||||||
StatisticsHandler stats = new StatisticsHandler();
|
|
||||||
server.setHandler(stats);
|
|
||||||
stats.setHandler(this.setupHandler);
|
|
||||||
|
|
||||||
server.start();
|
|
||||||
int port=connector.getLocalPort();
|
|
||||||
|
|
||||||
StringBuilder request = new StringBuilder("GET /");
|
|
||||||
|
|
||||||
if (query != null)
|
|
||||||
request.append("?").append(query);
|
|
||||||
|
|
||||||
request.append(" HTTP/1.1\r\n")
|
|
||||||
.append("Host: localhost\r\n")
|
|
||||||
.append("Connection: close\r\n");
|
|
||||||
|
|
||||||
if (content == null)
|
|
||||||
{
|
|
||||||
request.append("\r\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
request.append("Content-Length: ").append(content.length()).append("\r\n");
|
|
||||||
request.append("\r\n").append(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
try (Socket socket = new Socket("localhost", port))
|
|
||||||
{
|
|
||||||
socket.setSoTimeout(10000);
|
|
||||||
socket.getOutputStream().write(request.toString().getBytes(StandardCharsets.UTF_8));
|
|
||||||
socket.getOutputStream().flush();
|
|
||||||
return toString(socket.getInputStream());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (log != null)
|
|
||||||
{
|
|
||||||
for (int i=0;log.isEmpty()&&i<60;i++)
|
|
||||||
{
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
assertThat("Log.size", log.size(),is(1));
|
|
||||||
String entry = log.get(0);
|
|
||||||
assertThat("Log entry", entry, startsWith("200 "));
|
|
||||||
assertThat("Log entry", entry, endsWith(" /"));
|
|
||||||
}
|
|
||||||
server.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String toString(InputStream in) throws IOException
|
|
||||||
{
|
|
||||||
return IO.toString(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
private static class SuspendServlet extends HttpServlet
|
|
||||||
{
|
|
||||||
private final Timer _timer = new Timer();
|
|
||||||
private final List<String> history;
|
|
||||||
private final ContinuationListener listener;
|
|
||||||
|
|
||||||
public SuspendServlet(List<String> history, ContinuationListener listener)
|
|
||||||
{
|
|
||||||
this.history = history;
|
|
||||||
this.listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
|
|
||||||
{
|
|
||||||
final Continuation continuation = ContinuationSupport.getContinuation(request);
|
|
||||||
|
|
||||||
history.add(continuation.getClass().getName());
|
|
||||||
|
|
||||||
int read_before = 0;
|
|
||||||
long sleep_for = -1;
|
|
||||||
long suspend_for = -1;
|
|
||||||
long suspend2_for = -1;
|
|
||||||
long resume_after = -1;
|
|
||||||
long resume2_after = -1;
|
|
||||||
long complete_after = -1;
|
|
||||||
long complete2_after = -1;
|
|
||||||
boolean undispatch = false;
|
|
||||||
|
|
||||||
if (request.getParameter("read") != null)
|
|
||||||
read_before = Integer.parseInt(request.getParameter("read"));
|
|
||||||
if (request.getParameter("sleep") != null)
|
|
||||||
sleep_for = Integer.parseInt(request.getParameter("sleep"));
|
|
||||||
if (request.getParameter("suspend") != null)
|
|
||||||
suspend_for = Integer.parseInt(request.getParameter("suspend"));
|
|
||||||
if (request.getParameter("suspend2") != null)
|
|
||||||
suspend2_for = Integer.parseInt(request.getParameter("suspend2"));
|
|
||||||
if (request.getParameter("resume") != null)
|
|
||||||
resume_after = Integer.parseInt(request.getParameter("resume"));
|
|
||||||
if (request.getParameter("resume2") != null)
|
|
||||||
resume2_after = Integer.parseInt(request.getParameter("resume2"));
|
|
||||||
if (request.getParameter("complete") != null)
|
|
||||||
complete_after = Integer.parseInt(request.getParameter("complete"));
|
|
||||||
if (request.getParameter("complete2") != null)
|
|
||||||
complete2_after = Integer.parseInt(request.getParameter("complete2"));
|
|
||||||
if (request.getParameter("undispatch") != null)
|
|
||||||
undispatch = Boolean.parseBoolean(request.getParameter("undispatch"));
|
|
||||||
|
|
||||||
if (continuation.isInitial())
|
|
||||||
{
|
|
||||||
history.add("initial");
|
|
||||||
if (read_before > 0)
|
|
||||||
{
|
|
||||||
byte[] buf = new byte[read_before];
|
|
||||||
request.getInputStream().read(buf);
|
|
||||||
}
|
|
||||||
else if (read_before < 0)
|
|
||||||
{
|
|
||||||
InputStream in = request.getInputStream();
|
|
||||||
int b = in.read();
|
|
||||||
while (b != -1)
|
|
||||||
b = in.read();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (suspend_for >= 0)
|
|
||||||
{
|
|
||||||
if (suspend_for > 0)
|
|
||||||
continuation.setTimeout(suspend_for);
|
|
||||||
continuation.addContinuationListener(listener);
|
|
||||||
history.add("suspend");
|
|
||||||
continuation.suspend(response);
|
|
||||||
|
|
||||||
if (complete_after > 0)
|
|
||||||
{
|
|
||||||
TimerTask complete = new TimerTask()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
response.setStatus(200);
|
|
||||||
response.getOutputStream().println("COMPLETED");
|
|
||||||
continuation.complete();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_timer.schedule(complete, complete_after);
|
|
||||||
}
|
|
||||||
else if (complete_after == 0)
|
|
||||||
{
|
|
||||||
response.setStatus(200);
|
|
||||||
response.getOutputStream().println("COMPLETED");
|
|
||||||
continuation.complete();
|
|
||||||
}
|
|
||||||
else if (resume_after > 0)
|
|
||||||
{
|
|
||||||
TimerTask resume = new TimerTask()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
history.add("resume");
|
|
||||||
continuation.resume();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_timer.schedule(resume, resume_after);
|
|
||||||
}
|
|
||||||
else if (resume_after == 0)
|
|
||||||
{
|
|
||||||
history.add("resume");
|
|
||||||
continuation.resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (undispatch)
|
|
||||||
{
|
|
||||||
continuation.undispatch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (sleep_for >= 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Thread.sleep(sleep_for);
|
|
||||||
}
|
|
||||||
catch (InterruptedException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
response.setStatus(200);
|
|
||||||
response.getOutputStream().println("SLEPT");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response.setStatus(200);
|
|
||||||
response.getOutputStream().println("NORMAL");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
history.add("!initial");
|
|
||||||
if (suspend2_for >= 0 && request.getAttribute("2nd") == null)
|
|
||||||
{
|
|
||||||
request.setAttribute("2nd", "cycle");
|
|
||||||
|
|
||||||
if (suspend2_for > 0)
|
|
||||||
continuation.setTimeout(suspend2_for);
|
|
||||||
|
|
||||||
history.add("suspend");
|
|
||||||
continuation.suspend(response);
|
|
||||||
|
|
||||||
if (complete2_after > 0)
|
|
||||||
{
|
|
||||||
TimerTask complete = new TimerTask()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
response.setStatus(200);
|
|
||||||
response.getOutputStream().println("COMPLETED");
|
|
||||||
continuation.complete();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_timer.schedule(complete, complete2_after);
|
|
||||||
}
|
|
||||||
else if (complete2_after == 0)
|
|
||||||
{
|
|
||||||
response.setStatus(200);
|
|
||||||
response.getOutputStream().println("COMPLETED");
|
|
||||||
continuation.complete();
|
|
||||||
}
|
|
||||||
else if (resume2_after > 0)
|
|
||||||
{
|
|
||||||
TimerTask resume = new TimerTask()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
history.add("resume");
|
|
||||||
continuation.resume();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_timer.schedule(resume, resume2_after);
|
|
||||||
}
|
|
||||||
else if (resume2_after == 0)
|
|
||||||
{
|
|
||||||
history.add("resume");
|
|
||||||
continuation.resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (undispatch)
|
|
||||||
{
|
|
||||||
continuation.undispatch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (continuation.isExpired())
|
|
||||||
{
|
|
||||||
response.setStatus(200);
|
|
||||||
response.getOutputStream().println("TIMEOUT");
|
|
||||||
}
|
|
||||||
else if (continuation.isResumed())
|
|
||||||
{
|
|
||||||
response.setStatus(200);
|
|
||||||
response.getOutputStream().println("RESUMED");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response.setStatus(200);
|
|
||||||
response.getOutputStream().println("UNKNOWN");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Listener implements ContinuationListener
|
|
||||||
{
|
|
||||||
private final List<String> history;
|
|
||||||
|
|
||||||
public Listener(List<String> history)
|
|
||||||
{
|
|
||||||
this.history = history;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onComplete(Continuation continuation)
|
|
||||||
{
|
|
||||||
history.add("onComplete");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTimeout(Continuation continuation)
|
|
||||||
{
|
|
||||||
history.add("onTimeout");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Log extends AbstractLifeCycle implements RequestLog
|
|
||||||
{
|
|
||||||
private final List<String> log;
|
|
||||||
|
|
||||||
public Log(List<String> log)
|
|
||||||
{
|
|
||||||
this.log = log;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void log(Request request, Response response)
|
|
||||||
{
|
|
||||||
int status = response.getCommittedMetaData().getStatus();
|
|
||||||
long written = response.getHttpChannel().getBytesWritten();
|
|
||||||
log.add(status+" "+written+" "+request.getRequestURI());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
|
||||||
org.eclipse.jetty.LEVEL=WARN
|
|
||||||
# org.eclipse.jetty.server.LEVEL=DEBUG
|
|
@ -137,11 +137,6 @@
|
|||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-continuation</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-servlets</artifactId>
|
<artifactId>jetty-servlets</artifactId>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user