diff --git a/aws/core/pom.xml b/aws/core/pom.xml
index 3e973af576..3098676c68 100644
--- a/aws/core/pom.xml
+++ b/aws/core/pom.xml
@@ -45,13 +45,4 @@
options specified or
+ * @param bucketName
+ * namespace of the object you are retrieving
+ * @param key
+ * unique key in the s3Bucket identifying the object
+ * @return Future reference to a fully populated S3Object including data stored in S3 or
* {@link S3Object#NOT_FOUND} if not present.
+ *
* @throws org.jclouds.http.HttpResponseException
* if the conditions requested set were not satisfied by the object on the server.
- * @see #getObject(String, String)
+ * @see #getBlob(String, String)
* @see GetObjectOptions
*/
@GET
@Path("{key}")
- @ExceptionParser(ReturnS3ObjectNotFoundOn404.class)
+ @ExceptionParser(ThrowKeyNotFoundOn404.class)
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
- Future getObject(@HostPrefixParam String bucketName, @PathParam("key") String key,
+ Future getBlob(@HostPrefixParam String bucketName, @PathParam("key") String key);
+
+ @GET
+ @Path("{key}")
+ @ExceptionParser(ThrowKeyNotFoundOn404.class)
+ @ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
+ Future getBlob(@HostPrefixParam String bucketName, @PathParam("key") String key,
GetOptions options);
/**
- * Retrieves the {@link org.jclouds.aws.s3.domain.S3Object.Metadata metadata} of the object
- * associated with the key or {@link org.jclouds.aws.s3.domain.S3Object.Metadata#NOT_FOUND} if
- * not available.
+ * Retrieves the {@link org.jclouds.aws.s3.domain.ObjectMetadata metadata} of the object
+ * associated with the key or {@link org.jclouds.aws.s3.domain.ObjectMetadata#NOT_FOUND} if not
+ * available.
*
*
* The HEAD operation is used to retrieve information about a specific object or object size,
@@ -155,17 +151,17 @@ public interface S3Connection {
* @param key
* unique key in the s3Bucket identifying the object
* @return metadata associated with the key or
- * {@link org.jclouds.aws.s3.domain.S3Object.Metadata#NOT_FOUND} if not present;
- * @see #getObject(String, String)
+ * {@link org.jclouds.aws.s3.domain.ObjectMetadata#NOT_FOUND} if not present;
+ * @see #getBlob(String, String)
* @see
*/
@HEAD
@Path("{key}")
- @ExceptionParser(ReturnS3ObjectMetadataNotFoundOn404.class)
- @ResponseParser(ParseMetadataFromHeaders.class)
- S3Object.Metadata headObject(@HostPrefixParam String bucketName, @PathParam("key") String key);
+ @ExceptionParser(ThrowKeyNotFoundOn404.class)
+ @ResponseParser(ParseObjectMetadataFromHeaders.class)
+ ObjectMetadata blobMetadata(@HostPrefixParam String bucketName, @PathParam("key") String key);
/**
* Removes the object and metadata associated with the key.
@@ -186,7 +182,7 @@ public interface S3Connection {
*/
@DELETE
@Path("{key}")
- Future deleteObject(@HostPrefixParam String bucketName, @PathParam("key") String key);
+ Future removeBlob(@HostPrefixParam String bucketName, @PathParam("key") String key);
/**
* Store data by creating or overwriting an object.
@@ -201,7 +197,11 @@ public interface S3Connection {
* namespace of the object you are storing
* @param object
* contains the data and metadata to create or overwrite
+ * @param options
+ * options for creating the object
* @return MD5 hash of the content uploaded
+ * @throws org.jclouds.http.HttpResponseException
+ * if the conditions requested set are not satisfied by the object on the server.
* @see org.jclouds.aws.s3.domain.CannedAccessPolicy#PRIVATE
* @see putObject(
+ Future putBlob(
@HostPrefixParam String bucketName,
- @PathParam("key") @ParamParser(S3ObjectKey.class) @EntityParam(S3ObjectBinder.class) S3Object object);
+ @PathParam("key") @ParamParser(BlobKey.class) @EntityParam(S3ObjectBinder.class) S3Object object,
+ PutObjectOptions options);
- /**
- * Like {@link #putObject(String, S3Object)} except you can use {@link PutObjectOptions} to
- * control delivery of content.
- *
- *
- * @param options
- * options for creating the object
- * @throws org.jclouds.http.HttpResponseException
- * if the conditions requested set are not satisfied by the object on the server.
- * @see S3Connection#putObject(String, S3Object)
- * @see PutObjectOptions
- * @see
- */
@PUT
@Path("{key}")
@ResponseParser(ParseETagHeader.class)
- Future putObject(
+ Future putBlob(
@HostPrefixParam String bucketName,
- @PathParam("key") @ParamParser(S3ObjectKey.class) @EntityParam(S3ObjectBinder.class) S3Object object,
- PutObjectOptions options);
+ @PathParam("key") @ParamParser(BlobKey.class) @EntityParam(S3ObjectBinder.class) S3Object object);
/**
* Create and name your own bucket in which to store your objects.
*
- * @see
- * @return true, if the bucket was created or already exists
- * @see org.jclouds.aws.s3.commands.PutBucket
- */
- @PUT
- @Path("/")
- @ExceptionParser(ReturnTrueIfBucketAlreadyOwnedByYou.class)
- Future putBucketIfNotExists(@HostPrefixParam String bucketName);
-
- /**
- * Like {@link #putBucketIfNotExists(String)} except that you can use {@link PutBucketOptions} to
- * create the bucket in EU.
+ *
+ * you can use {@link PutBucketOptions} to create the bucket in EU.
*
* The PUT request operation with a bucket URI creates a new bucket. Depending on your latency
* and legal requirements, you can specify a location constraint that will affect where your data
@@ -262,6 +235,8 @@ public interface S3Connection {
*
* @param options
* for creating your bucket
+ * @return true, if the bucket was created or already exists
+ *
* @see PutBucketOptions
* @see putBucketIfNotExists(@HostPrefixParam String bucketName,
- @EntityParam(HttpRequestOptionsBinder.class) PutBucketOptions options);
+ Future createContainer(@HostPrefixParam String bucketName,
+ @Nullable @EntityParam(HttpRequestOptionsBinder.class) PutBucketOptions options);
+
+ @PUT
+ @Path("/")
+ @ExceptionParser(ReturnTrueIfBucketAlreadyOwnedByYou.class)
+ Future createContainer(@HostPrefixParam String bucketName);
/**
* Deletes the bucket, if it is empty.
@@ -294,7 +274,59 @@ public interface S3Connection {
@DELETE
@Path("/")
@ExceptionParser(ReturnTrueOn404FalseIfNotEmpty.class)
- boolean deleteBucketIfEmpty(@HostPrefixParam String bucketName);
+ Future deleteContainer(@HostPrefixParam String bucketName);
+
+ /**
+ * Issues a HEAD command to determine if the bucket exists or not.
+ */
+ @HEAD
+ @Path("/")
+ @QueryParams(keys = "max-keys", values = "0")
+ @ExceptionParser(ReturnFalseOn404.class)
+ boolean containerExists(@HostPrefixParam String bucketName);
+
+ /**
+ * Retrieve a S3Bucket
listing. A GET request operation using a bucket URI lists
+ * information about the objects in the bucket. You can use {@link ListBucketOptions} to control
+ * the amount of S3Objects to return.
+ *
+ * To list the keys of a bucket, you must have READ access to the bucket.
+ *
+ *
+ * @param bucketName
+ * namespace of the objects you wish to list
+ * @return Future reference to a fully populated S3Bucket including metadata of the S3Objects it
+ * contains or {@link BoundedList#NOT_FOUND} if not present.
+ * @see ListBucketOptions
+ *
+ * @see
+ */
+ @GET
+ @Path("/")
+ @XMLResponseParser(ListBucketHandler.class)
+ Future listBlobs(@HostPrefixParam String bucketName,
+ @Nullable ListBucketOptions options);
+
+ @GET
+ @Path("/")
+ @XMLResponseParser(ListBucketHandler.class)
+ Future listBlobs(@HostPrefixParam String bucketName);
+
+ /**
+ * Returns a list of all of the buckets owned by the authenticated sender of the request.
+ *
+ * @return list of all of the buckets owned by the authenticated sender of the request.
+ * @see
+ *
+ */
+ @GET
+ @XMLResponseParser(ListAllMyBucketsHandler.class)
+ @Path("/")
+ List listContainers();
/**
* Copies one object to another bucket, retaining UserMetadata from the source. The destination
@@ -313,97 +345,30 @@ public interface S3Connection {
* @see
+ * @throws org.jclouds.http.HttpResponseException
+ * if the conditions requested set are not satisfied by the object on the server.
* @see CopyObjectOptions
* @see org.jclouds.aws.s3.domain.CannedAccessPolicy
*/
@PUT
@Path("{destinationObject}")
- @Header(key = "x-amz-copy-source", value = "/{sourceBucket}/{sourceObject}")
+ @Headers(keys = "x-amz-copy-source", values = "/{sourceBucket}/{sourceObject}")
@XMLResponseParser(CopyObjectHandler.class)
- Future copyObject(@PathParam("sourceBucket") String sourceBucket,
+ Future copyBlob(@PathParam("sourceBucket") String sourceBucket,
+ @PathParam("sourceObject") String sourceObject,
+ @HostPrefixParam String destinationBucket,
+ @PathParam("destinationObject") String destinationObject,
+ @Nullable CopyObjectOptions options);
+
+ @PUT
+ @Path("{destinationObject}")
+ @Headers(keys = "x-amz-copy-source", values = "/{sourceBucket}/{sourceObject}")
+ @XMLResponseParser(CopyObjectHandler.class)
+ Future copyBlob(@PathParam("sourceBucket") String sourceBucket,
@PathParam("sourceObject") String sourceObject,
@HostPrefixParam String destinationBucket,
@PathParam("destinationObject") String destinationObject);
- /**
- * Like {@link #putObject(String, S3Object)} except you can use {@link PutObjectOptions} to
- * specify an alternate {@link org.jclouds.aws.s3.domain.CannedAccessPolicy acl}.
- *
- * @param options
- * options for creating the object
- * @throws org.jclouds.http.HttpResponseException
- * if the conditions requested set are not satisfied by the object on the server.
- * @see S3Connection#putObject(String, S3Object)
- * @see PutObjectOptions
- */
- @PUT
- @Path("{destinationObject}")
- @Header(key = "x-amz-copy-source", value = "/{sourceBucket}/{sourceObject}")
- @XMLResponseParser(CopyObjectHandler.class)
- Future copyObject(@PathParam("sourceBucket") String sourceBucket,
- @PathParam("sourceObject") String sourceObject,
- @HostPrefixParam String destinationBucket,
- @PathParam("destinationObject") String destinationObject, CopyObjectOptions options);
-
- /**
- * Issues a HEAD command to determine if the bucket exists or not.
- */
- @HEAD
- @Path("/")
- @Query(key = "max-keys", value = "0")
- @ExceptionParser(ReturnFalseOn404.class)
- boolean bucketExists(@HostPrefixParam String bucketName);
-
- /**
- * Retrieve a complete S3Bucket
listing. A GET request operation using a bucket URI
- * lists information about the objects in the bucket.
- *
- * To list the keys of a bucket, you must have READ access to the bucket.
- *
- *
- * @param bucketName
- * namespace of the objects you wish to list
- * @return Future reference to a fully populated S3Bucket including metadata of the S3Objects it
- * contains or {@link S3Bucket#NOT_FOUND} if not present.
- * @see
- */
- @GET
- @Path("/")
- @XMLResponseParser(ListBucketHandler.class)
- @ExceptionParser(ReturnS3BucketNotFoundOn404.class)
- Future listBucket(@HostPrefixParam String bucketName);
-
- /**
- * Like {@link #listBucket(String)} except you can use {@link ListBucketOptions} to control the
- * amount of S3Objects to return.
- *
- * @return S3Bucket containing a subset of {@link org.jclouds.aws.s3.domain.S3Object.Metadata}
- * depending on
- * options specified or {@link S3Bucket#NOT_FOUND} if not present.
- * @see #listBucket(String)
- * @see ListBucketOptions
- */
- @GET
- @Path("/")
- @XMLResponseParser(ListBucketHandler.class)
- Future listBucket(@HostPrefixParam String bucketName, ListBucketOptions options);
-
- /**
- * Returns a list of all of the buckets owned by the authenticated sender of the request.
- *
- * @return list of all of the buckets owned by the authenticated sender of the request.
- * @see
- *
- */
- @GET
- @XMLResponseParser(ListAllMyBucketsHandler.class)
- @Path("/")
- List listOwnedBuckets();
-
/**
*
* A GET request operation directed at an object or bucket URI with the "acl" parameter retrieves
@@ -416,11 +381,11 @@ public interface S3Connection {
* @see
*/
@GET
- @Query(key = "acl")
+ @QueryParams(keys = "acl")
@XMLResponseParser(AccessControlListHandler.class)
- @ExceptionParser(ReturnNotFoundIfBucketDoesntExist.class)
+ @ExceptionParser(ThrowContainerNotFoundOn404.class)
@Path("/")
- Future getBucketACL(@HostPrefixParam String bucketName);
+ Future getContainerACL(@HostPrefixParam String bucketName);
/**
* Update a bucket's Access Control List settings.
@@ -441,8 +406,8 @@ public interface S3Connection {
*/
@PUT
@Path("/")
- @Query(key = "acl")
- Future putBucketACL(@HostPrefixParam String bucketName,
+ @QueryParams(keys = "acl")
+ Future putContainerACL(@HostPrefixParam String bucketName,
@EntityParam(AccessControlListBinder.class) AccessControlList acl);
/**
@@ -456,11 +421,11 @@ public interface S3Connection {
* @see
*/
@GET
- @Query(key = "acl")
+ @QueryParams(keys = "acl")
@Path("{key}")
@XMLResponseParser(AccessControlListHandler.class)
- @ExceptionParser(ReturnNotFoundIfObjectDoesntExist.class)
- Future getObjectACL(@HostPrefixParam String bucketName,
+ @ExceptionParser(ThrowKeyNotFoundOn404.class)
+ Future getBlobACL(@HostPrefixParam String bucketName,
@PathParam("key") String key);
/**
@@ -483,9 +448,9 @@ public interface S3Connection {
* @see
*/
@PUT
- @Query(key = "acl")
+ @QueryParams(keys = "acl")
@Path("{key}")
- Future putObjectACL(@HostPrefixParam String bucketName, @PathParam("key") String key,
+ Future putBlobACL(@HostPrefixParam String bucketName, @PathParam("key") String key,
@EntityParam(AccessControlListBinder.class) AccessControlList acl);
}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3Context.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3Context.java
index 087732f211..d4dcef7695 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3Context.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3Context.java
@@ -23,8 +23,9 @@
*/
package org.jclouds.aws.s3;
-import org.jclouds.cloud.CloudContext;
-import org.jclouds.objectstore.ObjectStoreContext;
+import org.jclouds.aws.s3.domain.ObjectMetadata;
+import org.jclouds.aws.s3.domain.S3Object;
+import org.jclouds.blobstore.BlobStoreContext;
/**
* Represents an authenticated context to S3.
@@ -33,19 +34,11 @@ import org.jclouds.objectstore.ObjectStoreContext;
* release resources.
*
*
- * @see S3Connection
- * @see S3InputStreamMap
- * @see S3ObjectMap
+ * @see S3BlobStore
+ * @see BlobStoreContext
* @author Adrian Cole
*
*/
-public interface S3Context extends CloudContext, ObjectStoreContext {
-
- /**
- * Creates a Map
view of the specified bucket.
- *
- * @param bucket
- */
- S3ObjectMap createS3ObjectMap(String bucket);
+public interface S3Context extends BlobStoreContext {
}
\ No newline at end of file
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3ContextBuilder.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3ContextBuilder.java
index 07111cc02b..17f1617f41 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3ContextBuilder.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3ContextBuilder.java
@@ -26,6 +26,7 @@ package org.jclouds.aws.s3;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
+import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_ADDRESS;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_REDIRECTS;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_RETRIES;
@@ -63,7 +64,7 @@ import com.google.inject.Module;
* @author Adrian Cole, Andrew Newdigate
* @see S3Context
*/
-public class S3ContextBuilder extends CloudContextBuilder {
+public class S3ContextBuilder extends CloudContextBuilder {
public S3ContextBuilder(Properties props) {
super(props);
@@ -73,6 +74,7 @@ public class S3ContextBuilder extends CloudContextBuilder modules) {
modules.add(new S3ParserModule());
}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/binders/S3ObjectBinder.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/binders/S3ObjectBinder.java
index b4e1dae707..32c576ebd8 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/binders/S3ObjectBinder.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/binders/S3ObjectBinder.java
@@ -24,50 +24,45 @@
package org.jclouds.aws.s3.binders;
import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.aws.s3.domain.S3Object;
+import org.jclouds.blobstore.binders.BlobBinder;
+import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpUtils;
-import org.jclouds.rest.EntityBinder;
-public class S3ObjectBinder implements EntityBinder {
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
- public void addEntityToRequest(Object entity, HttpRequest request) {
- S3Object object = (S3Object) entity;
- checkArgument(object.getMetadata().getSize() >= 0, "size must be set");
-
- request.setEntity(checkNotNull(object.getData(), "object.getContent()"));
-
- request.getHeaders()
- .put(
- HttpHeaders.CONTENT_TYPE,
- checkNotNull(object.getMetadata().getContentType(),
- "object.metadata.contentType()"));
-
- request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, object.getMetadata().getSize() + "");
-
- if (object.getMetadata().getCacheControl() != null) {
- request.getHeaders()
- .put(HttpHeaders.CACHE_CONTROL, object.getMetadata().getCacheControl());
- }
- if (object.getMetadata().getContentDisposition() != null) {
- request.getHeaders().put("Content-Disposition",
- object.getMetadata().getContentDisposition());
- }
- if (object.getMetadata().getContentEncoding() != null) {
- request.getHeaders().put(HttpHeaders.CONTENT_ENCODING,
- object.getMetadata().getContentEncoding());
- }
-
- if (object.getMetadata().getETag() != null) {
- request.getHeaders().put("Content-MD5",
- HttpUtils.toBase64String(object.getMetadata().getETag()));
- }
-
- request.getHeaders().putAll(object.getMetadata().getUserMetadata());
+public class S3ObjectBinder extends BlobBinder {
+ @Inject
+ public S3ObjectBinder(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
+ super(metadataPrefix);
}
+ public void addEntityToRequest(Object entity, HttpRequest request) {
+ Blob> object = (Blob>) entity;
+ checkArgument(object.getMetadata().getSize() >= 0, "size must be set");
+
+ if (object instanceof S3Object) {
+ S3Object s3Object = (S3Object) object;
+ if (s3Object.getMetadata().getCacheControl() != null) {
+ request.getHeaders().put(HttpHeaders.CACHE_CONTROL,
+ s3Object.getMetadata().getCacheControl());
+ }
+
+ if (s3Object.getMetadata().getContentDisposition() != null) {
+ request.getHeaders().put("Content-Disposition",
+ s3Object.getMetadata().getContentDisposition());
+ }
+
+ if (s3Object.getMetadata().getContentEncoding() != null) {
+ request.getHeaders().put(HttpHeaders.CONTENT_ENCODING,
+ s3Object.getMetadata().getContentEncoding());
+ }
+ }
+ super.addEntityToRequest(entity, request);
+ }
}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/RestS3ConnectionModule.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/RestS3ConnectionModule.java
index 3a267f82e5..b96402a156 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/RestS3ConnectionModule.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/RestS3ConnectionModule.java
@@ -28,7 +28,7 @@ import java.net.URI;
import javax.annotation.Resource;
-import org.jclouds.aws.s3.S3Connection;
+import org.jclouds.aws.s3.S3BlobStore;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.s3.handlers.AWSRedirectionRetryHandler;
@@ -85,8 +85,8 @@ public class RestS3ConnectionModule extends AbstractModule {
@Provides
@Singleton
- protected S3Connection provideS3Connection(URI uri, RestClientFactory factory) {
- return factory.create(uri, S3Connection.class);
+ protected S3BlobStore provideS3Connection(URI uri, RestClientFactory factory) {
+ return factory.create(uri, S3BlobStore.class);
}
protected void bindErrorHandlers() {
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/S3ContextModule.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/S3ContextModule.java
index 6d1885b85f..0ea9398fd2 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/S3ContextModule.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/S3ContextModule.java
@@ -23,31 +23,47 @@
*/
package org.jclouds.aws.s3.config;
-import org.jclouds.aws.s3.S3Connection;
+import org.jclouds.aws.s3.S3BlobStore;
import org.jclouds.aws.s3.S3Context;
+import org.jclouds.aws.s3.domain.ObjectMetadata;
+import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.internal.GuiceS3Context;
import org.jclouds.aws.s3.internal.LiveS3InputStreamMap;
import org.jclouds.aws.s3.internal.LiveS3ObjectMap;
+import org.jclouds.blobstore.functions.ParseBlobFromHeadersAndHttpContent.BlobFactory;
+import org.jclouds.blobstore.functions.ParseBlobMetadataFromHeaders.BlobMetadataFactory;
import com.google.inject.AbstractModule;
+import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryProvider;
/**
- * Configures the {@link S3Context}; requires {@link S3Connection} bound.
+ * Configures the {@link S3Context}; requires {@link S3BlobStore} bound.
*
* @author Adrian Cole
*/
public class S3ContextModule extends AbstractModule {
+ protected final TypeLiteral> objectMetadataFactoryLiteral = new TypeLiteral>() {
+ };
+ protected final TypeLiteral> objectFactoryLiteral = new TypeLiteral>() {
+ };
@Override
protected void configure() {
- this.requireBinding(S3Connection.class);
+ this.requireBinding(S3BlobStore.class);
bind(GuiceS3Context.S3ObjectMapFactory.class).toProvider(
FactoryProvider.newFactory(GuiceS3Context.S3ObjectMapFactory.class,
LiveS3ObjectMap.class));
bind(GuiceS3Context.S3InputStreamMapFactory.class).toProvider(
FactoryProvider.newFactory(GuiceS3Context.S3InputStreamMapFactory.class,
LiveS3InputStreamMap.class));
+ bind(objectMetadataFactoryLiteral).toProvider(
+ FactoryProvider.newFactory(objectMetadataFactoryLiteral,
+ new TypeLiteral() {
+ }));
+ bind(objectFactoryLiteral).toProvider(
+ FactoryProvider.newFactory(objectFactoryLiteral, new TypeLiteral() {
+ }));
bind(S3Context.class).to(GuiceS3Context.class);
}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/AccessControlList.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/AccessControlList.java
index 88e80c95d3..a89bb8a721 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/AccessControlList.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/AccessControlList.java
@@ -31,7 +31,6 @@ import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
-
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
@@ -50,7 +49,6 @@ import com.google.common.collect.Collections2;
* @see
*/
public class AccessControlList {
- public static final AccessControlList NOT_FOUND = new AccessControlList();
private CanonicalUser owner;
private final List grants = new ArrayList();
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/ArrayListBucketResponse.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/ArrayListBucketResponse.java
new file mode 100644
index 0000000000..af9d71beaa
--- /dev/null
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/ArrayListBucketResponse.java
@@ -0,0 +1,72 @@
+/**
+ *
+ * Copyright (C) 2009 Global Cloud Specialists, Inc.
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+package org.jclouds.aws.s3.domain;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ *
+ * @author Adrian Cole
+ *
+ */
+public class ArrayListBucketResponse extends org.jclouds.rest.ArrayBoundedList
+ implements ListBucketResponse {
+ /** The serialVersionUID */
+ private static final long serialVersionUID = -4475709781001190244L;
+ private final String bucketName;
+ private final String delimiter;
+ private final SortedSet commonPrefixes;
+ private final boolean truncated;
+
+ public ArrayListBucketResponse(String bucketName, List contents, String prefix,
+ String marker, int maxResults, String delimiter, boolean isTruncated,
+ SortedSet commonPrefixes) {
+ super(contents, prefix, marker, maxResults);
+ this.delimiter = delimiter;
+ this.bucketName = bucketName;
+ this.commonPrefixes = commonPrefixes;
+ this.truncated = isTruncated;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public SortedSet getCommonPrefixes() {
+ return commonPrefixes;
+ }
+
+ public String getBucketName() {
+ return bucketName;
+ }
+
+ public String getDelimiter() {
+ return delimiter;
+ }
+
+ public boolean isTruncated() {
+ return truncated;
+ }
+
+}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/BucketMetadata.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/BucketMetadata.java
new file mode 100644
index 0000000000..dbfbe1804d
--- /dev/null
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/BucketMetadata.java
@@ -0,0 +1,132 @@
+/**
+ *
+ * Copyright (C) 2009 Global Cloud Specialists, Inc.
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+package org.jclouds.aws.s3.domain;
+
+import org.jclouds.blobstore.domain.ContainerMetadata;
+import org.joda.time.DateTime;
+
+/**
+ * System metadata of the S3Bucket
+ *
+ * @author Adrian Cole
+ */
+public class BucketMetadata extends ContainerMetadata {
+ protected DateTime creationDate;
+
+ public DateTime getCreationDate() {
+ return creationDate;
+ }
+
+ public void setCreationDate(DateTime creationDate) {
+ this.creationDate = creationDate;
+ }
+
+ /**
+ * Location constraint of the bucket.
+ *
+ * @author Adrian Cole
+ * @see
+ */
+ public static enum LocationConstraint {
+ EU
+ }
+
+ private CanonicalUser canonicalUser;
+
+ public BucketMetadata(String name) {
+ super(name);
+ }
+
+ public BucketMetadata() {
+ super();
+ }
+
+ /**
+ * To comply with Amazon S3 requirements, bucket names must:
+ *
+ * Contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)
+ *
+ * Start with a number or letter
+ *
+ * Be between 3 and 255 characters long
+ *
+ * Not be in an IP address style (e.g., "192.168.5.4")
+ */
+ @Override
+ public void setName(String name) {
+ // note that we cannot enforce this, as invalid buckets may already exist
+ super.setName(name);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Metadata [canonicalUser=").append(canonicalUser).append("]");
+ return builder.toString();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Every bucket and object in Amazon S3 has an owner, the user that created the bucket or
+ * object. The owner of a bucket or object cannot be changed. However, if the object is
+ * overwritten by another user (deleted and rewritten), the new object will have a new owner.
+ */
+ public CanonicalUser getOwner() {
+ return canonicalUser;
+ }
+
+ public void setOwner(CanonicalUser canonicalUser) {
+ this.canonicalUser = canonicalUser;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((canonicalUser == null) ? 0 : canonicalUser.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BucketMetadata other = (BucketMetadata) obj;
+ if (canonicalUser == null) {
+ if (other.canonicalUser != null)
+ return false;
+ } else if (!canonicalUser.equals(other.canonicalUser))
+ return false;
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/CanonicalUser.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/CanonicalUser.java
index b38861c321..c4d9f2e387 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/CanonicalUser.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/CanonicalUser.java
@@ -54,8 +54,8 @@ public class CanonicalUser {
/**
* To locate the CanonicalUser ID for a user, the user must perform the
- * {@link org.jclouds.aws.s3.S3Connection#listBucket(String)} and retrieve
- * {@link S3Bucket.Metadata#getOwner()}
+ * {@link org.jclouds.aws.s3.S3BlobStore#listBlobs(String)} and retrieve
+ * {@link BucketMetadata#getOwner()}
*/
public String getId() {
return id;
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/ListBucketResponse.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/ListBucketResponse.java
new file mode 100644
index 0000000000..c144f4deda
--- /dev/null
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/ListBucketResponse.java
@@ -0,0 +1,76 @@
+/**
+ *
+ * Copyright (C) 2009 Global Cloud Specialists, Inc.
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+package org.jclouds.aws.s3.domain;
+
+import java.util.SortedSet;
+
+/**
+ * A container that provides namespace, access control and aggregation of {@link S3Object}s
+ *
+ *
+ * Every object stored in Amazon S3 is contained in a bucket. Buckets partition the namespace of
+ * objects stored in Amazon S3 at the top level. Within a bucket, you can use any names for your
+ * objects, but bucket names must be unique across all of Amazon S3.
+ *
+ * Buckets are similar to Internet domain names. Just as Amazon is the only owner of the domain name
+ * Amazon.com, only one person or organization can own a bucket within Amazon S3. Once you create a
+ * uniquely named bucket in Amazon S3, you can organize and name the objects within the bucket in
+ * any way you like and the bucket will remain yours for as long as you like and as long as you have
+ * the Amazon S3 account.
+ *
+ * The similarities between buckets and domain names is not a coincidencethere is a direct mapping
+ * between Amazon S3 buckets and subdomains of s3.amazonaws.com. Objects stored in Amazon S3 are
+ * addressable using the REST API under the domain bucketname.s3.amazonaws.com. For example, if the
+ * object homepage.html?is stored in the Amazon S3 bucket mybucket its address would be
+ * http://mybucket.s3.amazonaws.com/homepage.html?
+ *
+ * @author Adrian Cole
+ * @see
+ */
+public interface ListBucketResponse extends org.jclouds.rest.BoundedList {
+
+ /**
+ * Example:
+ *
+ * if the following keys are in the bucket
+ *
+ * a/1/a
+ * a/1/b
+ * a/2/a
+ * a/2/b
+ *
+ * and prefix is set to a/
and delimiter is set to /
then
+ * commonprefixes would return 1,2
+ *
+ * @see org.jclouds.aws.s3.options.ListBucketOptions#getPrefix()
+ */
+ public SortedSet getCommonPrefixes();
+
+ public String getBucketName();
+
+ public String getDelimiter();
+
+ public boolean isTruncated();
+
+}
\ No newline at end of file
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/ObjectMetadata.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/ObjectMetadata.java
new file mode 100644
index 0000000000..b2041c6393
--- /dev/null
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/ObjectMetadata.java
@@ -0,0 +1,208 @@
+/**
+ *
+ * Copyright (C) 2009 Global Cloud Specialists, Inc.
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+package org.jclouds.aws.s3.domain;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import org.jclouds.blobstore.domain.BlobMetadata;
+
+/**
+ * /** Amazon S3 is designed to store objects. Objects are stored in {@link S3BucketListing buckets}
+ * and consist of a {@link org.jclouds.aws.s3.domain.S3Object#getData() value}, a
+ * {@link S3Object#getKey key}, {@link ObjectMetadata#getUserMetadata() metadata}, and an access
+ * control policy.
+ *
+ * @author Adrian Cole
+ * @see
+ */
+public class ObjectMetadata extends BlobMetadata implements Serializable {
+
+ /** The serialVersionUID */
+ private static final long serialVersionUID = -4415449798024051115L;
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Metadata [accessControlList=").append(accessControlList).append(
+ ", cacheControl=").append(cacheControl).append(", dataDisposition=").append(
+ dataDisposition).append(", owner=").append(owner).append(", storageClass=").append(
+ storageClass).append(", allHeaders=").append(allHeaders).append(", dataEncoding=")
+ .append(dataEncoding).append(", dataType=").append(dataType).append(", eTag=")
+ .append(Arrays.toString(eTag)).append(", key=").append(key)
+ .append(", lastModified=").append(lastModified).append(", size=").append(size)
+ .append(", userMetadata=").append(userMetadata).append("]");
+ return builder.toString();
+ }
+
+ private String cacheControl;
+ private String dataDisposition;
+ private AccessControlList accessControlList;
+
+ // only parsed on list
+ private CanonicalUser owner = null;
+ private String storageClass = null;
+ protected String dataEncoding;
+
+ public ObjectMetadata() {
+ super();
+ }
+
+ /**
+ * @param key
+ * @see #getKey()
+ */
+ public ObjectMetadata(String key) {
+ super(key);
+ }
+
+ public void setOwner(CanonicalUser owner) {
+ this.owner = owner;
+ }
+
+ /**
+ * Every bucket and object in Amazon S3 has an owner, the user that created the bucket or object.
+ * The owner of a bucket or object cannot be changed. However, if the object is overwritten by
+ * another user (deleted and rewritten), the new object will have a new owner.
+ */
+ public CanonicalUser getOwner() {
+ return owner;
+ }
+
+ public void setStorageClass(String storageClass) {
+ this.storageClass = storageClass;
+ }
+
+ /**
+ * Currently defaults to 'STANDARD' and not used.
+ */
+ public String getStorageClass() {
+ return storageClass;
+ }
+
+ public void setCacheControl(String cacheControl) {
+ this.cacheControl = cacheControl;
+ }
+
+ /**
+ * Can be used to specify caching behavior along the request/reply chain.
+ *
+ * @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.9.
+ */
+ public String getCacheControl() {
+ return cacheControl;
+ }
+
+ public void setContentDisposition(String dataDisposition) {
+ this.dataDisposition = dataDisposition;
+ }
+
+ /**
+ * Specifies presentational information for the object.
+ *
+ * @see
+ */
+ public String getContentDisposition() {
+ return dataDisposition;
+ }
+
+ public void setAccessControlList(AccessControlList acl) {
+ this.accessControlList = acl;
+ }
+
+ public AccessControlList getAccessControlList() {
+ return this.accessControlList;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((accessControlList == null) ? 0 : accessControlList.hashCode());
+ result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
+ result = prime * result + ((dataDisposition == null) ? 0 : dataDisposition.hashCode());
+ result = prime * result + ((owner == null) ? 0 : owner.hashCode());
+ result = prime * result + ((storageClass == null) ? 0 : storageClass.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ObjectMetadata other = (ObjectMetadata) obj;
+ if (accessControlList == null) {
+ if (other.accessControlList != null)
+ return false;
+ } else if (!accessControlList.equals(other.accessControlList))
+ return false;
+ if (cacheControl == null) {
+ if (other.cacheControl != null)
+ return false;
+ } else if (!cacheControl.equals(other.cacheControl))
+ return false;
+ if (dataDisposition == null) {
+ if (other.dataDisposition != null)
+ return false;
+ } else if (!dataDisposition.equals(other.dataDisposition))
+ return false;
+ if (owner == null) {
+ if (other.owner != null)
+ return false;
+ } else if (!owner.equals(other.owner))
+ return false;
+ if (storageClass == null) {
+ if (other.storageClass != null)
+ return false;
+ } else if (!storageClass.equals(other.storageClass))
+ return false;
+ return true;
+ }
+
+ public int compareTo(ObjectMetadata o) {
+ return (this == o) ? 0 : getKey().compareTo(o.getKey());
+ }
+
+ public void setContentEncoding(String dataEncoding) {
+ this.dataEncoding = dataEncoding;
+ }
+
+ /**
+ * Specifies what content encodings have been applied to the object and thus what decoding
+ * mechanisms must be applied in order to obtain the media-type referenced by the Content-Type
+ * header field.
+ *
+ * @see
+ */
+ public String getContentEncoding() {
+ return dataEncoding;
+ }
+
+}
\ No newline at end of file
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/S3Bucket.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/S3Bucket.java
deleted file mode 100644
index 62e2d9b410..0000000000
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/S3Bucket.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.domain;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import org.joda.time.DateTime;
-
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-/**
- * A container that provides namespace, access control and aggregation of {@link S3Object}s
- *
- *
- * Every object stored in Amazon S3 is contained in a bucket. Buckets partition the namespace of
- * objects stored in Amazon S3 at the top level. Within a bucket, you can use any names for your
- * objects, but bucket names must be unique across all of Amazon S3.
- *
- * Buckets are similar to Internet domain names. Just as Amazon is the only owner of the domain name
- * Amazon.com, only one person or organization can own a bucket within Amazon S3. Once you create a
- * uniquely named bucket in Amazon S3, you can organize and name the objects within the bucket in
- * any way you like and the bucket will remain yours for as long as you like and as long as you have
- * the Amazon S3 account.
- *
- * The similarities between buckets and domain names is not a coincidencethere is a direct mapping
- * between Amazon S3 buckets and subdomains of s3.amazonaws.com. Objects stored in Amazon S3 are
- * addressable using the REST API under the domain bucketname.s3.amazonaws.com. For example, if the
- * object homepage.html?is stored in the Amazon S3 bucket mybucket its address would be
- * http://mybucket.s3.amazonaws.com/homepage.html?
- *
- * @author Adrian Cole
- * @see
- */
-public class S3Bucket {
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("S3Bucket");
- sb.append("{metadata=").append(metadata);
- sb.append(", isTruncated=").append(isTruncated);
- sb.append('}');
- return sb.toString();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o)
- return true;
- if (!(o instanceof S3Bucket))
- return false;
-
- S3Bucket s3Bucket = (S3Bucket) o;
-
- if (isTruncated != s3Bucket.isTruncated)
- return false;
- if (!metadata.equals(s3Bucket.metadata))
- return false;
- if (objects != null ? !objects.equals(s3Bucket.objects) : s3Bucket.objects != null)
- return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = objects != null ? objects.hashCode() : 0;
- result = 31 * result + metadata.hashCode();
- result = 31 * result + (isTruncated ? 1 : 0);
- return result;
- }
-
- /**
- * System metadata of the S3Bucket
- *
- * @author Adrian Cole
- */
- public static class Metadata {
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("Metadata");
- sb.append("{name='").append(name).append('\'');
- sb.append(", creationDate=").append(creationDate);
- sb.append(", canonicalUser=").append(canonicalUser);
- sb.append('}');
- return sb.toString();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o)
- return true;
- if (!(o instanceof Metadata))
- return false;
-
- Metadata metadata = (Metadata) o;
- if (canonicalUser != null ? !canonicalUser.equals(metadata.canonicalUser)
- : metadata.canonicalUser != null)
- return false;
- if (!name.equals(metadata.name))
- return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = name.hashCode();
- result = 31 * result + (canonicalUser != null ? canonicalUser.hashCode() : 0);
- return result;
- }
-
- /**
- * Location constraint of the bucket.
- *
- * @author Adrian Cole
- * @see
- */
- public static enum LocationConstraint {
- EU
- }
-
- private String name;
- private DateTime creationDate;
- private CanonicalUser canonicalUser;
-
- /**
- * @see #getName()
- */
- public Metadata(String name) {
- this.name = checkNotNull(name, "name");
- }
-
- public Metadata() {
- super();
- }
-
- /**
- * To comply with Amazon S3 requirements, bucket names must:
- *
- * Contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)
- *
- * Start with a number or letter
- *
- * Be between 3 and 255 characters long
- *
- * Not be in an IP address style (e.g., "192.168.5.4")
- */
- public void setName(String name) {
- this.name = checkNotNull(name, "name");
- }
-
- public String getName() {
- return name;
- }
-
- public DateTime getCreationDate() {
- return creationDate;
- }
-
- public void setCreationDate(DateTime creationDate) {
- this.creationDate = creationDate;
- }
-
- /**
- * Every bucket and object in Amazon S3 has an owner, the user that created the bucket or
- * object. The owner of a bucket or object cannot be changed. However, if the object is
- * overwritten by another user (deleted and rewritten), the new object will have a new owner.
- */
- public CanonicalUser getOwner() {
- return canonicalUser;
- }
-
- public void setOwner(CanonicalUser canonicalUser) {
- this.canonicalUser = canonicalUser;
- }
-
- }
-
- public static final S3Bucket NOT_FOUND = new S3Bucket("NOT_FOUND");
-
- private SortedSet objects = new TreeSet();
- private SortedSet commonPrefixes = new TreeSet();
- private String prefix;
- private String marker;
- private String delimiter;
- private long maxKeys;
- private final Metadata metadata;
-
- private boolean isTruncated;
-
- public S3Bucket() {
- this.metadata = new Metadata();
- }
-
- public S3Bucket(String name) {
- this.metadata = new Metadata(name);
- }
-
- public String getName() {
- return this.metadata.getName();
- }
-
- public S3Bucket(Metadata metadata) {
- this.metadata = checkNotNull(metadata, "metadata");
- }
-
- public void setName(String name) {
- this.metadata.setName(name);
- }
-
- /**
- * @see org.jclouds.aws.s3.S3Connection#listBucket(String)
- */
- public SortedSet getContents() {
- return objects;
- }
-
- public long getSize() {
- return objects.size();
- }
-
- public void setContents(SortedSet objects) {
- this.objects = objects;
- }
-
- /**
- * @return true, if the list contains all objects.
- */
- public boolean isTruncated() {
- return isTruncated;
- }
-
- public void setTruncated(boolean truncated) {
- isTruncated = truncated;
- }
-
- public Metadata getMetadata() {
- return metadata;
- }
-
- public void setCommonPrefixes(SortedSet commonPrefixes) {
- this.commonPrefixes = commonPrefixes;
- }
-
- /**
- * Example:
- *
- * if the following keys are in the bucket
- *
- * a/1/a
- * a/1/b
- * a/2/a
- * a/2/b
- *
- * and prefix is set to a/
and delimiter is set to /
then
- * commonprefixes would return 1,2
- *
- * @see org.jclouds.aws.s3.options.ListBucketOptions#getPrefix()
- */
- public SortedSet getCommonPrefixes() {
- return commonPrefixes;
- }
-
- public void setPrefix(String prefix) {
- this.prefix = prefix;
- }
-
- /**
- * return keys that start with this.
- *
- * @see org.jclouds.aws.s3.options.ListBucketOptions#getPrefix()
- */
- public String getPrefix() {
- return prefix;
- }
-
- public void setMaxKeys(long maxKeys) {
- this.maxKeys = maxKeys;
- }
-
- /**
- * @return maximum results of the bucket.
- * @see org.jclouds.aws.s3.options.ListBucketOptions#getMaxKeys()
- */
- public long getMaxKeys() {
- return maxKeys;
- }
-
- public void setMarker(String marker) {
- this.marker = marker;
- }
-
- /**
- * when set, bucket contains results whose keys are lexigraphically after marker.
- *
- * @see org.jclouds.aws.s3.options.ListBucketOptions#getMarker()
- */
- public String getMarker() {
- return marker;
- }
-
- public void setDelimiter(String delimiter) {
- this.delimiter = delimiter;
- }
-
- /**
- * when set, bucket results will not contain keys that have text following this delimiter.
- *
- * note that delimiter has no effect on prefix. prefix can contain the delimiter many times, or
- * not at all. delimiter only restricts after the prefix.
- *
- * @see org.jclouds.aws.s3.options.ListBucketOptions#getMarker()
- */
- public String getDelimiter() {
- return delimiter;
- }
-
-}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/S3Object.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/S3Object.java
index f18fdebdd3..b8ac36a26f 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/S3Object.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/domain/S3Object.java
@@ -23,22 +23,10 @@
*/
package org.jclouds.aws.s3.domain;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
+import org.jclouds.blobstore.domain.Blob;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.http.HttpUtils;
-import org.jclouds.http.HttpUtils.ETagInputStreamResult;
-import org.joda.time.DateTime;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
/**
* Amazon S3 is designed to store objects. Objects are stored in {@link S3Bucket buckets} and
@@ -50,413 +38,23 @@ import com.google.common.collect.Multimap;
* @see
*/
-public class S3Object {
- public static final S3Object NOT_FOUND = new S3Object(Metadata.NOT_FOUND);
+public class S3Object extends Blob {
- private Object data;
- private final Metadata metadata;
- private long contentLength = -1;
- private String contentRange;
-
- public S3Object(String key) {
- this(new Metadata(key));
+ public S3Object(ObjectMetadata metadata, Object data) {
+ super(metadata, data);
}
- public S3Object(Metadata metadata) {
- this.metadata = metadata;
- }
-
- public S3Object(Metadata metadata, Object data) {
- this(metadata);
- setData(data);
+ @Inject
+ public S3Object(@Assisted ObjectMetadata metadata) {
+ super(metadata);
}
public S3Object(String key, Object data) {
- this(key);
- setData(data);
+ this(new ObjectMetadata(key), data);
}
- /**
- * System and user Metadata for the {@link S3Object}.
- *
- * @author Adrian Cole
- * @see
- */
- public static class Metadata implements Comparable {
- public static final Metadata NOT_FOUND = new Metadata("NOT_FOUND");
-
- // parsed during list, head, or get
- private String key;
- private byte[] eTag;
- private volatile long size = -1;
-
- // only parsed during head or get
- private Multimap allHeaders = HashMultimap.create();
- private Multimap userMetadata = HashMultimap.create();
- private DateTime lastModified;
- private String dataType = MediaType.APPLICATION_OCTET_STREAM;
- private String cacheControl;
- private String dataDisposition;
- private String dataEncoding;
- private AccessControlList accessControlList;
-
- // only parsed on list
- private CanonicalUser owner = null;
- private String storageClass = null;
-
- public Metadata() {
- super();
- }
-
- /**
- * @param key
- * @see #getKey()
- */
- public Metadata(String key) {
- setKey(key);
- }
-
- public void setKey(String key) {
- checkNotNull(key, "key");
- checkArgument(!key.startsWith("/"), "keys cannot start with /");
- this.key = key;
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("Metadata");
- sb.append("{key='").append(key).append('\'');
- sb.append(", lastModified=").append(lastModified);
- sb.append(", eTag=").append(
- getETag() == null ? "null" : Arrays.asList(getETag()).toString());
- sb.append(", size=").append(size);
- sb.append(", dataType='").append(dataType).append('\'');
- sb.append('}');
- return sb.toString();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o)
- return true;
- if (!(o instanceof Metadata))
- return false;
-
- Metadata metadata = (Metadata) o;
-
- if (size != metadata.size)
- return false;
- if (dataType != null ? !dataType.equals(metadata.dataType) : metadata.dataType != null)
- return false;
- if (!key.equals(metadata.key))
- return false;
- if (lastModified != null ? !lastModified.equals(metadata.lastModified)
- : metadata.lastModified != null)
- return false;
- if (!Arrays.equals(getETag(), metadata.getETag()))
- return false;
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = key.hashCode();
- result = 31 * result + (lastModified != null ? lastModified.hashCode() : 0);
- result = 31 * result + (getETag() != null ? Arrays.hashCode(getETag()) : 0);
- result = 31 * result + (int) (size ^ (size >>> 32));
- result = 31 * result + (dataType != null ? dataType.hashCode() : 0);
- return result;
- }
-
- /**
- * The key is the handle that you assign to an object that allows you retrieve it later. A key
- * is a sequence of Unicode characters whose UTF-8 encoding is at most 1024 bytes long. Each
- * object in a bucket must have a unique key.
- *
- * @see
- */
- public String getKey() {
- return key;
- }
-
- public DateTime getLastModified() {
- return lastModified;
- }
-
- public void setLastModified(DateTime lastModified) {
- this.lastModified = lastModified;
- }
-
- /**
- * The size of the object, in bytes.
- *
- * @see
- */
- public long getSize() {
- return size;
- }
-
- public void setSize(long size) {
- this.size = size;
- }
-
- /**
- * A standard MIME type describing the format of the contents. If none is provided, the
- * default is binary/octet-stream.
- *
- * @see
- */
- public String getContentType() {
- return dataType;
- }
-
- public void setContentType(String dataType) {
- this.dataType = dataType;
- }
-
- public void setETag(byte[] eTag) {
- this.eTag = new byte[eTag.length];
- System.arraycopy(eTag, 0, this.eTag, 0, eTag.length);
- }
-
- /**
- * @return the eTag value stored in the Etag header returned by S3.
- */
- public byte[] getETag() {
- if (eTag != null) {
- byte[] retval = new byte[eTag.length];
- System.arraycopy(this.eTag, 0, retval, 0, eTag.length);
- return retval;
- } else {
- return null;
- }
- }
-
- public void setUserMetadata(Multimap userMetadata) {
- this.userMetadata = userMetadata;
- }
-
- /**
- * Any header starting with x-amz-meta-
is considered user metadata. It will be
- * stored with the object and returned when you retrieve the object. The total size of the
- * HTTP request, not including the body, must be less than 8 KB.
- */
- public Multimap getUserMetadata() {
- return userMetadata;
- }
-
- public void setOwner(CanonicalUser owner) {
- this.owner = owner;
- }
-
- /**
- * Every bucket and object in Amazon S3 has an owner, the user that created the bucket or
- * object. The owner of a bucket or object cannot be changed. However, if the object is
- * overwritten by another user (deleted and rewritten), the new object will have a new owner.
- */
- public CanonicalUser getOwner() {
- return owner;
- }
-
- public void setStorageClass(String storageClass) {
- this.storageClass = storageClass;
- }
-
- /**
- * Currently defaults to 'STANDARD' and not used.
- */
- public String getStorageClass() {
- return storageClass;
- }
-
- public void setCacheControl(String cacheControl) {
- this.cacheControl = cacheControl;
- }
-
- /**
- * Can be used to specify caching behavior along the request/reply chain.
- *
- * @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.9.
- */
- public String getCacheControl() {
- return cacheControl;
- }
-
- public void setContentDisposition(String dataDisposition) {
- this.dataDisposition = dataDisposition;
- }
-
- /**
- * Specifies presentational information for the object.
- *
- * @see
- */
- public String getContentDisposition() {
- return dataDisposition;
- }
-
- public void setContentEncoding(String dataEncoding) {
- this.dataEncoding = dataEncoding;
- }
-
- /**
- * Specifies what content encodings have been applied to the object and thus what decoding
- * mechanisms must be applied in order to obtain the media-type referenced by the Content-Type
- * header field.
- *
- * @see
- */
- public String getContentEncoding() {
- return dataEncoding;
- }
-
- public void setAllHeaders(Multimap allHeaders) {
- this.allHeaders = allHeaders;
- }
-
- public void setAccessControlList(AccessControlList acl) {
- this.accessControlList = acl;
- }
-
- public AccessControlList getAccessControlList() {
- return this.accessControlList;
- }
-
- /**
- * @return all http response headers associated with this S3Object
- */
- public Multimap getAllHeaders() {
- return allHeaders;
- }
-
- public int compareTo(Metadata o) {
- return (this == o) ? 0 : getKey().compareTo(o.getKey());
- }
- }
-
- /**
- * @see Metadata#getKey()
- */
- public String getKey() {
- return metadata.getKey();
- }
-
- /**
- * Sets entity for the request or the content from the response. If size isn't set, this will
- * attempt to discover it.
- *
- * @param data
- * typically InputStream for downloads, or File, byte [], String, or InputStream for
- * uploads.
- */
- public void setData(Object data) {
- this.data = checkNotNull(data, "data");
- if (getMetadata().getSize() == -1)
- this.getMetadata().setSize(HttpUtils.calculateSize(data));
- }
-
- /**
- * generate an MD5 Hash for the current data.
- *
- * Note
- *
- * If this is an InputStream, it will be converted to a byte array first.
- *
- * @throws IOException
- * if there is a problem generating the hash.
- */
- public void generateETag() throws IOException {
- checkState(data != null, "data");
- if (data instanceof InputStream) {
- ETagInputStreamResult result = HttpUtils.generateETagResult((InputStream) data);
- getMetadata().setSize(result.length);
- getMetadata().setETag(result.eTag);
- setData(result.data);
- } else {
- getMetadata().setETag(HttpUtils.eTag(data));
- }
- }
-
- /**
- * @return InputStream, if downloading, or whatever was set during {@link #setData(Object)}
- */
- public Object getData() {
- return data;
- }
-
- /**
- * @return System and User metadata relevant to this object.
- */
- public Metadata getMetadata() {
- return metadata;
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("S3Object");
- sb.append("{metadata=").append(metadata);
- sb.append('}');
- return sb.toString();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o)
- return true;
- if (!(o instanceof S3Object))
- return false;
-
- S3Object s3Object = (S3Object) o;
-
- if (data != null ? !data.equals(s3Object.data) : s3Object.data != null)
- return false;
- if (!metadata.equals(s3Object.metadata))
- return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = data != null ? data.hashCode() : 0;
- result = 31 * result + metadata.hashCode();
- return result;
- }
-
- public void setContentLength(long contentLength) {
- this.contentLength = contentLength;
- }
-
- /**
- * Returns the total size of the downloaded object, or the chunk that's available.
- *
- * Chunking is only used when
- * {@link org.jclouds.aws.s3.S3Connection#getObject(String, String, org.jclouds.aws.s3.commands.options.GetObjectOptions) }
- * is called with options like tail, range, or startAt.
- *
- * @return the length in bytes that can be be obtained from {@link #getData()}
- * @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
- * @see GetObjectOptions
- */
- public long getContentLength() {
- return contentLength;
- }
-
- public void setContentRange(String contentRange) {
- this.contentRange = contentRange;
- }
-
- /**
- * If this is not-null, {@link #getContentLength() } will the size of chunk of the S3Object
- * available via {@link #getData()}
- *
- * @see org.jclouds.http.HttpHeaders#CONTENT_RANGE
- * @see GetObjectOptions
- */
- public String getContentRange() {
- return contentRange;
+ public S3Object(String key) {
+ this(new ObjectMetadata(key));
}
}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignature.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignature.java
index 5c41120bbf..66cd421f44 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignature.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignature.java
@@ -150,7 +150,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter {
Set headers = new TreeSet(request.getHeaders().keySet());
for (String header : headers) {
if (header.startsWith("x-amz-")) {
- toSign.append(header).append(":");
+ toSign.append(header.toLowerCase()).append(":");
for (String value : request.getHeaders().get(header))
toSign.append(value.replaceAll("\r?\n", "")).append(",");
toSign.deleteCharAt(toSign.lastIndexOf(","));
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ParseObjectFromHeadersAndHttpContent.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ParseObjectFromHeadersAndHttpContent.java
index ee06caa552..fd798b38ad 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ParseObjectFromHeadersAndHttpContent.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ParseObjectFromHeadersAndHttpContent.java
@@ -23,14 +23,10 @@
*/
package org.jclouds.aws.s3.functions;
-import javax.ws.rs.core.HttpHeaders;
-
+import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
-import org.jclouds.http.HttpException;
-import org.jclouds.http.HttpResponse;
+import org.jclouds.blobstore.functions.ParseBlobFromHeadersAndHttpContent;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
import com.google.inject.Inject;
/**
@@ -39,45 +35,13 @@ import com.google.inject.Inject;
* @see ParseMetadataFromHeaders
* @author Adrian Cole
*/
-public class ParseObjectFromHeadersAndHttpContent implements Function {
- private final ParseMetadataFromHeaders metadataParser;
+public class ParseObjectFromHeadersAndHttpContent extends ParseBlobFromHeadersAndHttpContent {
@Inject
- public ParseObjectFromHeadersAndHttpContent(ParseMetadataFromHeaders metadataParser) {
- this.metadataParser = metadataParser;
+ public ParseObjectFromHeadersAndHttpContent(
+ ParseObjectMetadataFromHeaders metadataParser,
+ BlobFactory blobFactory) {
+ super(metadataParser, blobFactory);
}
-
- /**
- * First, calls {@link ParseMetadataFromHeaders}.
- *
- * Then, sets the object size based on the Content-Length header and adds the content to the
- * {@link S3Object} result.
- *
- * @throws org.jclouds.http.HttpException
- */
- public S3Object apply(HttpResponse from) {
- S3Object.Metadata metadata = metadataParser.apply(from);
- S3Object object = new S3Object(metadata, from.getContent());
- parseContentLengthOrThrowException(from, object);
- return object;
- }
-
- @VisibleForTesting
- void parseContentLengthOrThrowException(HttpResponse from, S3Object object) throws HttpException {
- String contentLength = from.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH);
- String contentRange = from.getFirstHeaderOrNull("Content-Range");
- if (contentLength == null)
- throw new HttpException(HttpHeaders.CONTENT_LENGTH + " header not present in headers: "
- + from.getHeaders());
- object.setContentLength(Long.parseLong(contentLength));
-
- if (contentRange == null) {
- object.getMetadata().setSize(object.getContentLength());
- } else {
- object.setContentRange(contentRange);
- object.getMetadata().setSize(
- Long.parseLong(contentRange.substring(contentRange.lastIndexOf('/') + 1)));
- }
- }
-
+
}
\ No newline at end of file
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ParseObjectMetadataFromHeaders.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ParseObjectMetadataFromHeaders.java
new file mode 100644
index 0000000000..a703d89ff1
--- /dev/null
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ParseObjectMetadataFromHeaders.java
@@ -0,0 +1,84 @@
+/**
+ *
+ * Copyright (C) 2009 Global Cloud Specialists, Inc.
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+package org.jclouds.aws.s3.functions;
+
+import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
+
+import javax.ws.rs.core.HttpHeaders;
+
+import org.jclouds.aws.s3.domain.ObjectMetadata;
+import org.jclouds.aws.s3.reference.S3Headers;
+import org.jclouds.blobstore.functions.ParseBlobMetadataFromHeaders;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpUtils;
+import org.jclouds.util.DateService;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+/**
+ * This parses @{link {@link org.jclouds.aws.s3.domain.ObjectMetadata} from HTTP headers.
+ *
+ * @see
+ * @author Adrian Cole
+ */
+public class ParseObjectMetadataFromHeaders extends ParseBlobMetadataFromHeaders {
+
+ @Inject
+ public ParseObjectMetadataFromHeaders(DateService dateParser,
+ @Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix,
+ BlobMetadataFactory metadataFactory) {
+ super(dateParser, metadataPrefix, metadataFactory);
+ }
+
+ /**
+ * parses the http response headers to create a new
+ * {@link org.jclouds.aws.s3.domain.ObjectMetadata} object.
+ */
+ @Override
+ public ObjectMetadata apply(HttpResponse from) {
+ ObjectMetadata to = super.apply(from);
+ to.setCacheControl(from.getFirstHeaderOrNull(HttpHeaders.CACHE_CONTROL));
+ to.setContentDisposition(from.getFirstHeaderOrNull("Content-Disposition"));
+ to.setContentEncoding(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_ENCODING));
+ return to;
+ }
+
+ /**
+ * ETag == Content-MD5
+ */
+ @VisibleForTesting
+ protected void addETagTo(HttpResponse from, ObjectMetadata metadata) {
+ super.addETagTo(from, metadata);
+ if (metadata.getETag() == null) {
+ String eTagHeader = from.getFirstHeaderOrNull(S3Headers.AMZ_MD5);
+ if (eTagHeader != null) {
+ metadata.setETag(HttpUtils.fromHexString(eTagHeader));
+ }
+ }
+ metadata.setContentMD5(metadata.getETag());
+ }
+
+}
\ No newline at end of file
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ReturnNotFoundIfBucketDoesntExist.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ReturnNotFoundIfBucketDoesntExist.java
deleted file mode 100644
index e16d8a945e..0000000000
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ReturnNotFoundIfBucketDoesntExist.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.functions;
-
-import org.jclouds.aws.AWSResponseException;
-import org.jclouds.aws.s3.domain.AccessControlList;
-
-import com.google.common.base.Function;
-
-public class ReturnNotFoundIfBucketDoesntExist implements Function {
-
- public AccessControlList apply(Exception from) {
- if (from != null && from instanceof AWSResponseException) {
- AWSResponseException responseException = (AWSResponseException) from;
- if ("NoSuchBucket".equals(responseException.getError().getCode())) {
- return AccessControlList.NOT_FOUND;
- }
- }
- return null;
- }
-}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ReturnNotFoundIfObjectDoesntExist.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ReturnNotFoundIfObjectDoesntExist.java
deleted file mode 100644
index e60949bc83..0000000000
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ReturnNotFoundIfObjectDoesntExist.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.functions;
-
-import org.jclouds.aws.AWSResponseException;
-import org.jclouds.aws.s3.domain.AccessControlList;
-
-import com.google.common.base.Function;
-
-public class ReturnNotFoundIfObjectDoesntExist implements Function {
-
- public AccessControlList apply(Exception from) {
- if (from != null && from instanceof AWSResponseException) {
- AWSResponseException responseException = (AWSResponseException) from;
- if ("NoSuchKey".equals(responseException.getError().getCode())) {
- return AccessControlList.NOT_FOUND;
- }
- }
- return null;
- }
-
-}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ReturnS3ObjectMetadataNotFoundOn404.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ReturnS3ObjectMetadataNotFoundOn404.java
deleted file mode 100644
index d829a3f5a5..0000000000
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/functions/ReturnS3ObjectMetadataNotFoundOn404.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.functions;
-
-import org.jclouds.aws.s3.domain.S3Object.Metadata;
-import org.jclouds.http.HttpResponseException;
-
-import com.google.common.base.Function;
-
-public class ReturnS3ObjectMetadataNotFoundOn404 implements Function {
-
- public Metadata apply(Exception from) {
- if (from instanceof HttpResponseException) {
- HttpResponseException responseException = (HttpResponseException) from;
- if (responseException.getResponse().getStatusCode() == 404) {
- return Metadata.NOT_FOUND;
- }
- }
- return null;
- }
-
-}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java
deleted file mode 100644
index 235280315a..0000000000
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.jclouds.aws.s3.S3Connection;
-import org.jclouds.aws.s3.S3Map;
-import org.jclouds.aws.s3.domain.S3Bucket;
-import org.jclouds.aws.s3.domain.S3Object;
-import org.jclouds.aws.s3.reference.S3Constants;
-import org.jclouds.util.Utils;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.inject.Inject;
-import com.google.inject.assistedinject.Assisted;
-import com.google.inject.name.Named;
-
-/**
- * Implements core Map functionality with an {@link S3Connection}
- *
- * All commands will wait a maximum of ${jclouds.s3.map.timeout} milliseconds to complete before
- * throwing an exception.
- *
- * @author Adrian Cole
- * @param
- * value of the map
- */
-public abstract class BaseS3Map implements S3Map {
-
- protected final S3Connection connection;
- protected final String bucket;
-
- /**
- * maximum duration of an S3 Request
- */
- @Inject(optional = true)
- @Named(S3Constants.PROPERTY_OBJECTMAP_TIMEOUT)
- protected long requestTimeoutMilliseconds = 10000;
-
- /**
- * time to pause before retrying a transient failure
- */
- @Inject(optional = true)
- @Named(S3Constants.PROPERTY_OBJECTMAP_RETRY)
- protected long requestRetryMilliseconds = 10;
-
- @Inject
- public BaseS3Map(S3Connection connection, @Assisted String bucket) {
- this.connection = checkNotNull(connection, "connection");
- this.bucket = checkNotNull(bucket, "bucketName");
- }
-
- /**
- * {@inheritDoc}
- *
- * This returns the number of keys in the {@link S3Bucket}
- *
- * @see S3Bucket#getContents()
- */
- public int size() {
- try {
- S3Bucket bucket = refreshBucket();
- Set contents = bucket.getContents();
- return contents.size();
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException("Error getting size of bucketName" + bucket, e);
- }
- }
-
- protected boolean containsETag(byte[] eTag) throws InterruptedException, ExecutionException,
- TimeoutException {
- for (S3Object.Metadata metadata : refreshBucket().getContents()) {
- if (Arrays.equals(eTag, metadata.getETag()))
- return true;
- }
- return false;
- }
-
- protected byte[] getETag(Object value) throws IOException, FileNotFoundException,
- InterruptedException, ExecutionException, TimeoutException {
- S3Object object = null;
- if (value instanceof S3Object) {
- object = (S3Object) value;
- } else {
- object = new S3Object("dummy", value);
- }
- if (object.getMetadata().getETag() == null)
- object.generateETag();
- return object.getMetadata().getETag();
- }
-
- /**
- * attempts asynchronous gets on all objects.
- *
- * @see S3Connection#getObject(String, String)
- */
- protected Set getAllObjects() {
- Set objects = new HashSet();
- Set> futureObjects = new HashSet>();
- for (String key : keySet()) {
- futureObjects.add(connection.getObject(bucket, key));
- }
- for (Future futureObject : futureObjects) {
- try {
- ifNotFoundRetryOtherwiseAddToSet(futureObject, objects);
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException(String.format("Error getting value from bucket %1$s",
- bucket), e);
- }
-
- }
- return objects;
- }
-
- @VisibleForTesting
- void ifNotFoundRetryOtherwiseAddToSet(Future futureObject, Set objects)
- throws InterruptedException, ExecutionException, TimeoutException {
- for (int i = 0; i < 3; i++) {
- S3Object object = futureObject.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
- if (object != S3Object.NOT_FOUND) {
- objects.add(object);
- break;
- } else {
- Thread.sleep(requestRetryMilliseconds);
- }
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * Note that if value is an instance of InputStream, it will be read and closed following this
- * method. To reuse data from InputStreams, pass {@link java.io.InputStream}s inside
- * {@link S3Object}s
- */
- public boolean containsValue(Object value) {
- try {
- byte[] eTag = getETag(value);
- return containsETag(eTag);
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException(String.format(
- "Error searching for ETAG of value: [%2$s] in bucketName:%1$s", bucket, value), e);
- }
- }
-
- public static class S3RuntimeException extends RuntimeException {
- private static final long serialVersionUID = 1L;
-
- S3RuntimeException(String s) {
- super(s);
- }
-
- public S3RuntimeException(String s, Throwable throwable) {
- super(s, throwable);
- }
- }
-
- public void clear() {
- try {
- List> deletes = new ArrayList>();
- for (String key : keySet()) {
- deletes.add(connection.deleteObject(bucket, key));
- }
- for (Future isdeleted : deletes)
- if (!isdeleted.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)) {
- throw new S3RuntimeException("failed to delete entry");
- }
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException("Error clearing bucketName" + bucket, e);
- }
- }
-
- protected S3Bucket refreshBucket() throws InterruptedException, ExecutionException,
- TimeoutException {
- S3Bucket currentBucket = connection.listBucket(bucket).get(requestTimeoutMilliseconds,
- TimeUnit.MILLISECONDS);
- if (currentBucket == S3Bucket.NOT_FOUND)
- throw new S3RuntimeException("bucketName not found: " + bucket);
- else
- return currentBucket;
- }
-
- public Set keySet() {
- try {
- Set keys = new HashSet();
- for (S3Object.Metadata object : refreshBucket().getContents())
- keys.add(object.getKey());
- return keys;
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException("Error getting keys in bucketName: " + bucket, e);
- }
- }
-
- public boolean containsKey(Object key) {
- try {
- return connection.headObject(bucket, key.toString()) != S3Object.Metadata.NOT_FOUND;
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException(String.format("Error searching for %1$s:%2$s", bucket, key),
- e);
- }
- }
-
- public boolean isEmpty() {
- return keySet().size() == 0;
- }
-
- public S3Bucket getBucket() {
- try {
- return refreshBucket();
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException("Error getting bucketName" + bucket, e);
- }
- }
-}
\ No newline at end of file
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/GuiceS3Context.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/GuiceS3Context.java
index ad3224044b..9607109658 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/GuiceS3Context.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/GuiceS3Context.java
@@ -24,18 +24,23 @@
package org.jclouds.aws.s3.internal;
import java.io.IOException;
+import java.net.URI;
import javax.annotation.Resource;
-import org.jclouds.aws.s3.S3Connection;
+import org.jclouds.aws.s3.S3BlobStore;
import org.jclouds.aws.s3.S3Context;
-import org.jclouds.aws.s3.S3InputStreamMap;
-import org.jclouds.aws.s3.S3ObjectMap;
+import org.jclouds.aws.s3.domain.ObjectMetadata;
+import org.jclouds.aws.s3.domain.S3Object;
+import org.jclouds.aws.s3.reference.S3Constants;
+import org.jclouds.blobstore.BlobMap;
+import org.jclouds.blobstore.InputStreamMap;
import org.jclouds.lifecycle.Closer;
import org.jclouds.logging.Logger;
import com.google.inject.Inject;
import com.google.inject.Injector;
+import com.google.inject.name.Named;
/**
* Uses a Guice Injector to configure the objects served by S3Context methods.
@@ -45,11 +50,11 @@ import com.google.inject.Injector;
*/
public class GuiceS3Context implements S3Context {
public interface S3ObjectMapFactory {
- S3ObjectMap createMapView(String bucket);
+ BlobMap createMapView(String bucket);
}
public interface S3InputStreamMapFactory {
- S3InputStreamMap createMapView(String bucket);
+ InputStreamMap createMapView(String bucket);
}
@Resource
@@ -58,36 +63,41 @@ public class GuiceS3Context implements S3Context {
private final S3InputStreamMapFactory s3InputStreamMapFactory;
private final S3ObjectMapFactory s3ObjectMapFactory;
private final Closer closer;
+ private final String account;
+ private final URI endPoint;
@Inject
private GuiceS3Context(Injector injector, Closer closer, S3ObjectMapFactory s3ObjectMapFactory,
- S3InputStreamMapFactory s3InputStreamMapFactory) {
+ S3InputStreamMapFactory s3InputStreamMapFactory,
+ @Named(S3Constants.PROPERTY_AWS_ACCESSKEYID) String accessKey, URI endPoint) {
this.injector = injector;
this.s3InputStreamMapFactory = s3InputStreamMapFactory;
this.s3ObjectMapFactory = s3ObjectMapFactory;
this.closer = closer;
+ this.account = accessKey;
+ this.endPoint = endPoint;
}
/**
* {@inheritDoc}
*/
- public S3Connection getConnection() {
- return injector.getInstance(S3Connection.class);
+ public S3BlobStore getApi() {
+ return injector.getInstance(S3BlobStore.class);
}
/**
* {@inheritDoc}
*/
- public S3InputStreamMap createInputStreamMap(String bucket) {
- getConnection().putBucketIfNotExists(bucket);
+ public InputStreamMap createInputStreamMap(String bucket) {
+ getApi().createContainer(bucket);
return s3InputStreamMapFactory.createMapView(bucket);
}
/**
* {@inheritDoc}
*/
- public S3ObjectMap createS3ObjectMap(String bucket) {
- getConnection().putBucketIfNotExists(bucket);
+ public BlobMap createBlobMap(String bucket) {
+ getApi().createContainer(bucket);
return s3ObjectMapFactory.createMapView(bucket);
}
@@ -104,4 +114,48 @@ public class GuiceS3Context implements S3Context {
}
}
+ @Override
+ public String toString() {
+ return "GuiceS3Context [account=" + account + ", endPoint=" + endPoint + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((account == null) ? 0 : account.hashCode());
+ result = prime * result + ((endPoint == null) ? 0 : endPoint.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ GuiceS3Context other = (GuiceS3Context) obj;
+ if (account == null) {
+ if (other.account != null)
+ return false;
+ } else if (!account.equals(other.account))
+ return false;
+ if (endPoint == null) {
+ if (other.endPoint != null)
+ return false;
+ } else if (!endPoint.equals(other.endPoint))
+ return false;
+ return true;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public URI getEndPoint() {
+ return endPoint;
+ }
+
}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/LiveS3InputStreamMap.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/LiveS3InputStreamMap.java
index 3ec38d6b71..c35f04074f 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/LiveS3InputStreamMap.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/LiveS3InputStreamMap.java
@@ -23,259 +23,33 @@
*/
package org.jclouds.aws.s3.internal;
-import java.io.File;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-import org.jclouds.aws.s3.S3Connection;
-import org.jclouds.aws.s3.S3InputStreamMap;
+import org.jclouds.aws.s3.S3BlobStore;
+import org.jclouds.aws.s3.domain.BucketMetadata;
+import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
-import org.jclouds.util.Utils;
+import org.jclouds.blobstore.LiveInputStreamMap;
-import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
/**
- * Map representation of a live connection to S3. All put operations will result
- * in ETag calculation. If this is not desired, use {@link LiveS3ObjectMap}
- * instead.
- *
+ * Map representation of a live connection to S3. All put operations will result in ETag
+ * calculation. If this is not desired, use {@link LiveS3ObjectMap} instead.
+ *
* @author Adrian Cole
* @see S3Connection
* @see BaseS3Map
*/
-public class LiveS3InputStreamMap extends BaseS3Map implements
- S3InputStreamMap {
+public class LiveS3InputStreamMap extends
+ LiveInputStreamMap {
- @Inject
- public LiveS3InputStreamMap(S3Connection connection, @Assisted String bucket) {
- super(connection, bucket);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see S3Connection#getObject(String, String)
- */
- public InputStream get(Object o) {
- try {
- return (InputStream) (connection.getObject(bucket, o.toString())
- .get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS))
- .getData();
- } catch (Exception e) {
- Utils.rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException(String.format(
- "Error geting object %1$s:%2$s", bucket, o), e);
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see S3Connection#deleteObject(String, String)
- */
- public InputStream remove(Object o) {
- InputStream old = get(o);
- try {
- connection.deleteObject(bucket, o.toString()).get(
- requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- Utils.rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException(String.format(
- "Error removing object %1$s:%2$s", bucket, o), e);
- }
- return old;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #getAllObjects()
- */
- public Collection values() {
- Collection values = new LinkedList();
- Set objects = getAllObjects();
- for (S3Object object : objects) {
- values.add((InputStream) object.getData());
- }
- return values;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #getAllObjects()
- */
- public Set> entrySet() {
- Set> entrySet = new HashSet>();
- for (S3Object object : getAllObjects()) {
- entrySet.add(new Entry(object.getKey(), (InputStream) object
- .getData()));
- }
- return entrySet;
- }
-
- public class Entry implements java.util.Map.Entry {
-
- private InputStream value;
- private String key;
-
- Entry(String key, InputStream value) {
- this.key = key;
- this.value = value;
- }
-
- public String getKey() {
- return key;
- }
-
- public InputStream getValue() {
- return value;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see LiveS3InputStreamMap#put(String, InputStream)
- */
- public InputStream setValue(InputStream value) {
- return put(key, value);
- }
-
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #putAllInternal(Map)
- */
- public void putAll(Map extends String, ? extends InputStream> map) {
- putAllInternal(map);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #putAllInternal(Map)
- */
- public void putAllBytes(Map extends String, ? extends byte[]> map) {
- putAllInternal(map);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #putAllInternal(Map)
- */
- public void putAllFiles(Map extends String, ? extends File> map) {
- putAllInternal(map);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #putAllInternal(Map)
- */
- public void putAllStrings(Map extends String, ? extends String> map) {
- putAllInternal(map);
- }
-
- /**
- * submits requests to add all objects and collects the results later. All
- * values will have eTag calculated first. As a side-effect of this, the
- * content will be copied into a byte [].
- *
- * @see S3Connection#putObject(String, S3Object)
- */
- @VisibleForTesting
- void putAllInternal(Map extends String, ? extends Object> map) {
- try {
- List> puts = new ArrayList>();
- for (Map.Entry extends String, ? extends Object> entry : map.entrySet()) {
- S3Object object = new S3Object(entry.getKey());
- object.setData(entry.getValue());
- object.generateETag();
- puts.add(connection.putObject(bucket, object));
- /// ParamExtractor Funcion,String>
- /// response transformer set key on the way out.
- /// ExceptionHandler convert 404 to NOT_FOUND
- }
- for (Future put : puts)
- // this will throw an exception if there was a problem
- put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- Utils.rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException("Error putting into bucketName" + bucket,
- e);
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #putInternal(String, Object)
- */
- public InputStream putString(String key, String value) {
- return putInternal(key, value);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #putInternal(String, Object)
- */
- public InputStream putFile(String key, File value) {
- return putInternal(key, value);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #putInternal(String, Object)
- */
- public InputStream putBytes(String key, byte[] value) {
- return putInternal(key, value);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #putInternal(String, Object)
- */
- public InputStream put(String key, InputStream value) {
- return putInternal(key, value);
- }
-
- /**
- * calculates eTag before adding the object to s3. As a side-effect of this,
- * the content will be copied into a byte []. *
- *
- * @see S3Connection#putObject(String, S3Object)
- */
- @VisibleForTesting
- InputStream putInternal(String s, Object o) {
- S3Object object = new S3Object(s);
- try {
- InputStream returnVal = containsKey(s) ? get(s) : null;
- object.setData(o);
- object.generateETag();
- connection.putObject(bucket, object).get(
- requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
- return returnVal;
- } catch (Exception e) {
- Utils.rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException(String.format(
- "Error adding object %1$s:%2$s", bucket, object), e);
- }
- }
+ @Inject
+ public LiveS3InputStreamMap(S3BlobStore connection, @Assisted String container) {
+ super(connection, container);
+ }
+ @Override
+ protected S3Object createBlob(String s) {
+ return new S3Object(s);
+ }
}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/LiveS3ObjectMap.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/LiveS3ObjectMap.java
index ed28fc1192..c9df3a4253 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/LiveS3ObjectMap.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/LiveS3ObjectMap.java
@@ -23,19 +23,11 @@
*/
package org.jclouds.aws.s3.internal;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-import org.jclouds.aws.s3.S3Connection;
-import org.jclouds.aws.s3.S3ObjectMap;
+import org.jclouds.aws.s3.S3BlobStore;
+import org.jclouds.aws.s3.domain.BucketMetadata;
+import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
-import org.jclouds.util.Utils;
+import org.jclouds.blobstore.LiveBlobMap;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@@ -48,137 +40,11 @@ import com.google.inject.assistedinject.Assisted;
*
* @author Adrian Cole
*/
-public class LiveS3ObjectMap extends BaseS3Map implements S3ObjectMap {
+public class LiveS3ObjectMap extends LiveBlobMap {
- @Inject
- public LiveS3ObjectMap(S3Connection connection, @Assisted String bucket) {
- super(connection, bucket);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #values()
- */
- public Set> entrySet() {
- Set> entrySet = new HashSet>();
- for (S3Object value : values()) {
- Map.Entry entry = new Entry(value.getKey(), value);
- entrySet.add(entry);
- }
- return entrySet;
- }
-
- public class Entry implements java.util.Map.Entry {
-
- private S3Object value;
- private String key;
-
- Entry(String key, S3Object value) {
- this.key = key;
- this.value = value;
- }
-
- public String getKey() {
- return key;
- }
-
- public S3Object getValue() {
- return value;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see LiveS3ObjectMap#put(String, S3Object)
- */
- public S3Object setValue(S3Object value) {
- return put(key, value);
- }
-
- }
-
- /**
- * {@inheritDoc}
- *
- * @see S3Connection#getObject(String, String)
- */
- public S3Object get(Object key) {
- try {
- return connection.getObject(bucket, key.toString()).get(
- requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException(String.format(
- "Error geting object %1$s:%2$s", bucket, key), e);
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see S3Connection#putObject(String, S3Object)
- */
- public S3Object put(String key, S3Object value) {
- S3Object returnVal = get(key);
- try {
- connection.putObject(bucket, value).get(requestTimeoutMilliseconds,
- TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException(
- String.format("Error putting object %1$s:%2$s%n%3$s",
- bucket, key, value), e);
- }
- return returnVal;
- }
-
- /**
- * {@inheritDoc} attempts to put all objects asynchronously.
- *
- * @see S3Connection#putObject(String, S3Object)
- */
- public void putAll(Map extends String, ? extends S3Object> map) {
- try {
- List> puts = new ArrayList>();
- for (S3Object object : map.values()) {
- puts.add(connection.putObject(bucket, object));
- }
- for (Future put : puts)
- // this will throw an exception if there was a problem
- put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException("Error putting into bucketName" + bucket,
- e);
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see S3Connection#deleteObject(String, String)
- */
- public S3Object remove(Object key) {
- S3Object old = get(key);
- try {
- connection.deleteObject(bucket, key.toString()).get(
- requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- throw new S3RuntimeException(String.format(
- "Error removing object %1$s:%2$s", bucket, key), e);
- }
- return old;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #getAllObjects()
- */
- public Collection values() {
- return getAllObjects();
- }
+ @Inject
+ public LiveS3ObjectMap(S3BlobStore connection, @Assisted String container) {
+ super(connection, container);
+ }
}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/options/CopyObjectOptions.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/options/CopyObjectOptions.java
index 5fab528074..ac8c2605a3 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/options/CopyObjectOptions.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/options/CopyObjectOptions.java
@@ -23,9 +23,9 @@
*/
package org.jclouds.aws.s3.options;
-import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
+import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import java.io.UnsupportedEncodingException;
@@ -39,6 +39,8 @@ import org.joda.time.DateTime;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
/**
* Contains options supported in the REST API for the COPY object operation.
@@ -78,6 +80,13 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE;
+ private String metadataPrefix;
+
+ @Inject
+ public void setMetadataPrefix(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
+ this.metadataPrefix = metadataPrefix;
+ }
+
/**
* Override the default ACL (private) with the specified one.
*
@@ -245,10 +254,14 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
@Override
public Multimap buildRequestHeaders() {
+ checkState(metadataPrefix != null, "metadataPrefix should have been injected!");
Multimap returnVal = HashMultimap.create();
returnVal.putAll(headers);
if (metadata != null) {
- returnVal.putAll(metadata);
+ for (String key : metadata.keySet()) {
+ returnVal.putAll(key.startsWith(metadataPrefix) ? key : metadataPrefix + key, metadata
+ .get(key));
+ }
returnVal.put("x-amz-metadata-directive", "REPLACE");
}
return returnVal;
@@ -259,10 +272,6 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
*/
public CopyObjectOptions overrideMetadataWith(Multimap metadata) {
checkNotNull(metadata, "metadata");
- for (String header : metadata.keySet()) {
- checkArgument(header.startsWith("x-amz-meta-"),
- "Metadata keys must start with x-amz-meta-");
- }
this.metadata = metadata;
return this;
}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/options/PutBucketOptions.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/options/PutBucketOptions.java
index 83e1e80e08..f2050ea3c7 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/options/PutBucketOptions.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/options/PutBucketOptions.java
@@ -26,7 +26,7 @@ package org.jclouds.aws.s3.options;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.aws.s3.domain.CannedAccessPolicy;
-import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
+import org.jclouds.aws.s3.domain.BucketMetadata.LocationConstraint;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.http.options.BaseHttpRequestOptions;
@@ -88,7 +88,7 @@ public class PutBucketOptions extends BaseHttpRequestOptions {
}
/**
- * @see PutBucketOptions#createIn(org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint)
+ * @see PutBucketOptions#createIn(org.jclouds.aws.s3.domain.BucketMetadata.LocationConstraint)
*/
public LocationConstraint getLocationConstraint() {
return constraint;
@@ -96,7 +96,7 @@ public class PutBucketOptions extends BaseHttpRequestOptions {
public static class Builder {
/**
- * @see PutBucketOptions#createIn(org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint)
+ * @see PutBucketOptions#createIn(org.jclouds.aws.s3.domain.BucketMetadata.LocationConstraint)
*/
public static PutBucketOptions createIn(LocationConstraint constraint) {
PutBucketOptions options = new PutBucketOptions();
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/reference/S3Constants.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/reference/S3Constants.java
index 1a3e9051bd..6d2dd1ed7e 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/reference/S3Constants.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/reference/S3Constants.java
@@ -24,14 +24,14 @@
package org.jclouds.aws.s3.reference;
import org.jclouds.aws.reference.AWSConstants;
-import org.jclouds.keyvaluestore.reference.ObjectStoreConstants;
+import org.jclouds.blobstore.reference.BlobStoreConstants;
/**
* Configuration properties and constants used in S3 connections.
*
* @author Adrian Cole
*/
-public interface S3Constants extends AWSConstants, S3Headers, ObjectStoreConstants {
+public interface S3Constants extends AWSConstants, S3Headers, BlobStoreConstants {
/**
* S3 service's XML Namespace, as used in XML request and response documents.
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/reference/S3Headers.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/reference/S3Headers.java
index 9def3dd743..c2ea629316 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/reference/S3Headers.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/reference/S3Headers.java
@@ -40,12 +40,6 @@ public interface S3Headers {
* Policy.
*/
public static final String CANNED_ACL = "x-amz-acl";
- /**
- * Any header starting with this prefix is considered user metadata. It will be stored with the
- * object and returned when you retrieve the object. The total size of the HTTP request, not
- * including the body, must be less than 8 KB.
- */
- public static final String USER_METADATA_PREFIX = "x-amz-meta-";
public static final String AMZ_MD5 = "x-amz-meta-object-eTag";
public static final String REQUEST_ID = "x-amz-request-id";
public static final String REQUEST_TOKEN = "x-amz-id-2";
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/util/S3Utils.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/util/S3Utils.java
index 3c79ca6743..46512af7a9 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/util/S3Utils.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/util/S3Utils.java
@@ -27,19 +27,17 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.ByteArrayInputStream;
-import java.io.IOException;
import java.io.InputStream;
import org.jclouds.aws.domain.AWSError;
-import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.xml.S3ParserFactory;
+import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
-import org.jclouds.util.Utils;
import com.google.inject.Inject;
@@ -48,7 +46,7 @@ import com.google.inject.Inject;
*
* @author Adrian Cole
*/
-public class S3Utils {
+public class S3Utils extends BlobStoreUtils {
@Inject
RequestAuthorizeSignature signer;
@@ -86,19 +84,4 @@ public class S3Utils {
return bucketName;
}
- public static String getContentAsStringAndClose(S3Object object) throws IOException {
- checkNotNull(object, "s3Object");
- checkNotNull(object.getData(), "s3Object.content");
- Object o = object.getData();
-
- if (o instanceof InputStream) {
- String returnVal = Utils.toStringAndClose((InputStream) o);
- if (object.getMetadata().getContentType().indexOf("xml") >= 0) {
-
- }
- return returnVal;
- } else {
- throw new IllegalArgumentException("Object type not supported: " + o.getClass().getName());
- }
- }
}
\ No newline at end of file
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/CopyObjectHandler.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/CopyObjectHandler.java
index 8042e7f3d8..585411a801 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/CopyObjectHandler.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/CopyObjectHandler.java
@@ -23,7 +23,7 @@
*/
package org.jclouds.aws.s3.xml;
-import org.jclouds.aws.s3.domain.S3Object;
+import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.DateService;
@@ -38,14 +38,14 @@ import com.google.inject.Inject;
* @see
* @author Adrian Cole
*/
-public class CopyObjectHandler extends ParseSax.HandlerWithResult {
+public class CopyObjectHandler extends ParseSax.HandlerWithResult {
- private S3Object.Metadata metadata = new S3Object.Metadata();
+ private ObjectMetadata metadata = new ObjectMetadata();
private StringBuilder currentText = new StringBuilder();
@Inject
private DateService dateParser;
- public S3Object.Metadata getResult() {
+ public ObjectMetadata getResult() {
return metadata;
}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/ListAllMyBucketsHandler.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/ListAllMyBucketsHandler.java
index 6a0fa988da..28023658b8 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/ListAllMyBucketsHandler.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/ListAllMyBucketsHandler.java
@@ -27,7 +27,7 @@ import java.util.ArrayList;
import java.util.List;
import org.jclouds.aws.s3.domain.CanonicalUser;
-import org.jclouds.aws.s3.domain.S3Bucket;
+import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.DateService;
@@ -43,10 +43,10 @@ import com.google.inject.Inject;
* />
* @author Adrian Cole
*/
-public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult> {
+public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult> {
- private List buckets = new ArrayList();
- private S3Bucket.Metadata currentS3Bucket;
+ private List buckets = new ArrayList();
+ private BucketMetadata currentS3Bucket;
private CanonicalUser currentOwner;
private StringBuilder currentText = new StringBuilder();
@@ -57,7 +57,7 @@ public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult getResult() {
+ public List getResult() {
return buckets;
}
@@ -70,7 +70,7 @@ public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult
*/
-public class ListBucketHandler extends ParseSax.HandlerWithResult {
- private S3Bucket s3Bucket;
- private S3Object.Metadata currentObjectMetadata;
+public class ListBucketHandler extends ParseSax.HandlerWithResult {
+ private List contents;
+ private SortedSet commonPrefixes;
+ private ObjectMetadata currentObjectMetadata;
private CanonicalUser currentOwner;
private StringBuilder currentText = new StringBuilder();
private final DateService dateParser;
+ private String bucketName;
+ private String prefix;
+ private String marker;
+ private int maxResults;
+ private String delimiter;
+ private boolean isTruncated;
@Inject
public ListBucketHandler(DateService dateParser) {
this.dateParser = dateParser;
- this.s3Bucket = new S3Bucket();
+ this.contents = Lists.newArrayList();
+ this.commonPrefixes = new TreeSet();
}
- public S3Bucket getResult() {
- return s3Bucket;
+ public ListBucketResponse getResult() {
+ return new ArrayListBucketResponse(bucketName, contents, prefix, marker, maxResults,
+ delimiter, isTruncated, commonPrefixes);
}
private boolean inCommonPrefixes;
@@ -75,7 +90,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult {
} else if (qName.equals("DisplayName")) {
currentOwner.setDisplayName(currentText.toString());
} else if (qName.equals("Key")) { // content stuff
- currentObjectMetadata = new S3Object.Metadata(currentText.toString());
+ currentObjectMetadata = new ObjectMetadata(currentText.toString());
} else if (qName.equals("LastModified")) {
currentObjectMetadata.setLastModified(dateParser.iso8601DateParse(currentText.toString()));
} else if (qName.equals("ETag")) {
@@ -88,26 +103,25 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult {
} else if (qName.equals("StorageClass")) {
currentObjectMetadata.setStorageClass(currentText.toString());
} else if (qName.equals("Contents")) {
- s3Bucket.getContents().add(currentObjectMetadata);
+ contents.add(currentObjectMetadata);
} else if (qName.equals("Name")) {
- s3Bucket.setName(currentText.toString());
+ this.bucketName = currentText.toString();
} else if (qName.equals("Prefix")) {
String prefix = currentText.toString().trim();
if (inCommonPrefixes)
- s3Bucket.getCommonPrefixes().add(prefix);
+ commonPrefixes.add(prefix);
else
- s3Bucket.setPrefix(prefix);
+ this.prefix = prefix;
} else if (qName.equals("Delimiter")) {
if (!currentText.toString().equals(""))
- s3Bucket.setDelimiter(currentText.toString().trim());
+ this.delimiter = currentText.toString().trim();
} else if (qName.equals("Marker")) {
if (!currentText.toString().equals(""))
- s3Bucket.setMarker(currentText.toString());
+ this.marker = currentText.toString();
} else if (qName.equals("MaxKeys")) {
- s3Bucket.setMaxKeys(Long.parseLong(currentText.toString()));
+ this.maxResults = Integer.parseInt(currentText.toString());
} else if (qName.equals("IsTruncated")) {
- boolean isTruncated = Boolean.parseBoolean(currentText.toString());
- s3Bucket.setTruncated(isTruncated);
+ this.isTruncated = Boolean.parseBoolean(currentText.toString());
}
currentText = new StringBuilder();
}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/S3ParserFactory.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/S3ParserFactory.java
index 170cf2b6f5..66ccff09a0 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/S3ParserFactory.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/S3ParserFactory.java
@@ -27,8 +27,9 @@ import java.util.List;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.domain.AccessControlList;
-import org.jclouds.aws.s3.domain.S3Bucket;
-import org.jclouds.aws.s3.domain.S3Object;
+import org.jclouds.aws.s3.domain.BucketMetadata;
+import org.jclouds.aws.s3.domain.ListBucketResponse;
+import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.xml.ErrorHandler;
import org.jclouds.http.functions.ParseSax;
@@ -46,7 +47,7 @@ import com.google.inject.Provider;
public class S3ParserFactory {
@Inject
- private GenericParseFactory> parseListAllMyBucketsFactory;
+ private GenericParseFactory> parseListAllMyBucketsFactory;
@VisibleForTesting
public static interface GenericParseFactory {
@@ -59,12 +60,12 @@ public class S3ParserFactory {
/**
* @return a parser used to handle {@link org.jclouds.aws.s3.commands.ListOwnedBuckets} responses
*/
- public ParseSax> createListBucketsParser() {
+ public ParseSax> createListBucketsParser() {
return parseListAllMyBucketsFactory.create(ListAllMyBucketsHandlerprovider.get());
}
@Inject
- private GenericParseFactory parseListBucketFactory;
+ private GenericParseFactory parseListBucketFactory;
@Inject
Provider ListBucketHandlerprovider;
@@ -72,12 +73,12 @@ public class S3ParserFactory {
/**
* @return a parser used to handle {@link org.jclouds.aws.s3.commands.ListBucket} responses
*/
- public ParseSax createListBucketParser() {
+ public ParseSax createListBucketParser() {
return parseListBucketFactory.create(ListBucketHandlerprovider.get());
}
@Inject
- private GenericParseFactory parseCopyObjectFactory;
+ private GenericParseFactory parseCopyObjectFactory;
@Inject
Provider copyObjectHandlerProvider;
@@ -85,7 +86,7 @@ public class S3ParserFactory {
/**
* @return a parser used to handle {@link org.jclouds.aws.s3.commands.CopyObject} responses
*/
- public ParseSax createCopyObjectParser() {
+ public ParseSax createCopyObjectParser() {
return parseCopyObjectFactory.create(copyObjectHandlerProvider.get());
}
diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java
index bc6a3606f4..c465bfd05b 100644
--- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java
+++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java
@@ -27,8 +27,9 @@ import java.util.List;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.domain.AccessControlList;
-import org.jclouds.aws.s3.domain.S3Bucket;
-import org.jclouds.aws.s3.domain.S3Object;
+import org.jclouds.aws.s3.domain.BucketMetadata;
+import org.jclouds.aws.s3.domain.ListBucketResponse;
+import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.xml.AccessControlListHandler;
import org.jclouds.aws.s3.xml.CopyObjectHandler;
import org.jclouds.aws.s3.xml.ListAllMyBucketsHandler;
@@ -51,11 +52,11 @@ import com.google.inject.assistedinject.FactoryProvider;
public class S3ParserModule extends AbstractModule {
protected final TypeLiteral> errorTypeLiteral = new TypeLiteral>() {
};
- protected final TypeLiteral>> listBucketsTypeLiteral = new TypeLiteral>>() {
+ protected final TypeLiteral>> listBucketsTypeLiteral = new TypeLiteral>>() {
};
- protected final TypeLiteral> bucketTypeLiteral = new TypeLiteral>() {
+ protected final TypeLiteral> bucketTypeLiteral = new TypeLiteral>() {
};
- protected final TypeLiteral> objectMetadataTypeLiteral = new TypeLiteral>() {
+ protected final TypeLiteral> objectMetadataTypeLiteral = new TypeLiteral>() {
};
protected final TypeLiteral> accessControlListTypeLiteral = new TypeLiteral>() {
};
@@ -73,11 +74,11 @@ public class S3ParserModule extends AbstractModule {
}
private void bindParserImplementationsToReturnTypes() {
- bind(new TypeLiteral>>() {
+ bind(new TypeLiteral>>() {
}).to(ListAllMyBucketsHandler.class);
- bind(new TypeLiteral>() {
+ bind(new TypeLiteral>() {
}).to(ListBucketHandler.class);
- bind(new TypeLiteral>() {
+ bind(new TypeLiteral>() {
}).to(CopyObjectHandler.class);
bind(new TypeLiteral>() {
}).to(AccessControlListHandler.class);
@@ -86,14 +87,15 @@ public class S3ParserModule extends AbstractModule {
private void bindCallablesThatReturnParseResults() {
bind(listBucketsTypeLiteral).toProvider(
FactoryProvider.newFactory(listBucketsTypeLiteral,
- new TypeLiteral>>() {
+ new TypeLiteral>>() {
}));
bind(bucketTypeLiteral).toProvider(
- FactoryProvider.newFactory(bucketTypeLiteral, new TypeLiteral>() {
+ FactoryProvider.newFactory(bucketTypeLiteral,
+ new TypeLiteral>() {
}));
bind(objectMetadataTypeLiteral).toProvider(
FactoryProvider.newFactory(objectMetadataTypeLiteral,
- new TypeLiteral>() {
+ new TypeLiteral>() {
}));
bind(accessControlListTypeLiteral).toProvider(
FactoryProvider.newFactory(accessControlListTypeLiteral,
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3ContextBuilderTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3ContextBuilderTest.java
index 755f952369..a4fd2b064c 100644
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3ContextBuilderTest.java
+++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3ContextBuilderTest.java
@@ -25,21 +25,29 @@ package org.jclouds.aws.s3;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
+import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_ADDRESS;
import static org.testng.Assert.assertEquals;
+import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.jclouds.aws.s3.config.RestS3ConnectionModule;
import org.jclouds.aws.s3.config.S3ContextModule;
+import org.jclouds.aws.s3.domain.ObjectMetadata;
+import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.internal.GuiceS3Context;
import org.jclouds.aws.s3.xml.config.S3ParserModule;
+import org.jclouds.blobstore.functions.ParseBlobFromHeadersAndHttpContent.BlobFactory;
+import org.jclouds.blobstore.functions.ParseBlobMetadataFromHeaders.BlobMetadataFactory;
import org.jclouds.cloud.CloudContext;
import org.testng.annotations.Test;
import com.google.inject.Injector;
+import com.google.inject.Key;
import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
/**
* Tests behavior of modules configured in S3ContextBuilder
@@ -51,20 +59,31 @@ public class S3ContextBuilderTest {
public void testNewBuilder() {
S3ContextBuilder builder = S3ContextBuilder.newBuilder("id", "secret");
+ assertEquals(builder.getProperties().getProperty(PROPERTY_USER_METADATA_PREFIX),
+ "x-amz-meta-");
assertEquals(builder.getProperties().getProperty(PROPERTY_HTTP_ADDRESS), "s3.amazonaws.com");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_ACCESSKEYID), "id");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_SECRETACCESSKEY), "secret");
}
public void testBuildContext() {
- CloudContext context = S3ContextBuilder.newBuilder("id", "secret")
+ CloudContext context = S3ContextBuilder.newBuilder("id", "secret")
.buildContext();
assertEquals(context.getClass(), GuiceS3Context.class);
+ assertEquals(context.getAccount(), "id");
+ assertEquals(context.getEndPoint(), URI.create("https://s3.amazonaws.com:443"));
}
public void testBuildInjector() {
Injector i = S3ContextBuilder.newBuilder("id", "secret").buildInjector();
assert i.getInstance(S3Context.class) != null;
+
+ assert i.getInstance(GuiceS3Context.S3ObjectMapFactory.class) != null;
+ assert i.getInstance(GuiceS3Context.S3InputStreamMapFactory.class) != null;
+ assert i.getInstance(Key.get(new TypeLiteral>() {
+ })) != null;
+ assert i.getInstance(Key.get(new TypeLiteral>() {
+ })) != null;
}
protected void testAddParserModule() {
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java
deleted file mode 100644
index 2e9164d385..0000000000
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java
+++ /dev/null
@@ -1,355 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3;
-
-import static org.jclouds.aws.s3.options.PutBucketOptions.Builder.createIn;
-import static org.testng.Assert.assertEquals;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.jclouds.aws.s3.config.StubS3ConnectionModule;
-import org.jclouds.aws.s3.domain.S3Bucket;
-import org.jclouds.aws.s3.domain.S3Object;
-import org.jclouds.aws.s3.domain.S3Bucket.Metadata;
-import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
-import org.jclouds.aws.s3.reference.S3Constants;
-import org.jclouds.aws.s3.util.S3Utils;
-import org.jclouds.http.HttpUtils;
-import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
-import org.jclouds.logging.log4j.config.Log4JLoggingModule;
-import org.jclouds.util.Utils;
-import org.testng.ITestContext;
-import org.testng.annotations.AfterGroups;
-import org.testng.annotations.BeforeGroups;
-import org.testng.annotations.Optional;
-import org.testng.annotations.Parameters;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import com.google.inject.Module;
-
-public class S3IntegrationTest {
- protected static final String LOCAL_ENCODING = System.getProperty("file.encoding");
- protected static final String TEST_STRING = " ";
- protected static final String sysAWSAccessKeyId = System
- .getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID);
- protected static final String sysAWSSecretAccessKey = System
- .getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
-
- public static long INCONSISTENCY_WINDOW = 1000;
- protected static int bucketCount = 20;
- protected static volatile int bucketIndex = 0;
-
- protected byte[] goodETag;
- protected byte[] badETag;
- protected S3Connection client;
- protected S3Context context = null;
- protected boolean SANITY_CHECK_RETURNED_BUCKET_NAME = false;
- private String bucketPrefix = System.getProperty("user.name") + ".s3int";
-
- /**
- * two test groups integration and live.
- */
- private static final BlockingQueue bucketNames = new ArrayBlockingQueue(
- bucketCount);
-
- /**
- * Due to eventual consistency, bucket commands may not return correctly immediately. Hence, we
- * will try up to the inconsistency window to see if the assertion completes.
- */
- protected void assertEventually(Runnable assertion) throws InterruptedException {
- AssertionError error = null;
- for (int i = 0; i < 5; i++) {
- try {
- assertion.run();
- return;
- } catch (AssertionError e) {
- error = e;
- }
- Thread.sleep(INCONSISTENCY_WINDOW / 5);
- }
- if (error != null)
- throw error;
- }
-
- protected void createBucketAndEnsureEmpty(String bucketName) throws InterruptedException,
- ExecutionException, TimeoutException {
- client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS);
- emptyBucket(bucketName);
- }
-
- protected void addObjectToBucket(String sourceBucket, String key) throws InterruptedException,
- ExecutionException, TimeoutException, IOException {
- S3Object sourceObject = new S3Object(key);
- sourceObject.getMetadata().setContentType("text/xml");
- sourceObject.setData(TEST_STRING);
- addObjectToBucket(sourceBucket, sourceObject);
- }
-
- protected void addObjectToBucket(String sourceBucket, S3Object object)
- throws InterruptedException, ExecutionException, TimeoutException, IOException {
- client.putObject(sourceBucket, object).get(10, TimeUnit.SECONDS);
- }
-
- protected S3Object validateContent(String sourceBucket, String key) throws InterruptedException,
- ExecutionException, TimeoutException, IOException {
- assertEventuallyBucketSize(sourceBucket, 1);
- S3Object newObject = client.getObject(sourceBucket, key).get(10, TimeUnit.SECONDS);
- assert newObject != S3Object.NOT_FOUND;
- assertEquals(S3Utils.getContentAsStringAndClose(newObject), TEST_STRING);
- return newObject;
- }
-
- protected void assertEventuallyBucketSize(final String bucketName, final int count)
- throws InterruptedException {
- assertEventually(new Runnable() {
- public void run() {
- try {
- assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS).getContents()
- .size(), count);
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- }
- }
- });
- }
-
- @BeforeGroups(groups = { "integration", "live" })
- @Parameters( { S3Constants.PROPERTY_AWS_ACCESSKEYID, S3Constants.PROPERTY_AWS_SECRETACCESSKEY })
- public void setUpCredentials(@Optional String AWSAccessKeyId,
- @Optional String AWSSecretAccessKey, ITestContext testContext) throws Exception {
- AWSAccessKeyId = AWSAccessKeyId != null ? AWSAccessKeyId : sysAWSAccessKeyId;
- AWSSecretAccessKey = AWSSecretAccessKey != null ? AWSSecretAccessKey : sysAWSSecretAccessKey;
- if (AWSAccessKeyId != null)
- testContext.setAttribute(S3Constants.PROPERTY_AWS_ACCESSKEYID, AWSAccessKeyId);
- if (AWSSecretAccessKey != null)
- testContext.setAttribute(S3Constants.PROPERTY_AWS_SECRETACCESSKEY, AWSSecretAccessKey);
- }
-
- @BeforeGroups(dependsOnMethods = { "setUpCredentials" }, groups = { "integration", "live" })
- public void setUpClient(ITestContext testContext) throws Exception {
- if (testContext.getAttribute(S3Constants.PROPERTY_AWS_ACCESSKEYID) != null) {
- String AWSAccessKeyId = (String) testContext
- .getAttribute(S3Constants.PROPERTY_AWS_ACCESSKEYID);
- String AWSSecretAccessKey = (String) testContext
- .getAttribute(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
- createLiveS3Context(AWSAccessKeyId, AWSSecretAccessKey);
- } else {
- createStubS3Context();
- }
- client = context.getConnection();
- assert client != null;
- goodETag = HttpUtils.eTag(TEST_STRING);
- badETag = HttpUtils.eTag("alf");
- }
-
- protected void createStubS3Context() {
- context = S3ContextFactory.createS3Context("stub", "stub", new StubS3ConnectionModule());
- SANITY_CHECK_RETURNED_BUCKET_NAME = true;
- }
-
- protected void createLiveS3Context(String AWSAccessKeyId, String AWSSecretAccessKey) {
- context = buildS3ContextFactory(AWSAccessKeyId, AWSSecretAccessKey).buildContext();
- }
-
- public String getBucketName() throws InterruptedException, ExecutionException, TimeoutException {
- String bucketName = bucketNames.poll(30, TimeUnit.SECONDS);
- assert bucketName != null : "unable to get a bucket for the test";
- emptyBucket(bucketName);
- return bucketName;
- }
-
- /**
- * a bucket that should be deleted and recreated after the test is complete. This is due to
- * having an ACL or otherwise that makes it not compatible with normal buckets
- */
- public String getScratchBucketName() throws InterruptedException, ExecutionException,
- TimeoutException {
- return getBucketName();
- }
-
- public void returnBucket(final String bucketName) throws InterruptedException,
- ExecutionException, TimeoutException {
- if (bucketName != null) {
- bucketNames.add(bucketName);
- /*
- * Ensure that any returned bucket name actually exists on the server. Return of a
- * non-existent bucket introduces subtle testing bugs, where later unrelated tests will
- * fail.
- *
- * NOTE: This sanity check should only be run for Stub-based Integration testing -- it will
- * *substantially* slow down tests on a real server over a network.
- */
- if (SANITY_CHECK_RETURNED_BUCKET_NAME) {
- if (!Iterables.any(client.listOwnedBuckets(), new Predicate() {
- public boolean apply(Metadata md) {
- return bucketName.equals(md.getName());
- }
- })) {
- throw new IllegalStateException("Test returned the name of a non-existent bucket: "
- + bucketName);
- }
- }
- }
- }
-
- /**
- * abandon old bucket name instead of waiting for the bucket to be created.
- */
- public void returnScratchBucket(String scratchBucket) throws InterruptedException,
- ExecutionException, TimeoutException {
- if (scratchBucket != null) {
- deleteBucket(scratchBucket);
- String newScratchBucket = bucketPrefix + (++bucketIndex);
- createBucketAndEnsureEmpty(newScratchBucket);
- returnBucket(newScratchBucket);
- }
- }
-
- /**
- * There are a lot of retries here mainly from experience running inside amazon EC2.
- */
- @BeforeGroups(dependsOnMethods = { "setUpClient" }, groups = { "integration", "live" })
- public void setUpBuckets(ITestContext context) throws Exception {
- synchronized (bucketNames) {
- if (bucketNames.peek() == null) {
- deleteEverything();
- for (; bucketIndex < bucketCount; bucketIndex++) {
- String bucketName = bucketPrefix + bucketIndex;
- try {
- createBucketAndEnsureEmpty(bucketName);
- bucketNames.put(bucketName);
- } catch (AssertionError e) {
- // throw away the bucket and try again with the next index
- deleteBucket(bucketName);
- bucketCount++;
- }
- }
- }
- }
- }
-
- protected S3ContextBuilder buildS3ContextFactory(String AWSAccessKeyId, String AWSSecretAccessKey) {
- return (S3ContextBuilder) S3ContextBuilder.newBuilder(AWSAccessKeyId, AWSSecretAccessKey)
- .withSaxDebug().relaxSSLHostname().withModule(new Log4JLoggingModule());
- }
-
- protected Module createHttpModule() {
- return new JavaUrlHttpCommandExecutorServiceModule();
- }
-
- protected void deleteEverything() throws Exception {
- try {
- List metadata = client.listOwnedBuckets();
- for (S3Bucket.Metadata metaDatum : metadata) {
- if (metaDatum.getName().startsWith(bucketPrefix.toLowerCase())) {
- deleteBucket(metaDatum.getName());
- }
- }
- } catch (CancellationException e) {
- throw e;
- }
- }
-
- /**
- * Remove any objects in a bucket, leaving it empty.
- */
- protected void emptyBucket(final String name) throws InterruptedException, ExecutionException,
- TimeoutException {
- if (client.bucketExists(name)) {
- // This can fail to be zero length because of stale bucket lists. Ex. client.listBucket()
- // could return 9 keys, when there are 10. When all the deletions finish, one entry would
- // be left in this case. Instead of failing, we will attempt this entire bucket deletion
- // operation multiple times to ensure we can acheive a zero length bucket.
- assertEventually(new Runnable() {
- public void run() {
- try {
- Map map = context.createInputStreamMap(name);
- Set keys = map.keySet();
- if (keys.size() > 0) {
- map.clear();
- assertEquals(map.size(), 0, String.format(
- "deleting %s, we still have %s left in bucket %s, using encoding %s",
- keys, map.keySet(), name, LOCAL_ENCODING));
- }
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- }
- }
- });
-
- }
- }
-
- protected String createScratchBucketInEU() throws InterruptedException, ExecutionException,
- TimeoutException {
- String bucketName = getScratchBucketName();
- deleteBucket(bucketName);
- client.putBucketIfNotExists(bucketName, createIn(LocationConstraint.EU)).get(10,
- TimeUnit.SECONDS);
- return bucketName;
- }
-
- /**
- * Empty and delete a bucket.
- *
- * @param name
- * @throws InterruptedException
- * @throws ExecutionException
- * @throws TimeoutException
- */
- protected void deleteBucket(final String name) throws InterruptedException, ExecutionException,
- TimeoutException {
- if (client.bucketExists(name)) {
- emptyBucket(name);
- client.deleteBucketIfEmpty(name);
- assertEventually(new Runnable() {
- public void run() {
- try {
- assert !client.bucketExists(name) : "bucket " + name + " still exists";
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- }
- }
- });
- }
- }
-
- @AfterGroups(groups = { "integration", "live" })
- protected void tearDownClient() throws Exception {
- context.close();
- context = null;
- }
-
-}
\ No newline at end of file
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/CopyObjectIntegrationTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/CopyObjectIntegrationTest.java
deleted file mode 100644
index a66368cfd7..0000000000
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/CopyObjectIntegrationTest.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.commands;
-
-import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceETagDoesntMatch;
-import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceETagMatches;
-import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceModifiedSince;
-import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceUnmodifiedSince;
-import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.overrideMetadataWith;
-import static org.testng.Assert.assertEquals;
-
-import java.io.IOException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.jclouds.aws.s3.S3IntegrationTest;
-import org.jclouds.aws.s3.domain.S3Object;
-import org.jclouds.aws.s3.reference.S3Headers;
-import org.jclouds.http.HttpResponseException;
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-
-/**
- * Tests integrated functionality of all copyObject commands.
- *
- * Each test uses a different bucket name, so it should be perfectly fine to run in parallel.
- *
- * @author Adrian Cole
- */
-@Test(testName = "s3.CopyObjectIntegrationTest")
-public class CopyObjectIntegrationTest extends S3IntegrationTest {
- String sourceKey = "apples";
- String destinationKey = "pears";
-
- @Test(groups = { "integration", "live" })
- void testCopyObject() throws Exception {
- String bucketName = getBucketName();
- String destinationBucket = getScratchBucketName();
-
- try {
- addToBucketAndValidate(bucketName, sourceKey);
-
- client.copyObject(bucketName, sourceKey, destinationBucket, destinationKey).get(10,
- TimeUnit.SECONDS);
-
- validateContent(destinationBucket, destinationKey);
- } finally {
- returnBucket(bucketName);
- returnScratchBucket(destinationBucket);
-
- }
- }
-
- private void addToBucketAndValidate(String bucketName, String sourceKey)
- throws InterruptedException, ExecutionException, TimeoutException, IOException {
- addObjectToBucket(bucketName, sourceKey);
- validateContent(bucketName, sourceKey);
- }
-
- @Test(enabled = false, groups = { "integration", "live" })
- // TODO: fails on linux and windows
- void testCopyIfModifiedSince() throws InterruptedException, ExecutionException,
- TimeoutException, IOException {
- String bucketName = getBucketName();
- String destinationBucket = getScratchBucketName();
- try {
- DateTime before = new DateTime();
- addToBucketAndValidate(bucketName, sourceKey);
- DateTime after = new DateTime().plusSeconds(1);
-
- client.copyObject(bucketName, sourceKey, destinationBucket, destinationKey,
- ifSourceModifiedSince(before)).get(10, TimeUnit.SECONDS);
- validateContent(destinationBucket, destinationKey);
-
- try {
- client.copyObject(bucketName, sourceKey, destinationBucket, destinationKey,
- ifSourceModifiedSince(after)).get(10, TimeUnit.SECONDS);
- } catch (ExecutionException e) {
- HttpResponseException ex = (HttpResponseException) e.getCause();
- assertEquals(ex.getResponse().getStatusCode(), 412);
- }
- } finally {
- returnBucket(bucketName);
- returnScratchBucket(destinationBucket);
-
- }
- }
-
- @Test(enabled = false, groups = { "integration", "live" })
- // TODO: fails on linux and windows
- void testCopyIfUnmodifiedSince() throws InterruptedException, ExecutionException,
- TimeoutException, IOException {
- String bucketName = getBucketName();
- String destinationBucket = getScratchBucketName();
- try {
- DateTime before = new DateTime();
- addToBucketAndValidate(bucketName, sourceKey);
- DateTime after = new DateTime().plusSeconds(1);
-
- client.copyObject(bucketName, sourceKey, destinationBucket, destinationKey,
- ifSourceUnmodifiedSince(after)).get(10, TimeUnit.SECONDS);
- validateContent(destinationBucket, destinationKey);
-
- try {
- client.copyObject(bucketName, sourceKey, destinationBucket, destinationKey,
- ifSourceModifiedSince(before)).get(10, TimeUnit.SECONDS);
- } catch (ExecutionException e) {
- HttpResponseException ex = (HttpResponseException) e.getCause();
- assertEquals(ex.getResponse().getStatusCode(), 412);
- }
- } finally {
- returnBucket(bucketName);
- returnScratchBucket(destinationBucket);
- }
- }
-
- @Test(groups = { "integration", "live" })
- void testCopyIfMatch() throws InterruptedException, ExecutionException, TimeoutException,
- IOException {
- String bucketName = getBucketName();
- String destinationBucket = getScratchBucketName();
- try {
- addToBucketAndValidate(bucketName, sourceKey);
-
- client.copyObject(bucketName, sourceKey, destinationBucket, destinationKey,
- ifSourceETagMatches(goodETag)).get(10, TimeUnit.SECONDS);
- validateContent(destinationBucket, destinationKey);
-
- try {
- client.copyObject(bucketName, sourceKey, destinationBucket, destinationKey,
- ifSourceETagMatches(badETag)).get(10, TimeUnit.SECONDS);
- } catch (ExecutionException e) {
- HttpResponseException ex = (HttpResponseException) e.getCause();
- assertEquals(ex.getResponse().getStatusCode(), 412);
- }
- } finally {
- returnBucket(bucketName);
- returnScratchBucket(destinationBucket);
- }
- }
-
- @Test(groups = { "integration", "live" })
- void testCopyIfNoneMatch() throws IOException, InterruptedException, ExecutionException,
- TimeoutException {
- String bucketName = getBucketName();
- String destinationBucket = getScratchBucketName();
- try {
- addToBucketAndValidate(bucketName, sourceKey);
-
- client.copyObject(bucketName, sourceKey, destinationBucket, destinationKey,
- ifSourceETagDoesntMatch(badETag)).get(10, TimeUnit.SECONDS);
- validateContent(destinationBucket, destinationKey);
-
- try {
- client.copyObject(bucketName, sourceKey, destinationBucket, destinationKey,
- ifSourceETagDoesntMatch(goodETag)).get(10, TimeUnit.SECONDS);
- } catch (ExecutionException e) {
- HttpResponseException ex = (HttpResponseException) e.getCause();
- assertEquals(ex.getResponse().getStatusCode(), 412);
- }
- } finally {
- returnBucket(bucketName);
- returnScratchBucket(destinationBucket);
-
- }
- }
-
- @Test(groups = { "integration", "live" })
- void testCopyWithMetadata() throws InterruptedException, ExecutionException, TimeoutException,
- IOException {
- String bucketName = getBucketName();
- String destinationBucket = getScratchBucketName();
- try {
- addToBucketAndValidate(bucketName, sourceKey);
-
- Multimap metadata = HashMultimap.create();
- metadata.put(S3Headers.USER_METADATA_PREFIX + "adrian", "cole");
-
- client.copyObject(bucketName, sourceKey, destinationBucket, destinationKey,
- overrideMetadataWith(metadata)).get(10, TimeUnit.SECONDS);
-
- validateContent(destinationBucket, destinationKey);
-
- S3Object.Metadata objectMeta = client.headObject(destinationBucket, destinationKey);
-
- assertEquals(objectMeta.getUserMetadata(), metadata);
- } finally {
- returnBucket(bucketName);
- returnScratchBucket(destinationBucket);
-
- }
- }
-
-}
\ No newline at end of file
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/DeleteBucketIntegrationTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/DeleteBucketIntegrationTest.java
deleted file mode 100644
index 977506ce37..0000000000
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/DeleteBucketIntegrationTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.commands;
-
-import org.jclouds.aws.s3.S3IntegrationTest;
-import org.jclouds.util.Utils;
-import org.testng.annotations.Test;
-
-/**
- * Tests integrated functionality of all deleteBucket commands.
- *
- * Each test uses a different bucket name, so it should be perfectly fine to run in parallel.
- *
- * @author Adrian Cole
- */
-@Test(groups = { "integration", "live" }, testName = "s3.DeleteBucketIntegrationTest")
-public class DeleteBucketIntegrationTest extends S3IntegrationTest {
-
- /**
- * this method overrides bucketName to ensure it isn't found
- */
- @Test
- void deleteBucketIfEmptyNotFound() throws Exception {
- assert client.deleteBucketIfEmpty("dbienf");
- }
-
- @Test
- void deleteBucketIfEmptyButHasContents() throws Exception {
- String bucketName = getBucketName();
- try {
- addObjectToBucket(bucketName, "test");
- assert !client.deleteBucketIfEmpty(bucketName);
- } finally {
- returnBucket(bucketName);
- }
- }
-
- @Test
- void deleteBucketIfEmpty() throws Exception {
- final String bucketName = getScratchBucketName();
- try {
- assert client.deleteBucketIfEmpty(bucketName);
-
- assertEventually(new Runnable() {
- public void run() {
- try {
- assert !client.bucketExists(bucketName) : "bucket " + bucketName
- + " still exists";
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- }
- }
- });
- } finally {
- returnScratchBucket(bucketName);
- }
- }
-}
\ No newline at end of file
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/DeleteObjectIntegrationTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/DeleteObjectIntegrationTest.java
deleted file mode 100644
index 897abc1bbc..0000000000
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/DeleteObjectIntegrationTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.commands;
-
-import static org.testng.Assert.assertEquals;
-
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.jclouds.aws.AWSResponseException;
-import org.jclouds.aws.s3.S3IntegrationTest;
-import org.jclouds.aws.s3.domain.S3Bucket;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-/**
- * Tests integrated functionality of all deleteObject commands.
- *
- * Each test uses a different bucket name, so it should be perfectly fine to run in parallel.
- *
- * @author Adrian Cole
- */
-@Test(groups = { "integration", "live" }, testName = "s3.DeleteObjectIntegrationTest")
-public class DeleteObjectIntegrationTest extends S3IntegrationTest {
-
- @Test
- void deleteObjectNotFound() throws Exception {
- String bucketName = getBucketName();
- String key = "test";
- try {
- assert client.deleteObject(bucketName, key).get(10, TimeUnit.SECONDS);
- } finally {
- returnBucket(bucketName);
- }
- }
-
- @DataProvider(name = "delete")
- public Object[][] createData() {
- return new Object[][] { { "sp ace" }, { "unicde" }, { "qu?stion" } };
- }
-
- @Test(dataProvider = "delete")
- void deleteObject(String key) throws Exception {
- String bucketName = getBucketName();
- try {
- addObjectToBucket(bucketName, key);
- assert client.deleteObject(bucketName, key).get(10, TimeUnit.SECONDS);
- assertBucketEmptyDeleting(bucketName, key);
- } finally {
- returnBucket(bucketName);
- }
- }
-
- private void assertBucketEmptyDeleting(String bucketName, String key)
- throws InterruptedException, ExecutionException, TimeoutException {
- S3Bucket listing = client.listBucket(bucketName).get(10, TimeUnit.SECONDS);
- assertEquals(listing.getContents().size(), 0, String.format(
- "deleting %s, we still have %s left in bucket %s, using encoding %s", key, listing
- .getContents().size(), bucketName, LOCAL_ENCODING));
- }
-
- @Test
- void deleteObjectNoBucket() throws Exception {
- try {
- client.deleteObject("donb", "test").get(10, TimeUnit.SECONDS);
- } catch (ExecutionException e) {
- assert e.getCause() instanceof AWSResponseException;
- assertEquals(((AWSResponseException) e.getCause()).getResponse().getStatusCode(), 404);
- }
- }
-
-}
\ No newline at end of file
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/GetAccessControlListIntegrationTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/GetAccessControlListIntegrationTest.java
deleted file mode 100644
index 984e52d1cf..0000000000
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/GetAccessControlListIntegrationTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.commands;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
-import java.io.IOException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.jclouds.aws.s3.S3IntegrationTest;
-import org.jclouds.aws.s3.domain.AccessControlList;
-import org.jclouds.aws.s3.domain.CannedAccessPolicy;
-import org.jclouds.aws.s3.domain.S3Object;
-import org.jclouds.aws.s3.domain.AccessControlList.GroupGranteeURI;
-import org.jclouds.aws.s3.domain.AccessControlList.Permission;
-import org.jclouds.aws.s3.options.PutObjectOptions;
-import org.jclouds.util.Utils;
-import org.testng.annotations.Test;
-
-/**
- * Tests integrated functionality of all commands that retrieve Access Control Lists (ACLs).
- *
- * @author James Murty
- * @author Adrian Cole
- */
-@Test(groups = { "integration", "live" }, testName = "s3.GetAccessControlListIntegrationTest")
-public class GetAccessControlListIntegrationTest extends S3IntegrationTest {
-
- @Test
- void testPrivateAclIsDefaultForBucket() throws InterruptedException, ExecutionException,
- TimeoutException, IOException {
- String bucketName = getBucketName();
- try {
- AccessControlList acl = client.getBucketACL(bucketName).get(10, TimeUnit.SECONDS);
- assertEquals(acl.getGrants().size(), 1);
- assertTrue(acl.getOwner() != null);
- String ownerId = acl.getOwner().getId();
- assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL));
- } finally {
- returnBucket(bucketName);
- }
-
- }
-
- @Test
- void testPrivateAclIsDefaultForObject() throws InterruptedException, ExecutionException,
- TimeoutException, IOException {
- String privateObjectKey = "private-acl";
- String bucketName = getBucketName();
- try {
- // Private object
- addObjectToBucket(bucketName, privateObjectKey);
- AccessControlList acl = client.getObjectACL(bucketName, privateObjectKey).get(10,
- TimeUnit.SECONDS);
-
- assertEquals(acl.getGrants().size(), 1);
- assertTrue(acl.getOwner() != null);
- String ownerId = acl.getOwner().getId();
- assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL));
- } finally {
- returnBucket(bucketName);
- }
-
- }
-
- @Test
- void testPublicReadOnObject() throws InterruptedException, ExecutionException, TimeoutException,
- IOException {
- final String publicReadObjectKey = "public-read-acl";
- final String bucketName = getBucketName();
- try {
- client.putObject(bucketName, new S3Object(publicReadObjectKey, ""), new PutObjectOptions()
- .withAcl(CannedAccessPolicy.PUBLIC_READ));
-
- assertEventually(new Runnable() {
- public void run() {
- try {
- AccessControlList acl = client.getObjectACL(bucketName, publicReadObjectKey).get(
- 10, TimeUnit.SECONDS);
-
- assertEquals(acl.getGrants().size(), 2);
- assertEquals(acl.getPermissions(GroupGranteeURI.ALL_USERS).size(), 1);
- assertTrue(acl.getOwner() != null);
- String ownerId = acl.getOwner().getId();
- assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL));
- assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ));
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- }
- }
- });
-
- } finally {
- returnBucket(bucketName);
- }
-
- }
-
- @Test
- void testPublicWriteOnObject() throws InterruptedException, ExecutionException,
- TimeoutException, IOException {
- final String publicReadWriteObjectKey = "public-read-write-acl";
- final String bucketName = getBucketName();
- try {
- // Public Read-Write object
- client.putObject(bucketName, new S3Object(publicReadWriteObjectKey, ""),
- new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ_WRITE));
-
- assertEventually(new Runnable() {
- public void run() {
- try {
- AccessControlList acl = client.getObjectACL(bucketName, publicReadWriteObjectKey)
- .get(10, TimeUnit.SECONDS);
- assertEquals(acl.getGrants().size(), 3);
- assertEquals(acl.getPermissions(GroupGranteeURI.ALL_USERS).size(), 2);
- assertTrue(acl.getOwner() != null);
- String ownerId = acl.getOwner().getId();
- assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL));
- assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ));
- assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.WRITE));
- assertFalse(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ_ACP));
- assertFalse(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.WRITE_ACP));
- assertFalse(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.FULL_CONTROL));
- } catch (Exception e) {
- Utils. rethrowIfRuntimeOrSameType(e);
- }
- }
- });
- } finally {
- returnBucket(bucketName);
- }
-
- }
-}
\ No newline at end of file
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/GetObjectIntegrationTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/GetObjectIntegrationTest.java
deleted file mode 100644
index afa25747e1..0000000000
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/GetObjectIntegrationTest.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.commands;
-
-import static org.jclouds.http.options.GetOptions.Builder.ifETagDoesntMatch;
-import static org.jclouds.http.options.GetOptions.Builder.ifETagMatches;
-import static org.jclouds.http.options.GetOptions.Builder.ifModifiedSince;
-import static org.jclouds.http.options.GetOptions.Builder.ifUnmodifiedSince;
-import static org.jclouds.http.options.GetOptions.Builder.range;
-import static org.jclouds.http.options.GetOptions.Builder.startAt;
-import static org.jclouds.http.options.GetOptions.Builder.tail;
-import static org.testng.Assert.assertEquals;
-
-import java.io.IOException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.jclouds.aws.s3.S3IntegrationTest;
-import org.jclouds.aws.s3.domain.S3Object;
-import org.jclouds.aws.s3.util.S3Utils;
-import org.jclouds.http.HttpResponseException;
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-
-/**
- * Tests integrated functionality of all GetObject commands.
- *
- * Each test uses a different bucket name, so it should be perfectly fine to run in parallel.
- *
- * @author Adrian Cole
- */
-@Test(groups = { "integration", "live" }, testName = "s3.GetObjectIntegrationTest")
-public class GetObjectIntegrationTest extends S3IntegrationTest {
-
- @Test
- void testGetIfModifiedSince() throws InterruptedException, ExecutionException, TimeoutException,
- IOException {
- String bucketName = getBucketName();
- try {
- String key = "apples";
-
- DateTime before = new DateTime();
- addObjectAndValidateContent(bucketName, key);
- DateTime after = new DateTime().plusSeconds(1);
-
- client.getObject(bucketName, key, ifModifiedSince(before)).get(10, TimeUnit.SECONDS);
- validateContent(bucketName, key);
-
- try {
- client.getObject(bucketName, key, ifModifiedSince(after)).get(10, TimeUnit.SECONDS);
- validateContent(bucketName, key);
- } catch (ExecutionException e) {
- if (e.getCause() instanceof HttpResponseException) {
- HttpResponseException ex = (HttpResponseException) e.getCause();
- assertEquals(ex.getResponse().getStatusCode(), 304);
- } else if (e.getCause() instanceof RuntimeException) {
- // TODO enhance stub connection so that it throws the correct error
- } else {
- throw e;
- }
- }
- } finally {
- returnBucket(bucketName);
- }
-
- }
-
- @Test
- void testGetIfUnmodifiedSince() throws InterruptedException, ExecutionException,
- TimeoutException, IOException {
- String bucketName = getBucketName();
- try {
-
- String key = "apples";
-
- DateTime before = new DateTime();
- addObjectAndValidateContent(bucketName, key);
- DateTime after = new DateTime().plusSeconds(1);
-
- client.getObject(bucketName, key, ifUnmodifiedSince(after)).get(10, TimeUnit.SECONDS);
- validateContent(bucketName, key);
-
- try {
- client.getObject(bucketName, key, ifUnmodifiedSince(before)).get(10, TimeUnit.SECONDS);
- validateContent(bucketName, key);
- } catch (ExecutionException e) {
- if (e.getCause() instanceof HttpResponseException) {
- HttpResponseException ex = (HttpResponseException) e.getCause();
- assertEquals(ex.getResponse().getStatusCode(), 412);
- } else if (e.getCause() instanceof RuntimeException) {
- // TODO enhance stub connection so that it throws the correct error
- } else {
- throw e;
- }
- }
- } finally {
- returnBucket(bucketName);
- }
- }
-
- @Test
- void testGetIfMatch() throws InterruptedException, ExecutionException, TimeoutException,
- IOException {
- String bucketName = getBucketName();
- try {
-
- String key = "apples";
-
- addObjectAndValidateContent(bucketName, key);
-
- client.getObject(bucketName, key, ifETagMatches(goodETag)).get(10, TimeUnit.SECONDS);
- validateContent(bucketName, key);
-
- try {
- client.getObject(bucketName, key, ifETagMatches(badETag)).get(10, TimeUnit.SECONDS);
- validateContent(bucketName, key);
- } catch (ExecutionException e) {
- if (e.getCause() instanceof HttpResponseException) {
- HttpResponseException ex = (HttpResponseException) e.getCause();
- assertEquals(ex.getResponse().getStatusCode(), 412);
- } else if (e.getCause() instanceof RuntimeException) {
- // TODO enhance stub connection so that it throws the correct error
- } else {
- throw e;
- }
- }
- } finally {
- returnBucket(bucketName);
- }
- }
-
- @Test
- void testGetIfNoneMatch() throws InterruptedException, ExecutionException, TimeoutException,
- IOException {
- String bucketName = getBucketName();
- try {
-
- String key = "apples";
-
- addObjectAndValidateContent(bucketName, key);
-
- client.getObject(bucketName, key, ifETagDoesntMatch(badETag)).get(10, TimeUnit.SECONDS);
- validateContent(bucketName, key);
-
- try {
- client.getObject(bucketName, key, ifETagDoesntMatch(goodETag)).get(10, TimeUnit.SECONDS);
- validateContent(bucketName, key);
- } catch (ExecutionException e) {
- if (e.getCause() instanceof HttpResponseException) {
- HttpResponseException ex = (HttpResponseException) e.getCause();
- assertEquals(ex.getResponse().getStatusCode(), 304);
- } else {
- throw e;
- }
- }
- } finally {
- returnBucket(bucketName);
- }
- }
-
- @Test
- void testGetRange() throws InterruptedException, ExecutionException, TimeoutException,
- IOException {
- String bucketName = getBucketName();
- try {
-
- String key = "apples";
-
- addObjectAndValidateContent(bucketName, key);
- S3Object object1 = client.getObject(bucketName, key, range(0, 5))
- .get(10, TimeUnit.SECONDS);
- assertEquals(S3Utils.getContentAsStringAndClose(object1), TEST_STRING.substring(0, 6));
-
- S3Object object2 = client.getObject(bucketName, key, range(6, TEST_STRING.length())).get(
- 10, TimeUnit.SECONDS);
- assertEquals(S3Utils.getContentAsStringAndClose(object2), TEST_STRING.substring(6,
- TEST_STRING.length()));
- } finally {
- returnBucket(bucketName);
- }
- }
-
- @Test
- void testGetTwoRanges() throws InterruptedException, ExecutionException, TimeoutException,
- IOException {
- String bucketName = getBucketName();
- try {
-
- String key = "apples";
-
- addObjectAndValidateContent(bucketName, key);
- S3Object object = client.getObject(bucketName, key,
- range(0, 5).range(6, TEST_STRING.length())).get(10, TimeUnit.SECONDS);
-
- assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING);
- } finally {
- returnBucket(bucketName);
- }
- }
-
- @Test
- void testGetTail() throws InterruptedException, ExecutionException, TimeoutException,
- IOException {
- String bucketName = getBucketName();
- try {
-
- String key = "apples";
-
- addObjectAndValidateContent(bucketName, key);
- S3Object object = client.getObject(bucketName, key, tail(5)).get(10, TimeUnit.SECONDS);
- assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING.substring(TEST_STRING
- .length() - 5));
- assertEquals(object.getContentLength(), 5);
- assertEquals(object.getMetadata().getSize(), TEST_STRING.length());
- } finally {
- returnBucket(bucketName);
- }
- }
-
- @Test
- void testGetStartAt() throws InterruptedException, ExecutionException, TimeoutException,
- IOException {
- String bucketName = getBucketName();
- try {
- String key = "apples";
-
- addObjectAndValidateContent(bucketName, key);
- S3Object object = client.getObject(bucketName, key, startAt(5)).get(10, TimeUnit.SECONDS);
- assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING.substring(5,
- TEST_STRING.length()));
- assertEquals(object.getContentLength(), TEST_STRING.length() - 5);
- assertEquals(object.getMetadata().getSize(), TEST_STRING.length());
- } finally {
- returnBucket(bucketName);
- }
- }
-
- private void addObjectAndValidateContent(String sourcebucketName, String sourceKey)
- throws InterruptedException, ExecutionException, TimeoutException, IOException {
- addObjectToBucket(sourcebucketName, sourceKey);
- validateContent(sourcebucketName, sourceKey);
- }
-}
\ No newline at end of file
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/ListBucketIntegrationTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/ListBucketIntegrationTest.java
deleted file mode 100644
index e1b49a1d9d..0000000000
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/ListBucketIntegrationTest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.commands;
-
-import org.jclouds.aws.s3.S3IntegrationTest;
-
-import static org.jclouds.aws.s3.options.ListBucketOptions.Builder.*;
-
-import org.jclouds.aws.s3.domain.S3Bucket;
-import org.jclouds.aws.s3.domain.S3Object;
-import static org.testng.Assert.assertEquals;
-import org.testng.annotations.Test;
-
-import java.io.UnsupportedEncodingException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Tests integrated functionality of all getBucket commands.
- *
- * Each test uses a different bucket name, so it should be perfectly fine to run in parallel.
- *
- * @author Adrian Cole
- */
-@Test(groups = { "integration", "live" }, testName = "s3.ListBucketIntegrationTest")
-public class ListBucketIntegrationTest extends S3IntegrationTest {
-
- @Test()
- void testListBucketDelimiter() throws InterruptedException, ExecutionException,
- TimeoutException, UnsupportedEncodingException {
- String bucketName = getBucketName();
- try {
- String prefix = "apps";
- addTenObjectsUnderPrefix(bucketName, prefix);
- add15UnderRoot(bucketName);
- S3Bucket bucket = client.listBucket(bucketName, delimiter("/")).get(10, TimeUnit.SECONDS);
- assertEquals(bucket.getDelimiter(), "/");
- assert !bucket.isTruncated();
- assertEquals(bucket.getContents().size(), 15);
- assertEquals(bucket.getCommonPrefixes().size(), 1);
- } finally {
- returnBucket(bucketName);
- }
-
- }
-
- private void addAlphabetUnderRoot(String bucketName) throws InterruptedException,
- ExecutionException, TimeoutException {
- for (char letter = 'a'; letter <= 'z'; letter++) {
- client.putObject(bucketName, new S3Object(letter + "", letter + "content")).get(10,
- TimeUnit.SECONDS);
- }
- }
-
- @Test
- void testListBucketMarker() throws InterruptedException, ExecutionException, TimeoutException,
- UnsupportedEncodingException {
- String bucketName = getBucketName();
- try {
- addAlphabetUnderRoot(bucketName);
- S3Bucket bucket = client.listBucket(bucketName, afterMarker("y"))
- .get(10, TimeUnit.SECONDS);
- assertEquals(bucket.getMarker(), "y");
- assert !bucket.isTruncated();
- assertEquals(bucket.getContents().size(), 1);
- } finally {
- returnBucket(bucketName);
- }
- }
-
- @Test
- void testListBucketMaxResults() throws InterruptedException, ExecutionException,
- TimeoutException, UnsupportedEncodingException {
- String bucketName = getBucketName();
- try {
- addAlphabetUnderRoot(bucketName);
- S3Bucket bucket = client.listBucket(bucketName, maxResults(5)).get(10, TimeUnit.SECONDS);
- assertEquals(bucket.getMaxKeys(), 5);
- assert bucket.isTruncated();
- assertEquals(bucket.getContents().size(), 5);
- } finally {
- returnBucket(bucketName);
- }
- }
-
- @Test()
- void testListBucketPrefix() throws InterruptedException, ExecutionException, TimeoutException,
- UnsupportedEncodingException {
- String bucketName = getBucketName();
- try {
- String prefix = "apps";
- addTenObjectsUnderPrefix(bucketName, prefix);
- add15UnderRoot(bucketName);
-
- S3Bucket bucket = client.listBucket(bucketName, withPrefix("apps/")).get(10,
- TimeUnit.SECONDS);
- assert !bucket.isTruncated();
- assertEquals(bucket.getContents().size(), 10);
- assertEquals(bucket.getPrefix(), "apps/");
- } finally {
- returnBucket(bucketName);
- }
-
- }
-
- @Test()
- void testListBucket() throws InterruptedException, ExecutionException, TimeoutException,
- UnsupportedEncodingException {
- String bucketName = getBucketName();
- try {
- String prefix = "apps";
- addTenObjectsUnderPrefix(bucketName, prefix);
- S3Bucket bucket = client.listBucket(bucketName).get(10, TimeUnit.SECONDS);
- assertEquals(bucket.getContents().size(), 10);
- } finally {
- returnBucket(bucketName);
- }
-
- }
-
- private void add15UnderRoot(String bucketName) throws InterruptedException, ExecutionException,
- TimeoutException {
- for (int i = 0; i < 15; i++)
- client.putObject(bucketName, new S3Object(i + "", i + "content"))
- .get(10, TimeUnit.SECONDS);
- }
-
- private void addTenObjectsUnderPrefix(String bucketName, String prefix)
- throws InterruptedException, ExecutionException, TimeoutException {
- for (int i = 0; i < 10; i++)
- client.putObject(bucketName, new S3Object(prefix + "/" + i, i + "content")).get(10,
- TimeUnit.SECONDS);
- }
-
-}
\ No newline at end of file
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/PutAccessControlListIntegrationTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/PutAccessControlListIntegrationTest.java
deleted file mode 100644
index cb8211424a..0000000000
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/PutAccessControlListIntegrationTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.commands;
-
-import static org.jclouds.aws.s3.internal.StubS3Connection.TEST_ACL_EMAIL;
-import static org.jclouds.aws.s3.internal.StubS3Connection.TEST_ACL_ID;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import java.io.IOException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.jclouds.aws.s3.S3IntegrationTest;
-import org.jclouds.aws.s3.domain.AccessControlList;
-import org.jclouds.aws.s3.domain.AccessControlList.CanonicalUserGrantee;
-import org.jclouds.aws.s3.domain.AccessControlList.EmailAddressGrantee;
-import org.jclouds.aws.s3.domain.AccessControlList.GroupGranteeURI;
-import org.jclouds.aws.s3.domain.AccessControlList.Permission;
-import org.testng.annotations.Test;
-
-/**
- * Tests integrated functionality of all commands that retrieve Access Control Lists (ACLs).
- *
- * @author James Murty
- */
-@Test(groups = { "integration", "live" }, testName = "s3.PutAccessControlListIntegrationTest")
-public class PutAccessControlListIntegrationTest extends S3IntegrationTest {
-
- @Test
- void testUpdateBucketACL() throws InterruptedException, ExecutionException, TimeoutException,
- IOException, Exception {
- String bucketName = getScratchBucketName();
- try {
- // Confirm the bucket is private
- AccessControlList acl = client.getBucketACL(bucketName).get(10, TimeUnit.SECONDS);
- String ownerId = acl.getOwner().getId();
- assertEquals(acl.getGrants().size(), 1);
- assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL));
-
- addGrantsToACL(acl);
- assertEquals(acl.getGrants().size(), 4);
- assertTrue(client.putBucketACL(bucketName, acl).get(10, TimeUnit.SECONDS));
-
- // Confirm that the updated ACL has stuck.
- acl = client.getBucketACL(bucketName).get(10, TimeUnit.SECONDS);
- checkGrants(acl);
- } finally {
- returnScratchBucket(bucketName);
- }
-
- }
-
- @Test
- void testUpdateObjectACL() throws InterruptedException, ExecutionException, TimeoutException,
- IOException {
- String bucketName = getBucketName();
- try {
- String objectKey = "private-acl";
-
- // Private object
- addObjectToBucket(bucketName, objectKey);
- AccessControlList acl = client.getObjectACL(bucketName, objectKey).get(10,
- TimeUnit.SECONDS);
- String ownerId = acl.getOwner().getId();
-
- assertEquals(acl.getGrants().size(), 1);
- assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL));
-
- addGrantsToACL(acl);
- assertEquals(acl.getGrants().size(), 4);
- assertTrue(client.putObjectACL(bucketName, objectKey, acl).get(10, TimeUnit.SECONDS));
-
- // Confirm that the updated ACL has stuck.
- acl = client.getObjectACL(bucketName, objectKey).get(10, TimeUnit.SECONDS);
- checkGrants(acl);
-
- /*
- * Revoke all of owner's permissions!
- */
- acl.revokeAllPermissions(new CanonicalUserGrantee(ownerId));
- if (!ownerId.equals(TEST_ACL_ID))
- acl.revokeAllPermissions(new CanonicalUserGrantee(TEST_ACL_ID));
- assertEquals(acl.getGrants().size(), 1);
- // Only public read permission should remain...
- assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ));
-
- // Update the object's ACL settings
- assertTrue(client.putObjectACL(bucketName, objectKey, acl).get(10, TimeUnit.SECONDS));
-
- // Confirm that the updated ACL has stuck
- acl = client.getObjectACL(bucketName, objectKey).get(10, TimeUnit.SECONDS);
- assertEquals(acl.getGrants().size(), 1);
- assertEquals(acl.getPermissions(ownerId).size(), 0);
- assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ), acl.toString());
- } finally {
- returnBucket(bucketName);
- }
-
- }
-
- private void checkGrants(AccessControlList acl) {
- String ownerId = acl.getOwner().getId();
-
- assertEquals(acl.getGrants().size(), 4, acl.toString());
-
- assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL), acl.toString());
- assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ), acl.toString());
- assertTrue(acl.hasPermission(ownerId, Permission.WRITE_ACP), acl.toString());
- // EmailAddressGrantee is replaced by a CanonicalUserGrantee, so we cannot test by email addr
- assertTrue(acl.hasPermission(TEST_ACL_ID, Permission.READ_ACP), acl.toString());
- }
-
- private void addGrantsToACL(AccessControlList acl) {
- String ownerId = acl.getOwner().getId();
- acl.addPermission(GroupGranteeURI.ALL_USERS, Permission.READ);
- acl.addPermission(new EmailAddressGrantee(TEST_ACL_EMAIL), Permission.READ_ACP);
- acl.addPermission(new CanonicalUserGrantee(ownerId), Permission.WRITE_ACP);
- }
-
-}
\ No newline at end of file
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/PutObjectIntegrationTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/PutObjectIntegrationTest.java
deleted file mode 100644
index bf163f59bf..0000000000
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/PutObjectIntegrationTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.commands;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.commons.io.IOUtils;
-import org.jclouds.aws.s3.S3IntegrationTest;
-import org.jclouds.aws.s3.domain.S3Object;
-import org.jclouds.aws.s3.reference.S3Headers;
-import org.jclouds.aws.s3.util.S3Utils;
-import org.jclouds.http.HttpUtils;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-/**
- * Tests integrated functionality of all PutObject commands.
- *
- * Each test uses a different bucket name, so it should be perfectly fine to run in parallel.
- *
- * @author Adrian Cole
- */
-@Test(testName = "s3.PutObjectIntegrationTest")
-public class PutObjectIntegrationTest extends S3IntegrationTest {
- @DataProvider(name = "putTests")
- public Object[][] createData1() throws IOException {
-
- String realObject = IOUtils.toString(new FileInputStream("pom.xml"));
-
- return new Object[][] { { "file", "text/xml", new File("pom.xml"), realObject },
- { "string", "text/xml", realObject, realObject },
- { "bytes", "application/octet-stream", realObject.getBytes(), realObject } };
- }
-
- @Test(dataProvider = "putTests", groups = { "integration", "live" })
- void testPutObject(String key, String type, Object content, Object realObject) throws Exception {
- S3Object object = new S3Object(key);
- object.getMetadata().setContentType(type);
- object.setData(content);
- if (content instanceof InputStream) {
- object.generateETag();
- }
- String bucketName = getBucketName();
- try {
- assertNotNull(client.putObject(bucketName, object).get(10, TimeUnit.SECONDS));
- object = client.getObject(bucketName, object.getKey()).get(10, TimeUnit.SECONDS);
- String returnedString = S3Utils.getContentAsStringAndClose(object);
- assertEquals(returnedString, realObject);
- assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS).getContents().size(),
- 1);
- } finally {
- returnBucket(bucketName);
- }
- }
-
- @Test(groups = { "integration", "live" })
- void testMetadata() throws Exception {
- String key = "hello";
-
- S3Object object = new S3Object(key, TEST_STRING);
- object.getMetadata().setCacheControl("no-cache");
- object.getMetadata().setContentType("text/plain");
- object.getMetadata().setContentEncoding("x-compress");
- object.getMetadata().setSize(TEST_STRING.length());
- object.getMetadata().setContentDisposition("attachment; filename=hello.txt");
- object.getMetadata().getUserMetadata().put(S3Headers.USER_METADATA_PREFIX + "adrian",
- "powderpuff");
- object.getMetadata().setETag(HttpUtils.eTag(TEST_STRING.getBytes()));
- String bucketName = getBucketName();
- try {
- addObjectToBucket(bucketName, object);
- S3Object newObject = validateContent(bucketName, key);
-
- assertEquals(newObject.getMetadata().getContentType(), "text/plain");
- assertEquals(newObject.getMetadata().getContentEncoding(), "x-compress");
- assertEquals(newObject.getMetadata().getContentDisposition(),
- "attachment; filename=hello.txt");
- assertEquals(newObject.getMetadata().getCacheControl(), "no-cache");
- assertEquals(newObject.getMetadata().getSize(), TEST_STRING.length());
- assertEquals(newObject.getMetadata().getUserMetadata().values().iterator().next(),
- "powderpuff");
- assertEquals(newObject.getMetadata().getETag(), HttpUtils.eTag(TEST_STRING.getBytes()));
- } finally {
- returnBucket(bucketName);
- }
- }
-
-}
\ No newline at end of file
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/PutObjectLiveTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/PutObjectLiveTest.java
deleted file mode 100644
index 41ab55fbd4..0000000000
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/PutObjectLiveTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Global Cloud Specialists, Inc.
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-package org.jclouds.aws.s3.commands;
-
-import static org.jclouds.aws.s3.options.PutObjectOptions.Builder.withAcl;
-
-import java.net.URL;
-import java.util.concurrent.TimeUnit;
-
-import org.jclouds.aws.s3.S3IntegrationTest;
-import org.jclouds.aws.s3.domain.CannedAccessPolicy;
-import org.jclouds.aws.s3.domain.S3Object;
-import org.jclouds.util.Utils;
-import org.testng.annotations.Test;
-
-/**
- * Tests integrated functionality of all PutObject commands.
- *
- * Each test uses a different bucket name, so it should be perfectly fine to run in parallel.
- *
- * @author Adrian Cole
- */
-@Test(testName = "s3.PutObjectLiveTest")
-public class PutObjectLiveTest extends S3IntegrationTest {
-
- @Test(groups = { "live" })
- void testCannedAccessPolicyPublic() throws Exception {
- String bucketName = getBucketName();
- try {
- String key = "hello";
-
- client.putObject(bucketName, new S3Object(key, TEST_STRING),
-
- withAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS);
-
- URL url = new URL(String.format("http://%1$s.s3.amazonaws.com/%2$s", bucketName, key));
- Utils.toStringAndClose(url.openStream());
- } finally {
- returnBucket(bucketName);
- }
-
- }
-
-}
\ No newline at end of file
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/config/StubS3ConnectionModule.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/config/StubS3BlobStoreModule.java
old mode 100644
new mode 100755
similarity index 87%
rename from aws/s3/core/src/test/java/org/jclouds/aws/s3/config/StubS3ConnectionModule.java
rename to aws/s3/core/src/test/java/org/jclouds/aws/s3/config/StubS3BlobStoreModule.java
index f4f8b4af83..49ea2501d9
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/config/StubS3ConnectionModule.java
+++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/config/StubS3BlobStoreModule.java
@@ -25,8 +25,8 @@ package org.jclouds.aws.s3.config;
import java.net.URI;
-import org.jclouds.aws.s3.S3Connection;
-import org.jclouds.aws.s3.internal.StubS3Connection;
+import org.jclouds.aws.s3.S3BlobStore;
+import org.jclouds.aws.s3.internal.StubS3BlobStore;
import org.jclouds.cloud.ConfiguresCloudConnection;
import org.jclouds.http.functions.config.ParserModule;
@@ -38,10 +38,10 @@ import com.google.inject.AbstractModule;
* @author Adrian Cole
*/
@ConfiguresCloudConnection
-public class StubS3ConnectionModule extends AbstractModule {
+public class StubS3BlobStoreModule extends AbstractModule {
protected void configure() {
install(new ParserModule());
- bind(S3Connection.class).to(StubS3Connection.class);
+ bind(S3BlobStore.class).to(StubS3BlobStore.class);
bind(URI.class).toInstance(URI.create("http://localhost:8080"));
}
}
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignatureTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignatureTest.java
index e68adc5cfd..6bafc536fc 100644
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignatureTest.java
+++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignatureTest.java
@@ -111,6 +111,16 @@ public class RequestAuthorizeSignatureTest {
assertEquals(builder.toString(), "");
}
+
+ @Test
+ void testHeadersGoLowercase() {
+ URI host = URI.create("http://s3.amazonaws.com:80");
+ HttpRequest request = new HttpRequest(HttpMethod.GET, host);
+ request.getHeaders().put("x-amz-adrian", "s3.amazonaws.com");
+ StringBuilder builder = new StringBuilder();
+ filter.appendBucketName(request, builder);
+ assertEquals(builder.toString(), "");
+ }
@Test
void testAppendBucketNameURIHost() {
URI host = URI.create("http://adriancole.s3int5.s3-external-3.amazonaws.com:80");
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/functions/ListBucketHandlerTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/functions/ListBucketHandlerTest.java
index 4581ab790b..eb7d4cc658 100644
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/functions/ListBucketHandlerTest.java
+++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/functions/ListBucketHandlerTest.java
@@ -26,7 +26,7 @@ package org.jclouds.aws.s3.functions;
import static org.testng.Assert.assertEquals;
import org.apache.commons.io.IOUtils;
-import org.jclouds.aws.s3.domain.S3Bucket;
+import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.http.HttpException;
import org.jclouds.http.functions.ParseSax;
import org.testng.annotations.BeforeMethod;
@@ -38,15 +38,15 @@ public class ListBucketHandlerTest extends BaseHandlerTest {
public static final String listBucketWithSlashDelimiterAndCommonPrefixApps = " / apps/ ";
@BeforeMethod
- ParseSax createParser() {
- ParseSax parser = parserFactory.createListBucketParser();
+ ParseSax createParser() {
+ ParseSax parser = parserFactory.createListBucketParser();
return parser;
}
@Test
public void testListMyBucketsWithDelimiterSlashAndCommonPrefixesAppsSlash() throws HttpException {
- S3Bucket bucket = createParser().parse(
+ ListBucketResponse bucket = createParser().parse(
IOUtils.toInputStream(listBucketWithSlashDelimiterAndCommonPrefixApps));
assertEquals(bucket.getCommonPrefixes().iterator().next(), "apps/");
assertEquals(bucket.getDelimiter(), "/");
@@ -56,9 +56,9 @@ public class ListBucketHandlerTest extends BaseHandlerTest {
@Test
public void testListMyBucketsWithPrefixAppsSlash() throws HttpException {
- S3Bucket bucket = createParser().parse(IOUtils.toInputStream(listBucketWithPrefixAppsSlash));
+ ListBucketResponse bucket = createParser().parse(IOUtils.toInputStream(listBucketWithPrefixAppsSlash));
assertEquals(bucket.getPrefix(), "apps/");
- assertEquals(bucket.getMaxKeys(), 1000);
+ assertEquals(bucket.getMaxResults(), 1000);
assert bucket.getMarker() == null;
}
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/ReturnTrueIfBucketAlreadyOwnedByYouTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/functions/ReturnTrueIfBucketAlreadyOwnedByYouTest.java
old mode 100644
new mode 100755
similarity index 98%
rename from aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/ReturnTrueIfBucketAlreadyOwnedByYouTest.java
rename to aws/s3/core/src/test/java/org/jclouds/aws/s3/functions/ReturnTrueIfBucketAlreadyOwnedByYouTest.java
index 19e0aea812..d4a31cf082
--- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/ReturnTrueIfBucketAlreadyOwnedByYouTest.java
+++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/functions/ReturnTrueIfBucketAlreadyOwnedByYouTest.java
@@ -21,7 +21,7 @@
* under the License.
* ====================================================================
*/
-package org.jclouds.aws.s3.commands;
+package org.jclouds.aws.s3.functions;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/integration/S3BlobIntegrationTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/integration/S3BlobIntegrationTest.java
new file mode 100755
index 0000000000..c751762e3f
--- /dev/null
+++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/integration/S3BlobIntegrationTest.java
@@ -0,0 +1,424 @@
+/**
+ *
+ * Copyright (C) 2009 Global Cloud Specialists, Inc.
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+package org.jclouds.aws.s3.integration;
+
+import static org.jclouds.aws.s3.internal.StubS3BlobStore.TEST_ACL_EMAIL;
+import static org.jclouds.aws.s3.internal.StubS3BlobStore.TEST_ACL_ID;
+import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceETagDoesntMatch;
+import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceETagMatches;
+import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceModifiedSince;
+import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceUnmodifiedSince;
+import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.overrideMetadataWith;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.jclouds.aws.s3.S3BlobStore;
+import org.jclouds.aws.s3.domain.AccessControlList;
+import org.jclouds.aws.s3.domain.BucketMetadata;
+import org.jclouds.aws.s3.domain.CannedAccessPolicy;
+import org.jclouds.aws.s3.domain.ObjectMetadata;
+import org.jclouds.aws.s3.domain.S3Object;
+import org.jclouds.aws.s3.domain.AccessControlList.CanonicalUserGrantee;
+import org.jclouds.aws.s3.domain.AccessControlList.EmailAddressGrantee;
+import org.jclouds.aws.s3.domain.AccessControlList.GroupGranteeURI;
+import org.jclouds.aws.s3.domain.AccessControlList.Permission;
+import org.jclouds.aws.s3.options.PutObjectOptions;
+import org.jclouds.blobstore.integration.internal.BaseBlobIntegrationTest;
+import org.jclouds.http.HttpResponseException;
+import org.jclouds.util.Utils;
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+
+/**
+ *
+ * @author James Murty
+ * @author Adrian Cole
+ */
+@Test(groups = { "integration", "live" }, testName = "s3.S3BlobIntegrationTest")
+public class S3BlobIntegrationTest extends
+ BaseBlobIntegrationTest {
+ String sourceKey = "apples";
+ String destinationKey = "pears";
+
+ public void testPublicWriteOnObject() throws InterruptedException, ExecutionException,
+ TimeoutException, IOException {
+ final String publicReadWriteObjectKey = "public-read-write-acl";
+ final String containerName = getContainerName();
+ try {
+ // Public Read-Write object
+ client.putBlob(containerName, new S3Object(publicReadWriteObjectKey, ""),
+ new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ_WRITE)).get(10,
+ TimeUnit.SECONDS);
+
+ assertEventually(new Runnable() {
+ public void run() {
+ try {
+ AccessControlList acl = client
+ .getBlobACL(containerName, publicReadWriteObjectKey).get(10,
+ TimeUnit.SECONDS);
+ assertEquals(acl.getGrants().size(), 3);
+ assertEquals(acl.getPermissions(GroupGranteeURI.ALL_USERS).size(), 2);
+ assertTrue(acl.getOwner() != null);
+ String ownerId = acl.getOwner().getId();
+ assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL));
+ assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ));
+ assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.WRITE));
+ assertFalse(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ_ACP));
+ assertFalse(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.WRITE_ACP));
+ assertFalse(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.FULL_CONTROL));
+ } catch (Exception e) {
+ Utils. rethrowIfRuntimeOrSameType(e);
+ }
+ }
+ });
+ } finally {
+ returnContainer(containerName);
+ }
+
+ }
+
+ public void testUpdateObjectACL() throws InterruptedException, ExecutionException,
+ TimeoutException, IOException {
+ String containerName = getContainerName();
+ try {
+ String objectKey = "private-acl";
+
+ // Private object
+ addBlobToContainer(containerName, objectKey);
+ AccessControlList acl = client.getBlobACL(containerName, objectKey).get(10,
+ TimeUnit.SECONDS);
+ String ownerId = acl.getOwner().getId();
+
+ assertEquals(acl.getGrants().size(), 1);
+ assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL));
+
+ addGrantsToACL(acl);
+ assertEquals(acl.getGrants().size(), 4);
+ assertTrue(client.putBlobACL(containerName, objectKey, acl).get(10, TimeUnit.SECONDS));
+
+ // Confirm that the updated ACL has stuck.
+ acl = client.getBlobACL(containerName, objectKey).get(10, TimeUnit.SECONDS);
+ checkGrants(acl);
+
+ /*
+ * Revoke all of owner's permissions!
+ */
+ acl.revokeAllPermissions(new CanonicalUserGrantee(ownerId));
+ if (!ownerId.equals(TEST_ACL_ID))
+ acl.revokeAllPermissions(new CanonicalUserGrantee(TEST_ACL_ID));
+ assertEquals(acl.getGrants().size(), 1);
+ // Only public read permission should remain...
+ assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ));
+
+ // Update the object's ACL settings
+ assertTrue(client.putBlobACL(containerName, objectKey, acl).get(10, TimeUnit.SECONDS));
+
+ // Confirm that the updated ACL has stuck
+ acl = client.getBlobACL(containerName, objectKey).get(10, TimeUnit.SECONDS);
+ assertEquals(acl.getGrants().size(), 1);
+ assertEquals(acl.getPermissions(ownerId).size(), 0);
+ assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ), acl.toString());
+ } finally {
+ returnContainer(containerName);
+ }
+
+ }
+
+ private void checkGrants(AccessControlList acl) {
+ String ownerId = acl.getOwner().getId();
+
+ assertEquals(acl.getGrants().size(), 4, acl.toString());
+
+ assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL), acl.toString());
+ assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ), acl.toString());
+ assertTrue(acl.hasPermission(ownerId, Permission.WRITE_ACP), acl.toString());
+ // EmailAddressGrantee is replaced by a CanonicalUserGrantee, so we cannot test by email addr
+ assertTrue(acl.hasPermission(TEST_ACL_ID, Permission.READ_ACP), acl.toString());
+ }
+
+ private void addGrantsToACL(AccessControlList acl) {
+ String ownerId = acl.getOwner().getId();
+ acl.addPermission(GroupGranteeURI.ALL_USERS, Permission.READ);
+ acl.addPermission(new EmailAddressGrantee(TEST_ACL_EMAIL), Permission.READ_ACP);
+ acl.addPermission(new CanonicalUserGrantee(ownerId), Permission.WRITE_ACP);
+ }
+
+ public void testPrivateAclIsDefaultForObject() throws InterruptedException, ExecutionException,
+ TimeoutException, IOException {
+ String privateObjectKey = "private-acl";
+ String containerName = getContainerName();
+ try {
+ // Private object
+ addBlobToContainer(containerName, privateObjectKey);
+ AccessControlList acl = client.getBlobACL(containerName, privateObjectKey).get(10,
+ TimeUnit.SECONDS);
+
+ assertEquals(acl.getGrants().size(), 1);
+ assertTrue(acl.getOwner() != null);
+ String ownerId = acl.getOwner().getId();
+ assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL));
+ } finally {
+ returnContainer(containerName);
+ }
+
+ }
+
+ public void testPublicReadOnObject() throws InterruptedException, ExecutionException,
+ TimeoutException, IOException {
+ final String publicReadObjectKey = "public-read-acl";
+ final String containerName = getContainerName();
+ try {
+ client.putBlob(containerName, new S3Object(publicReadObjectKey, ""),
+ new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ)).get(10,
+ TimeUnit.SECONDS);
+
+ assertEventually(new Runnable() {
+ public void run() {
+ try {
+ AccessControlList acl = client.getBlobACL(containerName, publicReadObjectKey)
+ .get(10, TimeUnit.SECONDS);
+
+ assertEquals(acl.getGrants().size(), 2);
+ assertEquals(acl.getPermissions(GroupGranteeURI.ALL_USERS).size(), 1);
+ assertTrue(acl.getOwner() != null);
+ String ownerId = acl.getOwner().getId();
+ assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL));
+ assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ));
+ } catch (Exception e) {
+ Utils. rethrowIfRuntimeOrSameType(e);
+ }
+ }
+ });
+
+ } finally {
+ returnContainer(containerName);
+ }
+
+ }
+
+ public void testMetadataWithCacheControlAndContentDisposition() throws Exception {
+ String key = "hello";
+
+ S3Object object = objectFactory.createBlob(key);
+ object.setData(TEST_STRING);
+ object.getMetadata().setCacheControl("no-cache");
+ object.getMetadata().setContentDisposition("attachment; filename=hello.txt");
+ String containerName = getContainerName();
+ try {
+ addBlobToContainer(containerName, object);
+ S3Object newObject = validateContent(containerName, key);
+
+ assertEquals(newObject.getMetadata().getCacheControl(), "no-cache");
+ assertEquals(newObject.getMetadata().getContentDisposition(),
+ "attachment; filename=hello.txt");
+ } finally {
+ returnContainer(containerName);
+ }
+ }
+
+ @Test(groups = { "integration", "live" })
+ public void testMetadataContentEncoding() throws Exception {
+ String key = "hello";
+
+ S3Object object = objectFactory.createBlob(key);
+ object.setData(TEST_STRING);
+ object.getMetadata().setContentEncoding("x-compress");
+ String containerName = getContainerName();
+ try {
+ addBlobToContainer(containerName, object);
+ S3Object newObject = validateContent(containerName, key);
+
+ assertEquals(newObject.getMetadata().getContentEncoding(), "x-compress");
+ } finally {
+ returnContainer(containerName);
+ }
+ }
+
+ public void testCopyObject() throws Exception {
+ String containerName = getContainerName();
+ String destinationContainer = getContainerName();
+
+ try {
+ addToContainerAndValidate(containerName, sourceKey);
+
+ client.copyBlob(containerName, sourceKey, destinationContainer, destinationKey).get(10,
+ TimeUnit.SECONDS);
+
+ validateContent(destinationContainer, destinationKey);
+ } finally {
+ returnContainer(containerName);
+ returnContainer(destinationContainer);
+
+ }
+ }
+
+ private void addToContainerAndValidate(String containerName, String sourceKey)
+ throws InterruptedException, ExecutionException, TimeoutException, IOException {
+ addBlobToContainer(containerName, sourceKey);
+ validateContent(containerName, sourceKey);
+ }
+
+ // TODO: fails on linux and windows
+ public void testCopyIfModifiedSince() throws InterruptedException, ExecutionException,
+ TimeoutException, IOException {
+ String containerName = getContainerName();
+ String destinationContainer = getContainerName();
+ try {
+ DateTime before = new DateTime();
+ addToContainerAndValidate(containerName, sourceKey + "mod");
+ DateTime after = new DateTime().plusSeconds(1);
+
+ client.copyBlob(containerName, sourceKey + "mod", destinationContainer, destinationKey,
+ ifSourceModifiedSince(before)).get(10, TimeUnit.SECONDS);
+ validateContent(destinationContainer, destinationKey);
+
+ try {
+ client.copyBlob(containerName, sourceKey + "mod", destinationContainer, destinationKey,
+ ifSourceModifiedSince(after)).get(10, TimeUnit.SECONDS);
+ } catch (ExecutionException e) {
+ if (e.getCause() instanceof HttpResponseException) {
+ HttpResponseException ex = (HttpResponseException) e.getCause();
+ assertEquals(ex.getResponse().getStatusCode(), 412);
+ } else {
+ throw e;
+ }
+ }
+ } finally {
+ returnContainer(containerName);
+ returnContainer(destinationContainer);
+
+ }
+ }
+
+ // TODO: fails on linux and windows
+ public void testCopyIfUnmodifiedSince() throws InterruptedException, ExecutionException,
+ TimeoutException, IOException {
+ String containerName = getContainerName();
+ String destinationContainer = getContainerName();
+ try {
+ DateTime before = new DateTime();
+ addToContainerAndValidate(containerName, sourceKey + "un");
+ DateTime after = new DateTime().plusSeconds(1);
+
+ client.copyBlob(containerName, sourceKey + "un", destinationContainer, destinationKey,
+ ifSourceUnmodifiedSince(after)).get(10, TimeUnit.SECONDS);
+ validateContent(destinationContainer, destinationKey);
+
+ try {
+ client.copyBlob(containerName, sourceKey + "un", destinationContainer, destinationKey,
+ ifSourceModifiedSince(before)).get(10, TimeUnit.SECONDS);
+ } catch (ExecutionException e) {
+ HttpResponseException ex = (HttpResponseException) e.getCause();
+ assertEquals(ex.getResponse().getStatusCode(), 412);
+ }
+ } finally {
+ returnContainer(containerName);
+ returnContainer(destinationContainer);
+ }
+ }
+
+ public void testCopyIfMatch() throws InterruptedException, ExecutionException, TimeoutException,
+ IOException {
+ String containerName = getContainerName();
+ String destinationContainer = getContainerName();
+ try {
+ addToContainerAndValidate(containerName, sourceKey);
+
+ client.copyBlob(containerName, sourceKey, destinationContainer, destinationKey,
+ ifSourceETagMatches(goodETag)).get(10, TimeUnit.SECONDS);
+ validateContent(destinationContainer, destinationKey);
+
+ try {
+ client.copyBlob(containerName, sourceKey, destinationContainer, destinationKey,
+ ifSourceETagMatches(badETag)).get(10, TimeUnit.SECONDS);
+ } catch (ExecutionException e) {
+ HttpResponseException ex = (HttpResponseException) e.getCause();
+ assertEquals(ex.getResponse().getStatusCode(), 412);
+ }
+ } finally {
+ returnContainer(containerName);
+ returnContainer(destinationContainer);
+ }
+ }
+
+ public void testCopyIfNoneMatch() throws IOException, InterruptedException, ExecutionException,
+ TimeoutException {
+ String containerName = getContainerName();
+ String destinationContainer = getContainerName();
+ try {
+ addToContainerAndValidate(containerName, sourceKey);
+
+ client.copyBlob(containerName, sourceKey, destinationContainer, destinationKey,
+ ifSourceETagDoesntMatch(badETag)).get(10, TimeUnit.SECONDS);
+ validateContent(destinationContainer, destinationKey);
+
+ try {
+ client.copyBlob(containerName, sourceKey, destinationContainer, destinationKey,
+ ifSourceETagDoesntMatch(goodETag)).get(10, TimeUnit.SECONDS);
+ } catch (ExecutionException e) {
+ HttpResponseException ex = (HttpResponseException) e.getCause();
+ assertEquals(ex.getResponse().getStatusCode(), 412);
+ }
+ } finally {
+ returnContainer(containerName);
+ returnContainer(destinationContainer);
+
+ }
+ }
+
+ public void testCopyWithMetadata() throws InterruptedException, ExecutionException,
+ TimeoutException, IOException {
+ String containerName = getContainerName();
+ String destinationContainer = getContainerName();
+ try {
+ addToContainerAndValidate(containerName, sourceKey);
+
+ Multimap