Author: johnh
Date: Mon Jan 10 20:05:56 2011
New Revision: 1057339

URL: http://svn.apache.org/viewvc?rev=1057339&view=rev
Log:
Make ETag filter more extensible.


Modified:
    
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETagFilter.java
    
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponse.java
    
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponseTest.java

Modified: 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETagFilter.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETagFilter.java?rev=1057339&r1=1057338&r2=1057339&view=diff
==============================================================================
--- 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETagFilter.java
 (original)
+++ 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETagFilter.java
 Mon Jan 10 20:05:56 2011
@@ -50,8 +50,7 @@ public class ETagFilter implements Filte
   public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain)
       throws IOException, ServletException {
     if (request instanceof HttpServletRequest && response instanceof 
HttpServletResponse) {
-      ETaggingHttpResponse taggingResponse =
-          new ETaggingHttpResponse((HttpServletRequest) request, 
(HttpServletResponse) response);
+      ETaggingHttpResponse taggingResponse = createTaggingResponse(request, 
response);
       try {
         chain.doFilter(request, taggingResponse);
       } finally {
@@ -64,4 +63,8 @@ public class ETagFilter implements Filte
     }
   }
 
+  protected ETaggingHttpResponse createTaggingResponse(
+      ServletRequest request, ServletResponse response) {
+    return new ETaggingHttpResponse((HttpServletRequest) request, 
(HttpServletResponse) response);
+  }
 }

Modified: 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponse.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponse.java?rev=1057339&r1=1057338&r2=1057339&view=diff
==============================================================================
--- 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponse.java
 (original)
+++ 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponse.java
 Mon Jan 10 20:05:56 2011
@@ -17,6 +17,8 @@
  */
 package org.apache.shindig.gadgets.servlet;
 
+import com.google.common.annotations.VisibleForTesting;
+
 import org.apache.http.util.ByteArrayBuffer;
 import org.apache.shindig.common.util.HashUtil;
 
@@ -46,11 +48,11 @@ public class ETaggingHttpResponse extend
   public static final String RESPONSE_HEADER = "ETag";
   public static final String REQUEST_HEADER = "If-None-Match";
 
-  private final HttpServletRequest request;
-  private final BufferServletOutputStream stream;
-  private ServletOutputStream originalStream;
-  private PrintWriter writer;
-  private boolean batching;
+  protected final HttpServletRequest request;
+  protected final BufferServletOutputStream stream;
+  protected ServletOutputStream originalStream;
+  protected PrintWriter writer;
+  protected boolean batching;
 
   public ETaggingHttpResponse(HttpServletRequest request, HttpServletResponse 
response) {
     super(response);
@@ -155,8 +157,7 @@ public class ETaggingHttpResponse extend
       if (etag.equals(reqEtag)) {
         emitETagMatchedResult();
       } else {
-        getResponse().setContentLength(bytes.length);
-        getResponse().getOutputStream().write(bytes);
+        emitFullResponseBody(bytes);
       }
     } else if (bytes.length != 0) {
       originalStream.write(bytes);
@@ -164,18 +165,24 @@ public class ETaggingHttpResponse extend
     }
   }
 
