diff --git a/wsclient/src/main/java/com/google/gson/webservice/client/Preconditions.java b/wsclient/src/main/java/com/google/gson/webservice/client/Preconditions.java index 33422d79..b88220ba 100644 --- a/wsclient/src/main/java/com/google/gson/webservice/client/Preconditions.java +++ b/wsclient/src/main/java/com/google/gson/webservice/client/Preconditions.java @@ -15,6 +15,14 @@ */ package com.google.gson.webservice.client; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + final class Preconditions { public static void checkArgument(boolean condition) { @@ -23,9 +31,49 @@ final class Preconditions { } } + public static void checkArgument(boolean condition, HttpURLConnection conn) { + if (!condition) { + StringBuilder sb = new StringBuilder(); + try { + sb.append("HttpURLConnection Details\n"); + sb.append("ResponseCode:" + conn.getResponseCode()); + sb.append(", ContentType: " + conn.getContentType() + "\n"); + Map> headerFields = conn.getHeaderFields(); + for (Entry> header : headerFields.entrySet()) { + sb.append(header.getKey()).append(":"); + boolean first = true; + for (String value : header.getValue()) { + if (first) { + first = false; + } else { + sb.append(","); + } + sb.append(value); + } + sb.append("\n"); + } + byte[] data = readInByteArray(conn.getInputStream()); + sb.append(new String(data)); + } catch (IOException e) { + // ignore + } + throw new IllegalArgumentException(sb.toString()); + } + } + public static void checkNotNull(Object obj) { if (obj == null) { throw new IllegalArgumentException(); } } + + private static byte[] readInByteArray(InputStream src) { + ByteArrayOutputStream dst = new ByteArrayOutputStream(); + try { + Streams.copy(src, dst); + } catch (IOException e) { + // ignore + } + return dst.toByteArray(); + } } diff --git a/wsclient/src/main/java/com/google/gson/webservice/client/RequestSender.java b/wsclient/src/main/java/com/google/gson/webservice/client/RequestSender.java index c203b45c..bcf9cea5 100644 --- a/wsclient/src/main/java/com/google/gson/webservice/client/RequestSender.java +++ b/wsclient/src/main/java/com/google/gson/webservice/client/RequestSender.java @@ -16,8 +16,6 @@ package com.google.gson.webservice.client; import java.io.IOException; -import java.io.PrintWriter; -import java.io.Writer; import java.lang.reflect.Type; import java.net.HttpURLConnection; import java.util.Map; @@ -53,7 +51,7 @@ public final class RequestSender { public void send(HttpURLConnection conn, WebServiceRequest request) { try { conn.setRequestMethod(request.getHttpMethod().toString()); - conn.setRequestProperty("Content-Type", request.getContentType()); + setHeader(conn, "Content-Type", request.getContentType(), true); // Assume conservatively that the response will need to be read. // This is done here instead of in the response receiver because this property must be set @@ -62,10 +60,17 @@ public final class RequestSender { addRequestParams(conn, request.getHeaders()); RequestBody requestBody = request.getBody(); + String contentLength = "0"; + String requestBodyContents = null; if (requestBody.getSpec().size() > 0) { conn.setDoOutput(true); - addRequestBody(conn, requestBody); - } + requestBodyContents = gson.toJson(requestBody); + contentLength = String.valueOf(requestBodyContents.length()); + } + setHeader(conn, "Content-Length", contentLength, true); + if (requestBody.getSpec().size() > 0) { + Streams.copy(requestBodyContents, conn.getOutputStream()); + } // Initiate the sending of the request. conn.connect(); @@ -81,16 +86,18 @@ public final class RequestSender { Type type = spec.getTypeFor(paramName); Object value = entry.getValue(); String json = gson.toJson(value, type); - conn.addRequestProperty(paramName, json); - if (logger != null) { - logger.log(logLevel, String.format("Request param: %s:%s", paramName, json)); - } + setHeader(conn, paramName, json, false); } } - - private void addRequestBody(HttpURLConnection conn, RequestBody body) throws IOException { - Writer writer = new PrintWriter(conn.getOutputStream()); - gson.toJson(body, writer); - writer.close(); - } + + private void setHeader(HttpURLConnection conn, String name, String value, boolean overwrite) { + if (logger != null) { + logger.log(logLevel, String.format("Request param: %s:%s", name, value)); + } + if (overwrite) { + conn.setRequestProperty(name, value); + } else { + conn.addRequestProperty(name, value); + } + } } diff --git a/wsclient/src/main/java/com/google/gson/webservice/client/ResponseReceiver.java b/wsclient/src/main/java/com/google/gson/webservice/client/ResponseReceiver.java index 811722ff..87bf7dcb 100644 --- a/wsclient/src/main/java/com/google/gson/webservice/client/ResponseReceiver.java +++ b/wsclient/src/main/java/com/google/gson/webservice/client/ResponseReceiver.java @@ -90,7 +90,7 @@ public final class ResponseReceiver { return new ResponseBody.Builder(bodySpec).build(); } String connContentType = conn.getContentType(); - Preconditions.checkArgument(connContentType.contains(bodySpec.getContentType())); + Preconditions.checkArgument(connContentType.contains(bodySpec.getContentType()), conn); Reader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); ResponseBody body = gson.fromJson(reader, ResponseBody.class); return body; diff --git a/wsclient/src/main/java/com/google/gson/webservice/client/Streams.java b/wsclient/src/main/java/com/google/gson/webservice/client/Streams.java new file mode 100644 index 00000000..93e9142e --- /dev/null +++ b/wsclient/src/main/java/com/google/gson/webservice/client/Streams.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.gson.webservice.client; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +final class Streams { + + static void copy(String str, OutputStream dst) throws IOException { + byte[] bytes = str.getBytes("UTF-8"); + copy(new ByteArrayInputStream(bytes), dst); + } + /** + * Copy contents of src to dst. Exhausts src completely, and closes both streams. + */ + static void copy(InputStream src, OutputStream dst) throws IOException { + try { + final byte[] buf = new byte[2048]; + int count; + while ((count = src.read(buf)) != -1) { + dst.write(buf, 0, count); + } + } finally { + src.close(); + dst.close(); + } + } +} diff --git a/wsdef/src/main/java/com/google/gson/webservice/definition/WebServiceCallSpec.java b/wsdef/src/main/java/com/google/gson/webservice/definition/WebServiceCallSpec.java index 3a43f4b4..bbfd5b31 100644 --- a/wsdef/src/main/java/com/google/gson/webservice/definition/WebServiceCallSpec.java +++ b/wsdef/src/main/java/com/google/gson/webservice/definition/WebServiceCallSpec.java @@ -120,7 +120,7 @@ public final class WebServiceCallSpec { @Override public String toString() { StringBuilder sb = new StringBuilder("{path:"); - sb.append(path).append(",supportedHttpMethods:"); + sb.append(path).append(",supportedHttpMethods:["); boolean first = true; for (HttpMethod method : supportedHttpMethods) { if (first) { @@ -130,9 +130,8 @@ public final class WebServiceCallSpec { } sb.append(method); } - sb.append(path).append(",requestSpec:"); - sb.append(requestSpec).append(",responseSpec:"); - sb.append(responseSpec).append("}"); + sb.append("],requestSpec:").append(requestSpec); + sb.append(",responseSpec:").append(responseSpec).append("}"); return sb.toString(); } }