Issue #1676 Removed deprecated module jetty-continuations

This commit is contained in:
Greg Wilkins 2017-07-18 15:42:14 +02:00
parent 748d582994
commit 79cafb37a0
26 changed files with 2 additions and 2426 deletions

View File

@ -57,8 +57,6 @@
<includes>**/*</includes>
<excludes>
META-INF/**,
**/Servlet3Continuation*,
**/Jetty6Continuation*,
**/AppContextLeakPreventer*.java,
**/AWTLeakPreventer*.java,
**/IntrospectorCleaner*.java,

View File

@ -39,7 +39,7 @@
<configuration>
<classifier>sources</classifier>
<includes>**/*</includes>
<excludes>META-INF/**,**/Servlet3Continuation*,**/Jetty6Continuation*</excludes>
<excludes>META-INF/**</excludes>
<includeGroupIds>org.eclipse.jetty,org.eclipse.jetty.websocket</includeGroupIds>
<excludeArtifactIds>javax</excludeArtifactIds>
<excludeGroupIds>javax,org.eclipse.jetty.orbit,org.mortbay.jetty.alpn</excludeGroupIds>

View File

@ -156,11 +156,6 @@
<artifactId>jetty-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-continuation</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-deploy</artifactId>

View File

@ -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>

View File

@ -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 &lt;=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;
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -4,7 +4,6 @@
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Array id="serverClasses" type="java.lang.String">
<Item>-org.eclipse.jetty.continuation.</Item>
<Item>-org.eclipse.jetty.jndi.</Item>
<Item>-org.eclipse.jetty.plus.jaas.</Item>
<Item>-org.eclipse.jetty.websocket.</Item>
@ -19,7 +18,6 @@
<Item>org.xml.</Item>
<Item>org.w3c.</Item>
<Item>org.apache.commons.logging</Item>
<Item>org.eclipse.jetty.continuation</Item>
<Item>org.eclipse.jetty.plus.jaas.</Item>
<Item>org.eclipse.jetty.websocket</Item>
<Item>org.eclipse.jetty.servlet.DefaultServlet</Item>

View File

@ -7,7 +7,6 @@
</Call>
<!-- Array id="serverClasses" type="java.lang.String">
<Item>-org.eclipse.jetty.continuation.</Item>
<Item>-org.eclipse.jetty.jndi.</Item>
<Item>-org.eclipse.jetty.plus.jaas.</Item>
<Item>-org.eclipse.jetty.websocket.</Item>
@ -22,7 +21,6 @@
<Item>org.xml.</Item>
<Item>org.w3c.</Item>
<Item>org.apache.commons.logging</Item>
<Item>org.eclipse.jetty.continuation</Item>
<Item>org.eclipse.jetty.plus.jaas.</Item>
<Item>org.eclipse.jetty.websocket</Item>
<Item>org.eclipse.jetty.servlet.DefaultServlet</Item>

View File

@ -350,7 +350,7 @@
<arguments>
<argument>jetty.home=${assembly-directory}</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>
</configuration>
<goals>

View File

@ -450,11 +450,6 @@
<artifactId>jetty-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-continuation</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-proxy</artifactId>

View File

@ -104,11 +104,6 @@
<artifactId>jetty-annotations</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-continuation</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>

View File

@ -32,10 +32,6 @@
<!-- =========================================================== -->
<!-- One of each type! -->
<!-- =========================================================== -->
<!-- Use this connector for many frequently idle connections
and for threadless continuations.
-->
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.ServerConnector">

View File

@ -1367,7 +1367,6 @@ public class ServletHandler extends ScopedHandler
else
{
PathMappings<ServletHolder> pm = new PathMappings<>();
Map<String,ServletMapping> servletPathMappings = new HashMap<>();
//create a map of paths to set of ServletMappings that define that mapping
HashMap<String, List<ServletMapping>> sms = new HashMap<>();
@ -1445,7 +1444,6 @@ public class ServletHandler extends ScopedHandler
finalMapping.getServletName(),
_servletNameMap.get(finalMapping.getServletName()).getSource());
servletPathMappings.put(pathSpec, finalMapping);
pm.put(new ServletPathSpec(pathSpec),_servletNameMap.get(finalMapping.getServletName()));
}

View File

@ -25,11 +25,6 @@
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-continuation</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>

View File

@ -51,7 +51,6 @@
<module>jetty-io</module>
<module>jetty-http</module>
<module>jetty-http2</module>
<module>jetty-continuation</module>
<module>jetty-server</module>
<module>jetty-xml</module>
<module>jetty-security</module>

View File

@ -53,7 +53,6 @@
<modules>
<module>test-webapps</module>
<module>test-sessions</module>
<module>test-continuation</module>
<module>test-loginservice</module>
<module>test-integration</module>
<module>test-quickstart</module>

View File

@ -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>

View File

@ -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());
}
}
}

View File

@ -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

View File

@ -137,11 +137,6 @@
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-continuation</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>