405530 Wrap AsyncContext to throw ISE after complete

This commit is contained in:
Greg Wilkins 2013-04-22 11:33:44 +10:00
parent 22c3151ad6
commit c3325e8b04
7 changed files with 415 additions and 249 deletions

View File

@ -0,0 +1,153 @@
//
// ========================================================================
// Copyright (c) 1995-2013 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.server;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.eclipse.jetty.server.handler.ContextHandler.Context;
import org.eclipse.jetty.util.thread.Scheduler;
public class AsyncContextEvent extends AsyncEvent
{
final private Context _context;
final private AsyncContextState _asyncContext;
volatile HttpChannelState _state;
private ServletContext _dispatchContext;
private String _pathInContext;
private Scheduler.Task _timeoutTask;
private Throwable _throwable;
public AsyncContextEvent(Context context,AsyncContextState asyncContext, HttpChannelState state, Request baseRequest, ServletRequest request, ServletResponse response)
{
super(null,request,response,null);
_context=context;
_asyncContext=asyncContext;
_state=state;
// If we haven't been async dispatched before
if (baseRequest.getAttribute(AsyncContext.ASYNC_REQUEST_URI)==null)
{
// We are setting these attributes during startAsync, when the spec implies that
// they are only available after a call to AsyncContext.dispatch(...);
// have we been forwarded before?
String uri=(String)baseRequest.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
if (uri!=null)
{
baseRequest.setAttribute(AsyncContext.ASYNC_REQUEST_URI,uri);
baseRequest.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH,baseRequest.getAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH));
baseRequest.setAttribute(AsyncContext.ASYNC_SERVLET_PATH,baseRequest.getAttribute(RequestDispatcher.FORWARD_SERVLET_PATH));
baseRequest.setAttribute(AsyncContext.ASYNC_PATH_INFO,baseRequest.getAttribute(RequestDispatcher.FORWARD_PATH_INFO));
baseRequest.setAttribute(AsyncContext.ASYNC_QUERY_STRING,baseRequest.getAttribute(RequestDispatcher.FORWARD_QUERY_STRING));
}
else
{
baseRequest.setAttribute(AsyncContext.ASYNC_REQUEST_URI,baseRequest.getRequestURI());
baseRequest.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH,baseRequest.getContextPath());
baseRequest.setAttribute(AsyncContext.ASYNC_SERVLET_PATH,baseRequest.getServletPath());
baseRequest.setAttribute(AsyncContext.ASYNC_PATH_INFO,baseRequest.getPathInfo());
baseRequest.setAttribute(AsyncContext.ASYNC_QUERY_STRING,baseRequest.getQueryString());
}
}
}
public ServletContext getSuspendedContext()
{
return _context;
}
public Context getContext()
{
return _context;
}
public ServletContext getDispatchContext()
{
return _dispatchContext;
}
public ServletContext getServletContext()
{
return _dispatchContext==null?_context:_dispatchContext;
}
/**
* @return The path in the context
*/
public String getPath()
{
return _pathInContext;
}
public void setTimeoutTask(Scheduler.Task task)
{
_timeoutTask = task;
}
public void cancelTimeoutTask()
{
Scheduler.Task task=_timeoutTask;
_timeoutTask=null;
if (task!=null)
task.cancel();
}
@Override
public AsyncContext getAsyncContext()
{
return _asyncContext;
}
@Override
public Throwable getThrowable()
{
return _throwable;
}
public void setThrowable(Throwable throwable)
{
_throwable=throwable;
}
public void setDispatchTarget(ServletContext context, String path)
{
if (context!=null)
_dispatchContext=context;
if (path!=null)
_pathInContext=path;
}
public void completed()
{
_asyncContext.reset();
}
public HttpChannelState getHttpChannelState()
{
return _state;
}
}

View File

