diff --git a/Parse/src/main/java/com/parse/ParseDecompressInterceptor.java b/Parse/src/main/java/com/parse/ParseDecompressInterceptor.java index 9aecaf286..01f35a88b 100644 --- a/Parse/src/main/java/com/parse/ParseDecompressInterceptor.java +++ b/Parse/src/main/java/com/parse/ParseDecompressInterceptor.java @@ -33,7 +33,7 @@ public ParseHttpResponse intercept(Chain chain) throws IOException { // to -1 newHeaders.put(CONTENT_LENGTH_HEADER, "-1"); // TODO(mengyan): Add builder constructor based on an existing ParseHttpResponse - response = response.newBuilder() + response = new ParseHttpResponse.Builder(response) .setTotalSize(-1) .setHeaders(newHeaders) .setContent(new GZIPInputStream(response.getContent())) diff --git a/Parse/src/main/java/com/parse/ParseHttpRequest.java b/Parse/src/main/java/com/parse/ParseHttpRequest.java index 10a46d548..dd225326b 100644 --- a/Parse/src/main/java/com/parse/ParseHttpRequest.java +++ b/Parse/src/main/java/com/parse/ParseHttpRequest.java @@ -12,8 +12,15 @@ import java.util.HashMap; import java.util.Map; +/** + * The http request we send to parse server. Instances of this class are not immutable. The + * request body may be consumed only once. The other fields are immutable. + */ /** package */ class ParseHttpRequest { + /** + * The {@code ParseHttpRequest} method type. + */ public enum Method { GET, POST, PUT, DELETE; @@ -61,43 +68,14 @@ public String toString() { } } - private final String url; - private final ParseHttpRequest.Method method; - private final Map headers; - private final ParseHttpBody body; - - protected ParseHttpRequest(Builder builder) { - this.url = builder.url; - this.method = builder.method; - this.headers = Collections.unmodifiableMap(new HashMap<>(builder.headers)); - this.body = builder.body; - } - - public String getUrl() { - return url; - } - - public ParseHttpRequest.Method getMethod() { - return method; - } - - public Map getAllHeaders() { - return headers; - } - - public String getHeader(String name) { - return headers.get(name); - } - - public ParseHttpBody getBody() { - return body; - } - + /** + * Builder of {@code ParseHttpRequest}. + */ public static class Builder { - protected String url; - protected ParseHttpRequest.Method method; - protected Map headers; - protected ParseHttpBody body; + private String url; + private Method method; + private Map headers; + private ParseHttpBody body; public Builder() { this.headers = new HashMap<>(); @@ -130,8 +108,13 @@ public Builder addHeader(String name, String value) { return this; } + public Builder addHeaders(Map headers) { + this.headers.putAll(headers); + return this; + } + public Builder setHeaders(Map headers) { - this.headers = headers; + this.headers = new HashMap<>(headers); return this; } @@ -139,4 +122,36 @@ public ParseHttpRequest build() { return new ParseHttpRequest(this); } } + + private final String url; + private final Method method; + private final Map headers; + private final ParseHttpBody body; + + private ParseHttpRequest(Builder builder) { + this.url = builder.url; + this.method = builder.method; + this.headers = Collections.unmodifiableMap(new HashMap<>(builder.headers)); + this.body = builder.body; + } + + public String getUrl() { + return url; + } + + public Method getMethod() { + return method; + } + + public Map getAllHeaders() { + return headers; + } + + public String getHeader(String name) { + return headers.get(name); + } + + public ParseHttpBody getBody() { + return body; + } } diff --git a/Parse/src/main/java/com/parse/ParseHttpResponse.java b/Parse/src/main/java/com/parse/ParseHttpResponse.java index 092018c38..cf3c15ceb 100644 --- a/Parse/src/main/java/com/parse/ParseHttpResponse.java +++ b/Parse/src/main/java/com/parse/ParseHttpResponse.java @@ -14,11 +14,14 @@ import java.util.Map; /** - * The base class of a http response we receive from parse server. It can be implemented by - * different http library such as Apache http, Android URLConnection, Square OKHttp and so on. + * The http response we receive from parse server. Instances of this class are not immutable. The + * response body may be consumed only once. The other fields are immutable. */ /** package */ class ParseHttpResponse { + /** + * Base builder for {@code ParseHttpResponse}. + */ /* package */ static abstract class Init> { private int statusCode; private InputStream content; @@ -30,6 +33,7 @@ /* package */ abstract T self(); public Init() { + this.totalSize = -1; this.headers = new HashMap<>(); } @@ -64,7 +68,7 @@ public T addHeaders(Map headers) { } public T addHeader(String key, String value) { - this.headers.put(key, value); + headers.put(key, value); return self(); } @@ -74,6 +78,9 @@ public T setContentType(String contentType) { } } + /** + * Builder of {@code ParseHttpResponse}. + */ public static class Builder extends Init { @Override @@ -81,11 +88,18 @@ public static class Builder extends Init { return this; } - /* package */ Builder() { + public Builder() { super(); } - /* package */ Builder(ParseHttpResponse response) { + /** + * Makes a new {@code ParseHttpResponse} {@code Builder} based on the input + * {@code ParseHttpResponse}. + * + * @param response + * The {@code ParseHttpResponse} where the {@code Builder}'s values come from. + */ + public Builder(ParseHttpResponse response) { super(); this.setStatusCode(response.getStatusCode()); this.setContent(response.getContent()); @@ -100,12 +114,12 @@ public ParseHttpResponse build() { } } - /* package */ final int statusCode; - /* package */ final InputStream content; - /* package */ final long totalSize; - /* package */ final String reasonPhrase; - /* package */ final Map headers; - /* package */ final String contentType; + private final int statusCode; + private final InputStream content; + private final long totalSize; + private final String reasonPhrase; + private final Map headers; + private final String contentType; /* package */ ParseHttpResponse(Init builder) { this.statusCode = builder.statusCode; @@ -116,18 +130,26 @@ public ParseHttpResponse build() { this.contentType = builder.contentType; } - public Builder newBuilder() { - return new Builder(this); - } - public int getStatusCode() { return statusCode; } + /** + * Returns the content of the {@code ParseHttpResponse}'s body. The {@link InputStream} can only + * be read once and can't be reset. + * + * @return The {@link InputStream} of the {@code ParseHttpResponse}'s body. + */ public InputStream getContent() { return content; } + /** + * Returns the size of the {@code ParseHttpResponse}'s body. -1 if the size of the + * {@code ParseHttpResponse}'s body is unknown. + * + * @return The size of the {@code ParseHttpResponse}'s body. + */ public long getTotalSize() { return totalSize; } @@ -141,7 +163,7 @@ public String getContentType() { } public String getHeader(String name) { - return headers == null ? null : headers.get(name); + return headers.get(name); } public Map getAllHeaders() { diff --git a/Parse/src/main/java/com/parse/ParseLogInterceptor.java b/Parse/src/main/java/com/parse/ParseLogInterceptor.java index bda124025..ad729e4cb 100644 --- a/Parse/src/main/java/com/parse/ParseLogInterceptor.java +++ b/Parse/src/main/java/com/parse/ParseLogInterceptor.java @@ -287,7 +287,7 @@ public void done(InputStream proxyInput, IOException e) { logResponseInfo(getLogger(), requestId, response, IGNORED_BODY_INFO); } - return response.newBuilder() + return new ParseHttpResponse.Builder(response) .setContent(newResponseBodyStream) .build(); } diff --git a/Parse/src/main/java/com/parse/ParseStethoInterceptor.java b/Parse/src/main/java/com/parse/ParseStethoInterceptor.java index b44428e22..8f3bc08ee 100644 --- a/Parse/src/main/java/com/parse/ParseStethoInterceptor.java +++ b/Parse/src/main/java/com/parse/ParseStethoInterceptor.java @@ -276,7 +276,7 @@ public ParseHttpResponse intercept(Chain chain) throws IOException { new DefaultResponseHandler(stethoEventReporter, requestId) ); if (responseStream != null) { - response = response.newBuilder() + response = new ParseHttpResponse.Builder(response) .setContent(responseStream) .build(); } diff --git a/Parse/src/test/java/com/parse/ParseHttpRequestTest.java b/Parse/src/test/java/com/parse/ParseHttpRequestTest.java index d1a239078..2e73f6171 100644 --- a/Parse/src/test/java/com/parse/ParseHttpRequestTest.java +++ b/Parse/src/test/java/com/parse/ParseHttpRequestTest.java @@ -10,6 +10,7 @@ import org.junit.Test; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -17,6 +18,7 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; public class ParseHttpRequestTest { @@ -80,4 +82,38 @@ public void testParseHttpRequestBuilderInitialization() throws IOException { assertEquals(contentType, bodyAgain.getContentType()); assertArrayEquals(content.getBytes(), ParseIOUtils.toByteArray(body.getContent())); } + + @Test + public void testParseHttpRequestBuildWithParseHttpRequest() throws IOException { + String url = "www.parse.com"; + ParseHttpRequest.Method method = ParseHttpRequest.Method.POST; + Map headers = new HashMap<>(); + String name = "name"; + String value = "value"; + headers.put(name, value); + + String content = "content"; + String contentType = "application/json"; + ParseByteArrayHttpBody body = new ParseByteArrayHttpBody(content, contentType); + + ParseHttpRequest request = new ParseHttpRequest.Builder() + .setUrl(url) + .addHeader(name, value) + .setMethod(method) + .setBody(body) + .build(); + + String newURL = "www.api.parse.com"; + ParseHttpRequest newRequest = new ParseHttpRequest.Builder(request) + .setUrl(newURL) + .build(); + + assertEquals(newURL, newRequest.getUrl()); + assertEquals(method.toString(), newRequest.getMethod().toString()); + assertEquals(1, newRequest.getAllHeaders().size()); + assertEquals(value, newRequest.getHeader(name)); + ParseHttpBody bodyAgain = newRequest.getBody(); + assertEquals(contentType, bodyAgain.getContentType()); + assertArrayEquals(content.getBytes(), ParseIOUtils.toByteArray(body.getContent())); + } } diff --git a/Parse/src/test/java/com/parse/ParseHttpResponseTest.java b/Parse/src/test/java/com/parse/ParseHttpResponseTest.java index 9123c51fe..a7dd23888 100644 --- a/Parse/src/test/java/com/parse/ParseHttpResponseTest.java +++ b/Parse/src/test/java/com/parse/ParseHttpResponseTest.java @@ -31,7 +31,7 @@ public void testParseHttpResponseDefaults() throws IOException { assertNull(response.getContentType()); assertNull(response.getReasonPhrase()); assertEquals(0, response.getStatusCode()); - assertEquals(0, response.getTotalSize()); + assertEquals(-1, response.getTotalSize()); assertEquals(0, response.getAllHeaders().size()); assertNull(response.getHeader("test")); } @@ -88,7 +88,7 @@ public void testParseHttpResponseBuildWithParseHttpResponse() throws IOException .build(); String newReasonPhrase = "Failed"; - ParseHttpResponse newResponse = response.newBuilder() + ParseHttpResponse newResponse = new ParseHttpResponse.Builder(response) .setReasonPhrase(newReasonPhrase) .build();