You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by jo...@apache.org on 2010/05/04 02:20:04 UTC

svn commit: r940681 - in /shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets: http/HttpResponseBuilder.java rewrite/MutableContent.java

Author: johnh
Date: Tue May  4 00:20:03 2010
New Revision: 940681

URL: http://svn.apache.org/viewvc?rev=940681&view=rev
Log:
HttpResponseBuilder-as-MutableContent.

Makes HttpResponseBuilder extend MutableContent. The underlying semantics of the class remain the same -- two new mutation APIs are added as well. By default, HTML parsing is not supported (ie. with new HttpResponseBuilder().getDocument()), which is status quo.

This change is a step toward updating the HTTP object rewriter interface with HttpResponseBuilder as mutation object.


Modified:
    shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java
    shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java?rev=940681&r1=940680&r2=940681&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java Tue May  4 00:20:03 2010
@@ -26,6 +26,11 @@ import org.apache.commons.lang.ArrayUtil
 import org.apache.commons.lang.StringUtils;
 import org.apache.shindig.common.util.CharsetUtil;
 import org.apache.shindig.common.util.DateUtil;
+import org.apache.shindig.gadgets.GadgetException;
+import org.apache.shindig.gadgets.parse.GadgetHtmlParser;
+import org.apache.shindig.gadgets.rewrite.MutableContent;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
 
 import java.nio.charset.Charset;
 import java.util.Collection;
@@ -36,28 +41,32 @@ import java.util.Map;
 /**
  * Constructs HttpResponse objects.
  */
