Author: remy.maucherat(a)jboss.com
Date: 2009-10-08 06:44:14 -0400 (Thu, 08 Oct 2009)
New Revision: 1185
Modified:
trunk/java/javax/servlet/AsyncContext.java
trunk/java/javax/servlet/AsyncEvent.java
trunk/java/javax/servlet/AsyncListener.java
trunk/java/javax/servlet/ServletRequest.java
trunk/java/javax/servlet/ServletRequestWrapper.java
trunk/java/org/apache/catalina/connector/Request.java
trunk/java/org/apache/catalina/connector/RequestFacade.java
trunk/java/org/apache/catalina/core/StandardWrapperValve.java
Log:
- Today's spec update.
- Add a todo for start event.
Modified: trunk/java/javax/servlet/AsyncContext.java
===================================================================
--- trunk/java/javax/servlet/AsyncContext.java 2009-10-07 11:59:37 UTC (rev 1184)
+++ trunk/java/javax/servlet/AsyncContext.java 2009-10-08 10:44:14 UTC (rev 1185)
@@ -214,9 +214,19 @@
* {@link #complete}.</li>
* </ol>
*
- * @exception IllegalStateException if {@link #complete} has already
- * been called
+ * <p>There can be at most one asynchronous dispatch operation per
+ * asynchronous cycle, which is started by a call to one of the
+ * {@link ServletRequest#startAsync} methods. Any attempt to perform an
+ * additional asynchronous dispatch operation within the same
+ * asynchronous cycle will result in an IllegalStateException.
+ * If startAsync is subsequently called on the dispatched request,
+ * then any of the dispatch or {@link #complete} methods may be called.
*
+ * @throws IllegalStateException if one of the dispatch methods
+ * has been called and the startAsync method has not been
+ * called during the resulting dispatch, or if {@link #complete}
+ * was called
+ *
* @see ServletRequest#getDispatcherType
*/
public void dispatch();
@@ -240,14 +250,24 @@
* attributes will always reflect the original path elements, even under
* repeated dispatches.
*
+ * <p>There can be at most one asynchronous dispatch operation per
+ * asynchronous cycle, which is started by a call to one of the
+ * {@link ServletRequest#startAsync} methods. Any attempt to perform an
+ * additional asynchronous dispatch operation within the same
+ * asynchronous cycle will result in an IllegalStateException.
+ * If startAsync is subsequently called on the dispatched request,
+ * then any of the dispatch or {@link #complete} methods may be called.
+ *
* <p>See {@link #dispatch()} for additional details, including error
* handling.
*
* @param path the path of the dispatch target, scoped to the
* ServletContext from which this AsyncContext was initialized
*
- * @exception IllegalStateException if {@link #complete} has already
- * been called
+ * @throws IllegalStateException if one of the dispatch methods
+ * has been called and the startAsync method has not been
+ * called during the resulting dispatch, or if {@link #complete}
+ * was called
*
* @see ServletRequest#getDispatcherType
*/
@@ -271,6 +291,14 @@
* attributes will always reflect the original path elements, even under
* repeated dispatches.
*
+ * <p>There can be at most one asynchronous dispatch operation per
+ * asynchronous cycle, which is started by a call to one of the
+ * {@link ServletRequest#startAsync} methods. Any attempt to perform an
+ * additional asynchronous dispatch operation within the same
+ * asynchronous cycle will result in an IllegalStateException.
+ * If startAsync is subsequently called on the dispatched request,
+ * then any of the dispatch or {@link #complete} methods may be called.
+ *
* <p>See {@link #dispatch()} for additional details, including error
* handling.
*
@@ -278,8 +306,10 @@
* @param path the path of the dispatch target, scoped to the given
* ServletContext
*
- * @exception IllegalStateException if {@link #complete} has already
- * been called
+ * @throws IllegalStateException if one of the dispatch methods
+ * has been called and the startAsync method has not been
+ * called during the resulting dispatch, or if {@link #complete}
+ * was called
*
* @see ServletRequest#getDispatcherType
*/
@@ -317,4 +347,105 @@
* @param run the asynchronous handler
*/
public void start(Runnable run);
+
+
+ /**
+ * Registers the given {@link AsyncListener} with the most recent
+ * asynchronous cycle that was started by a call to one of the
+ * {@link ServletRequest#startAsync} methods.
+ *
+ * <p>The given AsyncListener will receive an {@link AsyncEvent} when
+ * the asynchronous cycle completes successfully, times out, or results
+ * in an error.
+ *
+ * <p>AsyncListener instances will be notified in the order in which
+ * they were added.
+ *
+ * @param listener the AsyncListener to be registered
+ *
+ * @throws IllegalStateException if this method is called after
+ * the container-initiated dispatch, during which one of the
+ * {@link ServletRequest#startAsync} methods was called, has
+ * returned to the container
+ */
+ public void addListener(AsyncListener listener);
+
+
+ /**
+ * Registers the given {@link AsyncListener} with the most recent
+ * asynchronous cycle that was started by a call to one of the
+ * {@link ServletRequest#startAsync} methods.
+ *
+ * <p>The given AsyncListener will receive an {@link AsyncEvent} when
+ * the asynchronous cycle completes successfully, times out, or results
+ * in an error.
+ *
+ * <p>AsyncListener instances will be notified in the order in which
+ * they were added.
+ *
+ * <p>The given ServletRequest and ServletResponse objects will
+ * be made available to the given AsyncListener via the
+ * {@link AsyncEvent#getSuppliedRequest getSuppliedRequest} and
+ * {@link AsyncEvent#getSuppliedResponse getSuppliedResponse} methods,
+ * respectively, of the {@link AsyncEvent} delivered to it. These objects
+ * should not be read from or written to, respectively, at the time the
+ * AsyncEvent is delivered, because additional wrapping may have
+ * occurred since the given AsyncListener was registered, but may be used
+ * in order to release any resources associated with them.
+ *
+ * @param listener the AsyncListener to be registered
+ * @param servletRequest the ServletRequest that will be included
+ * in the AsyncEvent
+ * @param servletResponse the ServletResponse that will be included
+ * in the AsyncEvent
+ *
+ * @throws IllegalStateException if this method is called after
+ * the container-initiated dispatch, during which one of the
+ * {@link ServletRequest#startAsync} methods was called, has
+ * returned to the container
+ */
+ public void addListener(AsyncListener listener,
+ ServletRequest servletRequest,
+ ServletResponse servletResponse);
+
+
+ /**
+ * Sets the timeout (in milliseconds) for this AsyncContext.
+ *
+ * <p>The timeout applies to this AsyncContext once the
+ * container-initiated dispatch during which one of the
+ * {@link ServletRequest#startAsync} methods was called has
+ * returned to the container.
+ *
+ * <p>The timeout will expire if neither the {@link #complete} method
+ * nor any of the dispatch methods are called. A timeout value of
+ * zero or less indicates no timeout.
+ *
+ * <p>If {@link #setTimeout} is not called, then the container's
+ * default timeout, which is available via a call to
+ * {@link #getTimeout}, will apply.
+ *
+ * @param timeout the timeout in milliseconds
+ *
+ * @throws IllegalStateException if this method is called after
+ * the container-initiated dispatch, during which one of the
+ * {@link ServletRequest#startAsync} methods was called, has
+ * returned to the container
+ */
+ public void setTimeout(long timeout);
+
+
+ /**
+ * Gets the timeout (in milliseconds) for this AsyncContext.
+ *
+ * <p>This method returns the container's default timeout for
+ * asynchronous operations, or the timeout value passed to the most
+ * recent invocation of {@link #setTimeout}.
+ *
+ * <p>A timeout value of zero or less indicates no timeout.
+ *
+ * @return the timeout in milliseconds
+ */
+ public long getTimeout();
+
}
Modified: trunk/java/javax/servlet/AsyncEvent.java
===================================================================
--- trunk/java/javax/servlet/AsyncEvent.java 2009-10-07 11:59:37 UTC (rev 1184)
+++ trunk/java/javax/servlet/AsyncEvent.java 2009-10-08 10:44:14 UTC (rev 1185)
@@ -117,11 +117,11 @@
* Gets the ServletRequest from this AsyncEvent.
*
* <p>If the AsyncListener to which this AsyncEvent is being delivered
- * was added using {@link ServletRequest#addAsyncListener(AsyncListener,
+ * was added using {@link AsyncContext#addListener(AsyncListener,
* ServletRequest, ServletResponse)}, the returned ServletRequest
* will be the same as the one supplied to the above method.
* If the AsyncListener was added via
- * {@link ServletRequest#addAsyncListener(AsyncListener)}, this method
+ * {@link AsyncContext#addListener(AsyncListener)}, this method
* must return null.
*
* @return the ServletRequest that was used to initialize this AsyncEvent,
@@ -135,11 +135,11 @@
* Gets the ServletResponse from this AsyncEvent.
*
* <p>If the AsyncListener to which this AsyncEvent is being delivered
- * was added using {@link ServletRequest#addAsyncListener(AsyncListener,
+ * was added using {@link AsyncContext#addListener(AsyncListener,
* ServletRequest, ServletResponse)}, the returned ServletResponse
* will be the same as the one supplied to the above method.
* If the AsyncListener was added via
- * {@link ServletRequest#addAsyncListener(AsyncListener)}, this method
+ * {@link AsyncContext#addListener(AsyncListener)}, this method
* must return null.
*
* @return the ServletResponse that was used to initialize this AsyncEvent,
Modified: trunk/java/javax/servlet/AsyncListener.java
===================================================================
--- trunk/java/javax/servlet/AsyncListener.java 2009-10-07 11:59:37 UTC (rev 1184)
+++ trunk/java/javax/servlet/AsyncListener.java 2009-10-08 10:44:14 UTC (rev 1185)
@@ -58,7 +58,7 @@
* <tt>event</tt>.
*
* <p>In addition, if this AsyncListener had been registered via a call
- * to {@link ServletRequest#addAsyncListener(AsyncListener,
+ * to {@link AsyncContext#addListener(AsyncListener,
* ServletRequest, ServletResponse)}, the supplied ServletRequest and
* ServletResponse objects may be retrieved by calling
* {@link AsyncEvent#getSuppliedRequest getSuppliedRequest} and
@@ -84,7 +84,7 @@
* <tt>event</tt>.
*
* <p>In addition, if this AsyncListener had been registered via a call
- * to {@link ServletRequest#addAsyncListener(AsyncListener,
+ * to {@link AsyncContext#addListener(AsyncListener,
* ServletRequest, ServletResponse)}, the supplied ServletRequest and
* ServletResponse objects may be retrieved by calling
* {@link AsyncEvent#getSuppliedRequest getSuppliedRequest} and
@@ -110,7 +110,7 @@
* <tt>event</tt>.
*
* <p>In addition, if this AsyncListener had been registered via a call
- * to {@link ServletRequest#addAsyncListener(AsyncListener,
+ * to {@link AsyncContext#addListener(AsyncListener,
* ServletRequest, ServletResponse)}, the supplied ServletRequest and
* ServletResponse objects may be retrieved by calling
* {@link AsyncEvent#getSuppliedRequest getSuppliedRequest} and
@@ -125,4 +125,36 @@
*/
public void onError(AsyncEvent event) throws IOException;
+
+ /**
+ * Notifies this AsyncListener that a new asynchronous cycle is being
+ * initiated via a call to one of the {@link ServletRequest#startAsync}
+ * methods.
+ *
+ * <p>The {@link AsyncContext} corresponding to the asynchronous
+ * operation that is being reinitialized may be obtained by calling
+ * {@link AsyncEvent#getAsyncContext getAsyncContext} on the given
+ * <tt>event</tt>.
+ *
+ * <p>In addition, if this AsyncListener had been registered via a call
+ * to {@link AsyncContext#addListener(AsyncListener,
+ * ServletRequest, ServletResponse)}, the supplied ServletRequest and
+ * ServletResponse objects may be retrieved by calling
+ * {@link AsyncEvent#getSuppliedRequest getSuppliedRequest} and
+ * {@link AsyncEvent#getSuppliedResponse getSuppliedResponse},
+ * respectively, on the given <tt>event</tt>.
+ *
+ * <p>This AsyncListener will not receive any events related to the
+ * new asynchronous cycle unless it registers itself (via a call
+ * to {@link AsyncContext#addListener}) with the AsyncContext that
+ * is delivered as part of the given AsyncEvent.
+ *
+ * @param event the AsyncEvent indicating that a new asynchronous
+ * cycle is being initiated
+ *
+ * @throws IOException if an I/O related error has occurred during the
+ * processing of the given AsyncEvent
+ */
+ public void onStartAsync(AsyncEvent event) throws IOException;
+
}
Modified: trunk/java/javax/servlet/ServletRequest.java
===================================================================
--- trunk/java/javax/servlet/ServletRequest.java 2009-10-07 11:59:37 UTC (rev 1184)
+++ trunk/java/javax/servlet/ServletRequest.java 2009-10-08 10:44:14 UTC (rev 1185)
@@ -605,21 +605,13 @@
/**
* Puts this request into asynchronous mode, and initializes its
* {@link AsyncContext} with the original (unwrapped) ServletRequest
- * and ServletResponse objects and the timeout as returned by
- * {@link #getAsyncTimeout}.
+ * and ServletResponse objects.
*
* <p>Calling this method will cause committal of the associated
* response to be delayed until {@link AsyncContext#complete} is
* called on the returned {@link AsyncContext}, or the asynchronous
* operation has timed out.
*
- * <p>The timer for asynchronous timeouts will not start until the
- * container-initiated dispatch that called <tt>startAsync</tt>
- * has returned to the container.
- *
- * <p>See {@link AsyncContext} for a description of how timeouts of
- * asynchronous operations are handled by the container.
- *
* <p>Calling {@link AsyncContext#hasOriginalRequestAndResponse()} on
* the returned AsyncContext will return <code>true</code>. Any filters
* invoked in the <i>outbound</i> direction after this request was put
@@ -629,6 +621,12 @@
* operation, and therefore any of their associated resources may be
* released.
*
+ * <p>This method clears the list of {@link AsyncListener} instances
+ * (if any) that were registered with the AsyncContext returned by the
+ * previous call to one of the startAsync methods, after calling each
+ * AsyncListener at its {@link AsyncListener#onStartAsync onStartAsync}
+ * method.
+ *
* <p>Subsequent invocations of this method, or its overloaded
* variant, will return the same AsyncContext instance, reinitialized
* as appropriate.
@@ -636,11 +634,13 @@
* @return the (re)initialized AsyncContext
*
* @throws IllegalStateException if this request is within the scope of
- * a filter or servlet that does not support asynchronous operation,
- * that is, if {@link #isAsyncSupported} returns false, or if this method
- * is called again outside the scope of a dispatch resulting from an
- * {@link AsyncContext#dispatch}, or if the response has already been
- * closed
+ * a filter or servlet that does not support asynchronous operations
+ * (that is, {@link #isAsyncSupported} returns false),
+ * or if this method is called again without any asynchronous dispatch
+ * (resulting from one of the {@link AsyncContext#dispatch} methods),
+ * is called outside the scope of any such dispatch, or is called again
+ * within the scope of the same dispatch, or if the response has
+ * already been closed
*
* @since Servlet 3.0
*/
@@ -649,8 +649,7 @@
/**
* Puts this request into asynchronous mode, and initializes its
- * {@link AsyncContext} with the given request and response objects
- * and the timeout as returned by {@link #getAsyncTimeout}.
+ * {@link AsyncContext} with the given request and response objects.
*
* <p>The ServletRequest and ServletResponse arguments must be
* the same instances, or instances of {@link ServletRequestWrapper} and
@@ -664,13 +663,6 @@
* called on the returned {@link AsyncContext}, or the asynchronous
* operation has timed out.
*
- * <p>The timer for asynchronous timeouts will not start until the
- * container-initiated dispatch that called <tt>startAsync</tt>
- * has returned to the container.
- *
- * <p>See {@link AsyncContext} for a description of how timeouts of
- * asynchronous operations are handled by the container.
- *
* <p>Calling {@link AsyncContext#hasOriginalRequestAndResponse()} on
* the returned AsyncContext will return <code>false</code>,
* unless the passed in ServletRequest and ServletResponse arguments
@@ -689,6 +681,12 @@
* ServletRequestWrapper. The same holds true for ServletResponseWrapper
* instances.
*
+ * <p>This method clears the list of {@link AsyncListener} instances
+ * (if any) that were registered with the AsyncContext returned by the
+ * previous call to one of the startAsync methods, after calling each
+ * AsyncListener at its {@link AsyncListener#onStartAsync onStartAsync}
+ * method.
+ *
* <p>Subsequent invocations of this method, or its zero-argument
* variant, will return the same AsyncContext instance, reinitialized
* as appropriate. If a call to this method is followed by a call to its
@@ -704,11 +702,13 @@
* @return the (re)initialized AsyncContext
*
* @throws IllegalStateException if this request is within the scope of
- * a filter or servlet that does not support asynchronous operation,
- * that is, if {@link #isAsyncSupported} returns false, or if this method
- * is called again outside the scope of a dispatch resulting from an
- * {@link AsyncContext#dispatch}, or if the response has already been
- * closed
+ * a filter or servlet that does not support asynchronous operations
+ * (that is, {@link #isAsyncSupported} returns false),
+ * or if this method is called again without any asynchronous dispatch
+ * (resulting from one of the {@link AsyncContext#dispatch} methods),
+ * is called outside the scope of any such dispatch, or is called again
+ * within the scope of the same dispatch, or if the response has
+ * already been closed
*
* @since Servlet 3.0
*/
@@ -773,110 +773,6 @@
/**
- * Registers the given {@link AsyncListener} with this request.
- *
- * <p>If this request is put into asynchronous mode, the given
- * AsyncListener will receive an {@link AsyncEvent} when the
- * asynchronous operation completes, times out, or fails to complete.
- *
- * <p>AsyncListener instances will be notified in the order
- * in which they were added to this request.
- *
- * @param listener the AsyncListener to be registered
- *
- * @since Servlet 3.0
- */
- public void addAsyncListener(AsyncListener listener);
-
-
- /**
- * Registers the given {@link AsyncListener} with this request for
- * asynchronous complete, timeout, and error events.
- *
- * <p>If this request is put into asynchronous mode, the given
- * AsyncListener will receive an {@link AsyncEvent} when the
- * asynchronous operation completes, times out, or fails to complete.
- *
- * <p>AsyncListener instances will be notified in the order
- * in which they were added to this request.
- *
- * <p>The given ServletRequest and ServletResponse objects will
- * be made available to the given AsyncListener via the
- * {@link AsyncEvent#getSuppliedRequest getSuppliedRequest} and
- * {@link AsyncEvent#getSuppliedResponse getSuppliedResponse} methods,
- * respectively, of the {@link AsyncEvent} delivered to it. These objects
- * should not be read from or written to, respectively, at the time the
- * AsyncEvent is delivered, because additional wrapping may have
- * occurred since the given AsyncListener was registered, but may be used
- * in order to release any resources associated with them.
- *
- * @param listener the AsyncListener to be registered
- * @param servletRequest the ServletRequest that will be included
- * in the AsyncEvent
- * @param servletResponse the ServletResponse that will be included
- * in the AsyncEvent
- *
- * @since Servlet 3.0
- */
- public void addAsyncListener(AsyncListener listener,
- ServletRequest servletRequest,
- ServletResponse servletResponse);
-
-
- /**
- * Sets the timeout (in milliseconds) for any asynchronous operations
- * started on this request by a call to {@link #startAsync} or
- * {@link #startAsync(ServletRequest, ServletResponse)}.
- *
- * <p>By default, the container's default timeout for asynchronous
- * operations, which is available via a call to
- * {@link #getAsyncTimeout}, will be used.
- * A timeout value of 0 or less indicates that the asynchronous
- * operations will never time out.
- *
- * <p>See {@link AsyncContext} for a description of how timeouts of
- * asynchronous operations are handled by the container.
- *
- * <p>This method raises an <code>IllegalStateException</code> if
- * called after {@link #startAsync}, unless it is called within the
- * scope of an {@link AsyncContext#dispatch}, in which case the specified
- * timeout will be used to initialize the AsyncContext created by a new
- * call to {@link #startAsync}, or will be ignored if {@link #startAsync}
- * is not called again.
- *
- * @param timeout the timeout in milliseconds for any asynchronous
- * operations started on this request
- *
- * @throws IllegalStateException if called after {@link #startAsync},
- * unless within the scope of a dispatch resulting from an
- * {@link AsyncContext#dispatch}
- *
- * @since Servlet 3.0
- */
- public void setAsyncTimeout(long timeout);
-
-
- /**
- * Gets the timeout (in milliseconds) for any asynchronous operations
- * initiated on this request by a call to {@link #startAsync} or
- * {@link #startAsync(ServletRequest, ServletResponse)}.
- *
- * <p>This method returns the container's default timeout for
- * asynchronous operations, or the timeout value passed to the most
- * recent invocation of {@link #setAsyncTimeout}.
- *
- * <p>A timeout value of 0 or less indicates that the asynchronous
- * operation will never time out.
- *
- * @return the timeout in milliseconds for any asynchronous
- * operations started on this request
- *
- * @since Servlet 3.0
- */
- public long getAsyncTimeout();
-
-
- /**
* Gets the dispatcher type of this request.
*
* <p>The dispatcher type of a request is used by the container
Modified: trunk/java/javax/servlet/ServletRequestWrapper.java
===================================================================
--- trunk/java/javax/servlet/ServletRequestWrapper.java 2009-10-07 11:59:37 UTC (rev
1184)
+++ trunk/java/javax/servlet/ServletRequestWrapper.java 2009-10-08 10:44:14 UTC (rev
1185)
@@ -396,19 +396,19 @@
/**
- * Puts the wrapped request into asynchronous mode, and initializes its
- * {@link AsyncContext} with the original ServletRequest and
- * ServletResponse objects and the timeout derived according to
- * the rules laid out in {@link #setAsyncTimeout}.
+ * The default behavior of this method is to invoke
+ * {@link ServletRequest#startAsync} on the wrapped request object.
*
* @return the (re)initialized AsyncContext
*
- * @throws IllegalStateException if this request is within the scope of
- * a filter or servlet that does not support asynchronous operation,
- * that is, if {@link #isAsyncSupported} returns false, or if this method
- * is called again outside the scope of a dispatch resulting from an
- * {@link AsyncContext#dispatch}, or if the response has already been
- * closed
+ * @throws IllegalStateException if the request is within the scope of
+ * a filter or servlet that does not support asynchronous operations
+ * (that is, {@link #isAsyncSupported} returns false),
+ * or if this method is called again without any asynchronous dispatch
+ * (resulting from one of the {@link AsyncContext#dispatch} methods),
+ * is called outside the scope of any such dispatch, or is called again
+ * within the scope of the same dispatch, or if the response has
+ * already been closed
*
* @see ServletRequest#startAsync
*
@@ -420,10 +420,9 @@
/**
- * Puts the wrapped request into asynchronous mode, and initializes its
- * {@link AsyncContext} with the given request and response objects
- * and the timeout derived according to the rules laid out in
- * {@link #setAsyncTimeout}.
+ * The default behavior of this method is to invoke
+ * {@link ServletRequest#startAsync(ServletRequest, ServletResponse)}
+ * on the wrapped request object.
*
* @param servletRequest the ServletRequest used to initialize the
* AsyncContext
@@ -431,14 +430,16 @@
* AsyncContext
*
* @return the (re)initialized AsyncContext
- *
- * @throws IllegalStateException if this request is within the scope of
- * a filter or servlet that does not support asynchronous operation,
- * that is, if {@link #isAsyncSupported} returns false, or if this method
- * is called again outside the scope of a dispatch resulting from an
- * {@link AsyncContext#dispatch}, or if the response has already been
- * closed
*
+ * @throws IllegalStateException if the request is within the scope of
+ * a filter or servlet that does not support asynchronous operations
+ * (that is, {@link #isAsyncSupported} returns false),
+ * or if this method is called again without any asynchronous dispatch
+ * (resulting from one of the {@link AsyncContext#dispatch} methods),
+ * is called outside the scope of any such dispatch, or is called again
+ * within the scope of the same dispatch, or if the response has
+ * already been closed
+ *
* @see ServletRequest#startAsync(ServletRequest, ServletResponse)
*
* @since Servlet 3.0
@@ -505,80 +506,6 @@
/**
- * Registers the given {@link AsyncListener} with the wrapped request
- * for asynchronous complete and timeout events.
- *
- * @param listener the AsyncListener to be registered
- *
- * @see ServletRequest#addAsyncListener(AsyncListener)
- *
- * @since Servlet 3.0
- */
- public void addAsyncListener(AsyncListener listener) {
- request.addAsyncListener(listener);
- }
-
-
- /**
- * Registers the given {@link AsyncListener}, {@link ServletRequest},
- * and {@link ServletResponse} with the wrapped request for asynchronous
- * complete and timeout events.
- *
- * @param listener the AsyncListener to be registered
- * @param servletRequest the ServletRequest that will be included
- * in the AsyncEvent
- * @param servletResponse the ServletResponse that will be included
- * in the AsyncEvent
- *
- * @see ServletRequest#addAsyncListener(AsyncListener, ServletRequest,
- * ServletResponse)
- *
- * @since Servlet 3.0
- */
- public void addAsyncListener(AsyncListener listener,
- ServletRequest servletRequest,
- ServletResponse servletResponse) {
- request.addAsyncListener(listener, servletRequest, servletResponse);
- }
-
-
- /**
- * Sets the timeout (in milliseconds) for any asynchronous operations
- * initiated on the wrapped request.
- *
- * @param timeout the timeout in milliseconds for any asynchronous
- * operations initiated on the wrapped request
- *
- * @throws IllegalStateException if called after {@link #startAsync},
- * unless within the scope of a dispatch resulting from an
- * {@link AsyncContext#dispatch}
- *
- * @see ServletRequest#setAsyncTimeout
- *
- * @since Servlet 3.0
- */
- public void setAsyncTimeout(long timeout) {
- request.setAsyncTimeout(timeout);
- }
-
-
- /**
- * Gets the timeout (in milliseconds) for any asynchronous operations
- * initiated on the wrapped request.
- *
- * @return the timeout in milliseconds for any asynchronous
- * operations initiated on the wrapped request
- *
- * @see ServletRequest#getAsyncTimeout
- *
- * @since Servlet 3.0
- */
- public long getAsyncTimeout() {
- return request.getAsyncTimeout();
- }
-
-
- /**
* Checks (recursively) if this ServletRequestWrapper wraps the given
* {@link ServletRequest} instance.
*
Modified: trunk/java/org/apache/catalina/connector/Request.java
===================================================================
--- trunk/java/org/apache/catalina/connector/Request.java 2009-10-07 11:59:37 UTC (rev
1184)
+++ trunk/java/org/apache/catalina/connector/Request.java 2009-10-08 10:44:14 UTC (rev
1185)
@@ -66,7 +66,6 @@
import javax.security.auth.Subject;
import javax.servlet.AsyncContext;
-import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
@@ -270,8 +269,8 @@
/**
* Async listeners.
*/
- protected LinkedHashMap<AsyncEvent, AsyncListener> asyncListeners =
- new LinkedHashMap<AsyncEvent, AsyncListener>();
+ protected LinkedHashMap<AsyncListener, AsyncListenerRegistration>
asyncListeners =
+ new LinkedHashMap<AsyncListener, AsyncListenerRegistration>();
/**
@@ -2972,16 +2971,6 @@
return true;
}
- public void addAsyncListener(AsyncListener listener,
- ServletRequest servletRequest, ServletResponse servletResponse) {
- AsyncEvent event = new AsyncEvent(asyncContext, servletRequest,
servletResponse);
- asyncListeners.put(event, listener);
- }
-
- public void addAsyncListener(AsyncListener listener) {
- addAsyncListener(listener, getRequest(), response.getResponse());
- }
-
public AsyncContext getAsyncContext() {
return asyncContext;
}
@@ -3010,20 +2999,19 @@
return true;
}
- public long getAsyncTimeout() {
- return this.asyncTimeout;
- }
-
- public void setAsyncTimeout(long asyncTimeout) {
- this.asyncTimeout = asyncTimeout;
- }
-
public AsyncContext startAsync() throws IllegalStateException {
return startAsync(null, null);
}
public AsyncContext startAsync(ServletRequest servletRequest,
ServletResponse servletResponse) throws IllegalStateException {
+ /* TODO
+ * <p>This method clears the list of {@link AsyncListener} instances
+ * (if any) that were registered with the AsyncContext returned by the
+ * previous call to one of the startAsync methods, after calling each
+ * AsyncListener at its {@link AsyncListener#onStartAsync onStartAsync}
+ * method.
+ */
int timeout = (asyncTimeout > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int)
asyncTimeout;
if (timeout <= 0) {
timeout = Integer.MAX_VALUE;
@@ -3170,8 +3158,8 @@
public class AsyncContextImpl implements AsyncContext {
- protected ServletRequest request = null;
- protected ServletResponse response = null;
+ protected ServletRequest servletRequest = null;
+ protected ServletResponse servletResponse = null;
protected ServletContext servletContext = null;
protected String path = null;
@@ -3186,12 +3174,12 @@
}
public void dispatch() {
- if (request == getRequestFacade()) {
+ if (servletRequest == getRequestFacade()) {
// Get the path directly
path = getRequestPathMB().toString();
- } else if (request instanceof HttpServletRequest) {
+ } else if (servletRequest instanceof HttpServletRequest) {
// Rebuild the path
- path = ((HttpServletRequest) request).getRequestURI();
+ path = ((HttpServletRequest) servletRequest).getRequestURI();
if (servletContext != null) {
path = path.substring(servletContext.getContextPath().length());
} else {
@@ -3214,23 +3202,23 @@
}
public ServletRequest getRequest() {
- if (request != null) {
- return request;
+ if (servletRequest != null) {
+ return servletRequest;
} else {
return getRequestFacade();
}
}
public ServletResponse getResponse() {
- if (response != null) {
- return response;
+ if (servletResponse != null) {
+ return servletResponse;
} else {
return getResponseFacade();
}
}
public boolean hasOriginalRequestAndResponse() {
- return (request == getRequestFacade() && response ==
getResponseFacade());
+ return (servletRequest == getRequestFacade() && servletResponse ==
getResponseFacade());
}
public void start(Runnable runnable) {
@@ -3246,12 +3234,12 @@
ready = false;
}
- public void setRequestAndResponse(ServletRequest request, ServletResponse
response) {
- if (request == null && response == null) {
+ public void setRequestAndResponse(ServletRequest servletRequest, ServletResponse
servletResponse) {
+ if (servletRequest == null && response == null) {
}
- this.request = request;
- this.response = response;
+ this.servletRequest = servletRequest;
+ this.servletResponse = servletResponse;
}
public ServletContext getServletContext() {
@@ -3278,11 +3266,55 @@
ready = true;
}
- public Map<AsyncEvent, AsyncListener> getAsyncListeners() {
+ public Map<AsyncListener, AsyncListenerRegistration> getAsyncListeners() {
return asyncListeners;
}
+ public void addListener(AsyncListener listener,
+ ServletRequest servletRequest, ServletResponse servletResponse) {
+ asyncListeners.put(listener,
+ new AsyncListenerRegistration(listener, servletRequest,
servletResponse));
+ }
+
+ public void addListener(AsyncListener listener) {
+ addListener(listener, getRequest(), response.getResponse());
+ }
+
+ public long getTimeout() {
+ return asyncTimeout;
+ }
+
+ public void setTimeout(long timeout) {
+ asyncTimeout = timeout;
+ }
+
}
+
+ // ------------------------------------------ RequestResponse Inner Class
+
+ public class AsyncListenerRegistration {
+ protected ServletRequest request;
+ protected ServletResponse response;
+ protected AsyncListener listener;
+ protected AsyncListenerRegistration(AsyncListener listener,
+ ServletRequest request, ServletResponse response)
+ {
+ this.listener = listener;
+ this.request = request;
+ this.response = response;
+ }
+ public ServletRequest getRequest() {
+ return request;
+ }
+ public ServletResponse getResponse() {
+ return response;
+ }
+ public AsyncListener getListener() {
+ return listener;
+ }
+ }
+
+
}
Modified: trunk/java/org/apache/catalina/connector/RequestFacade.java
===================================================================
--- trunk/java/org/apache/catalina/connector/RequestFacade.java 2009-10-07 11:59:37 UTC
(rev 1184)
+++ trunk/java/org/apache/catalina/connector/RequestFacade.java 2009-10-08 10:44:14 UTC
(rev 1185)
@@ -28,7 +28,6 @@
import java.util.Map;
import javax.servlet.AsyncContext;
-import javax.servlet.AsyncListener;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
@@ -942,27 +941,6 @@
}
- public void addAsyncListener(AsyncListener listener,
- ServletRequest servletRequest, ServletResponse servletResponse) {
- if (request == null) {
- throw new IllegalStateException(
- sm.getString("requestFacade.nullRequest"));
- }
-
- request.addAsyncListener(listener, servletRequest, servletResponse);
- }
-
-
- public void addAsyncListener(AsyncListener listener) {
- if (request == null) {
- throw new IllegalStateException(
- sm.getString("requestFacade.nullRequest"));
- }
-
- request.addAsyncListener(listener);
- }
-
-
public AsyncContext getAsyncContext() {
if (request == null) {
throw new IllegalStateException(
@@ -1003,26 +981,6 @@
}
- public void setAsyncTimeout(long timeout) {
- if (request == null) {
- throw new IllegalStateException(
- sm.getString("requestFacade.nullRequest"));
- }
-
- request.setAsyncTimeout(timeout);
- }
-
-
- public long getAsyncTimeout() {
- if (request == null) {
- throw new IllegalStateException(
- sm.getString("requestFacade.nullRequest"));
- }
-
- return request.getAsyncTimeout();
- }
-
-
public AsyncContext startAsync() throws IllegalStateException {
if (request == null) {
throw new IllegalStateException(
Modified: trunk/java/org/apache/catalina/core/StandardWrapperValve.java
===================================================================
--- trunk/java/org/apache/catalina/core/StandardWrapperValve.java 2009-10-07 11:59:37 UTC
(rev 1184)
+++ trunk/java/org/apache/catalina/core/StandardWrapperValve.java 2009-10-08 10:44:14 UTC
(rev 1185)
@@ -48,7 +48,6 @@
import java.io.IOException;
-import java.io.PrintWriter;
import java.util.Iterator;
import javax.management.MalformedObjectNameException;
@@ -58,7 +57,6 @@
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
-import javax.servlet.ServletOutputStream;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletResponse;
@@ -67,7 +65,7 @@
import org.apache.catalina.connector.ClientAbortException;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
-import org.apache.catalina.connector.ResponseFacade;
+import org.apache.catalina.connector.Request.AsyncListenerRegistration;
import org.apache.catalina.util.StringManager;
import org.apache.catalina.valves.ValveBase;
import org.apache.tomcat.util.log.SystemLogHandler;
@@ -407,22 +405,27 @@
// Invoke the listeners with onComplete or onTimeout
boolean timeout = (event.getType() == EventType.TIMEOUT) ? true : false;
boolean error = (event.getType() == EventType.ERROR) ? true : false;
- Iterator<AsyncEvent> asyncEvents =
asyncContext.getAsyncListeners().keySet().iterator();
- if (timeout && !asyncEvents.hasNext()) {
+ Iterator<AsyncListenerRegistration> asyncListenerRegistrations =
+ asyncContext.getAsyncListeners().values().iterator();
+ if (timeout && !asyncListenerRegistrations.hasNext()) {
// FIXME: MUST do an ERROR dispatch to the original URI and MUST set
the response code to 500
}
- while (asyncEvents.hasNext()) {
- AsyncEvent asyncEvent = asyncEvents.next();
- AsyncListener asyncListener =
asyncContext.getAsyncListeners().get(asyncEvent);
+ while (asyncListenerRegistrations.hasNext()) {
+ AsyncListenerRegistration asyncListenerRegistration =
asyncListenerRegistrations.next();
+ AsyncListener asyncListener =
asyncListenerRegistration.getListener();
try {
if (timeout) {
+ AsyncEvent asyncEvent = new AsyncEvent(asyncContext,
+ asyncListenerRegistration.getRequest(),
asyncListenerRegistration.getResponse());
asyncListener.onTimeout(asyncEvent);
} else if (error) {
Throwable t = (Throwable)
request.getAttribute(Globals.EXCEPTION_ATTR);
- AsyncEvent asyncEvent2 = new
AsyncEvent(asyncEvent.getAsyncContext(),
- asyncEvent.getSuppliedRequest(),
asyncEvent.getSuppliedResponse(), t);
- asyncListener.onError(asyncEvent2);
+ AsyncEvent asyncEvent = new AsyncEvent(asyncContext,
+ asyncListenerRegistration.getRequest(),
asyncListenerRegistration.getResponse(), t);
+ asyncListener.onError(asyncEvent);
} else {
+ AsyncEvent asyncEvent = new AsyncEvent(asyncContext,
+ asyncListenerRegistration.getRequest(),
asyncListenerRegistration.getResponse());
asyncListener.onComplete(asyncEvent);
}
} catch (Throwable e) {