You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by ro...@apache.org on 2007/01/14 21:45:57 UTC

svn commit: r496142 - in /labs/speedyfeed/servlet/trunk/src: main/java/org/apache/speedyfeed/SpeedyfeedResponseStream.java main/java/org/apache/speedyfeed/SpeedyfeedResponseWrapper.java test/java/org/apache/speedyfeed/test/BasicTest.java

Author: rooneg
Date: Sun Jan 14 12:45:56 2007
New Revision: 496142

URL: http://svn.apache.org/viewvc?view=rev&rev=496142
Log:
Avoid the requirement that servlets call close to trigger filtering.  Instead
we now only filter if the response has a Content-Length header, so we can tell
when we've hit the end of the content and need to filter it.

Based on suggestions from labs@l.a.o discussion with Geir and Leo.

* src/main/java/org/apache/speedyfeed/SpeedyfeedResponseStream.java
  (contentLength, bytesWritten): New fields.
  (checkContentType): Figure out the content length, and only enable
   filtering if we have one.
  (write, write): Maintain bytesWritten count, and if we hit the content
   length and we're filtering call filterResponse.
  (close): Move most content to filterResponse, don't dereference a null
   outputStream.
  (filterResponse): New method, holds most of what was in close, plus it
   sets outputStream to null when it's done.  Also updates Content-Length
   of the response to match the filtered data.

* src/main/java/org/apache/speedyfeed/SpeedyfeedResponseWrapper.java
  (contentLength): New field.
  (setContentLength): New method, grabs the content length as it's being
   set so we can return it.
  (getContentLength): New method.

* src/test/java/org/apache/speedyfeed/test/BasicTest.java
  (BasicServlet.doGet): Set Content-Length, remove call to close.

Modified:
    labs/speedyfeed/servlet/trunk/src/main/java/org/apache/speedyfeed/SpeedyfeedResponseStream.java
    labs/speedyfeed/servlet/trunk/src/main/java/org/apache/speedyfeed/SpeedyfeedResponseWrapper.java
    labs/speedyfeed/servlet/trunk/src/test/java/org/apache/speedyfeed/test/BasicTest.java

Modified: labs/speedyfeed/servlet/trunk/src/main/java/org/apache/speedyfeed/SpeedyfeedResponseStream.java
URL: http://svn.apache.org/viewvc/labs/speedyfeed/servlet/trunk/src/main/java/org/apache/speedyfeed/SpeedyfeedResponseStream.java?view=diff&rev=496142&r1=496141&r2=496142
==============================================================================
--- labs/speedyfeed/servlet/trunk/src/main/java/org/apache/speedyfeed/SpeedyfeedResponseStream.java (original)
+++ labs/speedyfeed/servlet/trunk/src/main/java/org/apache/speedyfeed/SpeedyfeedResponseStream.java Sun Jan 14 12:45:56 2007
@@ -41,6 +41,9 @@
 
   OutputStream outputStream = null;
 
+  int contentLength;
+  int bytesWritten = 0;
+
   boolean checkedContentType = false;
   boolean isAtomContent = false;
   boolean closed = false;
@@ -60,7 +63,18 @@
     if (! isAtomContent) {
       outputStream = response.getWrapped().getOutputStream();
     } else {
-      outputStream = new ByteArrayOutputStream();
+      contentLength = response.getContentLength();
+      if (contentLength <= 0) {
+        // If we don't have a content length, we won't know when to stop
+        // and parse the response, so just turn off the filter and let all
+        // the data through.
+
+        isAtomContent = false;
+
+        outputStream = response.getWrapped().getOutputStream();
+      } else {
+        outputStream = new ByteArrayOutputStream();
+      }
     }
   }
 
@@ -70,7 +84,13 @@
       checkContentType();
       write(b);
     } else {
+      bytesWritten += 4;
+
       outputStream.write(b);
+
+      if (isAtomContent && bytesWritten >= contentLength) {
+        filterResponse();
+      }
     }
   }
 
@@ -85,7 +105,13 @@
       checkContentType();
       write(b, off, len);
     } else {
+      bytesWritten += len;
+
       outputStream.write(b, off, len);
+
+      if (isAtomContent && bytesWritten >= contentLength) {
+        filterResponse();
+      }
     }
   }
 
