mirror of https://github.com/apache/jclouds.git
Merge pull request #827 from everett-toews/swift-copy-object-squashed-4
Squashed commits of my previous swift-copy-object pull request
This commit is contained in:
commit
b0a12bf303
|
@ -96,6 +96,7 @@ public class CloudFilesClientLiveTest extends CommonSwiftClientLiveTest<CloudFil
|
||||||
Set<ContainerCDNMetadata> cdnMetadataList = getApi().listCDNContainers();
|
Set<ContainerCDNMetadata> cdnMetadataList = getApi().listCDNContainers();
|
||||||
assertTrue(cdnMetadataList.size() >= 1);
|
assertTrue(cdnMetadataList.size() >= 1);
|
||||||
|
|
||||||
|
cdnMetadata = getApi().getCDNMetadata(containerNameWithCDN);
|
||||||
final long initialTTL = cdnMetadata.getTTL();
|
final long initialTTL = cdnMetadata.getTTL();
|
||||||
assertTrue(cdnMetadataList.contains(new ContainerCDNMetadata(containerNameWithCDN, true, initialTTL, cdnUri)));
|
assertTrue(cdnMetadataList.contains(new ContainerCDNMetadata(containerNameWithCDN, true, initialTTL, cdnUri)));
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,13 @@ import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
|
||||||
import org.jclouds.blobstore.domain.PageSet;
|
import org.jclouds.blobstore.domain.PageSet;
|
||||||
import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound;
|
import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound;
|
||||||
import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound;
|
import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound;
|
||||||
|
import org.jclouds.blobstore.functions.ReturnNullOnContainerNotFound;
|
||||||
import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound;
|
import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound;
|
||||||
import org.jclouds.http.functions.ParseETagHeader;
|
import org.jclouds.http.functions.ParseETagHeader;
|
||||||
import org.jclouds.http.options.GetOptions;
|
import org.jclouds.http.options.GetOptions;
|
||||||
import org.jclouds.openstack.filters.AuthenticateRequest;
|
import org.jclouds.openstack.filters.AuthenticateRequest;
|
||||||
|
import org.jclouds.openstack.swift.binders.BindIterableToHeadersWithContainerDeleteMetadataPrefix;
|
||||||
|
import org.jclouds.openstack.swift.binders.BindMapToHeadersWithContainerMetadataPrefix;
|
||||||
import org.jclouds.openstack.swift.binders.BindSwiftObjectMetadataToRequest;
|
import org.jclouds.openstack.swift.binders.BindSwiftObjectMetadataToRequest;
|
||||||
import org.jclouds.openstack.swift.domain.AccountMetadata;
|
import org.jclouds.openstack.swift.domain.AccountMetadata;
|
||||||
import org.jclouds.openstack.swift.domain.ContainerMetadata;
|
import org.jclouds.openstack.swift.domain.ContainerMetadata;
|
||||||
|
@ -47,14 +50,26 @@ import org.jclouds.openstack.swift.domain.ObjectInfo;
|
||||||
import org.jclouds.openstack.swift.domain.SwiftObject;
|
import org.jclouds.openstack.swift.domain.SwiftObject;
|
||||||
import org.jclouds.openstack.swift.functions.ObjectName;
|
import org.jclouds.openstack.swift.functions.ObjectName;
|
||||||
import org.jclouds.openstack.swift.functions.ParseAccountMetadataResponseFromHeaders;
|
import org.jclouds.openstack.swift.functions.ParseAccountMetadataResponseFromHeaders;
|
||||||
|
import org.jclouds.openstack.swift.functions.ParseContainerMetadataFromHeaders;
|
||||||
import org.jclouds.openstack.swift.functions.ParseObjectFromHeadersAndHttpContent;
|
import org.jclouds.openstack.swift.functions.ParseObjectFromHeadersAndHttpContent;
|
||||||
import org.jclouds.openstack.swift.functions.ParseObjectInfoFromHeaders;
|
import org.jclouds.openstack.swift.functions.ParseObjectInfoFromHeaders;
|
||||||
import org.jclouds.openstack.swift.functions.ParseObjectInfoListFromJsonResponse;
|
import org.jclouds.openstack.swift.functions.ParseObjectInfoListFromJsonResponse;
|
||||||
import org.jclouds.openstack.swift.functions.ReturnTrueOn404FalseOn409;
|
import org.jclouds.openstack.swift.functions.ReturnTrueOn404FalseOn409;
|
||||||
|
import org.jclouds.openstack.swift.options.CreateContainerOptions;
|
||||||
import org.jclouds.openstack.swift.options.ListContainerOptions;
|
import org.jclouds.openstack.swift.options.ListContainerOptions;
|
||||||
import org.jclouds.rest.annotations.*;
|
import org.jclouds.openstack.swift.reference.SwiftHeaders;
|
||||||
|
import org.jclouds.rest.annotations.BinderParam;
|
||||||
|
import org.jclouds.rest.annotations.Endpoint;
|
||||||
|
import org.jclouds.rest.annotations.ExceptionParser;
|
||||||
|
import org.jclouds.rest.annotations.Headers;
|
||||||
|
import org.jclouds.rest.annotations.ParamParser;
|
||||||
|
import org.jclouds.rest.annotations.QueryParams;
|
||||||
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.ResponseParser;
|
||||||
|
import org.jclouds.rest.annotations.SkipEncoding;
|
||||||
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
||||||
|
|
||||||
|
import com.google.common.annotations.Beta;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
@ -89,13 +104,50 @@ public interface CommonSwiftAsyncClient {
|
||||||
@Path("/")
|
@Path("/")
|
||||||
ListenableFuture<? extends Set<ContainerMetadata>> listContainers(ListContainerOptions... options);
|
ListenableFuture<? extends Set<ContainerMetadata>> listContainers(ListContainerOptions... options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CommonSwiftClient#getContainerMetadata
|
||||||
|
*/
|
||||||
|
@Beta
|
||||||
|
@HEAD
|
||||||
|
@ResponseParser(ParseContainerMetadataFromHeaders.class)
|
||||||
|
@ExceptionParser(ReturnNullOnContainerNotFound.class)
|
||||||
|
@Path("/{container}")
|
||||||
|
ListenableFuture<ContainerMetadata> getContainerMetadata(@PathParam("container") String container);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CommonSwiftClient#setContainerMetadata
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/{container}")
|
||||||
|
@ExceptionParser(ReturnFalseOnContainerNotFound.class)
|
||||||
|
ListenableFuture<Boolean> setContainerMetadata(@PathParam("container") String container,
|
||||||
|
@BinderParam(BindMapToHeadersWithContainerMetadataPrefix.class) Map<String, String> containerMetadata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CommonSwiftClient#deleteContainerMetadata
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/{container}")
|
||||||
|
@ExceptionParser(ReturnFalseOnContainerNotFound.class)
|
||||||
|
ListenableFuture<Boolean> deleteContainerMetadata(@PathParam("container") String container,
|
||||||
|
@BinderParam(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class) Iterable<String> metadataKeys);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CommonSwiftClient#createContainer
|
||||||
|
*/
|
||||||
|
@PUT
|
||||||
|
@Path("/{container}")
|
||||||
|
ListenableFuture<Boolean> createContainer(@PathParam("container") String container,
|
||||||
|
CreateContainerOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see CommonSwiftClient#setObjectInfo
|
* @see CommonSwiftClient#setObjectInfo
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
@Path("/{container}/{name}")
|
@Path("/{container}/{name}")
|
||||||
ListenableFuture<Boolean> setObjectInfo(@PathParam("container") String container, @PathParam("name") String name,
|
ListenableFuture<Boolean> setObjectInfo(@PathParam("container") String container,
|
||||||
@BinderParam(BindMapToHeadersWithPrefix.class) Map<String, String> userMetadata);
|
@PathParam("name") String name,
|
||||||
|
@BinderParam(BindMapToHeadersWithPrefix.class) Map<String, String> userMetadata);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see CommonSwiftClient#createContainer
|
* @see CommonSwiftClient#createContainer
|
||||||
|
@ -120,7 +172,7 @@ public interface CommonSwiftAsyncClient {
|
||||||
@ResponseParser(ParseObjectInfoListFromJsonResponse.class)
|
@ResponseParser(ParseObjectInfoListFromJsonResponse.class)
|
||||||
@Path("/{container}")
|
@Path("/{container}")
|
||||||
ListenableFuture<PageSet<ObjectInfo>> listObjects(@PathParam("container") String container,
|
ListenableFuture<PageSet<ObjectInfo>> listObjects(@PathParam("container") String container,
|
||||||
ListContainerOptions... options);
|
ListContainerOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see CommonSwiftClient#containerExists
|
* @see CommonSwiftClient#containerExists
|
||||||
|
@ -136,9 +188,20 @@ public interface CommonSwiftAsyncClient {
|
||||||
@PUT
|
@PUT
|
||||||
@Path("/{container}/{name}")
|
@Path("/{container}/{name}")
|
||||||
@ResponseParser(ParseETagHeader.class)
|
@ResponseParser(ParseETagHeader.class)
|
||||||
ListenableFuture<String> putObject(
|
ListenableFuture<String> putObject(@PathParam("container") String container,
|
||||||
@PathParam("container") String container,
|
@PathParam("name") @ParamParser(ObjectName.class) @BinderParam(BindSwiftObjectMetadataToRequest.class) SwiftObject object);
|
||||||
@PathParam("name") @ParamParser(ObjectName.class) @BinderParam(BindSwiftObjectMetadataToRequest.class) SwiftObject object);
|
|
||||||
|
/**
|
||||||
|
* @see CommonSwiftClient#copyObject
|
||||||
|
*/
|
||||||
|
@PUT
|
||||||
|
@Path("/{destinationContainer}/{destinationObject}")
|
||||||
|
@Headers(keys = SwiftHeaders.OBJECT_COPY_FROM, values = "/{sourceContainer}/{sourceObject}")
|
||||||
|
@ExceptionParser(ReturnFalseOnContainerNotFound.class)
|
||||||
|
ListenableFuture<Boolean> copyObject(@PathParam("sourceContainer") String sourceContainer,
|
||||||
|
@PathParam("sourceObject") String sourceObject,
|
||||||
|
@PathParam("destinationContainer") String destinationContainer,
|
||||||
|
@PathParam("destinationObject") String destinationObject);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see CommonSwiftClient#getObject
|
* @see CommonSwiftClient#getObject
|
||||||
|
@ -147,8 +210,9 @@ public interface CommonSwiftAsyncClient {
|
||||||
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
|
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
|
||||||
@ExceptionParser(ReturnNullOnKeyNotFound.class)
|
@ExceptionParser(ReturnNullOnKeyNotFound.class)
|
||||||
@Path("/{container}/{name}")
|
@Path("/{container}/{name}")
|
||||||
ListenableFuture<SwiftObject> getObject(@PathParam("container") String container, @PathParam("name") String name,
|
ListenableFuture<SwiftObject> getObject(@PathParam("container") String container,
|
||||||
GetOptions... options);
|
@PathParam("name") String name,
|
||||||
|
GetOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see CommonSwiftClient#getObjectInfo
|
* @see CommonSwiftClient#getObjectInfo
|
||||||
|
@ -158,7 +222,7 @@ public interface CommonSwiftAsyncClient {
|
||||||
@ExceptionParser(ReturnNullOnKeyNotFound.class)
|
@ExceptionParser(ReturnNullOnKeyNotFound.class)
|
||||||
@Path("/{container}/{name}")
|
@Path("/{container}/{name}")
|
||||||
ListenableFuture<MutableObjectInfoWithMetadata> getObjectInfo(@PathParam("container") String container,
|
ListenableFuture<MutableObjectInfoWithMetadata> getObjectInfo(@PathParam("container") String container,
|
||||||
@PathParam("name") String name);
|
@PathParam("name") String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see CommonSwiftClient#objectExists
|
* @see CommonSwiftClient#objectExists
|
||||||
|
@ -166,7 +230,8 @@ public interface CommonSwiftAsyncClient {
|
||||||
@HEAD
|
@HEAD
|
||||||
@ExceptionParser(ReturnFalseOnKeyNotFound.class)
|
@ExceptionParser(ReturnFalseOnKeyNotFound.class)
|
||||||
@Path("/{container}/{name}")
|
@Path("/{container}/{name}")
|
||||||
ListenableFuture<Boolean> objectExists(@PathParam("container") String container, @PathParam("name") String name);
|
ListenableFuture<Boolean> objectExists(@PathParam("container") String container,
|
||||||
|
@PathParam("name") String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see CommonSwiftClient#removeObject
|
* @see CommonSwiftClient#removeObject
|
||||||
|
@ -174,13 +239,14 @@ public interface CommonSwiftAsyncClient {
|
||||||
@DELETE
|
@DELETE
|
||||||
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
|
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
|
||||||
@Path("/{container}/{name}")
|
@Path("/{container}/{name}")
|
||||||
ListenableFuture<Void> removeObject(@PathParam("container") String container, @PathParam("name") String name);
|
ListenableFuture<Void> removeObject(@PathParam("container") String container,
|
||||||
|
@PathParam("name") String name);
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Path("/{container}/{name}")
|
@Path("/{container}/{name}")
|
||||||
@ResponseParser(ParseETagHeader.class)
|
@ResponseParser(ParseETagHeader.class)
|
||||||
@Headers(keys = "X-Object-Manifest", values="{container}/{name}")
|
@Headers(keys = "X-Object-Manifest", values="{container}/{name}")
|
||||||
ListenableFuture<String> putObjectManifest(@PathParam("container") String container,
|
ListenableFuture<String> putObjectManifest(@PathParam("container") String container,
|
||||||
@PathParam("name") String name);
|
@PathParam("name") String name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.jclouds.openstack.swift.domain.ContainerMetadata;
|
||||||
import org.jclouds.openstack.swift.domain.MutableObjectInfoWithMetadata;
|
import org.jclouds.openstack.swift.domain.MutableObjectInfoWithMetadata;
|
||||||
import org.jclouds.openstack.swift.domain.ObjectInfo;
|
import org.jclouds.openstack.swift.domain.ObjectInfo;
|
||||||
import org.jclouds.openstack.swift.domain.SwiftObject;
|
import org.jclouds.openstack.swift.domain.SwiftObject;
|
||||||
|
import org.jclouds.openstack.swift.options.CreateContainerOptions;
|
||||||
import org.jclouds.openstack.swift.options.ListContainerOptions;
|
import org.jclouds.openstack.swift.options.ListContainerOptions;
|
||||||
|
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
@ -87,24 +88,38 @@ public interface CommonSwiftClient {
|
||||||
*/
|
*/
|
||||||
Set<ContainerMetadata> listContainers(ListContainerOptions... options);
|
Set<ContainerMetadata> listContainers(ListContainerOptions... options);
|
||||||
|
|
||||||
boolean setObjectInfo(String container, String name, Map<String, String> userMetadata);
|
ContainerMetadata getContainerMetadata(String container);
|
||||||
|
|
||||||
|
boolean setContainerMetadata(String container, Map<String, String> containerMetadata);
|
||||||
|
|
||||||
|
boolean deleteContainerMetadata(String container, Iterable<String> metadataKeys);
|
||||||
|
|
||||||
boolean createContainer(String container);
|
boolean createContainer(String container);
|
||||||
|
|
||||||
|
boolean createContainer(String container, CreateContainerOptions... options);
|
||||||
|
|
||||||
boolean deleteContainerIfEmpty(String container);
|
boolean deleteContainerIfEmpty(String container);
|
||||||
|
|
||||||
PageSet<ObjectInfo> listObjects(String container, ListContainerOptions... options);
|
|
||||||
|
|
||||||
boolean containerExists(String container);
|
boolean containerExists(String container);
|
||||||
|
|
||||||
@Timeout(duration = 5 * 1024 * 1024 / 128, timeUnit = TimeUnit.SECONDS)
|
PageSet<ObjectInfo> listObjects(String container, ListContainerOptions... options);
|
||||||
String putObject(String container, SwiftObject object);
|
|
||||||
|
|
||||||
@Timeout(duration = 5 * 1024 * 1024 / 512, timeUnit = TimeUnit.SECONDS)
|
@Timeout(duration = 5 * 1024 * 1024 / 512, timeUnit = TimeUnit.SECONDS)
|
||||||
SwiftObject getObject(String container, String name, GetOptions... options);
|
SwiftObject getObject(String container, String name, GetOptions... options);
|
||||||
|
|
||||||
|
boolean setObjectInfo(String container, String name, Map<String, String> userMetadata);
|
||||||
|
|
||||||
MutableObjectInfoWithMetadata getObjectInfo(String container, String name);
|
MutableObjectInfoWithMetadata getObjectInfo(String container, String name);
|
||||||
|
|
||||||
|
@Timeout(duration = 5 * 1024 * 1024 / 128, timeUnit = TimeUnit.SECONDS)
|
||||||
|
String putObject(String container, SwiftObject object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True If the object was copied
|
||||||
|
* @throws CopyObjectException If the object was not copied
|
||||||
|
*/
|
||||||
|
boolean copyObject(String sourceContainer, String sourceObject, String destinationContainer, String destinationObject);
|
||||||
|
|
||||||
void removeObject(String container, String name);
|
void removeObject(String container, String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds 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.openstack.swift;
|
||||||
|
|
||||||
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when an object cannot be copied.
|
||||||
|
*
|
||||||
|
* @author Everett Toews
|
||||||
|
*/
|
||||||
|
public class CopyObjectException extends ResourceNotFoundException {
|
||||||
|
|
||||||
|
private String sourcePath;
|
||||||
|
private String destinationPath;
|
||||||
|
|
||||||
|
public CopyObjectException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CopyObjectException(String sourcePath, String destinationPath, String message) {
|
||||||
|
super(String.format("Either the source path %s or the destination path %s was not found. " +
|
||||||
|
"(message: %s)", sourcePath, destinationPath, message));
|
||||||
|
this.sourcePath = sourcePath;
|
||||||
|
this.destinationPath = destinationPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CopyObjectException(Exception from) {
|
||||||
|
super(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSourcePath() {
|
||||||
|
return sourcePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDestinationPath() {
|
||||||
|
return destinationPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The serialVersionUID */
|
||||||
|
private static final long serialVersionUID = -2272965726680721281L;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds 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.openstack.swift.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.openstack.swift.reference.SwiftHeaders;
|
||||||
|
import org.jclouds.rest.Binder;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.HashMultimap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Everett Toews
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class BindIterableToHeadersWithContainerDeleteMetadataPrefix implements Binder {
|
||||||
|
private final Function<String, String> FN;
|
||||||
|
|
||||||
|
public BindIterableToHeadersWithContainerDeleteMetadataPrefix() {
|
||||||
|
FN = new Function<String, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String element) {
|
||||||
|
String inLowercase = element.toLowerCase();
|
||||||
|
return (inLowercase.startsWith(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX)) ? inLowercase : SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + inLowercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "prefix: " + SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
|
checkArgument(checkNotNull(input, "input") instanceof Iterable<?>, "this binder is only valid for Iterable!");
|
||||||
|
checkNotNull(request, "request");
|
||||||
|
|
||||||
|
Iterable<String> metadataKeys = Iterables.transform((Iterable<String>) input, FN);
|
||||||
|
HashMultimap<String, String> headers = HashMultimap.create();
|
||||||
|
|
||||||
|
for (String metadataKey: metadataKeys) {
|
||||||
|
headers.put(metadataKey, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (R) request.toBuilder().replaceHeaders(headers).build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package org.jclouds.openstack.swift.binders;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
|
||||||
|
import org.jclouds.openstack.swift.reference.SwiftHeaders;
|
||||||
|
|
||||||
|
public class BindMapToHeadersWithContainerMetadataPrefix extends BindMapToHeadersWithPrefix {
|
||||||
|
|
||||||
|
public BindMapToHeadersWithContainerMetadataPrefix() {
|
||||||
|
super(SwiftHeaders.CONTAINER_METADATA_PREFIX);
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.hpcloud.objectstorage.functions;
|
package org.jclouds.openstack.swift.functions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
|
@ -32,6 +32,8 @@ import org.jclouds.http.HttpErrorHandler;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.openstack.swift.CopyObjectException;
|
||||||
|
import org.jclouds.openstack.swift.reference.SwiftHeaders;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,10 +63,21 @@ public class ParseSwiftErrorFromHttpResponse implements HttpErrorHandler {
|
||||||
exception = new AuthorizationException(exception.getMessage(), exception);
|
exception = new AuthorizationException(exception.getMessage(), exception);
|
||||||
break;
|
break;
|
||||||
case 404:
|
case 404:
|
||||||
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
|
String sourcePath = command.getCurrentRequest().getFirstHeaderOrNull(SwiftHeaders.OBJECT_COPY_FROM);
|
||||||
|
Exception oldException = exception;
|
||||||
|
|
||||||
|
if (sourcePath != null) {
|
||||||
|
String path = command.getCurrentRequest().getEndpoint().getPath();
|
||||||
|
int startOfDestinationPath = path.lastIndexOf("/", path.lastIndexOf("/")-1);
|
||||||
|
String destinationPath = path.substring(startOfDestinationPath);
|
||||||
|
|
||||||
|
exception = new CopyObjectException(sourcePath, destinationPath, message);
|
||||||
|
exception.initCause(oldException);
|
||||||
|
}
|
||||||
|
else if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
|
||||||
String path = command.getCurrentRequest().getEndpoint().getPath();
|
String path = command.getCurrentRequest().getEndpoint().getPath();
|
||||||
Matcher matcher = CONTAINER_PATH.matcher(path);
|
Matcher matcher = CONTAINER_PATH.matcher(path);
|
||||||
Exception oldException = exception;
|
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
exception = new ContainerNotFoundException(matcher.group(1), message);
|
exception = new ContainerNotFoundException(matcher.group(1), message);
|
||||||
exception.initCause(oldException);
|
exception.initCause(oldException);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.hpcloud.objectstorage.options;
|
package org.jclouds.openstack.swift.options;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
@ -61,17 +61,11 @@ public class CreateContainerOptions extends BaseHttpRequestOptions {
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
/**
|
|
||||||
* @see org.jclouds.hpcloud.objectstorage.options.CreateContainerOptions#withPublicAccess
|
|
||||||
*/
|
|
||||||
public static CreateContainerOptions withPublicAccess() {
|
public static CreateContainerOptions withPublicAccess() {
|
||||||
CreateContainerOptions options = new CreateContainerOptions();
|
CreateContainerOptions options = new CreateContainerOptions();
|
||||||
return options.withPublicAccess();
|
return options.withPublicAccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see org.jclouds.hpcloud.objectstorage.options.CreateContainerOptions#withMetadata(Multimap<String, String>)
|
|
||||||
*/
|
|
||||||
public static CreateContainerOptions withMetadata(Map<String, String> metadata) {
|
public static CreateContainerOptions withMetadata(Map<String, String> metadata) {
|
||||||
CreateContainerOptions options = new CreateContainerOptions();
|
CreateContainerOptions options = new CreateContainerOptions();
|
||||||
return (CreateContainerOptions) options.withMetadata(metadata);
|
return (CreateContainerOptions) options.withMetadata(metadata);
|
|
@ -29,7 +29,9 @@ public interface SwiftHeaders {
|
||||||
public static final String CONTAINER_BYTES_USED = "X-Container-Bytes-Used";
|
public static final String CONTAINER_BYTES_USED = "X-Container-Bytes-Used";
|
||||||
public static final String CONTAINER_OBJECT_COUNT = "X-Container-Object-Count";
|
public static final String CONTAINER_OBJECT_COUNT = "X-Container-Object-Count";
|
||||||
public static final String CONTAINER_METADATA_PREFIX = "X-Container-Meta-";
|
public static final String CONTAINER_METADATA_PREFIX = "X-Container-Meta-";
|
||||||
|
public static final String CONTAINER_DELETE_METADATA_PREFIX = "X-Remove-Container-Meta-";
|
||||||
public static final String USER_METADATA_PREFIX = "X-Object-Meta-";
|
public static final String USER_METADATA_PREFIX = "X-Object-Meta-";
|
||||||
|
public static final String OBJECT_COPY_FROM = "X-Copy-From";
|
||||||
|
|
||||||
public static final String CONTAINER_READ = "X-Container-Read";
|
public static final String CONTAINER_READ = "X-Container-Read";
|
||||||
public static final String CONTAINER_WRITE = "X-Container-Write";
|
public static final String CONTAINER_WRITE = "X-Container-Write";
|
||||||
|
|
|
@ -20,8 +20,10 @@ package org.jclouds.openstack.swift;
|
||||||
|
|
||||||
import static org.jclouds.openstack.swift.options.ListContainerOptions.Builder.underPath;
|
import static org.jclouds.openstack.swift.options.ListContainerOptions.Builder.underPath;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertFalse;
|
||||||
import static org.testng.Assert.assertNotNull;
|
import static org.testng.Assert.assertNotNull;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
import static org.testng.Assert.fail;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -274,6 +276,64 @@ public abstract class CommonSwiftClientLiveTest<C extends CommonSwiftClient> ext
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCopyObjectOperations() throws Exception {
|
||||||
|
String sourceContainer = getContainerName();
|
||||||
|
String sourceObject = "original.txt";
|
||||||
|
String sourcePath = "/" + sourceContainer + "/" + sourceObject;
|
||||||
|
String badSource = "badsource";
|
||||||
|
String destinationContainer = getContainerName();
|
||||||
|
String destinationObject = "copy.txt";
|
||||||
|
String destinationPath = "/" + destinationContainer + "/" + destinationObject;
|
||||||
|
String badDestination = "baddestination";
|
||||||
|
String data = "Hello World";
|
||||||
|
SwiftObject sourceSwiftObject = newSwiftObject(data, sourceObject);
|
||||||
|
|
||||||
|
getApi().putObject(sourceContainer, sourceSwiftObject);
|
||||||
|
|
||||||
|
// test that not giving a destination name *doesn't* copy source name to the destination container with
|
||||||
|
// the source name but copy still returns success :(
|
||||||
|
assertTrue(getApi().copyObject(sourceContainer, sourceObject, destinationContainer, ""));
|
||||||
|
assertTrue(!getApi().objectExists(destinationContainer, sourceObject));
|
||||||
|
|
||||||
|
// test copy works
|
||||||
|
assertTrue(getApi().copyObject(sourceContainer, sourceObject, destinationContainer, destinationObject));
|
||||||
|
assertTrue(getApi().objectExists(destinationContainer, destinationObject));
|
||||||
|
|
||||||
|
SwiftObject destinationSwiftObject = getApi().getObject(destinationContainer, destinationObject);
|
||||||
|
assertEquals(Strings2.toString(destinationSwiftObject.getPayload()), data);
|
||||||
|
|
||||||
|
// test exception thrown on bad destination container
|
||||||
|
try {
|
||||||
|
assertFalse(getApi().copyObject(sourceContainer, sourceObject, badDestination, destinationObject));
|
||||||
|
fail("Expected CopyObjectException");
|
||||||
|
}
|
||||||
|
catch (CopyObjectException e) {
|
||||||
|
assertEquals(e.getSourcePath(), sourcePath);
|
||||||
|
assertEquals(e.getDestinationPath(), "/" + badDestination + "/" + destinationObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test exception thrown on bad source container
|
||||||
|
try {
|
||||||
|
assertFalse(getApi().copyObject(badSource, sourceObject, destinationContainer, destinationObject));
|
||||||
|
fail("Expected CopyObjectException");
|
||||||
|
}
|
||||||
|
catch (CopyObjectException e) {
|
||||||
|
assertEquals(e.getSourcePath(), "/" + badSource + "/" + sourceObject);
|
||||||
|
assertEquals(e.getDestinationPath(), destinationPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test exception thrown on bad source name
|
||||||
|
try {
|
||||||
|
assertFalse(getApi().copyObject(sourceContainer, badSource, destinationContainer, destinationObject));
|
||||||
|
fail("Expected CopyObjectException");
|
||||||
|
}
|
||||||
|
catch (CopyObjectException e) {
|
||||||
|
assertEquals(e.getSourcePath(), "/" + sourceContainer + "/" + badSource);
|
||||||
|
assertEquals(e.getDestinationPath(), destinationPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void testGetObjectContentType(SwiftObject getBlob) {
|
protected void testGetObjectContentType(SwiftObject getBlob) {
|
||||||
String contentType = getBlob.getPayload().getContentMetadata().getContentType();
|
String contentType = getBlob.getPayload().getContentMetadata().getContentType();
|
||||||
assert contentType.startsWith("text/plain") || "application/x-www-form-urlencoded".equals(contentType): contentType;
|
assert contentType.startsWith("text/plain") || "application/x-www-form-urlencoded".equals(contentType): contentType;
|
||||||
|
|
|
@ -23,9 +23,14 @@ import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.openstack.swift.internal.BaseSwiftExpectTest;
|
import org.jclouds.openstack.swift.internal.BaseSwiftExpectTest;
|
||||||
|
import org.jclouds.openstack.swift.reference.SwiftHeaders;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -33,7 +38,8 @@ import org.testng.annotations.Test;
|
||||||
@Test(testName = "SwiftClientExpectTest")
|
@Test(testName = "SwiftClientExpectTest")
|
||||||
public class SwiftClientExpectTest extends BaseSwiftExpectTest<SwiftClient> {
|
public class SwiftClientExpectTest extends BaseSwiftExpectTest<SwiftClient> {
|
||||||
|
|
||||||
public void testContainerExistsWhenResponseIs2xxReturnsTrue() throws Exception {
|
@Test
|
||||||
|
public void testContainerExistsWhenResponseIs2xxReturnsTrue() {
|
||||||
HttpRequest headContainer = HttpRequest.builder()
|
HttpRequest headContainer = HttpRequest.builder()
|
||||||
.method("HEAD")
|
.method("HEAD")
|
||||||
.endpoint(swiftEndpointWithHostReplaced + "/foo")
|
.endpoint(swiftEndpointWithHostReplaced + "/foo")
|
||||||
|
@ -47,7 +53,8 @@ public class SwiftClientExpectTest extends BaseSwiftExpectTest<SwiftClient> {
|
||||||
assertTrue(clientWhenContainerExists.containerExists("foo"));
|
assertTrue(clientWhenContainerExists.containerExists("foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testContainerExistsWhenResponseIs404ReturnsFalse() throws Exception {
|
@Test
|
||||||
|
public void testContainerExistsWhenResponseIs404ReturnsFalse() {
|
||||||
HttpRequest headContainer = HttpRequest.builder()
|
HttpRequest headContainer = HttpRequest.builder()
|
||||||
.method("HEAD")
|
.method("HEAD")
|
||||||
.endpoint(swiftEndpointWithHostReplaced + "/foo")
|
.endpoint(swiftEndpointWithHostReplaced + "/foo")
|
||||||
|
@ -59,7 +66,150 @@ public class SwiftClientExpectTest extends BaseSwiftExpectTest<SwiftClient> {
|
||||||
authResponse, headContainer, headContainerResponse);
|
authResponse, headContainer, headContainerResponse);
|
||||||
|
|
||||||
assertFalse(clientWhenContainerDoesntExist.containerExists("foo"));
|
assertFalse(clientWhenContainerDoesntExist.containerExists("foo"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetContainerMetadataWhenResponseIs2xxReturnsTrue() {
|
||||||
|
HttpRequest setContainerMetadataRequest = HttpRequest.builder()
|
||||||
|
.method("POST")
|
||||||
|
.endpoint(swiftEndpointWithHostReplaced + "/foo")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_METADATA_PREFIX + "key", "value")
|
||||||
|
.addHeader("X-Auth-Token", authToken).build();
|
||||||
|
|
||||||
|
HttpResponse setContainerMetadataResponse = HttpResponse.builder().statusCode(204).build();
|
||||||
|
|
||||||
|
SwiftClient clientSetContainerMetadata = requestsSendResponses(authRequest,
|
||||||
|
authResponse, setContainerMetadataRequest, setContainerMetadataResponse);
|
||||||
|
|
||||||
|
assertTrue(clientSetContainerMetadata.setContainerMetadata("foo", ImmutableMap.<String, String> of("key", "value")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = HttpResponseException.class)
|
||||||
|
public void testSetContainerMetadataWhenResponseIs400ThrowsException() {
|
||||||
|
HttpRequest setContainerMetadataRequest = HttpRequest.builder()
|
||||||
|
.method("POST")
|
||||||
|
.endpoint(swiftEndpointWithHostReplaced + "/foo")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_METADATA_PREFIX, "value")
|
||||||
|
.addHeader("X-Auth-Token", authToken).build();
|
||||||
|
|
||||||
|
HttpResponse setContainerMetadataResponse = HttpResponse.builder()
|
||||||
|
.statusCode(400)
|
||||||
|
.message("Metadata name cannot be empty").build();
|
||||||
|
|
||||||
|
SwiftClient clientSetContainerMetadata = requestsSendResponses(authRequest,
|
||||||
|
authResponse, setContainerMetadataRequest, setContainerMetadataResponse);
|
||||||
|
|
||||||
|
clientSetContainerMetadata.setContainerMetadata("foo", ImmutableMap.<String, String> of("", "value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetContainerMetadataWhenResponseIs404ReturnsFalse() {
|
||||||
|
HttpRequest setContainerMetadataRequest = HttpRequest.builder()
|
||||||
|
.method("POST")
|
||||||
|
.endpoint(swiftEndpointWithHostReplaced + "/foo")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_METADATA_PREFIX + "key", "value")
|
||||||
|
.addHeader("X-Auth-Token", authToken).build();
|
||||||
|
|
||||||
|
HttpResponse setContainerMetadataResponse = HttpResponse.builder()
|
||||||
|
.statusCode(404).build();
|
||||||
|
|
||||||
|
SwiftClient clientSetContainerMetadata = requestsSendResponses(authRequest,
|
||||||
|
authResponse, setContainerMetadataRequest, setContainerMetadataResponse);
|
||||||
|
|
||||||
|
assertFalse(clientSetContainerMetadata.setContainerMetadata("foo", ImmutableMap.<String, String> of("key", "value")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteContainerMetadataWhenResponseIs2xxReturnsTrue() {
|
||||||
|
HttpRequest deleteContainerMetadataRequest = HttpRequest.builder()
|
||||||
|
.method("POST")
|
||||||
|
.endpoint(swiftEndpointWithHostReplaced + "/foo")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + "bar", "")
|
||||||
|
.addHeader("X-Auth-Token", authToken).build();
|
||||||
|
|
||||||
|
HttpResponse deleteContainerMetadataResponse = HttpResponse.builder().statusCode(204).build();
|
||||||
|
|
||||||
|
SwiftClient clientDeleteContainerMetadata = requestsSendResponses(authRequest,
|
||||||
|
authResponse, deleteContainerMetadataRequest, deleteContainerMetadataResponse);
|
||||||
|
|
||||||
|
assertTrue(clientDeleteContainerMetadata.deleteContainerMetadata("foo", ImmutableList.<String> of("bar")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteContainerMetadataEmptyWhenResponseIs2xxReturnsTrue() {
|
||||||
|
HttpRequest deleteContainerMetadataRequest = HttpRequest.builder()
|
||||||
|
.method("POST")
|
||||||
|
.endpoint(swiftEndpointWithHostReplaced + "/foo")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX, "")
|
||||||
|
.addHeader("X-Auth-Token", authToken).build();
|
||||||
|
|
||||||
|
HttpResponse deleteContainerMetadataResponse = HttpResponse.builder().statusCode(204).build();
|
||||||
|
|
||||||
|
SwiftClient clientDeleteContainerMetadata = requestsSendResponses(authRequest,
|
||||||
|
authResponse, deleteContainerMetadataRequest, deleteContainerMetadataResponse);
|
||||||
|
|
||||||
|
assertTrue(clientDeleteContainerMetadata.deleteContainerMetadata("foo", ImmutableList.<String> of("")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteContainerMetadataWhenResponseIs404ReturnsFalse() {
|
||||||
|
HttpRequest deleteContainerMetadataRequest = HttpRequest.builder()
|
||||||
|
.method("POST")
|
||||||
|
.endpoint(swiftEndpointWithHostReplaced + "/foo")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + "bar", "")
|
||||||
|
.addHeader("X-Auth-Token", authToken).build();
|
||||||
|
|
||||||
|
HttpResponse deleteContainerMetadataResponse = HttpResponse.builder().statusCode(404).build();
|
||||||
|
|
||||||
|
SwiftClient clientDeleteContainerMetadata = requestsSendResponses(authRequest,
|
||||||
|
authResponse, deleteContainerMetadataRequest, deleteContainerMetadataResponse);
|
||||||
|
|
||||||
|
assertFalse(clientDeleteContainerMetadata.deleteContainerMetadata("foo", ImmutableList.<String> of("bar")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCopyObjectWhenResponseIs2xxReturnsTrue() {
|
||||||
|
String sourceContainer = "bar";
|
||||||
|
String sourceObject = "foo.txt";
|
||||||
|
String sourcePath = "/" + sourceContainer + "/" + sourceObject;
|
||||||
|
String destinationContainer = "foo";
|
||||||
|
String destinationObject = "bar.txt";
|
||||||
|
String destinationPath = "/" + destinationContainer + "/" + destinationObject;
|
||||||
|
|
||||||
|
HttpRequest copyObjectRequest = HttpRequest.builder()
|
||||||
|
.method("PUT")
|
||||||
|
.endpoint(swiftEndpointWithHostReplaced + destinationPath)
|
||||||
|
.addHeader(SwiftHeaders.OBJECT_COPY_FROM, sourcePath)
|
||||||
|
.addHeader("X-Auth-Token", authToken).build();
|
||||||
|
|
||||||
|
HttpResponse copyObjectResponse = HttpResponse.builder().statusCode(201).build();
|
||||||
|
|
||||||
|
SwiftClient clientCopyObject = requestsSendResponses(authRequest,
|
||||||
|
authResponse, copyObjectRequest, copyObjectResponse);
|
||||||
|
|
||||||
|
assertTrue(clientCopyObject.copyObject(sourceContainer, sourceObject, destinationContainer, destinationObject));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = CopyObjectException.class)
|
||||||
|
public void testCopyObjectWhenResponseIs404ThrowsException() {
|
||||||
|
String sourceContainer = "bar";
|
||||||
|
String sourceObject = "foo.txt";
|
||||||
|
String sourcePath = "/" + sourceContainer + "/" + sourceObject;
|
||||||
|
String destinationContainer = "foo";
|
||||||
|
String destinationObject = "bar.txt";
|
||||||
|
String destinationPath = "/" + destinationContainer + "/" + destinationObject;
|
||||||
|
|
||||||
|
HttpRequest copyObjectRequest = HttpRequest.builder()
|
||||||
|
.method("PUT")
|
||||||
|
.endpoint(swiftEndpointWithHostReplaced + destinationPath)
|
||||||
|
.addHeader(SwiftHeaders.OBJECT_COPY_FROM, sourcePath)
|
||||||
|
.addHeader("X-Auth-Token", authToken).build();
|
||||||
|
|
||||||
|
HttpResponse copyObjectResponse = HttpResponse.builder().statusCode(404).build();
|
||||||
|
|
||||||
|
SwiftClient clientCopyObject = requestsSendResponses(authRequest,
|
||||||
|
authResponse, copyObjectRequest, copyObjectResponse);
|
||||||
|
|
||||||
|
assertTrue(clientCopyObject.copyObject(sourceContainer, sourceObject, destinationContainer, destinationObject));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds 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.openstack.swift.binders;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.openstack.swift.CommonSwiftClientTest;
|
||||||
|
import org.jclouds.openstack.swift.reference.SwiftHeaders;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code BindIterableToHeadersWithContainerDeleteMetadataPrefix}
|
||||||
|
*
|
||||||
|
* @author Everett Toews
|
||||||
|
*/
|
||||||
|
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||||
|
@Test(groups = "unit", testName = "BindIterableToHeadersWithContainerDeleteMetadataPrefixTest")
|
||||||
|
public class BindIterableToHeadersWithContainerDeleteMetadataPrefixTest extends CommonSwiftClientTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetadataKeysBind() {
|
||||||
|
List<String> metadataKeys = ImmutableList.of("foo", "bar");
|
||||||
|
|
||||||
|
HttpRequest request = HttpRequest.builder().method("PUT").endpoint("http://localhost").build();
|
||||||
|
BindIterableToHeadersWithContainerDeleteMetadataPrefix binder =
|
||||||
|
injector.getInstance(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class);
|
||||||
|
|
||||||
|
HttpRequest actualRequest = binder.bindToRequest(request, metadataKeys);
|
||||||
|
HttpRequest expectedRequest = HttpRequest.builder()
|
||||||
|
.method("PUT")
|
||||||
|
.endpoint("http://localhost")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + "foo", "")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + "bar", "")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertEquals(actualRequest, expectedRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testNullListIsBad() {
|
||||||
|
HttpRequest request = HttpRequest.builder().method("PUT").endpoint("http://localhost").build();
|
||||||
|
BindIterableToHeadersWithContainerDeleteMetadataPrefix binder =
|
||||||
|
injector.getInstance(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class);
|
||||||
|
|
||||||
|
binder.bindToRequest(request, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testNullRequestIsBad() {
|
||||||
|
List<String> metadataKeys = ImmutableList.of("foo", "bar");
|
||||||
|
BindIterableToHeadersWithContainerDeleteMetadataPrefix binder =
|
||||||
|
injector.getInstance(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class);
|
||||||
|
|
||||||
|
binder.bindToRequest(null, metadataKeys);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds 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.openstack.swift.binders;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.openstack.swift.CommonSwiftClientTest;
|
||||||
|
import org.jclouds.openstack.swift.reference.SwiftHeaders;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code BindListToHeadersWithContainerDeleteMetadataPrefix}
|
||||||
|
*
|
||||||
|
* @author Everett Toews
|
||||||
|
*/
|
||||||
|
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||||
|
@Test(groups = "unit", testName = "BindListToHeadersWithContainerDeleteMetadataPrefixTest")
|
||||||
|
public class BindMapToHeadersWithContainerMetadataPrefixTest extends CommonSwiftClientTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetadataKeysBind() {
|
||||||
|
List<String> metadataKeys = ImmutableList.of("foo", "bar");
|
||||||
|
|
||||||
|
HttpRequest request = HttpRequest.builder().method("PUT").endpoint("http://localhost").build();
|
||||||
|
BindIterableToHeadersWithContainerDeleteMetadataPrefix binder =
|
||||||
|
injector.getInstance(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class);
|
||||||
|
|
||||||
|
HttpRequest actualRequest = binder.bindToRequest(request, metadataKeys);
|
||||||
|
HttpRequest expectedRequest = HttpRequest.builder()
|
||||||
|
.method("PUT")
|
||||||
|
.endpoint("http://localhost")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + "foo", "")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + "bar", "")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertEquals(actualRequest, expectedRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testNullListIsBad() {
|
||||||
|
HttpRequest request = HttpRequest.builder().method("PUT").endpoint("http://localhost").build();
|
||||||
|
BindIterableToHeadersWithContainerDeleteMetadataPrefix binder =
|
||||||
|
injector.getInstance(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class);
|
||||||
|
|
||||||
|
binder.bindToRequest(request, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
|
public void testNullRequestIsBad() {
|
||||||
|
List<String> metadataKeys = ImmutableList.of("foo", "bar");
|
||||||
|
BindIterableToHeadersWithContainerDeleteMetadataPrefix binder =
|
||||||
|
injector.getInstance(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class);
|
||||||
|
|
||||||
|
binder.bindToRequest(null, metadataKeys);
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,15 +18,28 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.swift.blobstore.integration;
|
package org.jclouds.openstack.swift.blobstore.integration;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.BlobStore;
|
||||||
import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest;
|
import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
||||||
|
import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
|
||||||
|
import org.jclouds.openstack.swift.CommonSwiftClient;
|
||||||
|
import org.jclouds.openstack.swift.domain.ContainerMetadata;
|
||||||
|
import org.jclouds.openstack.swift.options.CreateContainerOptions;
|
||||||
|
import org.jclouds.rest.RestContext;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author James Murty
|
* @author James Murty
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
* @author Everett Toews
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live")
|
@Test(groups = "live")
|
||||||
public class SwiftContainerIntegrationLiveTest extends BaseContainerIntegrationTest {
|
public class SwiftContainerIntegrationLiveTest extends BaseContainerIntegrationTest {
|
||||||
|
@ -40,4 +53,53 @@ public class SwiftContainerIntegrationLiveTest extends BaseContainerIntegrationT
|
||||||
public SwiftContainerIntegrationLiveTest() {
|
public SwiftContainerIntegrationLiveTest() {
|
||||||
provider = System.getProperty("test.swift.provider", "swift");
|
provider = System.getProperty("test.swift.provider", "swift");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(groups = "live")
|
||||||
|
public void testSetGetContainerMetadata() throws InterruptedException {
|
||||||
|
BlobStore blobStore = view.getBlobStore();
|
||||||
|
RestContext<CommonSwiftClient, CommonSwiftAsyncClient> swift = blobStore.getContext().unwrap();
|
||||||
|
String containerName = getContainerName();
|
||||||
|
|
||||||
|
assertTrue(swift.getApi().createContainer(containerName));
|
||||||
|
|
||||||
|
ImmutableMap<String, String> metadata = ImmutableMap.<String, String> of(
|
||||||
|
"key1", "value1",
|
||||||
|
"key2", "value2");
|
||||||
|
|
||||||
|
assertTrue(swift.getApi().setContainerMetadata(containerName, metadata));
|
||||||
|
|
||||||
|
ContainerMetadata containerMetadata = swift.getApi().getContainerMetadata(containerName);
|
||||||
|
|
||||||
|
assertEquals(containerMetadata.getMetadata().get("key1"), "value1");
|
||||||
|
assertEquals(containerMetadata.getMetadata().get("key2"), "value2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(groups = "live")
|
||||||
|
public void testCreateDeleteContainerMetadata() throws InterruptedException {
|
||||||
|
BlobStore blobStore = view.getBlobStore();
|
||||||
|
RestContext<CommonSwiftClient, CommonSwiftAsyncClient> swift = blobStore.getContext().unwrap();
|
||||||
|
String containerName = getContainerName();
|
||||||
|
CreateContainerOptions options = CreateContainerOptions.Builder
|
||||||
|
.withPublicAccess()
|
||||||
|
.withMetadata(ImmutableMap.<String, String> of(
|
||||||
|
"key1", "value1",
|
||||||
|
"key2", "value2",
|
||||||
|
"key3", "value3"));
|
||||||
|
|
||||||
|
assertTrue(swift.getApi().createContainer(containerName, options));
|
||||||
|
|
||||||
|
ContainerMetadata containerMetadata = swift.getApi().getContainerMetadata(containerName);
|
||||||
|
|
||||||
|
assertEquals(containerMetadata.getMetadata().size(), 3);
|
||||||
|
assertEquals(containerMetadata.getMetadata().get("key1"), "value1");
|
||||||
|
assertEquals(containerMetadata.getMetadata().get("key2"), "value2");
|
||||||
|
assertEquals(containerMetadata.getMetadata().get("key3"), "value3");
|
||||||
|
|
||||||
|
assertTrue(swift.getApi().deleteContainerMetadata(containerName, ImmutableList.<String> of("key2","key3")));
|
||||||
|
|
||||||
|
containerMetadata = swift.getApi().getContainerMetadata(containerName);
|
||||||
|
|
||||||
|
assertEquals(containerMetadata.getMetadata().size(), 1);
|
||||||
|
assertEquals(containerMetadata.getMetadata().get("key1"), "value1");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,5 +46,4 @@ public class SwiftContainerLiveTest extends BaseContainerLiveTest {
|
||||||
public void testPublicAccess() throws MalformedURLException, InterruptedException, IOException {
|
public void testPublicAccess() throws MalformedURLException, InterruptedException, IOException {
|
||||||
super.testPublicAccess();
|
super.testPublicAccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds 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.openstack.swift.functions;
|
||||||
|
|
||||||
|
import static org.easymock.EasyMock.createMock;
|
||||||
|
import static org.easymock.EasyMock.expect;
|
||||||
|
import static org.easymock.EasyMock.replay;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.openstack.swift.domain.ContainerMetadata;
|
||||||
|
import org.jclouds.openstack.swift.functions.ParseContainerMetadataFromHeaders;
|
||||||
|
import org.jclouds.openstack.swift.reference.SwiftHeaders;
|
||||||
|
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code ParseContainerMetadataFromHeaders}
|
||||||
|
*
|
||||||
|
* @author Everett Toews
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit")
|
||||||
|
public class ParseContainerMetadataFromHeadersTest {
|
||||||
|
|
||||||
|
Injector i = Guice.createInjector(new AbstractModule() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public void testParseContainerMetadataHeaders() {
|
||||||
|
ParseContainerMetadataFromHeaders parser = i.getInstance(ParseContainerMetadataFromHeaders.class);
|
||||||
|
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
|
||||||
|
expect(request.getArgs()).andReturn(ImmutableList.<Object> of("container", "key")).atLeastOnce();
|
||||||
|
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/test")).atLeastOnce();
|
||||||
|
replay(request);
|
||||||
|
parser.setContext(request);
|
||||||
|
|
||||||
|
HttpResponse response = HttpResponse.builder().statusCode(204).message("No Content").payload("")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_BYTES_USED, "42")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_OBJECT_COUNT, "1")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_METADATA_PREFIX + "label1", "test1")
|
||||||
|
.addHeader(SwiftHeaders.CONTAINER_METADATA_PREFIX + "label2", "test2").build();
|
||||||
|
|
||||||
|
response.getPayload().getContentMetadata().setContentType("text/plain");
|
||||||
|
ContainerMetadata containerMetadata = parser.apply(response);
|
||||||
|
|
||||||
|
assertEquals(containerMetadata.getBytes(), 42);
|
||||||
|
assertEquals(containerMetadata.getCount(), 1);
|
||||||
|
assertEquals(containerMetadata.getMetadata().get("label1"), "test1");
|
||||||
|
assertEquals(containerMetadata.getMetadata().get("label2"), "test2");
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,9 +31,14 @@ import org.jclouds.blobstore.ContainerNotFoundException;
|
||||||
import org.jclouds.blobstore.KeyNotFoundException;
|
import org.jclouds.blobstore.KeyNotFoundException;
|
||||||
import org.jclouds.http.HttpCommand;
|
import org.jclouds.http.HttpCommand;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpRequest.Builder;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.openstack.swift.CopyObjectException;
|
||||||
|
import org.jclouds.openstack.swift.reference.SwiftHeaders;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -41,6 +46,13 @@ import org.testng.annotations.Test;
|
||||||
@Test(groups = { "unit" })
|
@Test(groups = { "unit" })
|
||||||
public class ParseSwiftErrorFromHttpResponseTest {
|
public class ParseSwiftErrorFromHttpResponseTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test404SetsCopyObjectException() {
|
||||||
|
assertCodeMakes("HEAD",
|
||||||
|
URI.create("http://host/v1/MossoCloudFS_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1/key"), 404,
|
||||||
|
"Not Found", "text/plain", "", "/bad/source/path", CopyObjectException.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test404SetsKeyNotFoundExceptionMosso() {
|
public void test404SetsKeyNotFoundExceptionMosso() {
|
||||||
assertCodeMakes("HEAD",
|
assertCodeMakes("HEAD",
|
||||||
|
@ -76,24 +88,34 @@ public class ParseSwiftErrorFromHttpResponseTest {
|
||||||
|
|
||||||
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
|
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
|
||||||
String content, Class<? extends Exception> expected) {
|
String content, Class<? extends Exception> expected) {
|
||||||
|
assertCodeMakes(method, uri, statusCode, message, contentType, content, "", expected);
|
||||||
ParseSwiftErrorFromHttpResponse function = new ParseSwiftErrorFromHttpResponse();
|
|
||||||
|
|
||||||
HttpCommand command = createMock(HttpCommand.class);
|
|
||||||
HttpRequest request = HttpRequest.builder().method(method).endpoint(uri).build();
|
|
||||||
HttpResponse response = HttpResponse.builder().statusCode(statusCode).message(message).payload(content).build();
|
|
||||||
response.getPayload().getContentMetadata().setContentType(contentType);
|
|
||||||
|
|
||||||
expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
|
|
||||||
command.setException(classEq(expected));
|
|
||||||
|
|
||||||
replay(command);
|
|
||||||
|
|
||||||
function.handleError(command, response);
|
|
||||||
|
|
||||||
verify(command);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
|
||||||
|
String content, String copyObjectSourcePath, Class<? extends Exception> expected) {
|
||||||
|
ParseSwiftErrorFromHttpResponse function = new ParseSwiftErrorFromHttpResponse();
|
||||||
|
|
||||||
|
HttpCommand command = createMock(HttpCommand.class);
|
||||||
|
Builder<?> requestBuilder = HttpRequest.builder().method(method).endpoint(uri);
|
||||||
|
|
||||||
|
if (!Strings.isNullOrEmpty(copyObjectSourcePath)) {
|
||||||
|
requestBuilder.addHeader(SwiftHeaders.OBJECT_COPY_FROM, copyObjectSourcePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequest request = requestBuilder.build();
|
||||||
|
HttpResponse response = HttpResponse.builder().statusCode(statusCode).message(message).payload(content).build();
|
||||||
|
response.getPayload().getContentMetadata().setContentType(contentType);
|
||||||
|
|
||||||
|
expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
|
||||||
|
command.setException(classEq(expected));
|
||||||
|
|
||||||
|
replay(command);
|
||||||
|
|
||||||
|
function.handleError(command, response);
|
||||||
|
|
||||||
|
verify(command);
|
||||||
|
}
|
||||||
|
|
||||||
public static Exception classEq(final Class<? extends Exception> in) {
|
public static Exception classEq(final Class<? extends Exception> in) {
|
||||||
reportMatcher(new IArgumentMatcher() {
|
reportMatcher(new IArgumentMatcher() {
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ import org.jclouds.openstack.swift.domain.ContainerMetadata;
|
||||||
import org.jclouds.openstack.swift.domain.MutableObjectInfoWithMetadata;
|
import org.jclouds.openstack.swift.domain.MutableObjectInfoWithMetadata;
|
||||||
import org.jclouds.openstack.swift.domain.ObjectInfo;
|
import org.jclouds.openstack.swift.domain.ObjectInfo;
|
||||||
import org.jclouds.openstack.swift.domain.SwiftObject;
|
import org.jclouds.openstack.swift.domain.SwiftObject;
|
||||||
|
import org.jclouds.openstack.swift.options.CreateContainerOptions;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
|
@ -160,12 +161,33 @@ public class StubSwiftAsyncClient implements CommonSwiftAsyncClient {
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<ContainerMetadata> getContainerMetadata(String container) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListenableFuture<Boolean> setContainerMetadata(String container, Map<String, String> containerMetadata) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListenableFuture<Boolean> deleteContainerMetadata(String container, Iterable<String> metadataKeys) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListenableFuture<Boolean> createContainer(String container, CreateContainerOptions... options) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
public ListenableFuture<PageSet<ObjectInfo>> listObjects(String container,
|
public ListenableFuture<PageSet<ObjectInfo>> listObjects(String container,
|
||||||
org.jclouds.openstack.swift.options.ListContainerOptions... optionsList) {
|
org.jclouds.openstack.swift.options.ListContainerOptions... optionsList) {
|
||||||
ListContainerOptions options = container2ContainerListOptions.apply(optionsList);
|
ListContainerOptions options = container2ContainerListOptions.apply(optionsList);
|
||||||
return Futures.compose(blobStore.list(container, options), resource2ObjectList, service);
|
return Futures.compose(blobStore.list(container, options), resource2ObjectList, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ListenableFuture<Boolean> copyObject(String sourceContainer, String sourceObject, String destinationContainer, String destinationObject) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
public ListenableFuture<String> putObject(String container, SwiftObject object) {
|
public ListenableFuture<String> putObject(String container, SwiftObject object) {
|
||||||
return blobStore.putBlob(container, object2Blob.apply(object));
|
return blobStore.putBlob(container, object2Blob.apply(object));
|
||||||
}
|
}
|
||||||
|
@ -195,5 +217,4 @@ public class StubSwiftAsyncClient implements CommonSwiftAsyncClient {
|
||||||
public ListenableFuture<Boolean> objectExists(String bucketName, String key) {
|
public ListenableFuture<Boolean> objectExists(String bucketName, String key) {
|
||||||
return blobStore.blobExists(bucketName, key);
|
return blobStore.blobExists(bucketName, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,11 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.hpcloud.objectstorage.options;
|
package org.jclouds.openstack.swift.options;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.swift.options.CreateContainerOptions;
|
||||||
import org.jclouds.openstack.swift.reference.SwiftHeaders;
|
import org.jclouds.openstack.swift.reference.SwiftHeaders;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
|
@ -23,16 +23,11 @@ import java.util.Set;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.HEAD;
|
|
||||||
import javax.ws.rs.PUT;
|
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.jclouds.blobstore.functions.ReturnNullOnContainerNotFound;
|
|
||||||
import org.jclouds.hpcloud.objectstorage.extensions.HPCloudCDNAsyncClient;
|
import org.jclouds.hpcloud.objectstorage.extensions.HPCloudCDNAsyncClient;
|
||||||
import org.jclouds.hpcloud.objectstorage.functions.ParseContainerMetadataFromHeaders;
|
|
||||||
import org.jclouds.hpcloud.objectstorage.options.CreateContainerOptions;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
||||||
import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
|
import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
|
||||||
import org.jclouds.openstack.swift.Storage;
|
import org.jclouds.openstack.swift.Storage;
|
||||||
|
@ -44,10 +39,8 @@ import org.jclouds.rest.annotations.Endpoint;
|
||||||
import org.jclouds.rest.annotations.ExceptionParser;
|
import org.jclouds.rest.annotations.ExceptionParser;
|
||||||
import org.jclouds.rest.annotations.QueryParams;
|
import org.jclouds.rest.annotations.QueryParams;
|
||||||
import org.jclouds.rest.annotations.RequestFilters;
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
import org.jclouds.rest.annotations.ResponseParser;
|
|
||||||
import org.jclouds.rest.annotations.SkipEncoding;
|
import org.jclouds.rest.annotations.SkipEncoding;
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
@ -69,24 +62,6 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||||
@Endpoint(Storage.class)
|
@Endpoint(Storage.class)
|
||||||
public interface HPCloudObjectStorageAsyncClient extends CommonSwiftAsyncClient {
|
public interface HPCloudObjectStorageAsyncClient extends CommonSwiftAsyncClient {
|
||||||
|
|
||||||
/**
|
|
||||||
* @see HPCloudObjectStorageClient#getCDNMetadata(String)
|
|
||||||
*/
|
|
||||||
@Beta
|
|
||||||
@HEAD
|
|
||||||
@ResponseParser(ParseContainerMetadataFromHeaders.class)
|
|
||||||
@ExceptionParser(ReturnNullOnContainerNotFound.class)
|
|
||||||
@Path("/{container}")
|
|
||||||
ListenableFuture<ContainerMetadata> getContainerMetadata(@PathParam("container") String container);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see HPCloudObjectStorageClient#createContainer
|
|
||||||
*/
|
|
||||||
@PUT
|
|
||||||
@Path("/{container}")
|
|
||||||
ListenableFuture<Boolean> createContainer(@PathParam("container") String container,
|
|
||||||
CreateContainerOptions... options);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.jclouds.openstack.swift.CommonSwiftClient#listContainers
|
* @see org.jclouds.openstack.swift.CommonSwiftClient#listContainers
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -22,9 +22,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.jclouds.concurrent.Timeout;
|
import org.jclouds.concurrent.Timeout;
|
||||||
import org.jclouds.hpcloud.objectstorage.extensions.HPCloudCDNClient;
|
import org.jclouds.hpcloud.objectstorage.extensions.HPCloudCDNClient;
|
||||||
import org.jclouds.hpcloud.objectstorage.options.CreateContainerOptions;
|
|
||||||
import org.jclouds.openstack.swift.CommonSwiftClient;
|
import org.jclouds.openstack.swift.CommonSwiftClient;
|
||||||
import org.jclouds.openstack.swift.domain.ContainerMetadata;
|
|
||||||
import org.jclouds.rest.annotations.Delegate;
|
import org.jclouds.rest.annotations.Delegate;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
|
@ -46,10 +44,6 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||||
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
|
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
|
||||||
public interface HPCloudObjectStorageClient extends CommonSwiftClient {
|
public interface HPCloudObjectStorageClient extends CommonSwiftClient {
|
||||||
|
|
||||||
boolean createContainer(String container, CreateContainerOptions... options);
|
|
||||||
|
|
||||||
ContainerMetadata getContainerMetadata(String container);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides synchronous access to CDN features.
|
* Provides synchronous access to CDN features.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue