Skip to content

Add ParseFileHttpBody and ParseCountingFileHttpBody #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 28, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Parse/src/main/java/com/parse/ParseAWSRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ protected Task<byte[]> onResponseAsync(ParseHttpResponse response,
return null;
}

int totalSize = response.getTotalSize();
long totalSize = response.getTotalSize();
int downloadedSize = 0;
InputStream responseStream = null;
try {
Expand Down
2 changes: 1 addition & 1 deletion Parse/src/main/java/com/parse/ParseApacheHttpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public ParseApacheHttpClient(int socketOperationTimeout, SSLSessionCache sslSess
private static class ParseApacheHttpEntity extends InputStreamEntity {
private ParseHttpBody parseBody;

public ParseApacheHttpEntity(ParseHttpBody parseBody) {
public ParseApacheHttpEntity(ParseHttpBody parseBody) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason for this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since parseBody.getContent() will try to create a fileStream in some cases, so we need to throw IOException here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

super(parseBody.getContent(), parseBody.getContentLength());
super.setContentType(parseBody.getContentType());
this.parseBody = parseBody;
Expand Down
58 changes: 58 additions & 0 deletions Parse/src/main/java/com/parse/ParseCountingFileHttpBody.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2015-present, Parse, LLC.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.parse;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

/** package */ class ParseCountingFileHttpBody extends ParseFileHttpBody {

private static final int DEFAULT_CHUNK_SIZE = 4096;
private static final int EOF = -1;

private final ProgressCallback progressCallback;

public ParseCountingFileHttpBody(File file, ProgressCallback progressCallback) {
this(file, null, progressCallback);
}

public ParseCountingFileHttpBody(
File file, String contentType, ProgressCallback progressCallback) {
super(file, contentType);
this.progressCallback = progressCallback;
}

@Override
public void writeTo(OutputStream output) throws IOException {
if (output == null) {
throw new IllegalArgumentException("Output stream may not be null");
}

final FileInputStream fileInput = new FileInputStream(file);;
try {
byte[] buffer = new byte[DEFAULT_CHUNK_SIZE];
int n;
long totalLength = file.length();
long position = 0;
while (EOF != (n = fileInput.read(buffer))) {
output.write(buffer, 0, n);
position += n;

if (progressCallback != null) {
int progress = (int) (100 * position / totalLength);
progressCallback.done(progress);
}
}
} finally {
ParseIOUtils.closeQuietly(fileInput);
}
}
}
48 changes: 48 additions & 0 deletions Parse/src/main/java/com/parse/ParseFileHttpBody.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2015-present, Parse, LLC.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.parse;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/** package */ class ParseFileHttpBody extends ParseHttpBody {

/* package */ final File file;

public ParseFileHttpBody(File file) {
this(file, null);
}

public ParseFileHttpBody(File file, String contentType) {
super(contentType, file.length());
this.file = file;
}

@Override
public InputStream getContent() throws IOException {
return new FileInputStream(file);
}

@Override
public void writeTo(OutputStream out) throws IOException {
if (out == null) {
throw new IllegalArgumentException("Output stream can not be null");
}

final FileInputStream fileInput = new FileInputStream(file);
try {
ParseIOUtils.copy(fileInput, out);
} finally {
ParseIOUtils.closeQuietly(fileInput);
}
}
}
8 changes: 4 additions & 4 deletions Parse/src/main/java/com/parse/ParseHttpBody.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@
*/
/** package */ abstract class ParseHttpBody {
protected final String contentType;
protected final int contentLength;
protected final long contentLength;

public abstract InputStream getContent();
public abstract InputStream getContent() throws IOException;
public abstract void writeTo(OutputStream out) throws IOException;

public ParseHttpBody(String contentType, int contentLength) {
public ParseHttpBody(String contentType, long contentLength) {
this.contentType = contentType;
this.contentLength = contentLength;
}

public int getContentLength() {
public long getContentLength() {
return contentLength;
}

Expand Down
8 changes: 4 additions & 4 deletions Parse/src/main/java/com/parse/ParseHttpResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
/* package */ static abstract class Init<T extends Init<T>> {
private int statusCode;
private InputStream content;
private int totalSize;
private long totalSize;
private String reasonPhrase;
private Map<String, String> headers;
private String contentType;
Expand All @@ -39,7 +39,7 @@ public T setContent(InputStream content) {
return self();
}

public T setTotalSize(int totalSize) {
public T setTotalSize(long totalSize) {
this.totalSize = totalSize;
return self();
}
Expand Down Expand Up @@ -74,7 +74,7 @@ public ParseHttpResponse build() {

/* package */ int statusCode;
/* package */ InputStream content;
/* package */ int totalSize;
/* package */ long totalSize;
/* package */ String reasonPhrase;
/* package */ Map<String, String> headers;
/* package */ String contentType;
Expand All @@ -96,7 +96,7 @@ public InputStream getContent() {
return content;
}

public int getTotalSize() {
public long getTotalSize() {
return totalSize;
}

Expand Down
2 changes: 1 addition & 1 deletion Parse/src/test/java/com/parse/ParseAWSRequestTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void test4XXThrowsException() throws Exception {
"An Error occurred while saving".getBytes());
ParseHttpResponse mockResponse = mock(ParseHttpResponse.class);
when(mockResponse.getStatusCode()).thenReturn(400);
when(mockResponse.getTotalSize()).thenReturn(0);
when(mockResponse.getTotalSize()).thenReturn(0L);
when(mockResponse.getReasonPhrase()).thenReturn("Bad Request");
when(mockResponse.getContent()).thenReturn(mockInputStream);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public void testCallFunctionInBackgroundSuccessWithResult() throws Exception {
ParseHttpResponse mockResponse = mock(ParseHttpResponse.class);
when(mockResponse.getStatusCode()).thenReturn(200);
when(mockResponse.getContent()).thenReturn(new ByteArrayInputStream(content.getBytes()));
when(mockResponse.getTotalSize()).thenReturn(content.length());
when(mockResponse.getTotalSize()).thenReturn((long) content.length());

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

ParseHttpClient restClient = mockParseHttpClientWithReponse(mockResponse);
ParseCloudCodeController controller = new ParseCloudCodeController(restClient);
Expand Down
88 changes: 88 additions & 0 deletions Parse/src/test/java/com/parse/ParseCountingFileHttpBodyTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright (c) 2015-present, Parse, LLC.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.parse;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class ParseCountingFileHttpBodyTest {

@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();

@Test
public void testWriteTo() throws Exception {
final Semaphore didReportIntermediateProgress = new Semaphore(0);
final Semaphore finish = new Semaphore(0);

ParseCountingFileHttpBody body = new ParseCountingFileHttpBody(
makeTestFile(temporaryFolder.getRoot()), new ProgressCallback() {
Integer maxProgressSoFar = 0;
@Override
public void done(Integer percentDone) {
if (percentDone > maxProgressSoFar) {
maxProgressSoFar = percentDone;
assertTrue(percentDone >= 0 && percentDone <= 100);

if (percentDone < 100 && percentDone > 0) {
didReportIntermediateProgress.release();
} else if (percentDone == 100) {
finish.release();
} else if (percentDone == 0) {
// do nothing
} else {
fail("percentDone should be within 0 - 100");
}
}
}
});

// Check content
ByteArrayOutputStream output = new ByteArrayOutputStream();
body.writeTo(output);
assertArrayEquals(getData().getBytes(), output.toByteArray());
// Check progress callback
assertTrue(didReportIntermediateProgress.tryAcquire(5, TimeUnit.SECONDS));
assertTrue(finish.tryAcquire(5, TimeUnit.SECONDS));
}

@Test(expected = IllegalArgumentException.class)
public void testWriteToWithNullOutput() throws Exception {
ParseCountingFileHttpBody body = new ParseCountingFileHttpBody(
makeTestFile(temporaryFolder.getRoot()), null);
body.writeTo(null);
}

private static String getData() {
char[] chars = new char[64 << 14]; // 1MB
Arrays.fill(chars, '1');
return new String(chars);
}

private static File makeTestFile(File root) throws IOException {
File file = new File(root, "test");
FileWriter writer = new FileWriter(file);
writer.write(getData());
writer.close();
return file;
}
}
4 changes: 2 additions & 2 deletions Parse/src/test/java/com/parse/ParseFileControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public void testSaveAsyncSuccess() throws Exception {
ParseHttpResponse response = mock(ParseHttpResponse.class);
when(response.getStatusCode()).thenReturn(200);
when(response.getContent()).thenReturn(new ByteArrayInputStream(content.getBytes()));
when(response.getTotalSize()).thenReturn(content.length());
when(response.getTotalSize()).thenReturn((long) content.length());

ParseHttpClient restClient = mock(ParseHttpClient.class);
when(restClient.execute(any(ParseHttpRequest.class))).thenReturn(response);
Expand Down Expand Up @@ -229,7 +229,7 @@ public void testFetchAsyncSuccess() throws Exception {
ParseHttpResponse response = mock(ParseHttpResponse.class);
when(response.getStatusCode()).thenReturn(200);
when(response.getContent()).thenReturn(new ByteArrayInputStream(data));
when(response.getTotalSize()).thenReturn(data.length);
when(response.getTotalSize()).thenReturn((long) data.length);

ParseHttpClient awsClient = mock(ParseHttpClient.class);
when(awsClient.execute(any(ParseHttpRequest.class))).thenReturn(response);
Expand Down
Loading