Author: violetagg Date: Wed Jun 26 07:48:36 2013 New Revision: 1496809 URL: http://svn.apache.org/r1496809 Log: Merged revisions 1496732, 1496734 from tomcat/trunk: When AsyncContext.dispatch(...) is invoked do not cast request and response to HttpServletRequest/HttpServletResponse. ServletRequest.startAsync(ServletRequest,ServletResponse) can be invoked with custom ServletRequest/ServletResponse.
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/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:r1496732,1496734 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=1496809&r1=1496808&r2=1496809&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 26 07:48:36 2013 @@ -168,9 +168,17 @@ public class AsyncContextImpl implements @Override public void dispatch() { check(); - HttpServletRequest sr = (HttpServletRequest)getRequest(); - String path = sr.getRequestURI(); - String cpath = sr.getContextPath(); + String path; + String cpath; + ServletRequest servletRequest = getRequest(); + if (servletRequest instanceof HttpServletRequest) { + HttpServletRequest sr = (HttpServletRequest) servletRequest; + path = sr.getRequestURI(); + cpath = sr.getContextPath(); + } else { + path = request.getRequestURI(); + cpath = request.getContextPath(); + } if (cpath.length()>1) path = path.substring(cpath.length()); dispatch(path); } @@ -205,10 +213,8 @@ public class AsyncContextImpl implements } final AsyncDispatcher applicationDispatcher = (AsyncDispatcher) requestDispatcher; - final HttpServletRequest servletRequest = - (HttpServletRequest) getRequest(); - final HttpServletResponse servletResponse = - (HttpServletResponse) getResponse(); + final ServletRequest servletRequest = getRequest(); + final ServletResponse servletResponse = getResponse(); Runnable run = new Runnable() { @Override public void run() { 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=1496809&r1=1496808&r2=1496809&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 26 07:48:36 2013 @@ -30,11 +30,15 @@ import javax.servlet.AsyncContext; import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; import javax.servlet.DispatcherType; +import javax.servlet.GenericServlet; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; +import javax.servlet.ServletRequest; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; +import javax.servlet.ServletRequestWrapper; import javax.servlet.ServletResponse; +import javax.servlet.ServletResponseWrapper; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -1741,9 +1745,9 @@ public class TestAsyncContextImpl extend Wrapper wrapper = Tomcat.addServlet(ctx, "nonAsyncServlet", nonAsyncServlet); wrapper.setAsyncSupported(true); - ctx.addServletMapping("/nonAsyncServlet", "nonAsyncServlet"); + ctx.addServletMapping("/target", "nonAsyncServlet"); - ForbiddenDispatchingServlet forbiddenDispatchingServlet = new ForbiddenDispatchingServlet(); + DispatchingGenericServlet forbiddenDispatchingServlet = new DispatchingGenericServlet(); Wrapper wrapper1 = Tomcat.addServlet(ctx, "forbiddenDispatchingServlet", forbiddenDispatchingServlet); wrapper1.setAsyncSupported(true); @@ -1767,20 +1771,92 @@ public class TestAsyncContextImpl extend assertTrue(body.toString().contains("NonAsyncServletGet")); } - private static class ForbiddenDispatchingServlet extends HttpServlet { + private static class DispatchingGenericServlet extends GenericServlet { private static final long serialVersionUID = 1L; + private static final String CUSTOM_REQ_RESP = "crr"; + private static final String EMPTY_DISPATCH = "empty"; @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) + public void service(ServletRequest req, ServletResponse 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"); + if (DispatcherType.ASYNC != req.getDispatcherType()) { + AsyncContext asyncContext; + if ("y".equals(req.getParameter(CUSTOM_REQ_RESP))) { + asyncContext = req.startAsync( + new ServletRequestWrapper(req), + new ServletResponseWrapper(resp)); + } else { + asyncContext = req.startAsync(); + } + if ("y".equals(req.getParameter(EMPTY_DISPATCH))) { + asyncContext.dispatch(); + } else { + asyncContext.dispatch("/target"); + } + try { + asyncContext.dispatch("/nonExistingServlet"); + resp.getWriter().print("FAIL"); + } catch (IllegalStateException e) { + resp.getWriter().print("OK"); + } + } else { + resp.getWriter().print("DispatchingGenericServletGet-"); + } + } + + } + + @Test + public void testDispatchWithCustomRequestResponse() 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()); + + DispatchingGenericServlet dispatch = new DispatchingGenericServlet(); + Wrapper wrapper = Tomcat.addServlet(ctx, "dispatch", dispatch); + wrapper.setAsyncSupported(true); + ctx.addServletMapping("/dispatch", "dispatch"); + + CustomGenericServlet customGeneric = new CustomGenericServlet(); + Wrapper wrapper2 = Tomcat.addServlet(ctx, "customGeneric", + customGeneric); + wrapper2.setAsyncSupported(true); + ctx.addServletMapping("/target", "customGeneric"); + + tomcat.start(); + + ByteChunk res = getUrl("http://localhost:" + getPort() + + "/dispatch?crr=y"); + + StringBuilder expected = new StringBuilder(); + expected.append("OK"); + expected.append("CustomGenericServletGet-"); + assertEquals(expected.toString(), res.toString()); + + res = getUrl("http://localhost:" + getPort() + + "/dispatch?crr=y&empty=y"); + + expected = new StringBuilder(); + expected.append("OK"); + expected.append("DispatchingGenericServletGet-"); + assertEquals(expected.toString(), res.toString()); + } + + private static class CustomGenericServlet extends GenericServlet { + + private static final long serialVersionUID = 1L; + + @Override + public void service(ServletRequest req, ServletResponse res) + throws ServletException, IOException { + if (req instanceof ServletRequestWrapper + && res instanceof ServletResponseWrapper) { + res.getWriter().print("CustomGenericServletGet-"); } } 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=1496809&r1=1496808&r2=1496809&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Wed Jun 26 07:48:36 2013 @@ -103,6 +103,13 @@ <code>Users:type=UserDatabase,database=UserDatabase</code> at Tomcat shutdown. (pero) </fix> + <fix> + Avoid <code>ClassCastException</code> when an asynchronous dispatch is + invoked in an asynchronous cycle which is started by a call to + <code>ServletRequest.startAsync(ServletRequest,ServletResponse)</code> + where ServletRequest/ServletResponse are custom implementations. + (violetagg) + </fix> </changelog> </subsection> <subsection name="Cluster"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org