From d51bc04e744887262911281cca00d084c6e170e2 Mon Sep 17 00:00:00 2001 From: hsbhathiya Date: Sat, 4 Apr 2015 02:50:56 +0530 Subject: [PATCH] JCLOUD-875: GCS Copy Object with Updated Metadata --- .../GoogleCloudStorageBlobStore.java | 15 +++++++++++ .../features/ObjectApi.java | 26 ++++++++++++++++++- .../features/ObjectApiLiveTest.java | 26 +++++++++++++++++++ .../features/ObjectApiMockTest.java | 15 +++++++++++ 4 files changed, 81 insertions(+), 1 deletion(-) 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 cab0646113..7ef2dafd45 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 @@ -23,6 +23,7 @@ import static org.jclouds.googlecloudstorage.domain.DomainResourceReferences.Obj import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Set; +import java.util.Map; import javax.inject.Inject; @@ -41,6 +42,7 @@ import org.jclouds.blobstore.options.CreateContainerOptions; import org.jclouds.blobstore.options.GetOptions; import org.jclouds.blobstore.options.ListContainerOptions; import org.jclouds.blobstore.options.PutOptions; +import org.jclouds.blobstore.options.CopyOptions; import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.collect.Memoized; @@ -302,4 +304,17 @@ public final class GoogleCloudStorageBlobStore extends BaseBlobStore { return false; } + + @Override + public String copyBlob(String fromContainer, String fromName, String toContainer, String toName, CopyOptions options) { + + if (options == CopyOptions.NONE) { + return api.getObjectApi().copyObject(toContainer, toName, fromContainer, fromName).etag(); + } else { + Map map = options.getUserMetadata().get(); + String contentType = api.getObjectApi().getObject(fromContainer, fromName).contentType(); + ObjectTemplate template = new ObjectTemplate().customMetadata(map).contentType(contentType); + return api.getObjectApi().copyObject(toContainer, toName, fromContainer, fromName, template).etag(); + } + } } diff --git a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java index 570a0891bd..29bbd57835 100644 --- a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java +++ b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java @@ -380,7 +380,7 @@ public interface ObjectApi { ComposeObjectOptions options); /** - * Copies an object to a specified location. Optionally overrides metadata. + * Copies an object to a specified location. * * @param destinationBucket * Name of the bucket in which to store the new object @@ -401,6 +401,30 @@ public interface ObjectApi { @PathParam("destinationObject") String destinationObject, @PathParam("sourceBucket") String sourceBucket, @PathParam("sourceObject") String sourceObject); + /** + * Copies an object to a specified location with updated metadata. + * + * @param destinationBucket + * Name of the bucket in which to store the new object + * @param destinationObject + * Name of the new object. + * @param sourceBucket + * Name of the bucket in which to find the source object + * @param sourceObject + * Name of the source object + * @param template + * Supply a {@link CopyObjectOptions} + * + * @return a {@link GoogleCloudStorageObject} + */ + @Named("Object:copy") + @POST + @Consumes(APPLICATION_JSON) + @Path("/storage/v1/b/{sourceBucket}/o/{sourceObject}/copyTo/b/{destinationBucket}/o/{destinationObject}") + GoogleCloudStorageObject copyObject(@PathParam("destinationBucket") String destinationBucket, + @PathParam("destinationObject") String destinationObject, @PathParam("sourceBucket") String sourceBucket, + @PathParam("sourceObject") String sourceObject, @BinderParam(BindToJsonPayload.class) ObjectTemplate template); + /** * Copies an object to a specified location. Optionally overrides metadata. * diff --git a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectApiLiveTest.java b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectApiLiveTest.java index ec117188eb..aa35d22d10 100644 --- a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectApiLiveTest.java +++ b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectApiLiveTest.java @@ -73,6 +73,7 @@ public class ObjectApiLiveTest extends BaseGoogleCloudStorageApiLiveTest { private static final String UPLOAD_OBJECT_NAME2 = "jcloudslogo.jpg"; private static final String MULTIPART_UPLOAD_OBJECT = "multipart_related.jpg"; private static final String COPIED_OBJECT_NAME = "copyofObjectOperation.txt"; + private static final String COPIED_OBJECT_NAME2 = "copyObjectWithMeta.txt"; private static final String COMPOSED_OBJECT = "ComposedObject1.txt"; private static final String COMPOSED_OBJECT2 = "ComposedObject2.json"; private static final String NONEXISTENT_OBJECT_NAME = "noSuchObject.txt"; @@ -205,6 +206,31 @@ public class ObjectApiLiveTest extends BaseGoogleCloudStorageApiLiveTest { } + @Test(groups = "live", dependsOnMethods = "testGetObject") + public void testCopyObjectWithUpdatedMetadata() throws IOException { + String METADATA_KEY = "key1"; + String METADATA_VALUE = "value1"; + + ObjectTemplate template = new ObjectTemplate().contentLanguage("fr").contentType("text/plain") + .contentDisposition("attachment").customMetadata(METADATA_KEY, METADATA_VALUE); + + GoogleCloudStorageObject gcsObject = api().copyObject(BUCKET_NAME2, COPIED_OBJECT_NAME2, BUCKET_NAME, UPLOAD_OBJECT_NAME, template); + + assertNotNull(gcsObject); + assertEquals(gcsObject.bucket(), BUCKET_NAME2); + assertEquals(gcsObject.name(), COPIED_OBJECT_NAME2); + assertNotNull(gcsObject.acl()); + assertEquals(gcsObject.contentType(), "text/plain"); + assertEquals(gcsObject.metadata().get(METADATA_KEY), METADATA_VALUE); + assertEquals(gcsObject.contentLanguage(), "fr"); + // Test for data + + PayloadEnclosing impl = api().download(BUCKET_NAME2, COPIED_OBJECT_NAME2); + assertNotNull(impl); + assertEquals(ByteStreams2.toByteArrayAndClose(impl.getPayload().openStream()), + ByteStreams2.toByteArrayAndClose(testPayload.getPayload().openStream())); + } + @Test(groups = "live", dependsOnMethods = "testCopyObject") public void testCopyObjectWithOptions() { CopyObjectOptions options = new CopyObjectOptions().ifSourceGenerationMatch(generation) diff --git a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectApiMockTest.java b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectApiMockTest.java index 1693386962..d95b0783f6 100644 --- a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectApiMockTest.java +++ b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectApiMockTest.java @@ -210,6 +210,21 @@ public class ObjectApiMockTest extends BaseGoogleCloudStorageApiMockTest { "/b/destination_bucket/o/destination_object", APPLICATION_JSON); } + public void copy_update_metadata() throws Exception { + server.enqueue(jsonResponse("/object_get.json")); + + ObjectTemplate template = new ObjectTemplate().name("file_name").size((long) 1000).crc32c("crc32c"); + + assertEquals(objectApi().copyObject("destination_bucket", "destination_object", "source_bucket", "source_object", template), + new ParseGoogleCloudStorageObject().expected()); + assertSent(server, "POST", "/storage/v1/b/source_bucket/o/source_object/copyTo" + + "/b/destination_bucket/o/destination_object", APPLICATION_JSON, "{" + + " \"name\": \"file_name\"," + + " \"size\": 1000," + + " \"crc32c\": \"crc32c\"" + + "}"); + } + public void copy_with_options() throws Exception { server.enqueue(jsonResponse("/object_get.json"));