You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ga...@apache.org on 2015/04/09 07:59:44 UTC

[1/4] jclouds git commit: JCLOUDS-651: portable copy object content metadata

Repository: jclouds
Updated Branches:
  refs/heads/master b35295c23 -> 0c6052f80


JCLOUDS-651: portable copy object content metadata


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/40ba1569
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/40ba1569
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/40ba1569

Branch: refs/heads/master
Commit: 40ba1569370be07dd28e64a7b98240980e1e3860
Parents: b35295c
Author: Andrew Gaul <ga...@apache.org>
Authored: Mon Apr 6 17:51:17 2015 -0700
Committer: Andrew Gaul <ga...@apache.org>
Committed: Wed Apr 8 17:58:41 2015 -0700

----------------------------------------------------------------------
 .../blobstore/config/LocalBlobStore.java        | 31 ++++++++++++++++----
 .../jclouds/blobstore/options/CopyOptions.java  | 16 ++++++++++
 .../internal/BaseBlobIntegrationTest.java       | 22 ++++++++++----
 3 files changed, 58 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/40ba1569/blobstore/src/main/java/org/jclouds/blobstore/config/LocalBlobStore.java
----------------------------------------------------------------------
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 2e1b636..6da6f1f 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<Map<String, String>> userMetadata = options.getUserMetadata();
          if (userMetadata.isPresent()) {
             builder.userMetadata(userMetadata.get());

http://git-wip-us.apache.org/repos/asf/jclouds/blob/40ba1569/blobstore/src/main/java/org/jclouds/blobstore/options/CopyOptions.java
----------------------------------------------------------------------
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 8886da7..4084cf9 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> contentMetadata;
    private final Optional<Map<String, String>> userMetadata;
 
    private CopyOptions(Builder builder) {
+      this.contentMetadata = Optional.fromNullable(builder.contentMetadata);
       this.userMetadata = Optional.fromNullable(builder.userMetadata);
    }
 
+   public Optional<ContentMetadata> getContentMetadata() {
+      return contentMetadata;
+   }
+
    public Optional<Map<String, String>> getUserMetadata() {
       return userMetadata;
    }
@@ -42,11 +52,17 @@ public final class CopyOptions {
    }
 
    public static class Builder {
+      ContentMetadata contentMetadata;
       Map<String, String> userMetadata;
 
       Builder() {
       }
 
+      public Builder contentMetadata(ContentMetadata contentMetadata) {
+         this.contentMetadata = checkNotNull(contentMetadata, "contentMetadata");
+         return this;
+      }
+
       public Builder userMetadata(Map<String, String> userMetadata) {
          this.userMetadata = ImmutableMap.copyOf(userMetadata);
          return this;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/40ba1569/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java
----------------------------------------------------------------------
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 12e83c3..23de246 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<String, String> 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);


[4/4] jclouds git commit: JCLOUDS-651: Swift copy object content metadata

Posted by ga...@apache.org.
JCLOUDS-651: Swift copy object content metadata


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/0c6052f8
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/0c6052f8
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/0c6052f8

Branch: refs/heads/master
Commit: 0c6052f8030bd17b56747e2e33abdb7c6b70368a
Parents: a43dcec
Author: Andrew Gaul <ga...@apache.org>
Authored: Mon Apr 6 17:51:58 2015 -0700
Committer: Andrew Gaul <ga...@apache.org>
Committed: Wed Apr 8 22:51:49 2015 -0700

----------------------------------------------------------------------
 .../blobstore/RegionScopedSwiftBlobStore.java   | 78 +++++++++++++-------
 .../SwiftBlobIntegrationLiveTest.java           |  5 ++
 2 files changed, 55 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/0c6052f8/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/blobstore/RegionScopedSwiftBlobStore.java
----------------------------------------------------------------------
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 4192a96..7962bbd 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
@@ -237,45 +237,67 @@ public class RegionScopedSwiftBlobStore implements BlobStore {
    public String copyBlob(String fromContainer, String fromName, String toContainer, String toName,
          CopyOptions options) {
       ObjectApi objectApi = api.getObjectApi(regionId, toContainer);
-      SwiftObject metadata = api.getObjectApi(regionId, fromContainer).getWithoutBody(fromName);
 
       Map<String, String> userMetadata;
-      if (options.getUserMetadata().isPresent()) {
-         userMetadata = options.getUserMetadata().get();
+      Map<String, String> systemMetadata = Maps.newHashMap();
+      ContentMetadata contentMetadata = options.getContentMetadata().orNull();
+
+      if (contentMetadata != null ||
+            options.getUserMetadata().isPresent()) {
+         if (contentMetadata != null) {
+            String contentDisposition = contentMetadata.getContentDisposition();
+            if (contentDisposition != null) {
+               systemMetadata.put(HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
+            }
+
+            String contentEncoding = contentMetadata.getContentEncoding();
+            if (contentEncoding != null) {
+               systemMetadata.put(HttpHeaders.CONTENT_ENCODING, contentEncoding);
+            }
+
+            String contentLanguage = contentMetadata.getContentLanguage();
+            if (contentLanguage != null) {
+               systemMetadata.put(HttpHeaders.CONTENT_LANGUAGE, contentLanguage);
+            }
+
+            String contentType = contentMetadata.getContentType();
+            if (contentType != null) {
+               systemMetadata.put(HttpHeaders.CONTENT_TYPE, contentType);
+            }
+         }
+         if (options.getUserMetadata().isPresent()) {
+            userMetadata = options.getUserMetadata().get();
+         } else {
+            userMetadata = Maps.newHashMap();
+         }
       } else {
+         SwiftObject metadata = api.getObjectApi(regionId, fromContainer).getWithoutBody(fromName);
+         contentMetadata = metadata.getPayload().getContentMetadata();
+         String contentDisposition = contentMetadata.getContentDisposition();
+         if (contentDisposition != null) {
+            systemMetadata.put(HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
+         }
+         String contentEncoding = contentMetadata.getContentEncoding();
+         if (contentEncoding != null) {
+            systemMetadata.put(HttpHeaders.CONTENT_ENCODING, contentEncoding);
+         }
+         String contentLanguage = contentMetadata.getContentLanguage();
+         if (contentLanguage != null) {
+            systemMetadata.put(HttpHeaders.CONTENT_LANGUAGE, contentLanguage);
+         }
+         String contentType = contentMetadata.getContentType();
+         if (contentType != null) {
+            systemMetadata.put(HttpHeaders.CONTENT_TYPE, contentType);
+         }
          userMetadata = metadata.getMetadata();
       }
 
-      // copy existing system metadata
-      Map<String, String> systemMetadata = Maps.newHashMap();
-      ContentMetadata contentMetadata = metadata.getPayload().getContentMetadata();
-      String contentDisposition = contentMetadata.getContentDisposition();
-      if (contentDisposition != null) {
-         systemMetadata.put(HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
-      }
-      String contentEncoding = contentMetadata.getContentEncoding();
-      if (contentEncoding != null) {
-         systemMetadata.put(HttpHeaders.CONTENT_ENCODING, contentEncoding);
-      }
-      String contentLanguage = contentMetadata.getContentLanguage();
-      if (contentLanguage != null) {
-         systemMetadata.put(HttpHeaders.CONTENT_LANGUAGE, contentLanguage);
-      }
-      String contentType = contentMetadata.getContentType();
-      if (contentType != null) {
-         systemMetadata.put(HttpHeaders.CONTENT_TYPE, contentType);
-      }
-
       boolean copied = objectApi.copy(toName, fromContainer, fromName, userMetadata, systemMetadata);
       if (!copied) {
          throw new RuntimeException("could not copy blob");
       }
 
-      // TODO: override content disposition
-      // TODO: override content encoding
-      // TODO: override content language
-      // TODO: override content type
-
+      // TODO: Swift copy object *appends* user metadata, does not overwrite
       return objectApi.getWithoutBody(toName).getETag();
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/0c6052f8/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/blobstore/integration/SwiftBlobIntegrationLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/blobstore/integration/SwiftBlobIntegrationLiveTest.java b/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/blobstore/integration/SwiftBlobIntegrationLiveTest.java
index f05b185..c3eb7de 100644
--- a/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/blobstore/integration/SwiftBlobIntegrationLiveTest.java
+++ b/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/blobstore/integration/SwiftBlobIntegrationLiveTest.java
@@ -78,4 +78,9 @@ public class SwiftBlobIntegrationLiveTest extends BaseBlobIntegrationTest {
    public void testSetBlobAccess() throws Exception {
       throw new SkipException("unsupported in swift");
    }
+
+   @Override
+   public void testCopyBlobReplaceMetadata() throws Exception {
+      throw new SkipException("Swift only supports appending to user metadata, not replacing it");
+   }
 }


[2/4] jclouds git commit: JCLOUDS-651: Azure copy object content metadata

Posted by ga...@apache.org.
JCLOUDS-651: Azure copy object content metadata


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/a761f4cf
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/a761f4cf
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/a761f4cf

Branch: refs/heads/master
Commit: a761f4cfa199fee39ee74829cdbbbfebf56c0c37
Parents: 40ba156
Author: Andrew Gaul <ga...@apache.org>
Authored: Mon Apr 6 22:06:14 2015 -0700
Committer: Andrew Gaul <ga...@apache.org>
Committed: Wed Apr 8 17:58:46 2015 -0700

----------------------------------------------------------------------
 .../org/jclouds/azureblob/AzureBlobClient.java  | 11 ++++
 .../BindAzureContentMetadataToRequest.java      | 59 ++++++++++++++++++++
 .../azureblob/blobstore/AzureBlobStore.java     | 33 +++++++++--
 3 files changed, 97 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/a761f4cf/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobClient.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobClient.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobClient.java
index 967681f..d34ae26 100644
--- a/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobClient.java
+++ b/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobClient.java
@@ -46,6 +46,7 @@ import org.jclouds.azure.storage.reference.AzureStorageHeaders;
 import org.jclouds.azureblob.binders.BindAzureBlobMetadataToRequest;
 import org.jclouds.azureblob.binders.BindAzureBlobMetadataToMultipartRequest;
 import org.jclouds.azureblob.binders.BindAzureBlocksToRequest;
+import org.jclouds.azureblob.binders.BindAzureContentMetadataToRequest;
 import org.jclouds.azureblob.binders.BindAzureCopyOptionsToRequest;
 import org.jclouds.azureblob.binders.BindPublicAccessToRequest;
 import org.jclouds.azureblob.domain.AzureBlob;
@@ -70,6 +71,7 @@ import org.jclouds.azureblob.xml.ContainerNameEnumerationResultsHandler;
 import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
 import org.jclouds.http.functions.ParseETagHeader;
 import org.jclouds.http.options.GetOptions;
+import org.jclouds.io.ContentMetadata;
 import org.jclouds.io.Payload;
 import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.Fallback;
@@ -413,6 +415,15 @@ public interface AzureBlobClient extends Closeable {
          @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
          @PathParam("name") String name);
 
+   @Named("SetBlobProperties")
+   @PUT
+   @Path("{container}/{name}")
+   @QueryParams(keys = { "comp" }, values = { "metadata" })
+   @ResponseParser(ParseETagHeader.class)
+   String setBlobProperties(
+         @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         @PathParam("name") String name,
+         @BinderParam(BindAzureContentMetadataToRequest.class) ContentMetadata contentMetadata);
 
    @Named("SetBlobMetadata")
    @PUT

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a761f4cf/providers/azureblob/src/main/java/org/jclouds/azureblob/binders/BindAzureContentMetadataToRequest.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/binders/BindAzureContentMetadataToRequest.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/binders/BindAzureContentMetadataToRequest.java
new file mode 100644
index 0000000..2bf496d
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azureblob/binders/BindAzureContentMetadataToRequest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azureblob.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.io.ContentMetadata;
+import org.jclouds.rest.Binder;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Multimaps;
+
+@Singleton
+public class BindAzureContentMetadataToRequest implements Binder {
+
+   public BindAzureContentMetadataToRequest() {
+   }
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      checkArgument(checkNotNull(input, "input") instanceof ContentMetadata,
+         "this binder is only valid for ContentMetadata");
+      checkNotNull(request, "request");
+      ContentMetadata contentMetadata = (ContentMetadata) input;
+
+      ImmutableMap.Builder<String, String> headers = ImmutableMap.builder();
+
+      String contentType = contentMetadata.getContentType();
+      if (contentType != null) {
+         headers.put("x-ms-blob-type", contentType);
+      }
+
+      String contentDisposition = contentMetadata.getContentDisposition();
+      if (contentDisposition != null) {
+         headers.put("x-ms-blob-content-disposition", contentDisposition);
+      }
+
+      return (R) request.toBuilder().replaceHeaders(Multimaps.forMap(headers.build())).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a761f4cf/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureBlobStore.java
----------------------------------------------------------------------
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 ccd31b5..7e8b0e9 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
@@ -60,11 +60,13 @@ import org.jclouds.blobstore.util.BlobUtils;
 import org.jclouds.collect.Memoized;
 import org.jclouds.domain.Location;
 import org.jclouds.http.options.GetOptions;
+import org.jclouds.io.ContentMetadata;
 
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Supplier;
 import com.google.common.collect.Iterables;
+import org.jclouds.io.ContentMetadataBuilder;
 import org.jclouds.io.Payload;
 
 @Singleton
@@ -233,13 +235,32 @@ public class AzureBlobStore extends BaseBlobStore {
       URI source = context.getSigner().signGetBlob(fromContainer, fromName).getEndpoint();
       sync.copyBlob(source, toContainer, toName, azureOptions.build());
 
-      String eTag = sync.getBlobProperties(toContainer, toName).getETag();
+      ContentMetadataBuilder builder = ContentMetadataBuilder.create();
 
-      // TODO: Azure does not allow updating system metadata during copy - call SetBlobProperties (not yet implemented)
-      // TODO: content disposition
-      // TODO: content encoding
-      // TODO: content language
-      // TODO: content type
+      String eTag = null;
+
+      Optional<ContentMetadata> contentMetadata = options.getContentMetadata();
+      if (contentMetadata.isPresent()) {
+         String contentDisposition = contentMetadata.get().getContentDisposition();
+         if (contentDisposition != null) {
+            builder.contentDisposition(contentDisposition);
+         }
+
+         String contentType = contentMetadata.get().getContentType();
+         if (contentType != null) {
+            builder.contentType(contentType);
+         }
+
+         eTag = sync.setBlobProperties(toContainer, toName, builder.build());
+      }
+
+      if (userMetadata.isPresent()) {
+         eTag = sync.setBlobMetadata(toContainer, toName, userMetadata.get());
+      }
+
+      if (eTag == null) {
+         eTag = sync.getBlobProperties(toContainer, toName).getETag();
+      }
 
       return eTag;
    }


[3/4] jclouds git commit: JCLOUDS-651: S3 copy object content metadata

Posted by ga...@apache.org.
JCLOUDS-651: S3 copy object content metadata


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/a43dcece
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/a43dcece
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/a43dcece

Branch: refs/heads/master
Commit: a43dcece16b7eb0569cfe2d96c76221c40356c27
Parents: a761f4c
Author: Andrew Gaul <ga...@apache.org>
Authored: Mon Apr 6 17:51:51 2015 -0700
Committer: Andrew Gaul <ga...@apache.org>
Committed: Wed Apr 8 18:07:28 2015 -0700

----------------------------------------------------------------------
 .../org/jclouds/s3/blobstore/S3BlobStore.java   | 27 ++++++--
 .../jclouds/s3/options/CopyObjectOptions.java   | 67 +++++++++++++++++++-
 2 files changed, 89 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/a43dcece/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStore.java
----------------------------------------------------------------------
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 cd38e52..c93f7e2 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
@@ -47,6 +47,7 @@ import org.jclouds.blobstore.util.BlobUtils;
 import org.jclouds.collect.Memoized;
 import org.jclouds.domain.Location;
 import org.jclouds.http.options.GetOptions;
+import org.jclouds.io.ContentMetadata;
 import org.jclouds.s3.S3Client;
 import org.jclouds.s3.blobstore.functions.BlobToObject;
 import org.jclouds.s3.blobstore.functions.BucketToResourceList;
@@ -282,10 +283,28 @@ public class S3BlobStore extends BaseBlobStore {
          CopyOptions options) {
       CopyObjectOptions s3Options = new CopyObjectOptions();
 
-      // TODO: content disposition
-      // TODO: content encoding
-      // TODO: content language
-      // TODO: content type
+      Optional<ContentMetadata> contentMetadata = options.getContentMetadata();
+      if (contentMetadata.isPresent()) {
+         String contentDisposition = contentMetadata.get().getContentDisposition();
+         if (contentDisposition != null) {
+            s3Options.contentDisposition(contentDisposition);
+         }
+
+         String contentEncoding = contentMetadata.get().getContentEncoding();
+         if (contentEncoding != null) {
+            s3Options.contentEncoding(contentEncoding);
+         }
+
+         String contentLanguage = contentMetadata.get().getContentLanguage();
+         if (contentLanguage != null) {
+            s3Options.contentLanguage(contentLanguage);
+         }
+
+         String contentType = contentMetadata.get().getContentType();
+         if (contentType != null) {
+            s3Options.contentType(contentType);
+         }
+      }
 
       Optional<Map<String, String>> userMetadata = options.getUserMetadata();
       if (userMetadata.isPresent()) {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a43dcece/apis/s3/src/main/java/org/jclouds/s3/options/CopyObjectOptions.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/options/CopyObjectOptions.java b/apis/s3/src/main/java/org/jclouds/s3/options/CopyObjectOptions.java
index 25f833c..2370bf5 100644
--- a/apis/s3/src/main/java/org/jclouds/s3/options/CopyObjectOptions.java
+++ b/apis/s3/src/main/java/org/jclouds/s3/options/CopyObjectOptions.java
@@ -43,6 +43,7 @@ import org.jclouds.s3.domain.CannedAccessPolicy;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Multimap;
+import com.google.common.net.HttpHeaders;
 
 /**
  * Contains options supported in the REST API for the COPY object operation.
@@ -71,6 +72,10 @@ import com.google.common.collect.Multimap;
 public class CopyObjectOptions extends BaseHttpRequestOptions {
    private static final DateService dateService = new SimpleDateFormatDateService();
    public static final CopyObjectOptions NONE = new CopyObjectOptions();
+   private String contentDisposition;
+   private String contentEncoding;
+   private String contentLanguage;
+   private String contentType;
    private Map<String, String> metadata;
    private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE;
 
@@ -249,16 +254,56 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
       for (Entry<String, String> entry : headers.entries()) {
          returnVal.put(entry.getKey().replace(DEFAULT_AMAZON_HEADERTAG, headerTag), entry.getValue());
       }
+      boolean replace = false;
+      if (contentDisposition != null) {
+         returnVal.put(HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
+         replace = true;
+      }
+      if (contentEncoding != null) {
+         returnVal.put(HttpHeaders.CONTENT_ENCODING, contentEncoding);
+         replace = true;
+      }
+      if (contentLanguage != null) {
+         returnVal.put(HttpHeaders.CONTENT_LANGUAGE, contentLanguage);
+         replace = true;
+      }
+      if (contentType != null) {
+         returnVal.put(HttpHeaders.CONTENT_TYPE, contentType);
+         replace = true;
+      }
       if (metadata != null) {
-         returnVal.put(METADATA_DIRECTIVE.replace(DEFAULT_AMAZON_HEADERTAG, headerTag), "REPLACE");
          for (Map.Entry<String, String> entry : metadata.entrySet()) {
             String key = entry.getKey();
             returnVal.put(key.startsWith(metadataPrefix) ? key : metadataPrefix + key, entry.getValue());
          }
+         replace = true;
+      }
+      if (replace) {
+         returnVal.put(METADATA_DIRECTIVE.replace(DEFAULT_AMAZON_HEADERTAG, headerTag), "REPLACE");
       }
       return returnVal.build();
    }
 
+   public CopyObjectOptions contentDisposition(String contentDisposition) {
+      this.contentDisposition = checkNotNull(contentDisposition, "contentDisposition");
+      return this;
+   }
+
+   public CopyObjectOptions contentEncoding(String contentEncoding) {
+      this.contentEncoding = checkNotNull(contentEncoding, "contentEncoding");
+      return this;
+   }
+
+   public CopyObjectOptions contentLanguage(String contentLanguage) {
+      this.contentLanguage = checkNotNull(contentLanguage, "contentLanguage");
+      return this;
+   }
+
+   public CopyObjectOptions contentType(String contentType) {
+      this.contentType = checkNotNull(contentType, "contentType");
+      return this;
+   }
+
    /**
     * Use the provided metadata instead of what is on the source object.
     */
@@ -309,6 +354,26 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
          return options.ifSourceETagDoesntMatch(eTag);
       }
 
+      public static CopyObjectOptions contentDisposition(String contentDisposition) {
+         CopyObjectOptions options = new CopyObjectOptions();
+         return options.contentDisposition(contentDisposition);
+      }
+
+      public static CopyObjectOptions contentEncoding(String contentEncoding) {
+         CopyObjectOptions options = new CopyObjectOptions();
+         return options.contentEncoding(contentEncoding);
+      }
+
+      public static CopyObjectOptions contentLanguage(String contentLanguage) {
+         CopyObjectOptions options = new CopyObjectOptions();
+         return options.contentLanguage(contentLanguage);
+      }
+
+      public static CopyObjectOptions contentType(String contentType) {
+         CopyObjectOptions options = new CopyObjectOptions();
+         return options.contentType(contentType);
+      }
+
       /**
        * @see #overrideMetadataWith(Multimap)
        */