@ -0,0 +1,180 @@
//
// ========================================================================
// Copyright (c) 1995-2013 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.server;
import java.io.IOException;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class AsyncContextState implements AsyncContext
{
volatile HttpChannelState _state;
public AsyncContextState(HttpChannelState state)
{
_state=state;
}
private HttpChannelState state()
{
HttpChannelState state=_state;
if (state==null)
throw new IllegalStateException("AsyncContext completed");
return state;
}
@Override
public void addListener(final AsyncListener listener, final ServletRequest request, final ServletResponse response)
{
AsyncListener wrap = new AsyncListener()
{
@Override
public void onTimeout(AsyncEvent event) throws IOException
{
listener.onTimeout(new AsyncEvent(event.getAsyncContext(),request,response,event.getThrowable()));
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException
{
listener.onStartAsync(new AsyncEvent(event.getAsyncContext(),request,response,event.getThrowable()));
}
@Override
public void onError(AsyncEvent event) throws IOException
{
listener.onComplete(new AsyncEvent(event.getAsyncContext(),request,response,event.getThrowable()));
}
@Override
public void onComplete(AsyncEvent event) throws IOException
{
listener.onComplete(new AsyncEvent(event.getAsyncContext(),request,response,event.getThrowable()));
}
};
state().addListener(wrap);
}
@Override
public void addListener(AsyncListener listener)
{
state().addListener(listener);
}
@Override
public void complete()
{
state().complete();
}
@Override
public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException
{
try
{
return clazz.newInstance();
}
catch(Exception e)
{
throw new ServletException(e);
}
}
@Override
public void dispatch()
{
state().dispatch(null,null);
}
@Override
public void dispatch(String path)
{
state().dispatch(null,path);
}
@Override
public void dispatch(ServletContext context, String path)
{
state().dispatch(context,path);
}
@Override
public ServletRequest getRequest()
{
return state().getAsyncContextEvent().getSuppliedRequest();
}
@Override
public ServletResponse getResponse()
{
return state().getAsyncContextEvent().getSuppliedResponse();
}
@Override
public long getTimeout()
{
return state().getTimeout();
}
@Override
public boolean hasOriginalRequestAndResponse()
{
HttpChannel<?> channel=state().getHttpChannel();
return channel.getRequest()==getRequest() && channel.getResponse()==getResponse();
}
@Override
public void setTimeout(long arg0)
{
state().setTimeout(arg0);
}
@Override
public void start(final Runnable task)
{
state().getHttpChannel().execute(new Runnable()
{
@Override
public void run()
{
state().getAsyncContextEvent().getContext().getContextHandler().handle(task);
}
});
}
public void reset()
{
_state=null;
}
public HttpChannelState getHttpChannelState()
{
return state();
}
}

View File

@ -21,19 +21,14 @@ package org.eclipse.jetty.server;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandler.Context;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Scheduler;
@ -56,7 +51,7 @@ import org.eclipse.jetty.util.thread.Scheduler;
* <tr><th align=right>COMPLETED:</th> <td></td> <td></td> <td></td> <td></td> <td></td> <td></td></tr>
* </table>
*/
public class HttpChannelState implements AsyncContext
public class HttpChannelState
{
private static final Logger LOG = Log.getLogger(HttpChannelState.class);
@ -86,7 +81,7 @@ public class HttpChannelState implements AsyncContext
private boolean _expired;
private volatile boolean _responseWrapped;
private long _timeoutMs=DEFAULT_TIMEOUT;
private AsyncEventState _event;
private AsyncContextEvent _event;
protected HttpChannelState(HttpChannel<?> channel)
{
@ -103,7 +98,6 @@ public class HttpChannelState implements AsyncContext
}
}
@Override
public void addListener(AsyncListener listener)
{
synchronized(this)
@ -114,19 +108,6 @@ public class HttpChannelState implements AsyncContext
}
}
@Override
public void addListener(AsyncListener listener,ServletRequest request, ServletResponse response)
{
synchronized(this)
{
if (_asyncListeners==null)
_asyncListeners=new ArrayList<>();
_asyncListeners.add(listener);
}
}
@Override
public void setTimeout(long ms)
{
synchronized(this)
@ -135,7 +116,6 @@ public class HttpChannelState implements AsyncContext
}
}
@Override
public long getTimeout()
{
synchronized(this)
@ -144,7 +124,7 @@ public class HttpChannelState implements AsyncContext
}
}
public AsyncEventState getAsyncEventState()
public AsyncContextEvent getAsyncContextEvent()
{
synchronized(this)
{
@ -218,7 +198,8 @@ public class HttpChannelState implements AsyncContext
}
}
public void startAsync()
public void startAsync(AsyncContextEvent event)
{
synchronized (this)
{
@ -228,56 +209,15 @@ public class HttpChannelState implements AsyncContext
case REDISPATCHED:
_dispatched=false;
_expired=false;
_responseWrapped=event.getSuppliedResponse()!=_channel.getResponse();
_responseWrapped=false;
_event=new AsyncEventState(_channel.getRequest().getServletContext(),_channel.getRequest(),_channel.getResponse());
_event=event;
_state=State.ASYNCSTARTED;
List<AsyncListener> listeners=_lastAsyncListeners;
_lastAsyncListeners=_asyncListeners;
if (listeners!=null)
listeners.clear();
_asyncListeners=listeners;
if (_asyncListeners!=null)
_asyncListeners.clear();
break;
default:
throw new IllegalStateException(this.getStatusString());
}
}
if (_lastAsyncListeners!=null)
{
for (AsyncListener listener : _lastAsyncListeners)
{
try
{
listener.onStartAsync(_event);
}
catch(Exception e)
{
LOG.warn(e);
}
}
}
}
public void startAsync(final ServletContext context,final ServletRequest request,final ServletResponse response)
{
synchronized (this)
{
switch(_state)
{
case DISPATCHED:
case REDISPATCHED:
_dispatched=false;
_expired=false;
_responseWrapped=response!=_channel.getResponse();
_event=new AsyncEventState(context,request,response);
_event._pathInContext = (request instanceof HttpServletRequest)?URIUtil.addPaths(((HttpServletRequest)request).getServletPath(),((HttpServletRequest)request).getPathInfo()):null;
_state=State.ASYNCSTARTED;
List<AsyncListener> listeners=_lastAsyncListeners;
_lastAsyncListeners=_asyncListeners;
_asyncListeners=listeners;
if (_asyncListeners!=null)
_asyncListeners.clear();
break;
default:
@ -306,7 +246,7 @@ public class HttpChannelState implements AsyncContext
synchronized (this)
{
if (_event!=null)
_event._cause=th;
_event.setThrowable(th);
}
}
@ -362,26 +302,29 @@ public class HttpChannelState implements AsyncContext
}
}
@Override
public void dispatch()
public void dispatch(ServletContext context, String path)
{
boolean dispatch;
synchronized (this)
{
switch(_state)
{
case ASYNCSTARTED:
_state=State.REDISPATCHING;
_event.setDispatchTarget(context,path);
_dispatched=true;
return;
case ASYNCWAIT:
dispatch=!_expired;
_state=State.REDISPATCH;
_event.setDispatchTarget(context,path);
_dispatched=true;
break;
case REDISPATCH:
_event.setDispatchTarget(context,path);
return;
default:
@ -453,7 +396,6 @@ public class HttpChannelState implements AsyncContext
scheduleDispatch();
}
@Override
public void complete()
{
// just like resume, except don't set _dispatched=true;
@ -488,19 +430,6 @@ public class HttpChannelState implements AsyncContext
}
}
@Override
public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException
{
try
{
return clazz.newInstance();
}
catch(Exception e)
{
throw new ServletException(e);
}
}
protected void completed()
{
final List<AsyncListener> aListeners;
@ -524,10 +453,10 @@ public class HttpChannelState implements AsyncContext
{
try
{
if (_event!=null && _event._cause!=null)
if (_event!=null && _event.getThrowable()!=null)
{
_event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION,_event._cause);
_event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_MESSAGE,_event._cause.getMessage());
_event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION,_event.getThrowable());
_event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_MESSAGE,_event.getThrowable().getMessage());
listener.onError(_event);
}
else
@ -539,6 +468,7 @@ public class HttpChannelState implements AsyncContext
}
}
}
_event.completed();
}
protected void recycle()
@ -563,14 +493,6 @@ public class HttpChannelState implements AsyncContext
}
}
public void cancel()
{
synchronized (this)
{
cancelTimeout();
}
}
protected void scheduleDispatch()
{
_channel.execute(_channel);
@ -580,18 +502,14 @@ public class HttpChannelState implements AsyncContext
{
Scheduler scheduler = _channel.getScheduler();
if (scheduler!=null && _timeoutMs>0)
_event._timeout=scheduler.schedule(new AsyncTimeout(),_timeoutMs,TimeUnit.MILLISECONDS);
_event.setTimeoutTask(scheduler.schedule(new AsyncTimeout(),_timeoutMs,TimeUnit.MILLISECONDS));
}
protected void cancelTimeout()
{
AsyncEventState event=_event;
AsyncContextEvent event=_event;
if (event!=null)
{
Scheduler.Task task=event._timeout;
if (task!=null)
task.cancel();
}
event.cancelTimeoutTask();
}
public boolean isExpired()
@ -656,71 +574,19 @@ public class HttpChannelState implements AsyncContext
}
}
@Override
public void dispatch(ServletContext context, String path)
{
_event._dispatchContext=context;
_event._pathInContext=path;
dispatch();
}
@Override
public void dispatch(String path)
{
_event._pathInContext=path;
dispatch();
}
public Request getBaseRequest()
{
return _channel.getRequest();
}
@Override
public ServletRequest getRequest()
public HttpChannel<?> getHttpChannel()
{
if (_event!=null)
return _event.getSuppliedRequest();
return _channel.getRequest();
}
@Override
public ServletResponse getResponse()
{
if (_responseWrapped && _event!=null && _event.getSuppliedResponse()!=null)
return _event.getSuppliedResponse();
return _channel.getResponse();
}
@Override
public void start(final Runnable run)
{
final AsyncEventState event=_event;
if (event!=null)
{
_channel.execute(new Runnable()
{
@Override
public void run()
{
((Context)event.getServletContext()).getContextHandler().handle(run);
}
});
}
}
@Override
public boolean hasOriginalRequestAndResponse()
{
synchronized (this)
{
return (_event!=null && _event.getSuppliedRequest()==_channel.getRequest() && _event.getSuppliedResponse()==_channel.getResponse());
}
return _channel;
}
public ContextHandler getContextHandler()
{
final AsyncEventState event=_event;
final AsyncContextEvent event=_event;
if (event!=null)
return ((Context)event.getServletContext()).getContextHandler();
return null;
@ -757,70 +623,4 @@ public class HttpChannelState implements AsyncContext
}
}
public class AsyncEventState extends AsyncEvent
{
final private ServletContext _suspendedContext;
private String _pathInContext;
private Scheduler.Task _timeout;
private ServletContext _dispatchContext;
private Throwable _cause;
public AsyncEventState(ServletContext context, ServletRequest request, ServletResponse response)
{
super(HttpChannelState.this, request,response);
_suspendedContext=context;
// Get the base request So we can remember the initial paths
Request r=_channel.getRequest();
// If we haven't been async dispatched before
if (r.getAttribute(AsyncContext.ASYNC_REQUEST_URI)==null)
{
// We are setting these attributes during startAsync, when the spec implies that
// they are only available after a call to AsyncContext.dispatch(...);
// have we been forwarded before?
String uri=(String)r.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
if (uri!=null)
{
r.setAttribute(AsyncContext.ASYNC_REQUEST_URI,uri);
r.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH,r.getAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH));
r.setAttribute(AsyncContext.ASYNC_SERVLET_PATH,r.getAttribute(RequestDispatcher.FORWARD_SERVLET_PATH));
r.setAttribute(AsyncContext.ASYNC_PATH_INFO,r.getAttribute(RequestDispatcher.FORWARD_PATH_INFO));
r.setAttribute(AsyncContext.ASYNC_QUERY_STRING,r.getAttribute(RequestDispatcher.FORWARD_QUERY_STRING));
}
else
{
r.setAttribute(AsyncContext.ASYNC_REQUEST_URI,r.getRequestURI());
r.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH,r.getContextPath());
r.setAttribute(AsyncContext.ASYNC_SERVLET_PATH,r.getServletPath());
r.setAttribute(AsyncContext.ASYNC_PATH_INFO,r.getPathInfo());
r.setAttribute(AsyncContext.ASYNC_QUERY_STRING,r.getQueryString());
}
}
}
public ServletContext getSuspendedContext()
{
return _suspendedContext;
}
public ServletContext getDispatchContext()
{
return _dispatchContext;
}
public ServletContext getServletContext()
{
return _dispatchContext==null?_suspendedContext:_dispatchContext;
}
/**
* @return The path in the context
*/
public String getPath()
{
return _pathInContext;
}
}
}