-  protected void emitETagMatchedResult() throws IOException {
+  protected void emitETagMatchedResult() {
     ((HttpServletResponse) 
getResponse()).setStatus(HttpServletResponse.SC_NOT_MODIFIED);
     getResponse().setContentLength(0);
   }
 
+  protected void emitFullResponseBody(byte[] bytes) throws IOException {
+    getResponse().setContentLength(bytes.length);
+    getResponse().getOutputStream().write(bytes);
+  }
+
   /**
    * A ServletOutputStream that stores the data in a byte array buffer.
    */
-  private class BufferServletOutputStream extends ServletOutputStream {
+  @VisibleForTesting
+  class BufferServletOutputStream extends ServletOutputStream {
     private static final int BUFFER_INITIAL_CAPACITY = 16384;
 
-    private MessageDigest digest = HashUtil.getMessageDigest();
+    private MessageDigest digest = null;
     private ByteArrayBuffer buffer = new 
ByteArrayBuffer(BUFFER_INITIAL_CAPACITY);
 
     @Override
@@ -194,20 +201,26 @@ public class ETaggingHttpResponse extend
 
     public void reset() {
       buffer.clear();
-      digest.reset();
+      digest = null;
     }
 
     public String getContentHash() {
+      ensureDigestObjectExists();
       String hash = HashUtil.bytesToHex(digest.digest());
       digest = null;
       return hash;
     }
 
     private void updateDigest(int b) {
+      ensureDigestObjectExists();
+      digest.update((byte) b);
+    }
+
+    private void ensureDigestObjectExists() {
       if (digest == null) {
         digest = HashUtil.getMessageDigest();
+        digest.update(buffer.toByteArray());
       }
-      digest.update((byte) b);
     }
   }
 }

Modified: 
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponseTest.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponseTest.java?rev=1057339&r1=1057338&r2=1057339&view=diff
==============================================================================
--- 
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponseTest.java
 (original)
+++ 
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponseTest.java
 Mon Jan 10 20:05:56 2011
@@ -20,6 +20,7 @@ package org.apache.shindig.gadgets.servl
 import static org.junit.Assert.*;
 
 import org.apache.http.util.ByteArrayBuffer;
+import 
org.apache.shindig.gadgets.servlet.ETaggingHttpResponse.BufferServletOutputStream;
 import org.easymock.EasyMock;
 import org.easymock.IMocksControl;
 import org.junit.Before;
@@ -41,9 +42,11 @@ public class ETaggingHttpResponseTest {
       new byte[] {-62, -95, 72, 111, 108, 97, 44, 32, 110, 105, -61, -79, 111, 
33};
   private static final String SECOND_RESPONSE_BODY = "你好";
   private static final byte[] AFTER_SECOND_RESPONSE_BODY_BYTES =
-      new byte[] {-62, -95, 72, 111, 108, 97, 44, 32, 110, 105, -61, -79, 111, 
33};
+      new byte[] {-62, -95, 72, 111, 108, 97, 44, 32, 110, 105, -61, -79, 111, 
33,
+          -28, -67, -96, -27, -91, -67};
   private static final int RESPONSE_BODY_LENGTH = RESPONSE_BODY_BYTES.length;
   private static final String GOOD_ETAG = "dae018f624d09423e7c4d7209fbea597";
+  private static final String SECOND_ETAG = "b6e56fb0129c3530f23dbb795daa3200";
   private static final String BAD_ETAG = "some bogus etag";
   private static final String EMPTY_CONTENT_ETAG = 
"d41d8cd98f00b204e9800998ecf8427e";
 
@@ -84,7 +87,7 @@ public class ETaggingHttpResponseTest {
   @Test
   public void testNotModifiedWithPrint() throws Exception {
     expectRequestETag(GOOD_ETAG);
-    expectNotModifiedResponse();
+    expectNotModifiedResponse(GOOD_ETAG);
     control.replay();
 
     response.getWriter().print(RESPONSE_BODY);
@@ -123,7 +126,7 @@ public class ETaggingHttpResponseTest {
   @Test
   public void testNotModifiedWithWrite() throws Exception {
     expectRequestETag(GOOD_ETAG);
-    expectNotModifiedResponse();
+    expectNotModifiedResponse(GOOD_ETAG);
     control.replay();
 
     response.getOutputStream().write(RESPONSE_BODY_BYTES);
@@ -171,9 +174,44 @@ public class ETaggingHttpResponseTest {
     response.startStreaming();
     assertArrayEquals(RESPONSE_BODY_BYTES, stream.getBuffer());
     
-    response.getWriter().print(SECOND_RESPONSE_BODY);
+    response.getOutputStream().write(SECOND_RESPONSE_BODY.getBytes("UTF-8"));
     assertArrayEquals(AFTER_SECOND_RESPONSE_BODY_BYTES, stream.getBuffer());   
 
   }
+  
+  @Test
+  public void testCanCalculateHashSeveralTimes() throws Exception {
+    expectRequestETag(GOOD_ETAG);
+    expectNotModifiedResponse(GOOD_ETAG);
+    control.replay();
+    
+    response.getOutputStream().write(RESPONSE_BODY.getBytes("UTF-8"));
+    String hash = ((BufferServletOutputStream) 
response.getOutputStream()).getContentHash();
+    assertEquals(GOOD_ETAG, hash);
+    hash = ((BufferServletOutputStream) 
response.getOutputStream()).getContentHash();
+    assertEquals(GOOD_ETAG, hash);
+    
+    response.flushBuffer();
+    assertResponseBodyIsEmpty();
+    control.verify();
+  }
+  
+  @Test
+  public void testHashVariesAsDataIsAdded() throws Exception {
+    expectRequestETag(SECOND_ETAG);
+    expectNotModifiedResponse(SECOND_ETAG);
+    control.replay();
+    
+    response.getOutputStream().write(RESPONSE_BODY.getBytes("UTF-8"));
+    String hash = ((BufferServletOutputStream) 
response.getOutputStream()).getContentHash();
+    assertEquals(GOOD_ETAG, hash);
+    response.getOutputStream().write(SECOND_RESPONSE_BODY.getBytes("UTF-8"));
+    hash = ((BufferServletOutputStream) 
response.getOutputStream()).getContentHash();
+    assertEquals(SECOND_ETAG, hash);
+
+    response.flushBuffer();
+    assertResponseBodyIsEmpty();
+    control.verify();
+  }
 
   private void expectRequestETag(String eTag) {
     
EasyMock.expect(request.getHeader(ETaggingHttpResponse.REQUEST_HEADER)).andReturn(eTag);
@@ -184,8 +222,8 @@ public class ETaggingHttpResponseTest {
     origResponse.setContentLength(RESPONSE_BODY_LENGTH);
   }
 
-  private void expectNotModifiedResponse() {
-    origResponse.setHeader(ETaggingHttpResponse.RESPONSE_HEADER, GOOD_ETAG);
+  private void expectNotModifiedResponse(String eTag) {
+    origResponse.setHeader(ETaggingHttpResponse.RESPONSE_HEADER, eTag);
     origResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
     origResponse.setContentLength(0);
   }


Reply via email to