Author: violetagg Date: Wed Jun 5 05:02:38 2013 New Revision: 1489706 URL: http://svn.apache.org/r1489706 Log: Merged revision 1489536 from tomcat/trunk: IllegalStateException will be thrown if more than one asynchronous dispatch operation is started within the same asynchronous cycle.
Modified: tomcat/tc7.0.x/trunk/ (props changed) tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/LocalStrings.properties tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Propchange: tomcat/tc7.0.x/trunk/ ------------------------------------------------------------------------------ Merged /tomcat/trunk:r1489536 Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java?rev=1489706&r1=1489705&r2=1489706&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java Wed Jun 5 05:02:38 2013 @@ -187,6 +187,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()); @@ -350,7 +354,9 @@ public class AsyncContextImpl implements logDebug("intDispatch"); } try { - dispatch.run(); + Runnable runnable = dispatch; + dispatch = null; + runnable.run(); if (!request.isAsync()) { fireOnComplete(); } Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/LocalStrings.properties?rev=1489706&r1=1489705&r2=1489706&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/LocalStrings.properties (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/LocalStrings.properties Wed Jun 5 05:02:38 2013 @@ -73,6 +73,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/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java?rev=1489706&r1=1489705&r2=1489706&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java (original) +++ tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java Wed Jun 5 05:02:38 2013 @@ -1721,4 +1721,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"); + } + } + + } } Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1489706&r1=1489705&r2=1489706&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Wed Jun 5 05:02:38 2013 @@ -130,6 +130,12 @@ logging properties without prefixes if the property cannot be found with a prefix. (markt) </add> + <fix> + Ensure that only the first asynchronous dispatch operation for a given + asynchronous cycle will be performed. Any subsequent asynchronous + dispatch operation for the same asynchronous cycle will be ignored and + <code>IllegalStateException</code> will be thrown. (violetagg) + </fix> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org