This is an automated email from the ASF dual-hosted git repository.
gaul pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jclouds.git
The following commit(s) were added to refs/heads/master by this push:
new 6e6f8eb JCLOUDS-912: JCLOUDS-1547: GCS InputStream single-part upload
6e6f8eb is described below
commit 6e6f8ebf779d8edc5cedec687558637d8212ab18
Author: Andrew Gaul <[email protected]>
AuthorDate: Sat May 23 13:25:24 2020 +0900
JCLOUDS-912: JCLOUDS-1547: GCS InputStream single-part upload
Previously this provider worked around a RestAnnotationProcessor quirk
by using multi-part uploads for InputStream payloads. Instead work
around the quirk another way which allows a single-part upload. This
allows inclusion of the Content-MD5 header during object creation.
Backfill tests with both ByteSource and InputStream inputs.
---
.../internal/BaseBlobIntegrationTest.java | 38 +++++++++++++++++-----
.../http/internal/PayloadEnclosingImpl.java | 8 +++++
.../main/java/org/jclouds/io/PayloadEnclosing.java | 1 +
.../integration/B2BlobIntegrationLiveTest.java | 14 ++++++--
.../binders/MultipartUploadBinder.java | 1 +
.../blobstore/GoogleCloudStorageBlobStore.java | 2 +-
6 files changed, 53 insertions(+), 11 deletions(-)
diff --git
a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java
b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java
index ef5bd7f..a814c00 100644
---
a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java
+++
b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java
@@ -267,7 +267,7 @@ public class BaseBlobIntegrationTest extends
BaseBlobStoreIntegrationTest {
}
}
- private void putBlobWithMd5(byte[] payload, HashCode contentMD5) throws
InterruptedException, IOException {
+ private void putBlobWithMd5(Payload payload, long contentLength, HashCode
contentMD5) throws InterruptedException, IOException {
String container = getContainerName();
BlobStore blobStore = view.getBlobStore();
try {
@@ -275,6 +275,7 @@ public class BaseBlobIntegrationTest extends
BaseBlobStoreIntegrationTest {
Blob blob = blobStore
.blobBuilder(blobName)
.payload(payload)
+ .contentLength(contentLength)
.contentMD5(contentMD5)
.build();
blobStore.putBlob(container, blob);
@@ -288,18 +289,39 @@ public class BaseBlobIntegrationTest extends
BaseBlobStoreIntegrationTest {
}
@Test(groups = { "integration", "live" })
- public void testPutCorrectContentMD5() throws InterruptedException,
IOException {
- byte[] payload = createTestInput(1024).read();
- HashCode contentMD5 = md5().hashBytes(payload);
- putBlobWithMd5(payload, contentMD5);
+ public void testPutCorrectContentMD5ByteSource() throws
InterruptedException, IOException {
+ ByteSource payload = createTestInput(1024);
+ HashCode contentMD5 = md5().hashBytes(payload.read());
+ putBlobWithMd5(new ByteSourcePayload(payload), payload.size(),
contentMD5);
+ }
+
+ @Test(groups = { "integration", "live" })
+ public void testPutIncorrectContentMD5ByteSource() throws
InterruptedException, IOException {
+ ByteSource payload = createTestInput(1024);
+ HashCode contentMD5 = md5().hashBytes(new byte[0]);
+ try {
+ putBlobWithMd5(new ByteSourcePayload(payload), payload.size(),
contentMD5);
+ fail();
+ } catch (HttpResponseException hre) {
+ if (hre.getResponse().getStatusCode() !=
getIncorrectContentMD5StatusCode()) {
+ throw hre;
+ }
+ }
}
@Test(groups = { "integration", "live" })
- public void testPutIncorrectContentMD5() throws InterruptedException,
IOException {
- byte[] payload = createTestInput(1024).read();
+ public void testPutCorrectContentMD5InputStream() throws
InterruptedException, IOException {
+ ByteSource payload = createTestInput(1024);
+ HashCode contentMD5 = md5().hashBytes(payload.read());
+ putBlobWithMd5(new InputStreamPayload(payload.openStream()),
payload.size(), contentMD5);
+ }
+
+ @Test(groups = { "integration", "live" })
+ public void testPutIncorrectContentMD5InputStream() throws
InterruptedException, IOException {
+ ByteSource payload = createTestInput(1024);
HashCode contentMD5 = md5().hashBytes(new byte[0]);
try {
- putBlobWithMd5(payload, contentMD5);
+ putBlobWithMd5(new InputStreamPayload(payload.openStream()),
payload.size(), contentMD5);
fail();
} catch (HttpResponseException hre) {
if (hre.getResponse().getStatusCode() !=
getIncorrectContentMD5StatusCode()) {
diff --git
a/core/src/main/java/org/jclouds/http/internal/PayloadEnclosingImpl.java
b/core/src/main/java/org/jclouds/http/internal/PayloadEnclosingImpl.java
index a8b5196..bff39b6 100644
--- a/core/src/main/java/org/jclouds/http/internal/PayloadEnclosingImpl.java
+++ b/core/src/main/java/org/jclouds/http/internal/PayloadEnclosingImpl.java
@@ -98,6 +98,14 @@ public class PayloadEnclosingImpl implements
PayloadEnclosing {
}
@Override
+ public void resetPayload(boolean release) {
+ if (release && payload != null) {
+ payload.release();
+ }
+ payload = null;
+ }
+
+ @Override
public int hashCode() {
final int prime = 31;
int result = 1;
diff --git a/core/src/main/java/org/jclouds/io/PayloadEnclosing.java
b/core/src/main/java/org/jclouds/io/PayloadEnclosing.java
index 3ed2983..dd3f28b 100644
--- a/core/src/main/java/org/jclouds/io/PayloadEnclosing.java
+++ b/core/src/main/java/org/jclouds/io/PayloadEnclosing.java
@@ -48,4 +48,5 @@ public interface PayloadEnclosing {
@Nullable
Payload getPayload();
+ void resetPayload(boolean release);
}
diff --git
a/providers/b2/src/test/java/org/jclouds/b2/blobstore/integration/B2BlobIntegrationLiveTest.java
b/providers/b2/src/test/java/org/jclouds/b2/blobstore/integration/B2BlobIntegrationLiveTest.java
index 0ecb6bd..3f45077 100644
---
a/providers/b2/src/test/java/org/jclouds/b2/blobstore/integration/B2BlobIntegrationLiveTest.java
+++
b/providers/b2/src/test/java/org/jclouds/b2/blobstore/integration/B2BlobIntegrationLiveTest.java
@@ -80,9 +80,19 @@ public final class B2BlobIntegrationLiveTest extends
BaseBlobIntegrationTest {
}
@Override
- public void testPutIncorrectContentMD5() throws InterruptedException,
IOException {
+ public void testPutIncorrectContentMD5ByteSource() throws
InterruptedException, IOException {
try {
- super.testPutIncorrectContentMD5();
+ super.testPutIncorrectContentMD5ByteSource();
+ failBecauseExceptionWasNotThrown(AssertionError.class);
+ } catch (AssertionError ae) {
+ throw new SkipException("B2 does not enforce Content-MD5", ae);
+ }
+ }
+
+ @Override
+ public void testPutIncorrectContentMD5InputStream() throws
InterruptedException, IOException {
+ try {
+ super.testPutIncorrectContentMD5InputStream();
failBecauseExceptionWasNotThrown(AssertionError.class);
} catch (AssertionError ae) {
throw new SkipException("B2 does not enforce Content-MD5", ae);
diff --git
a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/binders/MultipartUploadBinder.java
b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/binders/MultipartUploadBinder.java
index ca6422b..848b8c6 100644
---
a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/binders/MultipartUploadBinder.java
+++
b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/binders/MultipartUploadBinder.java
@@ -57,6 +57,7 @@ public final class MultipartUploadBinder implements MapBinder
{
Part jsonPart = Part.create("Metadata", jsonPayload, new
Part.PartOptions().contentType(APPLICATION_JSON));
Part mediaPart = Part.create(template.name(), payload, new
Part.PartOptions().contentType(contentType));
+ request.resetPayload(/*release=*/ false);
request.setPayload(new MultipartForm(BOUNDARY_HEADER, jsonPart,
mediaPart));
// HeaderPart
request.toBuilder().replaceHeader(CONTENT_TYPE, "Multipart/related;
boundary= " + BOUNDARY_HEADER).build();
diff --git
a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GoogleCloudStorageBlobStore.java
b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GoogleCloudStorageBlobStore.java
index 029ca03..8777643 100644
---
a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GoogleCloudStorageBlobStore.java
+++
b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GoogleCloudStorageBlobStore.java
@@ -211,7 +211,7 @@ public final class GoogleCloudStorageBlobStore extends
BaseBlobStore {
public String putBlob(String container, Blob blob, PutOptions options) {
long length =
checkNotNull(blob.getPayload().getContentMetadata().getContentLength());
- if (length != 0 && (options.isMultipart() ||
!blob.getPayload().isRepeatable())) {
+ if (length != 0 && options.isMultipart()) {
// JCLOUDS-912 prevents using single-part uploads with InputStream
payloads.
// Work around this with multi-part upload which buffers parts
in-memory.
return putMultipartBlob(container, blob, options);