View File

@ -203,7 +203,8 @@ public class Request implements HttpServletRequest
private long _dispatchTime;
private HttpURI _uri;
private MultiPartInputStreamParser _multiPartInputStream; //if the request is a multi-part mime
private AsyncContextState _async;
/* ------------------------------------------------------------ */
public Request(HttpChannel<?> channel, HttpInput<?> input)
{
@ -369,10 +370,11 @@ public class Request implements HttpServletRequest
@Override
public AsyncContext getAsyncContext()
{
HttpChannelState continuation = getHttpChannelState();
if (continuation.isInitial() && !continuation.isAsync())
throw new IllegalStateException(continuation.getStatusString());
return continuation;
HttpChannelState state = getHttpChannelState();
if (_async==null || state.isInitial() && !state.isAsync())
throw new IllegalStateException(state.getStatusString());
return _async;
}
/* ------------------------------------------------------------ */
@ -1506,6 +1508,9 @@ public class Request implements HttpServletRequest
setAuthentication(Authentication.NOT_CHECKED);
getHttpChannelState().recycle();
if (_async!=null)
_async.reset();
_async=null;
_asyncSupported = true;
_handled = false;
if (_context != null)
@ -1989,8 +1994,11 @@ public class Request implements HttpServletRequest
if (!_asyncSupported)
throw new IllegalStateException("!asyncSupported");
HttpChannelState state = getHttpChannelState();
state.startAsync();
return state;
if (_async==null)
_async=new AsyncContextState(state);
AsyncContextEvent event = new AsyncContextEvent(_context,_async,state,this,this,getResponse());
state.startAsync(event);
return _async;
}
/* ------------------------------------------------------------ */
@ -2000,8 +2008,12 @@ public class Request implements HttpServletRequest
if (!_asyncSupported)
throw new IllegalStateException("!asyncSupported");
HttpChannelState state = getHttpChannelState();
state.startAsync(_context, servletRequest, servletResponse);
return state;
if (_async==null)
_async=new AsyncContextState(state);
AsyncContextEvent event = new AsyncContextEvent(_context,_async,state,this,servletRequest,servletResponse);
event.setDispatchTarget(getServletContext(),URIUtil.addPaths(getServletPath(),getPathInfo()));
state.startAsync(event);
return _async;
}
/* ------------------------------------------------------------ */

