From 87eda150853c30d996bb9574af7123717f5b6782 Mon Sep 17 00:00:00 2001 From: Andrew Gaul Date: Wed, 8 Mar 2017 14:43:58 -0800 Subject: [PATCH] Return more metadata from listMultipartUpload Include Content-Length and Last-Modified. --- .../v1/blobstore/RegionScopedSwiftBlobStore.java | 6 ++++-- .../org/jclouds/s3/blobstore/S3BlobStore.java | 15 +++++++++------ .../jclouds/blobstore/config/LocalBlobStore.java | 4 ++-- .../jclouds/blobstore/domain/MultipartPart.java | 10 +++++++++- .../internal/BaseBlobIntegrationTest.java | 15 +++++++++++++-- .../azureblob/blobstore/AzureBlobStore.java | 9 +++++---- 6 files changed, 42 insertions(+), 17 deletions(-) diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/blobstore/RegionScopedSwiftBlobStore.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/blobstore/RegionScopedSwiftBlobStore.java index 91d70c3459..c8b52ab37a 100644 --- a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/blobstore/RegionScopedSwiftBlobStore.java +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/blobstore/RegionScopedSwiftBlobStore.java @@ -35,6 +35,7 @@ import java.lang.reflect.Method; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; @@ -528,7 +529,8 @@ public class RegionScopedSwiftBlobStore implements BlobStore { String partName = getMPUPartName(mpu, partNumber); String eTag = api.getObjectApi(regionId, mpu.containerName()).put(partName, payload); long partSize = payload.getContentMetadata().getContentLength(); - return MultipartPart.create(partNumber, partSize, eTag); + Date lastModified = null; // Swift does not return Last-Modified + return MultipartPart.create(partNumber, partSize, eTag, lastModified); } @Override @@ -540,7 +542,7 @@ public class RegionScopedSwiftBlobStore implements BlobStore { for (StorageMetadata sm : pageSet) { int lastSlash = sm.getName().lastIndexOf('/'); int partNumber = Integer.parseInt(sm.getName().substring(lastSlash + 1)); - parts.add(MultipartPart.create(partNumber, sm.getSize(), sm.getETag())); + parts.add(MultipartPart.create(partNumber, sm.getSize(), sm.getETag(), sm.getLastModified())); } return parts.build(); } diff --git a/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStore.java b/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStore.java index 4895791f52..195b637202 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStore.java +++ b/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStore.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static org.jclouds.util.Predicates2.retry; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; @@ -64,6 +65,7 @@ import org.jclouds.s3.domain.AccessControlList.GroupGranteeURI; import org.jclouds.s3.domain.AccessControlList.Permission; import org.jclouds.s3.domain.BucketMetadata; import org.jclouds.s3.domain.CannedAccessPolicy; +import org.jclouds.s3.domain.ListMultipartUploadResponse; import org.jclouds.s3.domain.ListMultipartUploadsResponse; import org.jclouds.s3.options.CopyObjectOptions; import org.jclouds.s3.options.ListBucketOptions; @@ -385,18 +387,19 @@ public class S3BlobStore extends BaseBlobStore { @Override public MultipartPart uploadMultipartPart(MultipartUpload mpu, int partNumber, Payload payload) { - long partSize = -1; // TODO: how to get this from payload? + long partSize = payload.getContentMetadata().getContentLength(); String eTag = sync.uploadPart(mpu.containerName(), mpu.blobName(), partNumber, mpu.id(), payload); - return MultipartPart.create(partNumber, partSize, eTag); + Date lastModified = null; // S3 does not return Last-Modified + return MultipartPart.create(partNumber, partSize, eTag, lastModified); } @Override public List listMultipartUpload(MultipartUpload mpu) { ImmutableList.Builder parts = ImmutableList.builder(); - Map s3Parts = sync.listMultipartParts(mpu.containerName(), mpu.blobName(), mpu.id()); - for (Map.Entry entry : s3Parts.entrySet()) { - long partSize = -1; // TODO: could call getContentLength but did not above - parts.add(MultipartPart.create(entry.getKey(), partSize, entry.getValue())); + Map s3Parts = sync.listMultipartPartsFull(mpu.containerName(), mpu.blobName(), mpu.id()); + for (Map.Entry entry : s3Parts.entrySet()) { + ListMultipartUploadResponse response = entry.getValue(); + parts.add(MultipartPart.create(entry.getKey(), response.size(), response.eTag(), response.lastModified())); } return parts.build(); } diff --git a/blobstore/src/main/java/org/jclouds/blobstore/config/LocalBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/config/LocalBlobStore.java index b20f40e2fb..f45e27aca5 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/config/LocalBlobStore.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/config/LocalBlobStore.java @@ -866,7 +866,7 @@ public final class LocalBlobStore implements BlobStore { String partETag = putBlob(mpu.containerName(), blob); BlobMetadata metadata = blobMetadata(mpu.containerName(), partName); // TODO: racy, how to get this from payload? long partSize = metadata.getContentMetadata().getContentLength(); - return MultipartPart.create(partNumber, partSize, partETag); + return MultipartPart.create(partNumber, partSize, partETag, metadata.getLastModified()); } @Override @@ -882,7 +882,7 @@ public final class LocalBlobStore implements BlobStore { } int partNumber = Integer.parseInt(sm.getName().substring((MULTIPART_PREFIX + mpu.id() + "-" + mpu.blobName() + "-").length())); long partSize = sm.getSize(); - parts.add(MultipartPart.create(partNumber, partSize, sm.getETag())); + parts.add(MultipartPart.create(partNumber, partSize, sm.getETag(), sm.getLastModified())); } if (pageSet.isEmpty() || pageSet.getNextMarker() == null) { break; diff --git a/blobstore/src/main/java/org/jclouds/blobstore/domain/MultipartPart.java b/blobstore/src/main/java/org/jclouds/blobstore/domain/MultipartPart.java index d394308ce7..279e0a230f 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/domain/MultipartPart.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/domain/MultipartPart.java @@ -17,6 +17,8 @@ package org.jclouds.blobstore.domain; +import java.util.Date; + import org.jclouds.javax.annotation.Nullable; import com.google.auto.value.AutoValue; @@ -26,8 +28,14 @@ public abstract class MultipartPart { public abstract int partNumber(); public abstract long partSize(); @Nullable public abstract String partETag(); + @Nullable public abstract Date lastModified(); + @Deprecated public static MultipartPart create(int partNumber, long partSize, @Nullable String partETag) { - return new AutoValue_MultipartPart(partNumber, partSize, partETag); + return MultipartPart.create(partNumber, partSize, partETag, null); + } + + public static MultipartPart create(int partNumber, long partSize, @Nullable String partETag, @Nullable Date lastModified) { + return new AutoValue_MultipartPart(partNumber, partSize, partETag, lastModified); } } 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 9f294e3609..2e13783a12 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 @@ -1215,7 +1215,11 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { MultipartPart part = blobStore.uploadMultipartPart(mpu, 1, payload); List parts = blobStore.listMultipartUpload(mpu); - assertThat(parts).isEqualTo(ImmutableList.of(part)); + assertThat(parts).hasSize(1); + assertThat(parts.get(0).partNumber()).isEqualTo(part.partNumber()); + assertThat(parts.get(0).partSize()).isEqualTo(part.partSize()); + assertThat(parts.get(0).partETag()).isEqualTo(part.partETag()); + // not checking lastModified since B2, S3, and Swift do not return it from uploadMultipartPart blobStore.completeMultipartUpload(mpu, ImmutableList.of(part)); @@ -1254,7 +1258,14 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { MultipartPart part2 = blobStore.uploadMultipartPart(mpu, 2, payload2); List parts = blobStore.listMultipartUpload(mpu); - assertThat(parts).isEqualTo(ImmutableList.of(part1, part2)); + assertThat(parts).hasSize(2); + assertThat(parts.get(0).partNumber()).isEqualTo(part1.partNumber()); + assertThat(parts.get(0).partSize()).isEqualTo(part1.partSize()); + assertThat(parts.get(0).partETag()).isEqualTo(part1.partETag()); + assertThat(parts.get(1).partNumber()).isEqualTo(part2.partNumber()); + assertThat(parts.get(1).partSize()).isEqualTo(part2.partSize()); + assertThat(parts.get(1).partETag()).isEqualTo(part2.partETag()); + // not checking lastModified since B2, S3, and Swift do not return it from uploadMultipartPart blobStore.completeMultipartUpload(mpu, ImmutableList.of(part1, part2)); diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureBlobStore.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureBlobStore.java index a0ea4112ec..a64db15d0d 100644 --- a/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureBlobStore.java +++ b/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureBlobStore.java @@ -21,6 +21,7 @@ import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetad import java.io.InputStream; import java.net.URI; +import java.util.Date; import java.util.EnumSet; import java.util.List; import java.util.Map; @@ -435,8 +436,8 @@ public class AzureBlobStore extends BaseBlobStore { String blockId = BaseEncoding.base64().encode(Ints.toByteArray(partNumber)); sync.putBlock(mpu.containerName(), mpu.blobName(), blockId, payload); String eTag = ""; // putBlock does not return ETag - long partSize = -1; // TODO: how to get this from payload? - return MultipartPart.create(partNumber, partSize, eTag); + Date lastModified = null; // putBlob does not return Last-Modified + return MultipartPart.create(partNumber, payload.getContentMetadata().getContentLength(), eTag); } @Override @@ -452,8 +453,8 @@ public class AzureBlobStore extends BaseBlobStore { for (BlobBlockProperties properties : response.getBlocks()) { int partNumber = Ints.fromByteArray(BaseEncoding.base64().decode(properties.getBlockName())); String eTag = ""; // getBlockList does not return ETag - long partSize = -1; // TODO: could call getContentLength but did not above - parts.add(MultipartPart.create(partNumber, partSize, eTag)); + Date lastModified = null; // getBlockList does not return LastModified + parts.add(MultipartPart.create(partNumber, properties.getContentLength(), eTag, lastModified)); } return parts.build(); }