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/07 00:42:34 UTC
[1/3] jclouds git commit: Allows copying an object and modifying
metadata (user and object)
Repository: jclouds
Updated Branches:
refs/heads/master a6a232a7a -> d8f48c48b
Allows copying an object and modifying metadata (user and object)
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/a1cbec10
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/a1cbec10
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/a1cbec10
Branch: refs/heads/master
Commit: a1cbec10925a05bf0a05c6ddb3f9eb51c7f155ea
Parents: a6a232a
Author: Zack Shoylev <za...@rackspace.com>
Authored: Tue Mar 31 17:30:56 2015 -0500
Committer: Andrew Gaul <ga...@apache.org>
Committed: Mon Apr 6 15:35:58 2015 -0700
----------------------------------------------------------------------
.../swift/v1/binders/BindMetadataToHeaders.java | 6 +++
.../openstack/swift/v1/features/ObjectApi.java | 33 ++++++++++++
.../swift/v1/features/ObjectApiMockTest.java | 56 ++++++++++++++++++--
3 files changed, 91 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/a1cbec10/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java
----------------------------------------------------------------------
diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java
index 9451934..d27e19d 100644
--- a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java
+++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java
@@ -85,6 +85,12 @@ public class BindMetadataToHeaders implements Binder {
}
}
+ public static class BindHeaderMetadataToHeaders extends BindMetadataToHeaders {
+ BindHeaderMetadataToHeaders() {
+ super("");
+ }
+ }
+
public static class BindRemoveObjectMetadataToHeaders extends BindMetadataToHeaders.ForRemoval {
BindRemoveObjectMetadataToHeaders() {
super(OBJECT_METADATA_PREFIX);
http://git-wip-us.apache.org/repos/asf/jclouds/blob/a1cbec10/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java
index 4d4d603..7d89ba3 100644
--- a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java
+++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java
@@ -41,6 +41,7 @@ import org.jclouds.http.options.GetOptions;
import org.jclouds.io.Payload;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindHeaderMetadataToHeaders;
import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindObjectMetadataToHeaders;
import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindRemoveObjectMetadataToHeaders;
import org.jclouds.openstack.swift.v1.binders.SetPayload;
@@ -262,4 +263,36 @@ public interface ObjectApi {
@PathParam("sourceContainer") String sourceContainer,
@PathParam("sourceObject") String sourceObject);
+ /**
+ * Copies an object from one container to another.
+ *
+ * <h3>NOTE</h3>
+ * This is a server side copy.
+ *
+ * @param destinationObject
+ * the destination object name.
+ * @param sourceContainer
+ * the source container name.
+ * @param sourceObject
+ * the source object name.
+ * @param userMetadata
+ * Freeform metadata for the object, automatically prefixed/escaped
+ * @param objectMetadata
+ * Unprefixed/unescaped metadata, such as Content-Disposition
+ *
+ * @return {@code true} if the object was successfully copied, {@code false} if not.
+ *
+ * @throws org.jclouds.openstack.swift.v1.CopyObjectException if the source or destination container do not exist.
+ */
+ @Named("object:copy")
+ @PUT
+ @Path("/{destinationObject}")
+ @Headers(keys = OBJECT_COPY_FROM, values = "/{sourceContainer}/{sourceObject}")
+ @Fallback(FalseOnContainerNotFound.class)
+ boolean copy(@PathParam("destinationObject") String destinationObject,
+ @PathParam("sourceContainer") String sourceContainer,
+ @PathParam("sourceObject") String sourceObject,
+ @BinderParam(BindObjectMetadataToHeaders.class) Map<String, String> userMetadata,
+ @BinderParam(BindHeaderMetadataToHeaders.class) Map<String, String> objectMetadata);
+
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/a1cbec10/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiMockTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiMockTest.java b/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiMockTest.java
index 87166df..81a856e 100644
--- a/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiMockTest.java
+++ b/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiMockTest.java
@@ -39,6 +39,7 @@ import static org.testng.Assert.fail;
import java.io.IOException;
import java.net.URI;
import java.util.Date;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
@@ -193,7 +194,8 @@ public class ObjectApiMockTest extends BaseOpenStackMockTest<SwiftApi> {
public void testCreateWithSpacesAndSpecialCharacters() throws Exception {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
- server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(201).addHeader("ETag", "d9f5eb4bba4e2f2f046e54611bc8196b")));
+ server.enqueue(addCommonHeaders(
+ new MockResponse().setResponseCode(201).addHeader("ETag", "d9f5eb4bba4e2f2f046e54611bc8196b")));
final String containerName = "container # ! special";
final String objectName = "object # ! special";
@@ -279,7 +281,8 @@ public class ObjectApiMockTest extends BaseOpenStackMockTest<SwiftApi> {
assertEquals(server.getRequestCount(), 2);
assertAuthentication(server);
- assertRequest(server.takeRequest(), "HEAD", "/v1/MossoCloudFS_5bcf396e-39dd-45ff-93a1-712b9aba90a9/myContainer/myObject");
+ assertRequest(server.takeRequest(), "HEAD",
+ "/v1/MossoCloudFS_5bcf396e-39dd-45ff-93a1-712b9aba90a9/myContainer/myObject");
} finally {
server.shutdown();
}
@@ -339,7 +342,7 @@ public class ObjectApiMockTest extends BaseOpenStackMockTest<SwiftApi> {
fail("testReplaceTimeout test should have failed with an HttpResponseException.");
} finally {
- try {
+ try {
server.shutdown();
} catch (IOException e) {
// MockWebServer 2.1.0 introduces an active wait for its executor termination.
@@ -469,7 +472,7 @@ public class ObjectApiMockTest extends BaseOpenStackMockTest<SwiftApi> {
try {
SwiftApi api = api(server.getUrl("/").toString(), "openstack-swift");
assertTrue(api.getObjectApi("DFW", "foo")
- .copy("bar.txt", "bar", "foo.txt"));
+ .copy("bar.txt", "bar", "foo.txt"));
assertEquals(server.getRequestCount(), 2);
assertEquals(server.takeRequest().getRequestLine(), "POST /tokens HTTP/1.1");
@@ -498,6 +501,51 @@ public class ObjectApiMockTest extends BaseOpenStackMockTest<SwiftApi> {
}
}
+ public void testCopyObjectWithMetadata() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(201)
+ .addHeader(SwiftHeaders.OBJECT_COPY_FROM, "/bar/foo.txt")));
+
+ try {
+ SwiftApi api = api(server.getUrl("/").toString(), "openstack-swift");
+ assertTrue(api.getObjectApi("DFW", "foo")
+ .copy("bar.txt", "bar", "foo.txt", ImmutableMap.of("someUserHeader", "someUserMetadataValue"),
+ ImmutableMap.of("Content-Disposition", "attachment; filename=\"fname.ext\"")));
+
+ assertEquals(server.getRequestCount(), 2);
+ assertEquals(server.takeRequest().getRequestLine(), "POST /tokens HTTP/1.1");
+
+ RecordedRequest copyRequest = server.takeRequest();
+ assertEquals(copyRequest.getRequestLine(),
+ "PUT /v1/MossoCloudFS_5bcf396e-39dd-45ff-93a1-712b9aba90a9/foo/bar.txt HTTP/1.1");
+
+ List<String> requestHeaders = copyRequest.getHeaders();
+ assertTrue(requestHeaders.contains("X-Object-Meta-someuserheader: someUserMetadataValue"));
+ assertTrue(requestHeaders.contains("content-disposition: attachment; filename=\"fname.ext\""));
+ assertTrue(requestHeaders.contains(SwiftHeaders.OBJECT_COPY_FROM + ": /bar/foo.txt"));
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ @Test(expectedExceptions = CopyObjectException.class)
+ public void testCopyObjectWithMetadataFail() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)
+ .addHeader(SwiftHeaders.OBJECT_COPY_FROM, "/bar/foo.txt")));
+
+ try {
+ SwiftApi api = api(server.getUrl("/").toString(), "openstack-swift");
+ assertTrue(api.getObjectApi("DFW", "foo")
+ .copy("bar.txt", "bar", "foo.txt", ImmutableMap.of("someUserHeader", "someUserMetadataValue"),
+ ImmutableMap.of("Content-Disposition", "attachment; filename=\"fname.ext\"")));
+ } finally {
+ server.shutdown();
+ }
+ }
+
private static final Map<String, String> metadata = ImmutableMap.of("ApiName", "swift", "ApiVersion", "v1.1");
static MockResponse objectResponse() {
[3/3] jclouds git commit: JCLOUDS-651: Copy Swift system metadata
Posted by ga...@apache.org.
JCLOUDS-651: Copy Swift system metadata
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/d8f48c48
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/d8f48c48
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/d8f48c48
Branch: refs/heads/master
Commit: d8f48c48b41e229e89c4b5db2641e15003b99277
Parents: 576005a
Author: Andrew Gaul <ga...@apache.org>
Authored: Thu Apr 2 17:16:36 2015 -0700
Committer: Andrew Gaul <ga...@apache.org>
Committed: Mon Apr 6 15:35:59 2015 -0700
----------------------------------------------------------------------
.../blobstore/RegionScopedSwiftBlobStore.java | 49 ++++++++++++++------
.../internal/BaseBlobIntegrationTest.java | 3 +-
2 files changed, 37 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/d8f48c48/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 4516264..4192a96 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
@@ -53,6 +53,7 @@ import org.jclouds.blobstore.options.PutOptions;
import org.jclouds.blobstore.strategy.ClearListStrategy;
import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location;
+import org.jclouds.io.ContentMetadata;
import org.jclouds.io.Payload;
import org.jclouds.io.payloads.ByteSourcePayload;
import org.jclouds.openstack.swift.v1.SwiftApi;
@@ -78,7 +79,9 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
import com.google.common.io.ByteSource;
+import com.google.common.net.HttpHeaders;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.assistedinject.Assisted;
@@ -234,25 +237,45 @@ 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);
- boolean copied = objectApi.copy(toName, fromContainer, fromName);
- if (!copied) {
- throw new RuntimeException("could not copy blob");
+ Map<String, String> userMetadata;
+ if (options.getUserMetadata().isPresent()) {
+ userMetadata = options.getUserMetadata().get();
+ } else {
+ userMetadata = metadata.getMetadata();
}
- // TODO: content disposition
- // TODO: content encoding
- // TODO: content language
- // TODO: content type
+ // 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);
+ }
- Optional<Map<String, String>> userMetadata = options.getUserMetadata();
- if (userMetadata.isPresent()) {
- boolean updated = objectApi.updateMetadata(toName, userMetadata.get());
- if (!updated) {
- throw new RuntimeException("could not copy blob");
- }
+ 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
+
return objectApi.getWithoutBody(toName).getETag();
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/d8f48c48/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 0d57fc5..1be2597 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
@@ -759,8 +759,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
} finally {
Closeables2.closeQuietly(is);
}
- // TODO: Swift does not preserve system metadata
- //checkContentMetadata(toBlob);
+ checkContentMetadata(toBlob);
assertThat(toBlob.getMetadata().getUserMetadata()).isEqualTo(userMetadata);
} finally {
returnContainer(toContainer);
[2/3] jclouds git commit: Adds live test.
Posted by ga...@apache.org.
Adds live test.
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/576005a3
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/576005a3
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/576005a3
Branch: refs/heads/master
Commit: 576005a33553d3b682bdd7088c10c5e7da1c004e
Parents: a1cbec1
Author: Zack Shoylev <za...@rackspace.com>
Authored: Thu Apr 2 15:55:01 2015 -0500
Committer: Andrew Gaul <ga...@apache.org>
Committed: Mon Apr 6 15:35:59 2015 -0700
----------------------------------------------------------------------
.../swift/v1/binders/BindMetadataToHeaders.java | 4 +-
.../openstack/swift/v1/features/ObjectApi.java | 24 +++++-
.../swift/v1/features/ObjectApiLiveTest.java | 81 ++++++++++++++++++++
3 files changed, 105 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/576005a3/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java
----------------------------------------------------------------------
diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java
index d27e19d..59ff29a 100644
--- a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java
+++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java
@@ -85,8 +85,8 @@ public class BindMetadataToHeaders implements Binder {
}
}
- public static class BindHeaderMetadataToHeaders extends BindMetadataToHeaders {
- BindHeaderMetadataToHeaders() {
+ public static class BindRawMetadataToHeaders extends BindMetadataToHeaders {
+ BindRawMetadataToHeaders() {
super("");
}
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/576005a3/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java
index 7d89ba3..841fd9d 100644
--- a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java
+++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java
@@ -41,8 +41,8 @@ import org.jclouds.http.options.GetOptions;
import org.jclouds.io.Payload;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
-import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindHeaderMetadataToHeaders;
import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindObjectMetadataToHeaders;
+import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindRawMetadataToHeaders;
import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindRemoveObjectMetadataToHeaders;
import org.jclouds.openstack.swift.v1.binders.SetPayload;
import org.jclouds.openstack.swift.v1.domain.ObjectList;
@@ -208,6 +208,26 @@ public interface ObjectApi {
@BinderParam(BindObjectMetadataToHeaders.class) Map<String, String> metadata);
/**
+ * Creates or updates the metadata for a {@link SwiftObject} without escaping the key.
+ * This will also update metadata such as content-disposition.
+ *
+ * @param objectName
+ * corresponds to {@link SwiftObject#getName()}.
+ * @param metadata
+ * the metadata to create or update.
+ *
+ * @return {@code true} if the metadata was successfully created or updated,
+ * {@code false} if not.
+ */
+ @Named("object:updateMetadata")
+ @POST
+ @Path("/{objectName}")
+ @Produces("")
+ @Fallback(FalseOnNotFoundOr404.class)
+ boolean updateRawMetadata(@PathParam("objectName") String objectName,
+ @BinderParam(BindRawMetadataToHeaders.class) Map<String, String> metadata);
+
+ /**
* Deletes the metadata from a {@link SwiftObject}.
*
* @param objectName
@@ -293,6 +313,6 @@ public interface ObjectApi {
@PathParam("sourceContainer") String sourceContainer,
@PathParam("sourceObject") String sourceObject,
@BinderParam(BindObjectMetadataToHeaders.class) Map<String, String> userMetadata,
- @BinderParam(BindHeaderMetadataToHeaders.class) Map<String, String> objectMetadata);
+ @BinderParam(BindRawMetadataToHeaders.class) Map<String, String> objectMetadata);
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/576005a3/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiLiveTest.java b/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiLiveTest.java
index 5a472ff..12d769d 100644
--- a/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiLiveTest.java
+++ b/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiLiveTest.java
@@ -45,6 +45,7 @@ import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Multimap;
import com.google.common.io.ByteSource;
/**
@@ -96,6 +97,7 @@ public class ObjectApiLiveTest extends BaseSwiftApiLiveTest<SwiftApi> {
api.getObjectApi(regionId, containerName).delete(objectName);
}
}
+
public void testCopyObject() throws Exception {
for (String regionId : regions) {
// source
@@ -153,6 +155,85 @@ public class ObjectApiLiveTest extends BaseSwiftApiLiveTest<SwiftApi> {
}
}
+ public void testCopyObjectWithMetadata() throws Exception {
+ for (String regionId : regions) {
+ // source
+ String sourceContainer = "src" + containerName;
+ String sourceObjectName = "original.txt";
+ String badSource = "badSource";
+
+ // destination
+ String destinationContainer = "dest" + containerName;
+ String destinationObject = "copy.txt";
+ String destinationPath = "/" + destinationContainer + "/" + destinationObject;
+
+ ContainerApi containerApi = api.getContainerApi(regionId);
+
+ // create source and destination dirs
+ containerApi.create(sourceContainer);
+ containerApi.create(destinationContainer);
+
+ // get the api for this region and container
+ ObjectApi srcApi = api.getObjectApi(regionId, sourceContainer);
+ ObjectApi destApi = api.getObjectApi(regionId, destinationContainer);
+
+ // Create source object
+ assertNotNull(srcApi.put(sourceObjectName, PAYLOAD));
+ SwiftObject sourceObject = srcApi.get(sourceObjectName);
+ checkObject(sourceObject);
+
+ srcApi.updateMetadata(sourceObjectName,
+ ImmutableMap.of("userProvidedMetadataKey", "userProvidedMetadataValue"));
+
+ // Create the destination object
+ assertNotNull(destApi.put(destinationObject, PAYLOAD));
+ SwiftObject object = destApi.get(destinationObject);
+ checkObject(object);
+
+ // check the copy operation
+ assertTrue(destApi.copy(destinationObject, sourceContainer, sourceObjectName,
+ ImmutableMap.<String, String>of("additionalUserMetakey", "additionalUserMetavalue"),
+ ImmutableMap.of("Content-Disposition", "attachment; filename=\"updatedname.txt\"")));
+ assertNotNull(destApi.get(destinationObject));
+
+ // now get a real SwiftObject
+ SwiftObject destSwiftObject = destApi.get(destinationObject);
+ assertEquals(toStringAndClose(destSwiftObject.getPayload().openStream()), "swifty");
+
+ /**
+ * Make sure all src metadata is in dest
+ * Make sure the new content disposition is in dest
+ */
+ Multimap<String, String> srcHeaders = null;
+ Multimap<String, String> destHeaders = null;
+ srcHeaders = srcApi.get(sourceObjectName).getHeaders();
+ destHeaders = destApi.get(destinationObject).getHeaders();
+ for (Entry<String, String> header : srcHeaders.entries()) {
+ if (header.getKey().equals("Date"))continue;
+ if (header.getKey().equals("Last-Modified"))continue;
+ if (header.getKey().equals("X-Trans-Id"))continue;
+ if (header.getKey().equals("X-Timestamp"))continue;
+ assertTrue(destHeaders.containsEntry(header.getKey(), header.getValue()), "Could not find: " + header);
+ }
+ assertEquals(destApi.get(destinationObject).getPayload().getContentMetadata().getContentDisposition(), "attachment; filename=\"updatedname.txt\"");
+
+ // test exception thrown on bad source name
+ try {
+ destApi.copy(destinationObject, badSource, sourceObjectName);
+ fail("Expected CopyObjectException");
+ } catch (CopyObjectException e) {
+ assertEquals(e.getSourcePath(), "/" + badSource + "/" + sourceObjectName);
+ assertEquals(e.getDestinationPath(), destinationPath);
+ }
+
+ deleteAllObjectsInContainer(regionId, sourceContainer);
+ containerApi.deleteIfEmpty(sourceContainer);
+
+ deleteAllObjectsInContainer(regionId, destinationContainer);
+ containerApi.deleteIfEmpty(destinationContainer);
+ }
+ }
+
public void testList() throws Exception {
for (String regionId : regions) {
ObjectApi objectApi = api.getObjectApi(regionId, containerName);