Adds DELETE, HEAD and PUT methods to RequestBuilder.

Patch by: t.broyer
Review by: jlabanca,jgw
Issue: 3388



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7283 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/http/client/RequestBuilder.java b/user/src/com/google/gwt/http/client/RequestBuilder.java
index 38a9fb6..f566b24 100644
--- a/user/src/com/google/gwt/http/client/RequestBuilder.java
+++ b/user/src/com/google/gwt/http/client/RequestBuilder.java
@@ -25,17 +25,6 @@
 /**
  * Builder for constructing {@link com.google.gwt.http.client.Request} objects.
  * 
- * <p>
- * By default, this builder is restricted to building HTTP GET and POST requests
- * due to a bug in Safari's implementation of the <code>XmlHttpRequest</code>
- * object.
- * </p>
- * 
- * <p>
- * Please see <a href="http://bugs.webkit.org/show_bug.cgi?id=3812">
- * http://bugs.webkit.org/show_bug.cgi?id=3812</a> for more details.
- * </p>
- * 
  * <h3>Required Module</h3> Modules that use this class should inherit
  * <code>com.google.gwt.http.HTTP</code>.
  * 
@@ -61,16 +50,31 @@
   }
 
   /**
+   * Specifies that the HTTP DELETE method should be used.
+   */
+  public static final Method DELETE = new Method("DELETE");
+
+  /**
    * Specifies that the HTTP GET method should be used.
    */
   public static final Method GET = new Method("GET");
 
   /**
+   * Specifies that the HTTP HEAD method should be used.
+   */
+  public static final Method HEAD = new Method("HEAD");
+
+  /**
    * Specifies that the HTTP POST method should be used.
    */
   public static final Method POST = new Method("POST");
 
   /**
+   * Specifies that the HTTP PUT method should be used.
+   */
+  public static final Method PUT = new Method("PUT");
+
+  /**
    * The callback to call when the request completes.
    */
   private RequestCallback callback;
@@ -136,13 +140,6 @@
    *          how to do this.
    * @throws IllegalArgumentException if the httpMethod or URL are empty
    * @throws NullPointerException if the httpMethod or the URL are null
