Skip to content

Commit c7554b9

Browse files
committed
Add ParseFileHttpBody and ParseCountingFileHttpBody
1 parent 44d3133 commit c7554b9

13 files changed

+304
-18
lines changed

Parse/src/main/java/com/parse/ParseAWSRequest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ protected Task<byte[]> onResponseAsync(ParseHttpResponse response,
4141
return null;
4242
}
4343

44-
int totalSize = response.getTotalSize();
44+
long totalSize = response.getTotalSize();
4545
int downloadedSize = 0;
4646
InputStream responseStream = null;
4747
try {

Parse/src/main/java/com/parse/ParseApacheHttpClient.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ public ParseApacheHttpClient(int socketOperationTimeout, SSLSessionCache sslSess
212212
private static class ParseApacheHttpEntity extends InputStreamEntity {
213213
private ParseHttpBody parseBody;
214214

215-
public ParseApacheHttpEntity(ParseHttpBody parseBody) {
215+
public ParseApacheHttpEntity(ParseHttpBody parseBody) throws IOException {
216216
super(parseBody.getContent(), parseBody.getContentLength());
217217
super.setContentType(parseBody.getContentType());
218218
this.parseBody = parseBody;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2015-present, Parse, LLC.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
package com.parse;
10+
11+
import java.io.File;
12+
import java.io.FileInputStream;
13+
import java.io.IOException;
14+
import java.io.OutputStream;
15+
16+
/** package */ class ParseCountingFileHttpBody extends ParseFileHttpBody {
17+
18+
private static final int DEFAULT_CHUNK_SIZE = 4096;
19+
private static final int EOF = -1;
20+
21+
private final ProgressCallback progressCallback;
22+
23+
public ParseCountingFileHttpBody(File file, ProgressCallback progressCallback) {
24+
this(file, null, progressCallback);
25+
}
26+
27+
public ParseCountingFileHttpBody(
28+
File file, String contentType, ProgressCallback progressCallback) {
29+
super(file, contentType);
30+
this.progressCallback = progressCallback;
31+
}
32+
33+
@Override
34+
public void writeTo(OutputStream output) throws IOException {
35+
if (output == null) {
36+
throw new IllegalArgumentException("Output stream may not be null");
37+
}
38+
39+
final FileInputStream fileInput = new FileInputStream(file);;
40+
try {
41+
byte[] buffer = new byte[DEFAULT_CHUNK_SIZE];
42+
int n;
43+
long totalLength = file.length();
44+
long position = 0;
45+
while (EOF != (n = fileInput.read(buffer))) {
46+
output.write(buffer, 0, n);
47+
position += n;
48+
49+
if (progressCallback != null) {
50+
int progress = (int) (100 * position / totalLength);
51+
progressCallback.done(progress);
52+
}
53+
}
54+
} finally {
55+
ParseIOUtils.closeQuietly(fileInput);
56+
}
57+
}
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) 2015-present, Parse, LLC.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
package com.parse;
10+
11+
import java.io.File;
12+
import java.io.FileInputStream;
13+
import java.io.IOException;
14+
import java.io.InputStream;
15+
import java.io.OutputStream;
16+
17+
/** package */ class ParseFileHttpBody extends ParseHttpBody {
18+
19+
/* package */ final File file;
20+
21+
public ParseFileHttpBody(File file) {
22+
this(file, null);
23+
}
24+
25+
public ParseFileHttpBody(File file, String contentType) {
26+
super(contentType, file.length());
27+
this.file = file;
28+
}
29+
30+
@Override
31+
public InputStream getContent() throws IOException {
32+
return new FileInputStream(file);
33+
}
34+
35+
@Override
36+
public void writeTo(OutputStream out) throws IOException {
37+
if (out == null) {
38+
throw new IllegalArgumentException("Output stream can not be null");
39+
}
40+
41+
final FileInputStream fileInput = new FileInputStream(file);
42+
try {
43+
ParseIOUtils.copy(fileInput, out);
44+
} finally {
45+
ParseIOUtils.closeQuietly(fileInput);
46+
}
47+
}
48+
}

Parse/src/main/java/com/parse/ParseHttpBody.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@
1818
*/
1919
/** package */ abstract class ParseHttpBody {
2020
protected final String contentType;
21-
protected final int contentLength;
21+
protected final long contentLength;
2222

23-
public abstract InputStream getContent();
23+
public abstract InputStream getContent() throws IOException;
2424
public abstract void writeTo(OutputStream out) throws IOException;
2525

26-
public ParseHttpBody(String contentType, int contentLength) {
26+
public ParseHttpBody(String contentType, long contentLength) {
2727
this.contentType = contentType;
2828
this.contentLength = contentLength;
2929
}
3030

31-
public int getContentLength() {
31+
public long getContentLength() {
3232
return contentLength;
3333
}
3434

Parse/src/main/java/com/parse/ParseHttpResponse.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
/* package */ static abstract class Init<T extends Init<T>> {
2323
private int statusCode;
2424
private InputStream content;
25-
private int totalSize;
25+
private long totalSize;
2626
private String reasonPhrase;
2727
private Map<String, String> headers;
2828
private String contentType;
@@ -39,7 +39,7 @@ public T setContent(InputStream content) {
3939
return self();
4040
}
4141

42-
public T setTotalSize(int totalSize) {
42+
public T setTotalSize(long totalSize) {
4343
this.totalSize = totalSize;
4444
return self();
4545
}
@@ -74,7 +74,7 @@ public ParseHttpResponse build() {
7474

7575
/* package */ int statusCode;
7676
/* package */ InputStream content;
77-
/* package */ int totalSize;
77+
/* package */ long totalSize;
7878
/* package */ String reasonPhrase;
7979
/* package */ Map<String, String> headers;
8080
/* package */ String contentType;
@@ -96,7 +96,7 @@ public InputStream getContent() {
9696
return content;
9797
}
9898

99-
public int getTotalSize() {
99+
public long getTotalSize() {
100100
return totalSize;
101101
}
102102

Parse/src/test/java/com/parse/ParseAWSRequestTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public void test4XXThrowsException() throws Exception {
3737
"An Error occurred while saving".getBytes());
3838
ParseHttpResponse mockResponse = mock(ParseHttpResponse.class);
3939
when(mockResponse.getStatusCode()).thenReturn(400);
40-
when(mockResponse.getTotalSize()).thenReturn(0);
40+
when(mockResponse.getTotalSize()).thenReturn(0L);
4141
when(mockResponse.getReasonPhrase()).thenReturn("Bad Request");
4242
when(mockResponse.getContent()).thenReturn(mockInputStream);
4343

Parse/src/test/java/com/parse/ParseCloudCodeControllerTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public void testCallFunctionInBackgroundSuccessWithResult() throws Exception {
107107
ParseHttpResponse mockResponse = mock(ParseHttpResponse.class);
108108
when(mockResponse.getStatusCode()).thenReturn(200);
109109
when(mockResponse.getContent()).thenReturn(new ByteArrayInputStream(content.getBytes()));
110-
when(mockResponse.getTotalSize()).thenReturn(content.length());
110+
when(mockResponse.getTotalSize()).thenReturn((long) content.length());
111111

112112
ParseHttpClient restClient = mockParseHttpClientWithReponse(mockResponse);
113113
ParseCloudCodeController controller = new ParseCloudCodeController(restClient);
@@ -128,7 +128,7 @@ public void testCallFunctionInBackgroundSuccessWithoutResult() throws Exception
128128
ParseHttpResponse mockResponse = mock(ParseHttpResponse.class);
129129
when(mockResponse.getStatusCode()).thenReturn(200);
130130
when(mockResponse.getContent()).thenReturn(new ByteArrayInputStream(content.getBytes()));
131-
when(mockResponse.getTotalSize()).thenReturn(content.length());
131+
when(mockResponse.getTotalSize()).thenReturn((long) content.length());
132132

133133
ParseHttpClient restClient = mockParseHttpClientWithReponse(mockResponse);
134134
ParseCloudCodeController controller = new ParseCloudCodeController(restClient);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright (c) 2015-present, Parse, LLC.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
package com.parse;
10+
11+
import org.junit.Rule;
12+
import org.junit.Test;
13+
import org.junit.rules.TemporaryFolder;
14+
15+
import java.io.ByteArrayOutputStream;
16+
import java.io.File;
17+
import java.io.FileWriter;
18+
import java.io.IOException;
19+
import java.util.Arrays;
20+
import java.util.concurrent.Semaphore;
21+
import java.util.concurrent.TimeUnit;
22+
23+
import static org.junit.Assert.assertArrayEquals;
24+
import static org.junit.Assert.assertTrue;
25+
import static org.junit.Assert.fail;
26+
27+
public class ParseCountingFileHttpBodyTest {
28+
29+
@Rule
30+
public TemporaryFolder temporaryFolder = new TemporaryFolder();
31+
32+
@Test
33+
public void testWriteTo() throws Exception {
34+
final Semaphore didReportIntermediateProgress = new Semaphore(0);
35+
final Semaphore finish = new Semaphore(0);
36+
37+
ParseCountingFileHttpBody body = new ParseCountingFileHttpBody(
38+
makeTestFile(temporaryFolder.getRoot()), new ProgressCallback() {
39+
Integer maxProgressSoFar = 0;
40+
@Override
41+
public void done(Integer percentDone) {
42+
if (percentDone > maxProgressSoFar) {
43+
maxProgressSoFar = percentDone;
44+
assertTrue(percentDone >= 0 && percentDone <= 100);
45+
46+
if (percentDone < 100 && percentDone > 0) {
47+
didReportIntermediateProgress.release();
48+
} else if (percentDone == 100) {
49+
finish.release();
50+
} else if (percentDone == 0) {
51+
// do nothing
52+
} else {
53+
fail("percentDone should be within 0 - 100");
54+
}
55+
}
56+
}
57+
});
58+
59+
// Check content
60+
ByteArrayOutputStream output = new ByteArrayOutputStream();
61+
body.writeTo(output);
62+
assertArrayEquals(getData().getBytes(), output.toByteArray());
63+
// Check progress callback
64+
assertTrue(didReportIntermediateProgress.tryAcquire(5, TimeUnit.SECONDS));
65+
assertTrue(finish.tryAcquire(5, TimeUnit.SECONDS));
66+
}
67+
68+
@Test(expected = IllegalArgumentException.class)
69+
public void testWriteToWithNullOutput() throws Exception {
70+
ParseCountingFileHttpBody body = new ParseCountingFileHttpBody(
71+
makeTestFile(temporaryFolder.getRoot()), null);
72+
body.writeTo(null);
73+
}
74+
75+
private static String getData() {
76+
char[] chars = new char[64 << 14]; // 1MB
77+
Arrays.fill(chars, '1');
78+
return new String(chars);
79+
}
80+
81+
private static File makeTestFile(File root) throws IOException {
82+
File file = new File(root, "test");
83+
FileWriter writer = new FileWriter(file);
84+
writer.write(getData());
85+
writer.close();
86+
return file;
87+
}
88+
}

Parse/src/test/java/com/parse/ParseFileControllerTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public void testSaveAsyncSuccess() throws Exception {
130130
ParseHttpResponse response = mock(ParseHttpResponse.class);
131131
when(response.getStatusCode()).thenReturn(200);
132132
when(response.getContent()).thenReturn(new ByteArrayInputStream(content.getBytes()));
133-
when(response.getTotalSize()).thenReturn(content.length());
133+
when(response.getTotalSize()).thenReturn((long) content.length());
134134

135135
ParseHttpClient restClient = mock(ParseHttpClient.class);
136136
when(restClient.execute(any(ParseHttpRequest.class))).thenReturn(response);
@@ -229,7 +229,7 @@ public void testFetchAsyncSuccess() throws Exception {
229229
ParseHttpResponse response = mock(ParseHttpResponse.class);
230230
when(response.getStatusCode()).thenReturn(200);
231231
when(response.getContent()).thenReturn(new ByteArrayInputStream(data));
232-
when(response.getTotalSize()).thenReturn(data.length);
232+
when(response.getTotalSize()).thenReturn((long) data.length);
233233

234234
ParseHttpClient awsClient = mock(ParseHttpClient.class);
235235
when(awsClient.execute(any(ParseHttpRequest.class))).thenReturn(response);

0 commit comments

Comments
 (0)