Author: markt
Date: Fri Oct 14 20:50:57 2011
New Revision: 1183494

URL: http://svn.apache.org/viewvc?rev=1183494&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=52009
Fix the NPE if an error occurs during comet processing
Add test cases for errors during comet processing
Ensure access log entries are made if an error occurs

Modified:
    tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
    tomcat/trunk/test/org/apache/catalina/comet/TestCometProcessor.java

Modified: tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java?rev=1183494&r1=1183493&r2=1183494&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java Fri Oct 
14 20:50:57 2011
@@ -249,6 +249,10 @@ public class CoyoteAdapter implements Ad
             req.getRequestProcessor().setWorkerThreadName(null);
             // Recycle the wrapper request and response
             if (error || response.isClosed() || !request.isComet()) {
+                ((Context) request.getMappingData().context).logAccess(
+                        request, response,
+                        System.currentTimeMillis() - req.getStartTime(),
+                        false);
                 request.recycle();
                 request.setFilterChain(null);
                 response.recycle();
@@ -430,9 +434,12 @@ public class CoyoteAdapter implements Ad
             } else if (!comet) {
                 request.finishRequest();
                 response.finishResponse();
-                if (postParseSuccess) {
+                if (postParseSuccess &&
+                        request.getMappingData().context != null) {
                     // Log only if processing was invoked.
                     // If postParseRequest() failed, it has already logged it.
+                    // If context is null this was the start of a comet request
+                    // that failed and has already been logged.
                     ((Context) request.getMappingData().context).logAccess(
                             request, response,
                             System.currentTimeMillis() - req.getStartTime(),

Modified: tomcat/trunk/test/org/apache/catalina/comet/TestCometProcessor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/comet/TestCometProcessor.java?rev=1183494&r1=1183493&r2=1183494&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/comet/TestCometProcessor.java 
(original)
+++ tomcat/trunk/test/org/apache/catalina/comet/TestCometProcessor.java Fri Oct 
14 20:50:57 2011
@@ -36,12 +36,14 @@ import static org.junit.Assert.fail;
 import org.junit.Test;
 
 import org.apache.catalina.Context;
+import org.apache.catalina.Wrapper;
 import org.apache.catalina.comet.CometEvent.EventType;
 import org.apache.catalina.connector.CometEventImpl;
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.connector.Response;
 import org.apache.catalina.startup.Tomcat;
 import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.catalina.valves.TesterAccessLogValve;
 import org.apache.catalina.valves.ValveBase;
 
 public class TestCometProcessor extends TomcatBaseTest {
@@ -116,7 +118,25 @@ public class TestCometProcessor extends 
 
     @Test
     public void testSimpleCometClient() throws Exception {
+        doSimpleCometTest(null);
+    }
+
+    @Test
+    public void testSimpleCometClientBeginFail() throws Exception {
+        doSimpleCometTest(SimpleCometServlet.FAIL_ON_BEGIN);
+    }
+
+    @Test
+    public void testSimpleCometClientReadFail() throws Exception {
+        doSimpleCometTest(SimpleCometServlet.FAIL_ON_READ);
+    }
 
+    @Test
+    public void testSimpleCometClientEndFail() throws Exception {
+        doSimpleCometTest(SimpleCometServlet.FAIL_ON_END);
+    }
+
+    private void doSimpleCometTest(String initParam) throws Exception {
         if (!isCometSupported()) {
             return;
         }
@@ -124,8 +144,15 @@ public class TestCometProcessor extends 
         // Setup Tomcat instance
         Tomcat tomcat = getTomcatInstance();
         Context root = tomcat.addContext("", TEMP_DIR);
-        Tomcat.addServlet(root, "comet", new SimpleCometServlet());
+        Wrapper w = Tomcat.addServlet(root, "comet", new SimpleCometServlet());
+        if (initParam != null) {
+            w.addInitParameter(initParam, "true");
+        }
         root.addServletMapping("/", "comet");
+
+        TesterAccessLogValve alv = new TesterAccessLogValve();
+        root.getPipeline().addValve(alv);
+
         tomcat.start();
 
         // Create connection to Comet servlet
@@ -151,36 +178,51 @@ public class TestCometProcessor extends 
         os.close();
         is.close();
 
-        // Validate response
         String[] response = readThread.getResponse().split("\r\n");
-        assertEquals("HTTP/1.1 200 OK", response[0]);
-        assertEquals("Server: Apache-Coyote/1.1", response[1]);
-        assertTrue(response[2].startsWith("Set-Cookie: JSESSIONID="));
-        assertEquals("Content-Type: text/plain;charset=ISO-8859-1", 
response[3]);
-        assertEquals("Transfer-Encoding: chunked", response[4]);
-        assertTrue(response[5].startsWith("Date: "));
-        assertEquals("", response[6]);
-        assertEquals("7", response[7]);
-        assertEquals("BEGIN", response[8]);
-        assertEquals("", response[9]);
-        assertEquals("17", response[10]);
-        assertEquals("Client: READ: 4 bytes", response[11]);
-        assertEquals("", response[12]);
-        assertEquals("17", response[13]);
-        assertEquals("Client: READ: 4 bytes", response[14]);
-        assertEquals("", response[15]);
-        assertEquals("17", response[16]);
-        assertEquals("Client: READ: 4 bytes", response[17]);
-        assertEquals("", response[18]);
-        assertEquals("17", response[19]);
-        assertEquals("Client: READ: 4 bytes", response[20]);
-        assertEquals("", response[21]);
-        assertEquals("d", response[22]);
-        assertEquals("Client: END", response[23]);
-        assertEquals("", response[24]);
-        assertEquals("0", response[25]);
-        // Expect 26 lines
-        assertEquals(26, response.length);
+        if (initParam == null) {
+            // Normal response expected
+            // Validate response
+            assertEquals("HTTP/1.1 200 OK", response[0]);
+            assertEquals("Server: Apache-Coyote/1.1", response[1]);
+            assertTrue(response[2].startsWith("Set-Cookie: JSESSIONID="));
+            assertEquals("Content-Type: text/plain;charset=ISO-8859-1", 
response[3]);
+            assertEquals("Transfer-Encoding: chunked", response[4]);
+            assertTrue(response[5].startsWith("Date: "));
+            assertEquals("", response[6]);
+            assertEquals("7", response[7]);
+            assertEquals("BEGIN", response[8]);
+            assertEquals("", response[9]);
+            assertEquals("17", response[10]);
+            assertEquals("Client: READ: 4 bytes", response[11]);
+            assertEquals("", response[12]);
+            assertEquals("17", response[13]);
+            assertEquals("Client: READ: 4 bytes", response[14]);
+            assertEquals("", response[15]);
+            assertEquals("17", response[16]);
+            assertEquals("Client: READ: 4 bytes", response[17]);
+            assertEquals("", response[18]);
+            assertEquals("17", response[19]);
+            assertEquals("Client: READ: 4 bytes", response[20]);
+            assertEquals("", response[21]);
+            assertEquals("d", response[22]);
+            assertEquals("Client: END", response[23]);
+            assertEquals("", response[24]);
+            assertEquals("0", response[25]);
+            // Expect 26 lines
+            assertEquals(26, response.length);
+        } else {
+            // Failure expected only expected for the fail on begin
+            // Failure at any later stage and the reponse headers (including 
the
+            // 200 response code will already have been sent to the client
+            if (initParam == SimpleCometServlet.FAIL_ON_BEGIN) {
+                assertEquals("HTTP/1.1 500 Internal Server Error", 
response[0]);
+                alv.validateAccessLog(1, 500, 0, 1000);
+            } else {
+                assertEquals("HTTP/1.1 200 OK", response[0]);
+                alv.validateAccessLog(1, 200, 0, 5000);
+            }
+
+        }
     }
 
     /**
@@ -267,6 +309,26 @@ public class TestCometProcessor extends 
 
         private static final long serialVersionUID = 1L;
 
+        public static final String FAIL_ON_BEGIN = "failOnBegin";
+        public static final String FAIL_ON_READ = "failOnRead";
+        public static final String FAIL_ON_END = "failOnEnd";
+
+        private boolean failOnBegin = false;
+        private boolean failOnRead = false;
+        private boolean failOnEnd = false;
+
+
+        @Override
+        public void init() throws ServletException {
+            failOnBegin = Boolean.valueOf(getServletConfig().getInitParameter(
+                    FAIL_ON_BEGIN)).booleanValue();
+            failOnRead = Boolean.valueOf(getServletConfig().getInitParameter(
+                    FAIL_ON_READ)).booleanValue();
+            failOnEnd = Boolean.valueOf(getServletConfig().getInitParameter(
+                    FAIL_ON_END)).booleanValue();
+        }
+
+
         @Override
         public void event(CometEvent event) throws IOException,
                 ServletException {
@@ -278,9 +340,15 @@ public class TestCometProcessor extends 
             session.setMaxInactiveInterval(30);
 
             if (event.getEventType() == EventType.BEGIN) {
+                if (failOnBegin) {
+                    throw new IOException("Fail on begin");
+                }
                 response.setContentType("text/plain");
                 response.getWriter().print("BEGIN" + "\r\n");
             } else if (event.getEventType() == EventType.READ) {
+                if (failOnRead) {
+                    throw new IOException("Fail on read");
+                }
                 InputStream is = request.getInputStream();
                 int count = 0;
                 while (is.available() > 0) {
@@ -290,6 +358,9 @@ public class TestCometProcessor extends 
                 String msg = "READ: " + count + " bytes";
                 response.getWriter().print("Client: " + msg + "\r\n");
             } else if (event.getEventType() == EventType.END) {
+                if (failOnEnd) {
+                    throw new IOException("Fail on end");
+                }
                 String msg = "END";
                 response.getWriter().print("Client: " + msg + "\r\n");
                 event.close();



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to