-   * 
-   *           <p>
-   *           <b>WARNING:</b>This method is provided in order to allow the
-   *           creation of HTTP request other than GET and POST to be made. If
-   *           this is done, the developer must accept that the behavior on
-   *           Safari is undefined.
-   *           </p>
    */
   protected RequestBuilder(String httpMethod, String url) {
 
diff --git a/user/test/com/google/gwt/http/client/RequestBuilderTest.java b/user/test/com/google/gwt/http/client/RequestBuilderTest.java
index e2ccbc9..c965442 100644
--- a/user/test/com/google/gwt/http/client/RequestBuilderTest.java
+++ b/user/test/com/google/gwt/http/client/RequestBuilderTest.java
@@ -24,9 +24,11 @@
  */
 public class RequestBuilderTest extends RequestTestBase {
 
+  public static final String SERVLET_DELETE_RESPONSE = "delete";
   public static final String SERVLET_GET_RESPONSE = "get";
   public static final String SERVLET_POST_RESPONSE = "post";
-  public static final String SERVLET_HEAD_RESPONSE = "head";
+  // W3C's XMLHttpRequest requires it be the empty string
+  public static final String SERVLET_HEAD_RESPONSE = "";
   public static final String SERVLET_PUT_RESPONSE = "put";
 
   private static String getTestBaseURL() {
@@ -154,7 +156,7 @@
 
   /**
    * Test method for
-   * {@link com.google.gwt.http.client.RequestBuilder#RequestBuilder(java.lang.String, java.lang.String)}. *
+   * {@link com.google.gwt.http.client.RequestBuilder#RequestBuilder(java.lang.String, java.lang.String)}.
    */
   public void testRequestBuilderStringString_HTTPMethodRestrictionOverride() {
     new RequestBuilder(RequestBuilder.GET, "FOO");
@@ -169,96 +171,71 @@
     // should reach here without any exceptions being thrown
   }
 
-  /**
-   * Test method for
-   * {@link com.google.gwt.http.client.RequestBuilder#sendRequest(java.lang.String, com.google.gwt.http.client.RequestCallback)}.
-   */
-  public void testSend_GET() throws RequestException {
-    delayTestFinishForRequest();
+  public void testSend_DELETE() throws RequestException {
+    RequestBuilder builder = new RequestBuilder(RequestBuilder.DELETE,
+        getTestBaseURL());
+    testSend(builder, SERVLET_DELETE_RESPONSE);
+  }
 
+  public void testSend_GET() throws RequestException {
     RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,
         getTestBaseURL() + "send_GET");
-    builder.setCallback(new RequestCallback() {
-      public void onError(Request request, Throwable exception) {
-        fail(exception.getMessage());
-      }
-
-      public void onResponseReceived(Request request, Response response) {
-        assertEquals(SERVLET_GET_RESPONSE, response.getText());
-        assertEquals(200, response.getStatusCode());
-        finishTest();
-      }
-    });
-    builder.send();
+    testSend(builder, SERVLET_GET_RESPONSE);
   }
 
-  /**
-   * Test method for {@link com.google.gwt.http.client.RequestBuilder#send()}.
-   */
-  public void testSend_POST() throws RequestException {
-    delayTestFinishForRequest();
+  public void testSend_HEAD() throws RequestException {
+    RequestBuilder builder = new RequestBuilder(RequestBuilder.HEAD,
+        getTestBaseURL());
+    testSend(builder, SERVLET_HEAD_RESPONSE);
+  }
 
+  public void testSend_POST() throws RequestException {
     RequestBuilder builder = new RequestBuilder(RequestBuilder.POST,
         getTestBaseURL() + "sendRequest_POST");
     builder.setHeader("Content-Type", "application/x-www-form-urlencoded");
-    builder.setCallback(new RequestCallback() {
-      public void onError(Request request, Throwable exception) {
-        fail(exception.getMessage());
-      }
-
-      public void onResponseReceived(Request request, Response response) {
-        assertEquals(SERVLET_POST_RESPONSE, response.getText());
-        assertEquals(200, response.getStatusCode());
-        finishTest();
-      }
-    });
     builder.setRequestData("method=test+request");
-    builder.send();
+    testSend(builder, SERVLET_POST_RESPONSE);
   }
 
-  /**
-   * Test method for
-   * {@link com.google.gwt.http.client.RequestBuilder#sendRequest(java.lang.String, com.google.gwt.http.client.RequestCallback)}.
-   */
-  public void testSendRequest_GET() throws RequestException {
-    delayTestFinishForRequest();
+  public void testSend_PUT() throws RequestException {
+    RequestBuilder builder = new RequestBuilder(RequestBuilder.PUT,
+        getTestBaseURL());
+    builder.setHeader("Content-Type", "text/html");
+    builder.setRequestData("<html><body>Put Me</body></html>");
+    testSend(builder, SERVLET_PUT_RESPONSE);
+  }
 
+  public void testSendRequest_DELETE() throws RequestException {
+    RequestBuilder builder = new RequestBuilder(RequestBuilder.DELETE,
+        getTestBaseURL());
+    testSendRequest(builder, null, SERVLET_DELETE_RESPONSE);
+  }
+
+  public void testSendRequest_GET() throws RequestException {
     RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,
         getTestBaseURL() + "sendRequest_GET");
-    builder.sendRequest(null, new RequestCallback() {
-      public void onError(Request request, Throwable exception) {
-        fail(exception.getMessage());
-      }
-
-      public void onResponseReceived(Request request, Response response) {
-        assertEquals(SERVLET_GET_RESPONSE, response.getText());
-        assertEquals(200, response.getStatusCode());
-        finishTest();
-      }
-    });
+    testSendRequest(builder, null, SERVLET_GET_RESPONSE);
   }
 
-  /**
-   * Test method for
-   * {@link com.google.gwt.http.client.RequestBuilder#sendRequest(java.lang.String, com.google.gwt.http.client.RequestCallback)}.
-   */
-  public void testSendRequest_POST() throws RequestException {
-    delayTestFinishForRequest();
+  public void testSendRequest_HEAD() throws RequestException {
+    RequestBuilder builder = new RequestBuilder(RequestBuilder.HEAD,
+        getTestBaseURL());
+    testSendRequest(builder, null, SERVLET_HEAD_RESPONSE);
+  }
 
+  public void testSendRequest_POST() throws RequestException {
     RequestBuilder builder = new RequestBuilder(RequestBuilder.POST,
         getTestBaseURL() + "sendRequest_POST");
     builder.setHeader("Content-Type", "application/x-www-form-urlencoded");
-    builder.sendRequest("method=test+request", new RequestCallback() {
-      public void onError(Request request, Throwable exception) {
-        fail(exception.getMessage());
-      }
+    testSendRequest(builder, "method=test+request", SERVLET_POST_RESPONSE);
+  }
 
-      public void onResponseReceived(Request request, Response response) {
-        assertEquals(SERVLET_POST_RESPONSE, response.getText());
-        assertEquals(200, response.getStatusCode());
-        finishTest();
-      }
-    });
+  public void testSendRequest_PUT() throws RequestException {
+    RequestBuilder builder = new RequestBuilder(RequestBuilder.PUT,
+        getTestBaseURL());
+    builder.setHeader("Content-Type", "application/x-www-form-urlencoded");
+    testSendRequest(builder, "<html><body>Put Me</body></html>",
+        SERVLET_PUT_RESPONSE);
   }
 
   public void testSetCallback() {
@@ -431,4 +408,51 @@
     } catch (IllegalArgumentException expected) {
     }
   }
+
+  /**
+   * Helper method to test {@link RequestBuilder#send()}.
+   * 
+   * @param builder the {@link RequestBuilder}
+   * @param expectedResponse the expected response
+   */
+  private void testSend(RequestBuilder builder, final String expectedResponse)
+      throws RequestException {
+    delayTestFinishForRequest();
+    builder.setCallback(new RequestCallback() {
+      public void onError(Request request, Throwable exception) {
+        fail(exception.getMessage());
+      }
+
+      public void onResponseReceived(Request request, Response response) {
+        assertEquals(expectedResponse, response.getText());
+        assertEquals(200, response.getStatusCode());
+        finishTest();
+      }
+    });
+    builder.send();
+  }
+
+  /**
+   * Helper method to test
+   * {@link RequestBuilder#sendRequest(String, RequestCallback)}.
+   * 
+   * @param builder the {@link RequestBuilder}
+   * @param requestData the data to request
+   * @param expectedResponse the expected response
+   */
+  private void testSendRequest(RequestBuilder builder, String requestData,
+      final String expectedResponse) throws RequestException {
+    delayTestFinishForRequest();
+    builder.sendRequest(requestData, new RequestCallback() {
+      public void onError(Request request, Throwable exception) {
+        fail(exception.getMessage());
+      }
+
+      public void onResponseReceived(Request request, Response response) {
+        assertEquals(expectedResponse, response.getText());
+        assertEquals(200, response.getStatusCode());
+        finishTest();
+      }
+    });
+  }
 }
diff --git a/user/test/com/google/gwt/http/server/RequestBuilderTestServlet.java b/user/test/com/google/gwt/http/server/RequestBuilderTestServlet.java
index 8101b5d..e07692b 100644
--- a/user/test/com/google/gwt/http/server/RequestBuilderTestServlet.java
+++ b/user/test/com/google/gwt/http/server/RequestBuilderTestServlet.java
@@ -37,7 +37,12 @@
   @Override
   protected void doDelete(HttpServletRequest request,
       HttpServletResponse response) {
-    response.setStatus(HttpServletResponse.SC_OK);
+    try {
+      response.setStatus(HttpServletResponse.SC_OK);
+      response.getWriter().print(RequestBuilderTest.SERVLET_DELETE_RESPONSE);
+    } catch (IOException e) {
+      response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+    }
   }
 
   @Override
@@ -90,12 +95,7 @@
 
   @Override
   protected void doHead(HttpServletRequest request, HttpServletResponse response) {
-    try {
-      response.setStatus(HttpServletResponse.SC_OK);
-      response.getWriter().print(RequestBuilderTest.SERVLET_HEAD_RESPONSE);
-    } catch (IOException e) {
-      response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-    }
+    response.setStatus(HttpServletResponse.SC_OK);
   }
 
   @Override