View File

@ -476,16 +476,16 @@ public class Server extends HandlerWrapper implements Attributes
*/
public void handleAsync(HttpChannel<?> connection) throws IOException, ServletException
{
final HttpChannelState async = connection.getRequest().getHttpChannelState();
final HttpChannelState.AsyncEventState state = async.getAsyncEventState();
final HttpChannelState state = connection.getRequest().getHttpChannelState();
final AsyncContextEvent event = state.getAsyncContextEvent();
final Request baseRequest=connection.getRequest();
final String path=state.getPath();
final String path=event.getPath();
if (path!=null)
{
// this is a dispatch with a path
ServletContext context=state.getServletContext();
ServletContext context=event.getServletContext();
HttpURI uri = new HttpURI(context==null?path:URIUtil.addPaths(context.getContextPath(),path));
baseRequest.setUri(uri);
baseRequest.setRequestURI(null);
@ -495,8 +495,8 @@ public class Server extends HandlerWrapper implements Attributes
}
final String target=baseRequest.getPathInfo();
final HttpServletRequest request=(HttpServletRequest)async.getRequest();
final HttpServletResponse response=(HttpServletResponse)async.getResponse();
final HttpServletRequest request=(HttpServletRequest)event.getSuppliedRequest();
final HttpServletResponse response=(HttpServletResponse)event.getSuppliedResponse();
if (LOG.isDebugEnabled())
{
@ -509,7 +509,6 @@ public class Server extends HandlerWrapper implements Attributes
}
/* ------------------------------------------------------------ */
public void join() throws InterruptedException
{

View File

@ -28,6 +28,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.AsyncContextEvent;
import org.eclipse.jetty.server.HttpChannelState;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
@ -76,12 +77,13 @@ public class StatisticsHandler extends HandlerWrapper
public void onError(AsyncEvent event) throws IOException
{
}
@Override
public void onComplete(AsyncEvent event) throws IOException
{
HttpChannelState state = (HttpChannelState)event.getAsyncContext();
HttpChannelState state = ((AsyncContextEvent)event).getHttpChannelState();
Request request = state.getBaseRequest();
final long elapsed = System.currentTimeMillis()-request.getTimeStamp();
@ -93,7 +95,7 @@ public class StatisticsHandler extends HandlerWrapper
if (!state.isDispatched())
_asyncWaitStats.decrement();
}
};
/**

View File

@ -103,6 +103,7 @@ public class AsyncContextTest
Assert.assertEquals("servlet gets right path", "doGet:getServletPath:/servletPath", br.readLine());
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath",br.readLine());
Assert.assertEquals("async context gets right path in async","async:run:attr:servletPath:/servletPath",br.readLine());
}
@Test
@ -121,6 +122,16 @@ public class AsyncContextTest
Assert.assertEquals("query string attr is correct","async:run:attr:queryString:dispatch=true",br.readLine());
Assert.assertEquals("context path attr is correct","async:run:attr:contextPath:",br.readLine());
Assert.assertEquals("request uri attr is correct","async:run:attr:requestURI:/servletPath",br.readLine());
try
{
__asyncContext.getRequest();
Assert.fail();
}
catch (IllegalStateException e)
{
}
}
@Test
@ -193,8 +204,11 @@ public class AsyncContextTest
@Test
public void testDispatchRequestResponse() throws Exception
{
String request = "GET /forward?dispatchRequestResponse=true HTTP/1.1\r\n" + "Host: localhost\r\n"
+ "Content-Type: application/x-www-form-urlencoded\r\n" + "Connection: close\r\n" + "\r\n";
String request = "GET /forward?dispatchRequestResponse=true HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Connection: close\r\n" +
"\r\n";
String responseString = _connector.getResponses(request);
@ -233,10 +247,12 @@ public class AsyncContextTest
}
}
public static volatile AsyncContext __asyncContext;
private class AsyncDispatchingServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, final HttpServletResponse response) throws ServletException, IOException
{
@ -253,13 +269,14 @@ public class AsyncContextTest
{
wrapped = true;
asyncContext = request.startAsync(request, new Wrapper(response));
__asyncContext=asyncContext;
}
else
{
asyncContext = request.startAsync();
__asyncContext=asyncContext;
}
new Thread(new DispatchingRunnable(asyncContext, wrapped)).start();
}
}
@ -301,12 +318,14 @@ public class AsyncContextTest
if (request.getParameter("dispatch") != null)
{
AsyncContext asyncContext = request.startAsync(request,response);
__asyncContext=asyncContext;
asyncContext.dispatch("/servletPath2");
}
else
{
response.getOutputStream().print("doGet:getServletPath:" + request.getServletPath() + "\n");
AsyncContext asyncContext = request.startAsync(request,response);
__asyncContext=asyncContext;
response.getOutputStream().print("doGet:async:getServletPath:" + ((HttpServletRequest)asyncContext.getRequest()).getServletPath() + "\n");
asyncContext.start(new AsyncRunnable(asyncContext));
@ -323,6 +342,7 @@ public class AsyncContextTest
{
response.getOutputStream().print("doGet:getServletPath:" + request.getServletPath() + "\n");
AsyncContext asyncContext = request.startAsync(request, response);
__asyncContext=asyncContext;
response.getOutputStream().print("doGet:async:getServletPath:" + ((HttpServletRequest)asyncContext.getRequest()).getServletPath() + "\n");
asyncContext.start(new AsyncRunnable(asyncContext));
}