Author: violetagg Date: Tue Jun 4 18:03:04 2013 New Revision: 1489536 URL: http://svn.apache.org/r1489536 Log: IllegalStateException will be thrown if more than one asynchronous dispatch operation is started within the same asynchronous cycle.
Modified: tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java Modified: tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java?rev=1489536&r1=1489535&r2=1489536&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java Tue Jun 4 18:03:04 2013 @@ -185,6 +185,10 @@ public class AsyncContextImpl implements logDebug("dispatch "); } check(); + if (dispatch != null) { + throw new IllegalStateException( + sm.getString("asyncContextImpl.dispatchingStarted")); + } if (request.getAttribute(ASYNC_REQUEST_URI)==null) { request.setAttribute(ASYNC_REQUEST_URI, request.getRequestURI()); request.setAttribute(ASYNC_CONTEXT_PATH, request.getContextPath()); @@ -347,7 +351,9 @@ public class AsyncContextImpl implements logDebug("intDispatch"); } try { - dispatch.run(); + Runnable runnable = dispatch; + dispatch = null; + runnable.run(); if (!request.isAsync()) { fireOnComplete(); } Modified: tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties?rev=1489536&r1=1489535&r2=1489536&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties Tue Jun 4 18:03:04 2013 @@ -66,6 +66,7 @@ aprListener.initializedOpenSSL=OpenSSL s asyncContextImpl.requestEnded=The request associated with the AsyncContext has already completed processing. asyncContextImpl.noAsyncDispatcher=The dispatcher returned from the ServletContext does not support asynchronous dispatching +asyncContextImpl.dispatchingStarted=Asynchronous dispatch operation has already been called. Additional asynchronous dispatch operation within the same asynchronous cycle is not allowed. containerBase.threadedStartFailed=A child container failed during start containerBase.threadedStopFailed=A child container failed during stop containerBase.backgroundProcess.cluster=Exception processing cluster {0} background process Modified: tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java?rev=1489536&r1=1489535&r2=1489536&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java (original) +++ tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java Tue Jun 4 18:03:04 2013 @@ -1720,4 +1720,63 @@ public class TestAsyncContextImpl extend // NO-OP } } + + @Test + public void testForbiddenDispatching() throws Exception { + // Setup Tomcat instance + Tomcat tomcat = getTomcatInstance(); + + // Must have a real docBase - just use temp + File docBase = new File(System.getProperty("java.io.tmpdir")); + + Context ctx = tomcat.addContext("", docBase.getAbsolutePath()); + + NonAsyncServlet nonAsyncServlet = new NonAsyncServlet(); + Wrapper wrapper = Tomcat.addServlet(ctx, "nonAsyncServlet", + nonAsyncServlet); + wrapper.setAsyncSupported(true); + ctx.addServletMapping("/nonAsyncServlet", "nonAsyncServlet"); + + ForbiddenDispatchingServlet forbiddenDispatchingServlet = new ForbiddenDispatchingServlet(); + Wrapper wrapper1 = Tomcat.addServlet(ctx, + "forbiddenDispatchingServlet", forbiddenDispatchingServlet); + wrapper1.setAsyncSupported(true); + ctx.addServletMapping("/forbiddenDispatchingServlet", + "forbiddenDispatchingServlet"); + + tomcat.start(); + + ByteChunk body = new ByteChunk(); + + try { + getUrl("http://localhost:" + getPort() + + "/forbiddenDispatchingServlet", body, null); + } catch (IOException ioe) { + // This may happen if test fails. Output the exception in case it is + // useful and let asserts handle the failure + ioe.printStackTrace(); + } + + assertTrue(body.toString().contains("OK")); + assertTrue(body.toString().contains("NonAsyncServletGet")); + } + + private static class ForbiddenDispatchingServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + AsyncContext asyncContext = req.startAsync(); + asyncContext.dispatch("/nonAsyncServlet"); + try { + asyncContext.dispatch("/nonExistingServlet"); + resp.getWriter().println("FAIL"); + } catch (IllegalStateException e) { + resp.getWriter().println("OK"); + } + } + + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org