-public class HttpResponseBuilder {
+public class HttpResponseBuilder extends MutableContent {
   private int httpStatusCode = HttpResponse.SC_OK;
   private final Multimap<String, String> headers = HttpResponse.newHeaderMultimap();
-  private byte[] responseBytes = ArrayUtils.EMPTY_BYTE_ARRAY;
   private final Map<String, String> metadata = Maps.newHashMap();
 
-  public HttpResponseBuilder() {}
+  public HttpResponseBuilder() {
+    super(unsupportedParser(), (String)null);
+    this.setResponse(null);
+  }
 
   public HttpResponseBuilder(HttpResponseBuilder builder) {
+    super(unsupportedParser(), builder.create());
     httpStatusCode = builder.httpStatusCode;
     headers.putAll(builder.headers);
     metadata.putAll(builder.metadata);
-    responseBytes = builder.responseBytes;
   }
 
   public HttpResponseBuilder(HttpResponse response) {
+    this(unsupportedParser(), response);
+  }
+  
+  public HttpResponseBuilder(GadgetHtmlParser parser, HttpResponse response) {
+    super(parser, response);
     httpStatusCode = response.getHttpStatusCode();
-
     headers.putAll(response.getHeaders());
-
     metadata.putAll(response.getMetadata());
-    responseBytes = response.getResponseAsBytes();
   }
 
   /**
@@ -71,7 +80,7 @@ public class HttpResponseBuilder {
    * @param body The response string.  Converted to UTF-8 bytes and copied when set.
    */
   public HttpResponseBuilder setResponseString(String body) {
-    responseBytes = CharsetUtil.getUtf8Bytes(body);
+    setContentBytes(CharsetUtil.getUtf8Bytes(body));
     setEncoding(CharsetUtil.UTF8);
     return this;
   }
@@ -103,8 +112,9 @@ public class HttpResponseBuilder {
     if (responseBytes == null) {
       responseBytes = ArrayUtils.EMPTY_BYTE_ARRAY;
     }
-    this.responseBytes = new byte[responseBytes.length];
-    System.arraycopy(responseBytes, 0, this.responseBytes, 0, responseBytes.length);
+    byte[] newBytes = new byte[responseBytes.length];
+    System.arraycopy(responseBytes, 0, newBytes, 0, responseBytes.length);
+    setContentBytes(newBytes);
     return this;
   }
 
@@ -115,23 +125,15 @@ public class HttpResponseBuilder {
     if (responseBytes == null) {
       responseBytes = ArrayUtils.EMPTY_BYTE_ARRAY;
     }
-    this.responseBytes = responseBytes;
+    setContentBytes(responseBytes);
     return this;
   }
 
-  /**
-   * @param httpStatusCode The HTTP response status, defined on HttpResponse.
-   */
   public HttpResponseBuilder setHttpStatusCode(int httpStatusCode) {
     this.httpStatusCode = httpStatusCode;
     return this;
   }
 
-  /**
-   * Add a single header to the response. If a value for the given name is already set, a second
-   * value is added. If you wish to overwrite any possible values for a header, use
-   * {@link #setHeader(String, String)}.
-   */
   public HttpResponseBuilder addHeader(String name, String value) {
     if (name != null) {
       headers.put(name, value);
@@ -139,9 +141,6 @@ public class HttpResponseBuilder {
     return this;
   }
 
-  /**
-   * Sets a single header value, overwriting any previously set headers with the same name.
-   */
   public HttpResponseBuilder setHeader(String name, String value) {
     if (name != null) {
       headers.replaceValues(name, Lists.newArrayList(value));
@@ -149,9 +148,13 @@ public class HttpResponseBuilder {
     return this;
   }
 
-  /**
-   * Adds an entire map of headers to the response.
-   */
+  public String getHeader(String name) {
+    if (name != null && headers.containsKey(name)) {
+      return headers.get(name).iterator().next();
+    }
+    return null;
+  }
+
   public HttpResponseBuilder addHeaders(Map<String, String> headers) {
     for (Map.Entry<String,String> entry : headers.entrySet()) {
       this.headers.put(entry.getKey(), entry.getValue());
@@ -159,9 +162,6 @@ public class HttpResponseBuilder {
     return this;
   }
 
-  /**
-   * Adds all headers in the provided multimap to the response.
-   */
   public HttpResponseBuilder addAllHeaders(Map<String, ? extends List<String>> headers) {
     for (Map.Entry<String,? extends List<String>> entry : headers.entrySet()) {
       this.headers.putAll(entry.getKey(), entry.getValue());
@@ -169,18 +169,10 @@ public class HttpResponseBuilder {
     return this;
   }
 
-  /**
-   * Remove all headers with the given name from the response.
-   *
-   * @return Any values that were removed from the response.
-   */
   public Collection<String> removeHeader(String name) {
     return headers.removeAll(name);
   }
 
-  /**
-   * @param cacheTtl The time to live for this response, in seconds.
-   */
   public HttpResponseBuilder setCacheTtl(int cacheTtl) {
     headers.removeAll("Pragma");
     headers.removeAll("Expires");
@@ -188,10 +180,6 @@ public class HttpResponseBuilder {
     return this;
   }
 
-  /**
-   * @param expirationTime The expiration time for this response, in
-   * milliseconds since the Unix epoch.
-   */
   public HttpResponseBuilder setExpirationTime(long expirationTime) {
     headers.removeAll("Cache-Control");
     headers.removeAll("Pragma");
@@ -210,17 +198,11 @@ public class HttpResponseBuilder {
     return this;
   }
 
-  /**
-   * Adds a new piece of metadata to the response.
-   */
   public HttpResponseBuilder setMetadata(String key, String value) {
     metadata.put(key, value);
     return this;
   }
 
-  /**
-   * Merges the given Map of metadata into the existing metadata.
-   */
   public HttpResponseBuilder setMetadata(Map<String, String> metadata) {
     this.metadata.putAll(metadata);
     return this;
@@ -233,12 +215,28 @@ public class HttpResponseBuilder {
   Map<String, String> getMetadata() {
     return metadata;
   }
-
+  
   byte[] getResponse() {
-    return responseBytes;
+    // Supported to avoid copying data unnecessarily.
+    return getRawContentBytes();
   }
 
   public int getHttpStatusCode() {
     return httpStatusCode;
   }
+  
+  private static GadgetHtmlParser unsupportedParser() {
+    return new GadgetHtmlParser(null) {
+      @Override
+      protected Document parseDomImpl(String source) throws GadgetException {
+        throw new UnsupportedOperationException("Using HttpResponseBuilder in non-rewriting context");
+      }
+
+      @Override
+      protected DocumentFragment parseFragmentImpl(String source)
+          throws GadgetException {
+        throw new UnsupportedOperationException("Using HttpResponseBuilder in non-rewriting context");
+      }
+    };
+  }
 }

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java?rev=940681&r1=940680&r2=940681&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java Tue May  4 00:20:03 2010
@@ -18,6 +18,7 @@
 package org.apache.shindig.gadgets.rewrite;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.shindig.common.util.CharsetUtil;
 import org.apache.shindig.gadgets.GadgetException;
 import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.parse.GadgetHtmlParser;
@@ -118,7 +119,7 @@ public class MutableContent {
       document = null;
       contentSource = null;
       contentBytes = null;
-      numChanges++;
+      incrementNumChanges();
     }
   }
 
@@ -127,6 +128,10 @@ public class MutableContent {
    * @return Active content as InputStream.
    */
   public InputStream getContentBytes() {
+    return new ByteArrayInputStream(getRawContentBytes());
+  }
+  
+  protected byte[] getRawContentBytes() {
     if (contentBytes == null) {
       if (contentSource != null) {
         try {
@@ -136,25 +141,20 @@ public class MutableContent {
           // Doesn't occur; responseBytes wrapped as a ByteArrayInputStream.
         }
       } else if (content != null) {
-        try {
-          contentBytes = content.getBytes("UTF8");
-        } catch (UnsupportedEncodingException e) {
-          // Doesn't happen.
-        }
+        contentBytes = CharsetUtil.getUtf8Bytes(content);
       } else if (document != null) {
-        try {
-          contentBytes = HtmlSerialization.serialize(document).getBytes("UTF8");
-        } catch (UnsupportedEncodingException e) {
-          // Doesn't happen.
-        }
+        CharsetUtil.getUtf8Bytes(HtmlSerialization.serialize(document));
       }
     }
-    return new ByteArrayInputStream(contentBytes);
+    return contentBytes;
   }
   
   /**
    * Sets the object's contentBytes as the given raw input.
    * Note, this operation may clear the document if the content has changed.
+   * Also note, it's mandated that the new bytes array will NOT be modified
+   * by the caller of this API. The array is not copied, for performance reasons.
+   * If the caller may modify a byte array, it MUST pass in a new copy.
    * @param newBytes New content.
    */
   public void setContentBytes(byte[] newBytes) {
@@ -163,7 +163,7 @@ public class MutableContent {
       document = null;
       contentSource = null;
       content = null;
-      numChanges++;
+      incrementNumChanges();
     }
   }
 
@@ -176,7 +176,7 @@ public class MutableContent {
       content = null;
       contentSource = null;
       contentBytes = null;
-      numChanges++;
+      incrementNumChanges();
     }
   }
   
@@ -207,6 +207,10 @@ public class MutableContent {
   public int getNumChanges() {
     return numChanges;
   }
+  
+  protected void incrementNumChanges() {
+    ++numChanges;
+  }
 
   /**
    * True if current state has a parsed document. Allows rewriters to switch mode based on