mirror of https://github.com/apache/jclouds.git
Allows copying an object and modifying metadata (user and object)
This commit is contained in:
parent
c87e2052ac
commit
b5491c4848
|
@ -85,6 +85,12 @@ public class BindMetadataToHeaders implements Binder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class BindHeaderMetadataToHeaders extends BindMetadataToHeaders {
|
||||||
|
BindHeaderMetadataToHeaders() {
|
||||||
|
super("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class BindRemoveObjectMetadataToHeaders extends BindMetadataToHeaders.ForRemoval {
|
public static class BindRemoveObjectMetadataToHeaders extends BindMetadataToHeaders.ForRemoval {
|
||||||
BindRemoveObjectMetadataToHeaders() {
|
BindRemoveObjectMetadataToHeaders() {
|
||||||
super(OBJECT_METADATA_PREFIX);
|
super(OBJECT_METADATA_PREFIX);
|
||||||
|
|
|
@ -41,6 +41,7 @@ import org.jclouds.http.options.GetOptions;
|
||||||
import org.jclouds.io.Payload;
|
import org.jclouds.io.Payload;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
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.BindObjectMetadataToHeaders;
|
||||||
import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindRemoveObjectMetadataToHeaders;
|
import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindRemoveObjectMetadataToHeaders;
|
||||||
import org.jclouds.openstack.swift.v1.binders.SetPayload;
|
import org.jclouds.openstack.swift.v1.binders.SetPayload;
|
||||||
|
@ -262,4 +263,36 @@ public interface ObjectApi {
|
||||||
@PathParam("sourceContainer") String sourceContainer,
|
@PathParam("sourceContainer") String sourceContainer,
|
||||||
@PathParam("sourceObject") String sourceObject);
|
@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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ import static org.testng.Assert.fail;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
@ -193,7 +194,8 @@ public class ObjectApiMockTest extends BaseOpenStackMockTest<SwiftApi> {
|
||||||
public void testCreateWithSpacesAndSpecialCharacters() throws Exception {
|
public void testCreateWithSpacesAndSpecialCharacters() throws Exception {
|
||||||
MockWebServer server = mockOpenStackServer();
|
MockWebServer server = mockOpenStackServer();
|
||||||
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
|
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 containerName = "container # ! special";
|
||||||
final String objectName = "object # ! special";
|
final String objectName = "object # ! special";
|
||||||
|
@ -279,7 +281,8 @@ public class ObjectApiMockTest extends BaseOpenStackMockTest<SwiftApi> {
|
||||||
|
|
||||||
assertEquals(server.getRequestCount(), 2);
|
assertEquals(server.getRequestCount(), 2);
|
||||||
assertAuthentication(server);
|
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 {
|
} finally {
|
||||||
server.shutdown();
|
server.shutdown();
|
||||||
}
|
}
|
||||||
|
@ -469,7 +472,7 @@ public class ObjectApiMockTest extends BaseOpenStackMockTest<SwiftApi> {
|
||||||
try {
|
try {
|
||||||
SwiftApi api = api(server.getUrl("/").toString(), "openstack-swift");
|
SwiftApi api = api(server.getUrl("/").toString(), "openstack-swift");
|
||||||
assertTrue(api.getObjectApi("DFW", "foo")
|
assertTrue(api.getObjectApi("DFW", "foo")
|
||||||
.copy("bar.txt", "bar", "foo.txt"));
|
.copy("bar.txt", "bar", "foo.txt"));
|
||||||
|
|
||||||
assertEquals(server.getRequestCount(), 2);
|
assertEquals(server.getRequestCount(), 2);
|
||||||
assertEquals(server.takeRequest().getRequestLine(), "POST /tokens HTTP/1.1");
|
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");
|
private static final Map<String, String> metadata = ImmutableMap.of("ApiName", "swift", "ApiVersion", "v1.1");
|
||||||
|
|
||||||
static MockResponse objectResponse() {
|
static MockResponse objectResponse() {
|
||||||
|
|
Loading…
Reference in New Issue