@@ -96,55 +122,72 @@
 
   public void close() throws IOException
   {
-    if (checkedContentType && ! isAtomContent) {
+    if (checkedContentType && ! isAtomContent && outputStream != null) {
       outputStream.close();
     } else if (! checkedContentType) {
       checkContentType();
       close();
     } else {
-      byte buf[] = ((ByteArrayOutputStream) outputStream).toByteArray();
+      if (outputStream != null) {
+        filterResponse();
+      }
+    }
 
-      InputStream is = new ByteArrayInputStream(buf);
+    closed = true;
+  }
 
-      Parser p = Abdera.getNewParser();
+  private void filterResponse() throws IOException
+  {
+    byte buf[] = ((ByteArrayOutputStream) outputStream).toByteArray();
 
-      boolean parseFailed = false;
+    InputStream is = new ByteArrayInputStream(buf);
 
-      Date ifModifiedSince = response.getIfModifiedSince();
+    Parser p = Abdera.getNewParser();
 
-      // At this point we're done with buffered data, so just create the
-      // final output stream so we can write either our modified version
-      // or the original to it.
-      outputStream = response.getWrapped().getOutputStream();
+    boolean parseFailed = false;
 
-      try {
-        Document<Feed> doc = p.parse(is); // XXX calculate and pass base href
+    Date ifModifiedSince = response.getIfModifiedSince();
 
-        for (Entry e : doc.getRoot().getEntries()) {
-          Date d = e.getUpdated();
-          if (d == null) {
-            d = e.getPublished();
-          }
-
-          if (d != null && d.before(ifModifiedSince)) {
-            e.discard();
-          }
+    // At this point we're done with buffered data, so just create the
+    // final output stream so we can write either our modified version
+    // or the original to it.
+    outputStream = response.getWrapped().getOutputStream();
+
+    try {
+      Document<Feed> doc = p.parse(is); // XXX calculate and pass base href
+
+      for (Entry e : doc.getRoot().getEntries()) {
+        Date d = e.getUpdated();
+        if (d == null) {
+          d = e.getPublished();
         }
 
-        doc.writeTo(outputStream);
-      } catch (ParseException pe) {
-        parseFailed = true;
-      } catch (IRISyntaxException irise) {
-        parseFailed = true;
-      } finally {
-        if (parseFailed) {
-          outputStream.write(buf);
+        if (d != null && d.before(ifModifiedSince)) {
+          e.discard();
         }
+      }
 
-        outputStream.close();
+      // It's unfortunate that this is the only way to get the length of
+      // the content we're going to write...
+      ByteArrayOutputStream tos = new ByteArrayOutputStream();
+
+      doc.writeTo(tos);
+
+      buf = tos.toByteArray();
+
+      response.getWrapped().setContentLength(buf.length);
+
+      outputStream.write(buf);
+    } catch (ParseException pe) {
+      parseFailed = true;
+    } catch (IRISyntaxException irise) {
+      parseFailed = true;
+    } finally {
+      if (parseFailed) {
+        outputStream.write(buf);
       }
     }
 
-    closed = true;
+    outputStream = null;
   }
 }

Modified: labs/speedyfeed/servlet/trunk/src/main/java/org/apache/speedyfeed/SpeedyfeedResponseWrapper.java
URL: http://svn.apache.org/viewvc/labs/speedyfeed/servlet/trunk/src/main/java/org/apache/speedyfeed/SpeedyfeedResponseWrapper.java?view=diff&rev=496142&r1=496141&r2=496142
==============================================================================
--- labs/speedyfeed/servlet/trunk/src/main/java/org/apache/speedyfeed/SpeedyfeedResponseWrapper.java (original)
+++ labs/speedyfeed/servlet/trunk/src/main/java/org/apache/speedyfeed/SpeedyfeedResponseWrapper.java Sun Jan 14 12:45:56 2007
@@ -33,6 +33,8 @@
   String ifModifiedSince = null;
   String contentType = null;
 
+  int contentLength = 0;
+
   public SpeedyfeedResponseWrapper(HttpServletResponse wrapped,
                                    String ifModifiedSince)
   {
@@ -47,6 +49,12 @@
     wrapped.setContentType(contentType);
   }
 
+  public void setContentLength(int cl)
+  {
+    contentLength = cl;
+    wrapped.setContentLength(cl);
+  }
+
   HttpServletResponse getWrapped() { return wrapped; }
 
   boolean isAtomContent()
@@ -57,6 +65,11 @@
   Date getIfModifiedSince()
   {
     return AtomDate.parse(ifModifiedSince);
+  }
+
+  int getContentLength()
+  {
+    return contentLength;
   }
 
   public ServletOutputStream getOutputStream()

Modified: labs/speedyfeed/servlet/trunk/src/test/java/org/apache/speedyfeed/test/BasicTest.java
URL: http://svn.apache.org/viewvc/labs/speedyfeed/servlet/trunk/src/test/java/org/apache/speedyfeed/test/BasicTest.java?view=diff&rev=496142&r1=496141&r2=496142
==============================================================================
--- labs/speedyfeed/servlet/trunk/src/test/java/org/apache/speedyfeed/test/BasicTest.java (original)
+++ labs/speedyfeed/servlet/trunk/src/test/java/org/apache/speedyfeed/test/BasicTest.java Sun Jan 14 12:45:56 2007
@@ -54,17 +54,27 @@
       InputStream in = BasicServlet.class.getResourceAsStream("/basic.xml");
       OutputStream out = response.getOutputStream();
 
-      response.setContentType("application/atom+xml");
-
       byte buffer[] = new byte[1024];
-      int len;
+      int len, clen;
+
+      if (in.markSupported()) {
+        in.mark(1024 * 1024);
+
+        clen = 0;
 
-      try {
         while ((len = in.read(buffer)) != -1) {
-          out.write(buffer, 0, len);
+          clen += len;
         }
-      } finally {
-        out.close();
+
+        in.reset();
+
+        response.setContentLength(clen);
+      }
+
+      response.setContentType("application/atom+xml");
+
+      while ((len = in.read(buffer)) != -1) {
+        out.write(buffer, 0, len);
       }
     }
   }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org