From 0647ba8c5506a506dde9cadb2db3cb7013afb1be Mon Sep 17 00:00:00 2001 From: Andrew Gaul Date: Mon, 6 Apr 2015 17:51:17 -0700 Subject: [PATCH] JCLOUDS-651: portable copy object content metadata --- .../blobstore/config/LocalBlobStore.java | 31 ++++++++++++++++--- .../blobstore/options/CopyOptions.java | 16 ++++++++++ .../internal/BaseBlobIntegrationTest.java | 22 +++++++++---- 3 files changed, 58 insertions(+), 11 deletions(-) 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 2e1b63695d..6da6f1fb03 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/config/LocalBlobStore.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/config/LocalBlobStore.java @@ -511,15 +511,36 @@ public final class LocalBlobStore implements BlobStore { is = blob.getPayload().openStream(); ContentMetadata metadata = blob.getMetadata().getContentMetadata(); BlobBuilder.PayloadBlobBuilder builder = blobBuilder(toName) - .payload(is) - .contentDisposition(metadata.getContentDisposition()) - .contentEncoding(metadata.getContentEncoding()) - .contentLanguage(metadata.getContentLanguage()) - .contentType(metadata.getContentType()); + .payload(is); Long contentLength = metadata.getContentLength(); if (contentLength != null) { builder.contentLength(contentLength); } + + if (options.getContentMetadata().isPresent()) { + ContentMetadata contentMetadata = options.getContentMetadata().get(); + String contentDisposition = contentMetadata.getContentDisposition(); + if (contentDisposition != null) { + builder.contentDisposition(contentDisposition); + } + String contentEncoding = contentMetadata.getContentEncoding(); + if (contentEncoding != null) { + builder.contentEncoding(contentEncoding); + } + String contentLanguage = contentMetadata.getContentLanguage(); + if (contentLanguage != null) { + builder.contentLanguage(contentLanguage); + } + String contentType = contentMetadata.getContentType(); + if (contentType != null) { + builder.contentType(contentType); + } + } else { + builder.contentDisposition(metadata.getContentDisposition()) + .contentEncoding(metadata.getContentEncoding()) + .contentLanguage(metadata.getContentLanguage()) + .contentType(metadata.getContentType()); + } Optional> userMetadata = options.getUserMetadata(); if (userMetadata.isPresent()) { builder.userMetadata(userMetadata.get()); diff --git a/blobstore/src/main/java/org/jclouds/blobstore/options/CopyOptions.java b/blobstore/src/main/java/org/jclouds/blobstore/options/CopyOptions.java index 8886da77d3..4084cf9963 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/options/CopyOptions.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/options/CopyOptions.java @@ -17,8 +17,12 @@ package org.jclouds.blobstore.options; +import static com.google.common.base.Preconditions.checkNotNull; + import java.util.Map; +import org.jclouds.io.ContentMetadata; + import com.google.common.annotations.Beta; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; @@ -27,12 +31,18 @@ import com.google.common.collect.ImmutableMap; public final class CopyOptions { public static final CopyOptions NONE = builder().build(); + private final Optional contentMetadata; private final Optional> userMetadata; private CopyOptions(Builder builder) { + this.contentMetadata = Optional.fromNullable(builder.contentMetadata); this.userMetadata = Optional.fromNullable(builder.userMetadata); } + public Optional getContentMetadata() { + return contentMetadata; + } + public Optional> getUserMetadata() { return userMetadata; } @@ -42,11 +52,17 @@ public final class CopyOptions { } public static class Builder { + ContentMetadata contentMetadata; Map userMetadata; Builder() { } + public Builder contentMetadata(ContentMetadata contentMetadata) { + this.contentMetadata = checkNotNull(contentMetadata, "contentMetadata"); + return this; + } + public Builder userMetadata(Map userMetadata) { this.userMetadata = ImmutableMap.copyOf(userMetadata); return this; 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 12e83c3db9..23de2468e9 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 @@ -62,6 +62,7 @@ import org.jclouds.blobstore.options.PutOptions; import org.jclouds.crypto.Crypto; import org.jclouds.encryption.internal.JCECrypto; import org.jclouds.http.HttpResponseException; +import org.jclouds.io.ContentMetadataBuilder; import org.jclouds.io.Payload; import org.jclouds.io.Payloads; import org.jclouds.io.payloads.ByteSourcePayload; @@ -777,7 +778,11 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { .blobBuilder(fromName) .userMetadata(ImmutableMap.of("key1", "value1", "key2", "value2")) .payload(payload) - .contentLength(payload.size()); + .contentLength(payload.size()) + .contentDisposition("attachment; filename=original.jpg") + .contentEncoding("compress") + .contentLanguage("fr") + .contentType("audio/ogg"); addContentMetadata(blobBuilder); Blob blob = blobBuilder.build(); @@ -786,8 +791,15 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { try { blobStore.putBlob(fromContainer, blob); Map userMetadata = ImmutableMap.of("key3", "value3", "key4", "value4"); - blobStore.copyBlob(fromContainer, fromName, toContainer, toName, - CopyOptions.builder().userMetadata(userMetadata).build()); + blobStore.copyBlob(fromContainer, fromName, toContainer, toName, CopyOptions.builder() + .contentMetadata(ContentMetadataBuilder.create() + .contentType("text/csv") + .contentDisposition("attachment; filename=photo.jpg") + .contentEncoding("gzip") + .contentLanguage("en") + .build()) + .userMetadata(userMetadata) + .build()); Blob toBlob = blobStore.getBlob(toContainer, toName); InputStream is = null; try { @@ -796,9 +808,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { } finally { Closeables2.closeQuietly(is); } - // TODO: S3 overrideMetadataWith also overrides system metadata - // TODO: Swift does not preserve system metadata - //checkContentMetadata(toBlob); + checkContentMetadata(toBlob); checkUserMetadata(toBlob.getMetadata().getUserMetadata(), userMetadata); } finally { returnContainer(toContainer);