mirror of https://github.com/apache/jclouds.git
JCLOUDS-150 add SubmissionAsyncBlobStore; unasync s3 and aws-s3
This commit is contained in:
parent
2cbb5e26c0
commit
c68078c22d
|
@ -29,14 +29,14 @@ import java.net.URI;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.apis.ApiMetadata;
|
||||
import org.jclouds.rest.internal.BaseHttpApiMetadata;
|
||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
||||
import org.jclouds.s3.blobstore.S3BlobStoreContext;
|
||||
import org.jclouds.s3.blobstore.config.S3BlobStoreContextModule;
|
||||
import org.jclouds.s3.config.S3RestClientModule;
|
||||
import org.jclouds.s3.config.S3HttpApiModule;
|
||||
import org.jclouds.s3.reference.S3Headers;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
|
@ -44,9 +44,8 @@ import com.google.inject.Module;
|
|||
*
|
||||
* <h3>note</h3>
|
||||
* <p/>
|
||||
* This class allows overriding of types {@code S}(client) and {@code A}
|
||||
* (asyncClient), so that children can add additional methods not declared here,
|
||||
* such as new features from AWS.
|
||||
* This class allows overriding of types {@code A}(api), so that children can
|
||||
* add additional methods not declared here, such as new features from AWS.
|
||||
* <p/>
|
||||
*
|
||||
* As this is a popular api, we also allow overrides for type {@code C}
|
||||
|
@ -54,19 +53,10 @@ import com.google.inject.Module;
|
|||
* not present in the base api. For example, you could make a subtype for
|
||||
* context, that exposes admin operations.
|
||||
*/
|
||||
public class S3ApiMetadata extends BaseRestApiMetadata {
|
||||
|
||||
/**
|
||||
* @deprecated please use {@code org.jclouds.ContextBuilder#buildClient(S3Client.class)} as
|
||||
* {@link S3AsyncClient} interface will be removed in jclouds 1.7.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final TypeToken<org.jclouds.rest.RestContext<? extends S3Client, ? extends S3AsyncClient>> CONTEXT_TOKEN = new TypeToken<org.jclouds.rest.RestContext<? extends S3Client, ? extends S3AsyncClient>>() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
};
|
||||
public class S3ApiMetadata extends BaseHttpApiMetadata {
|
||||
|
||||
@Override
|
||||
public Builder<?> toBuilder() {
|
||||
public Builder<?, ?> toBuilder() {
|
||||
return new ConcreteBuilder().fromApiMetadata(this);
|
||||
}
|
||||
|
||||
|
@ -74,7 +64,7 @@ public class S3ApiMetadata extends BaseRestApiMetadata {
|
|||
this(new ConcreteBuilder());
|
||||
}
|
||||
|
||||
protected S3ApiMetadata(Builder<?> builder) {
|
||||
protected S3ApiMetadata(Builder<?, ?> builder) {
|
||||
super(builder);
|
||||
}
|
||||
|
||||
|
@ -90,14 +80,15 @@ public class S3ApiMetadata extends BaseRestApiMetadata {
|
|||
return properties;
|
||||
}
|
||||
|
||||
public abstract static class Builder<T extends Builder<T>> extends BaseRestApiMetadata.Builder<T> {
|
||||
@SuppressWarnings("deprecation")
|
||||
public abstract static class Builder<A extends S3Client, T extends Builder<A, T>> extends
|
||||
BaseHttpApiMetadata.Builder<A, T> {
|
||||
|
||||
protected Builder() {
|
||||
this(S3Client.class, S3AsyncClient.class);
|
||||
this(Class.class.cast(S3Client.class));
|
||||
}
|
||||
|
||||
protected Builder(Class<?> syncClient, Class<?> asyncClient) {
|
||||
super(syncClient, asyncClient);
|
||||
protected Builder(Class<A> syncClient) {
|
||||
super(syncClient);
|
||||
id("s3")
|
||||
.name("Amazon Simple Storage Service (S3) API")
|
||||
.identityName("Access Key ID")
|
||||
|
@ -106,9 +97,8 @@ public class S3ApiMetadata extends BaseRestApiMetadata {
|
|||
.documentation(URI.create("http://docs.amazonwebservices.com/AmazonS3/latest/API"))
|
||||
.version("2006-03-01")
|
||||
.defaultProperties(S3ApiMetadata.defaultProperties())
|
||||
.context(CONTEXT_TOKEN)
|
||||
.view(typeToken(S3BlobStoreContext.class))
|
||||
.defaultModules(ImmutableSet.<Class<? extends Module>>of(S3RestClientModule.class, S3BlobStoreContextModule.class));
|
||||
.defaultModules(ImmutableSet.<Class<? extends Module>>of(S3HttpApiModule.class, S3BlobStoreContextModule.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,7 +107,7 @@ public class S3ApiMetadata extends BaseRestApiMetadata {
|
|||
}
|
||||
}
|
||||
|
||||
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||
private static class ConcreteBuilder extends Builder<S3Client, ConcreteBuilder> {
|
||||
@Override
|
||||
protected ConcreteBuilder self() {
|
||||
return this;
|
||||
|
|
|
@ -1,363 +0,0 @@
|
|||
/*
|
||||
* 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.s3;
|
||||
|
||||
import static com.google.common.net.HttpHeaders.EXPECT;
|
||||
import static org.jclouds.blobstore.attr.BlobScopes.CONTAINER;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HEAD;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
|
||||
import org.jclouds.blobstore.BlobStoreFallbacks.FalseOnContainerNotFound;
|
||||
import org.jclouds.blobstore.BlobStoreFallbacks.FalseOnKeyNotFound;
|
||||
import org.jclouds.blobstore.BlobStoreFallbacks.NullOnKeyNotFound;
|
||||
import org.jclouds.blobstore.BlobStoreFallbacks.ThrowContainerNotFoundOn404;
|
||||
import org.jclouds.blobstore.BlobStoreFallbacks.ThrowKeyNotFoundOn404;
|
||||
import org.jclouds.blobstore.attr.BlobScope;
|
||||
import org.jclouds.http.functions.ParseETagHeader;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.Endpoint;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.annotations.ParamParser;
|
||||
import org.jclouds.rest.annotations.ParamValidators;
|
||||
import org.jclouds.rest.annotations.QueryParams;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.ResponseParser;
|
||||
import org.jclouds.rest.annotations.VirtualHost;
|
||||
import org.jclouds.rest.annotations.XMLResponseParser;
|
||||
import org.jclouds.s3.S3Fallbacks.TrueOn404OrNotFoundFalseOnIllegalState;
|
||||
import org.jclouds.s3.binders.BindACLToXMLPayload;
|
||||
import org.jclouds.s3.binders.BindAsHostPrefixIfConfigured;
|
||||
import org.jclouds.s3.binders.BindBucketLoggingToXmlPayload;
|
||||
import org.jclouds.s3.binders.BindNoBucketLoggingToXmlPayload;
|
||||
import org.jclouds.s3.binders.BindPayerToXmlPayload;
|
||||
import org.jclouds.s3.binders.BindS3ObjectMetadataToRequest;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
import org.jclouds.s3.domain.BucketLogging;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
import org.jclouds.s3.domain.ListBucketResponse;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.domain.Payer;
|
||||
import org.jclouds.s3.domain.S3Object;
|
||||
import org.jclouds.s3.fallbacks.FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists;
|
||||
import org.jclouds.s3.filters.RequestAuthorizeSignature;
|
||||
import org.jclouds.s3.functions.AssignCorrectHostnameForBucket;
|
||||
import org.jclouds.s3.functions.BindRegionToXmlPayload;
|
||||
import org.jclouds.s3.functions.DefaultEndpointThenInvalidateRegion;
|
||||
import org.jclouds.s3.functions.ObjectKey;
|
||||
import org.jclouds.s3.functions.ParseObjectFromHeadersAndHttpContent;
|
||||
import org.jclouds.s3.functions.ParseObjectMetadataFromHeaders;
|
||||
import org.jclouds.s3.options.CopyObjectOptions;
|
||||
import org.jclouds.s3.options.ListBucketOptions;
|
||||
import org.jclouds.s3.options.PutBucketOptions;
|
||||
import org.jclouds.s3.options.PutObjectOptions;
|
||||
import org.jclouds.s3.predicates.validators.BucketNameValidator;
|
||||
import org.jclouds.s3.xml.AccessControlListHandler;
|
||||
import org.jclouds.s3.xml.BucketLoggingHandler;
|
||||
import org.jclouds.s3.xml.CopyObjectHandler;
|
||||
import org.jclouds.s3.xml.ListAllMyBucketsHandler;
|
||||
import org.jclouds.s3.xml.ListBucketHandler;
|
||||
import org.jclouds.s3.xml.LocationConstraintHandler;
|
||||
import org.jclouds.s3.xml.PayerHandler;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to S3 via their REST API.
|
||||
* <p/>
|
||||
* All commands return a ListenableFuture of the result from S3. Any exceptions incurred during
|
||||
* processing will be backend in an {@link ExecutionException} as documented in
|
||||
* {@link ListenableFuture#get()}.
|
||||
*
|
||||
* @see AWSS3Client
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAPI.html" />
|
||||
* @deprecated please use
|
||||
* {@code org.jclouds.ContextBuilder#buildApi(S3Client.class)}
|
||||
* as {@link S3AsyncClient} interface will be removed in jclouds 1.7.
|
||||
*/
|
||||
@Deprecated
|
||||
@RequestFilters(RequestAuthorizeSignature.class)
|
||||
@BlobScope(CONTAINER)
|
||||
public interface S3AsyncClient extends Closeable {
|
||||
static final String VERSION = "2006-03-01";
|
||||
|
||||
/**
|
||||
* Creates a default implementation of S3Object
|
||||
*/
|
||||
@Provides
|
||||
S3Object newS3Object();
|
||||
|
||||
/**
|
||||
* @see S3Client#getObject
|
||||
*/
|
||||
@Named("GetObject")
|
||||
@GET
|
||||
@Path("/{key}")
|
||||
@Fallback(NullOnKeyNotFound.class)
|
||||
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
|
||||
ListenableFuture<S3Object> getObject(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key, GetOptions... options);
|
||||
|
||||
/**
|
||||
* @see S3Client#headObject
|
||||
*/
|
||||
@Named("GetObject")
|
||||
@HEAD
|
||||
@Path("/{key}")
|
||||
@Fallback(NullOnKeyNotFound.class)
|
||||
@ResponseParser(ParseObjectMetadataFromHeaders.class)
|
||||
ListenableFuture<ObjectMetadata> headObject(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key);
|
||||
|
||||
/**
|
||||
* @see S3Client#objectExists
|
||||
*/
|
||||
@Named("GetObject")
|
||||
@HEAD
|
||||
@Path("/{key}")
|
||||
@Fallback(FalseOnKeyNotFound.class)
|
||||
ListenableFuture<Boolean> objectExists(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key);
|
||||
|
||||
/**
|
||||
* @see S3Client#deleteObject
|
||||
*/
|
||||
@Named("DeleteObject")
|
||||
@DELETE
|
||||
@Path("/{key}")
|
||||
@Fallback(VoidOnNotFoundOr404.class)
|
||||
ListenableFuture<Void> deleteObject(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key);
|
||||
|
||||
/**
|
||||
* @see S3Client#putObject
|
||||
*/
|
||||
@Named("PutObject")
|
||||
@PUT
|
||||
@Path("/{key}")
|
||||
@Headers(keys = EXPECT, values = "100-continue")
|
||||
@ResponseParser(ParseETagHeader.class)
|
||||
ListenableFuture<String> putObject(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") @ParamParser(ObjectKey.class) @BinderParam(BindS3ObjectMetadataToRequest.class) S3Object object,
|
||||
PutObjectOptions... options);
|
||||
|
||||
/**
|
||||
* @see S3Client#putBucketInRegion
|
||||
*/
|
||||
@Named("CreateBucket")
|
||||
@PUT
|
||||
@Path("/")
|
||||
@Endpoint(Bucket.class)
|
||||
@Fallback(FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists.class)
|
||||
ListenableFuture<Boolean> putBucketInRegion(
|
||||
@BinderParam(BindRegionToXmlPayload.class) @Nullable String region,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
PutBucketOptions... options);
|
||||
|
||||
/**
|
||||
* @see S3Client#deleteBucketIfEmpty
|
||||
*/
|
||||
@Named("DeleteBucket")
|
||||
@DELETE
|
||||
@Path("/")
|
||||
@Fallback(TrueOn404OrNotFoundFalseOnIllegalState.class)
|
||||
ListenableFuture<Boolean> deleteBucketIfEmpty(
|
||||
@Bucket @EndpointParam(parser = DefaultEndpointThenInvalidateRegion.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
|
||||
/**
|
||||
* @see S3Client#bucketExists
|
||||
*/
|
||||
@Named("BucketExists")
|
||||
@HEAD
|
||||
@Path("/")
|
||||
@Fallback(FalseOnContainerNotFound.class)
|
||||
ListenableFuture<Boolean> bucketExists(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
|
||||
|
||||
/**
|
||||
* @see S3Client#getBucketLocation
|
||||
*/
|
||||
@Named("GetBucketLocation")
|
||||
@GET
|
||||
@QueryParams(keys = "location")
|
||||
@Path("/")
|
||||
@Endpoint(Bucket.class)
|
||||
@XMLResponseParser(LocationConstraintHandler.class)
|
||||
ListenableFuture<String> getBucketLocation(
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
|
||||
/**
|
||||
* @see S3Client#getBucketPayer
|
||||
*/
|
||||
@Named("GetBucketRequestPayment")
|
||||
@GET
|
||||
@QueryParams(keys = "requestPayment")
|
||||
@Path("/")
|
||||
@XMLResponseParser(PayerHandler.class)
|
||||
ListenableFuture<Payer> getBucketPayer(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
|
||||
/**
|
||||
* @see S3Client#setBucketPayer
|
||||
*/
|
||||
@Named("PutBucketRequestPayment")
|
||||
@PUT
|
||||
@QueryParams(keys = "requestPayment")
|
||||
@Path("/")
|
||||
ListenableFuture<Void> setBucketPayer(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@BinderParam(BindPayerToXmlPayload.class) Payer payer);
|
||||
|
||||
/**
|
||||
* @see S3Client#listBucket
|
||||
*/
|
||||
@Named("ListBucket")
|
||||
@GET
|
||||
@Path("/")
|
||||
@XMLResponseParser(ListBucketHandler.class)
|
||||
ListenableFuture<ListBucketResponse> listBucket(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
ListBucketOptions... options);
|
||||
|
||||
/**
|
||||
* @see S3Client#listOwnedBuckets
|
||||
*/
|
||||
@Named("ListAllMyBuckets")
|
||||
@GET
|
||||
@XMLResponseParser(ListAllMyBucketsHandler.class)
|
||||
@Path("/")
|
||||
@VirtualHost
|
||||
ListenableFuture<? extends Set<BucketMetadata>> listOwnedBuckets();
|
||||
|
||||
/**
|
||||
* @see S3Client#copyObject
|
||||
*/
|
||||
@Named("PutObject")
|
||||
@PUT
|
||||
@Path("/{destinationObject}")
|
||||
@Headers(keys = "x-amz-copy-source", values = "/{sourceBucket}/{sourceObject}")
|
||||
@XMLResponseParser(CopyObjectHandler.class)
|
||||
ListenableFuture<ObjectMetadata> copyObject(
|
||||
@PathParam("sourceBucket") String sourceBucket,
|
||||
@PathParam("sourceObject") String sourceObject,
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String destinationBucket,
|
||||
@PathParam("destinationObject") String destinationObject, CopyObjectOptions... options);
|
||||
|
||||
/**
|
||||
* @see S3Client#getBucketACL
|
||||
*/
|
||||
@Named("GetBucketAcl")
|
||||
@GET
|
||||
@QueryParams(keys = "acl")
|
||||
@XMLResponseParser(AccessControlListHandler.class)
|
||||
@Fallback(ThrowContainerNotFoundOn404.class)
|
||||
@Path("/")
|
||||
ListenableFuture<AccessControlList> getBucketACL(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
|
||||
/**
|
||||
* @see S3Client#putBucketACL
|
||||
*/
|
||||
@Named("PutBucketAcl")
|
||||
@PUT
|
||||
@Path("/")
|
||||
@QueryParams(keys = "acl")
|
||||
ListenableFuture<Boolean> putBucketACL(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@BinderParam(BindACLToXMLPayload.class) AccessControlList acl);
|
||||
|
||||
/**
|
||||
* @see S3Client#getObjectACL
|
||||
*/
|
||||
@Named("GetObjectAcl")
|
||||
@GET
|
||||
@QueryParams(keys = "acl")
|
||||
@Path("/{key}")
|
||||
@XMLResponseParser(AccessControlListHandler.class)
|
||||
@Fallback(ThrowKeyNotFoundOn404.class)
|
||||
ListenableFuture<AccessControlList> getObjectACL(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key);
|
||||
|
||||
/**
|
||||
* @see S3Client#putObjectACL
|
||||
*/
|
||||
@Named("PutObjectAcl")
|
||||
@PUT
|
||||
@QueryParams(keys = "acl")
|
||||
@Path("/{key}")
|
||||
ListenableFuture<Boolean> putObjectACL(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key, @BinderParam(BindACLToXMLPayload.class) AccessControlList acl);
|
||||
|
||||
/**
|
||||
* @see S3Client#getBucketLogging
|
||||
*/
|
||||
@Named("GetBucketLogging")
|
||||
@GET
|
||||
@QueryParams(keys = "logging")
|
||||
@XMLResponseParser(BucketLoggingHandler.class)
|
||||
@Fallback(ThrowContainerNotFoundOn404.class)
|
||||
@Path("/")
|
||||
ListenableFuture<BucketLogging> getBucketLogging(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
|
||||
/**
|
||||
* @see S3Client#enableBucketLogging
|
||||
*/
|
||||
@Named("PutBucketLogging")
|
||||
@PUT
|
||||
@Path("/")
|
||||
@QueryParams(keys = "logging")
|
||||
ListenableFuture<Void> enableBucketLogging(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@BinderParam(BindBucketLoggingToXmlPayload.class) BucketLogging logging);
|
||||
|
||||
/**
|
||||
* @see S3Client#putBucketLogging
|
||||
*/
|
||||
@Named("PutBucketLogging")
|
||||
@PUT
|
||||
@Path("/")
|
||||
@QueryParams(keys = "logging")
|
||||
@Produces(MediaType.TEXT_XML)
|
||||
ListenableFuture<Void> disableBucketLogging(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindNoBucketLoggingToXmlPayload.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
|
||||
}
|
|
@ -16,11 +16,51 @@
|
|||
*/
|
||||
package org.jclouds.s3;
|
||||
|
||||
import static com.google.common.net.HttpHeaders.EXPECT;
|
||||
import static org.jclouds.blobstore.attr.BlobScopes.CONTAINER;
|
||||
import static org.jclouds.s3.S3Fallbacks.TrueOn404OrNotFoundFalseOnIllegalState;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HEAD;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
|
||||
import org.jclouds.blobstore.BlobStoreFallbacks.FalseOnContainerNotFound;
|
||||
import org.jclouds.blobstore.BlobStoreFallbacks.FalseOnKeyNotFound;
|
||||
import org.jclouds.blobstore.BlobStoreFallbacks.NullOnKeyNotFound;
|
||||
import org.jclouds.blobstore.BlobStoreFallbacks.ThrowContainerNotFoundOn404;
|
||||
import org.jclouds.blobstore.BlobStoreFallbacks.ThrowKeyNotFoundOn404;
|
||||
import org.jclouds.blobstore.attr.BlobScope;
|
||||
import org.jclouds.http.functions.ParseETagHeader;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.Endpoint;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.annotations.ParamParser;
|
||||
import org.jclouds.rest.annotations.ParamValidators;
|
||||
import org.jclouds.rest.annotations.QueryParams;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.ResponseParser;
|
||||
import org.jclouds.rest.annotations.VirtualHost;
|
||||
import org.jclouds.rest.annotations.XMLResponseParser;
|
||||
import org.jclouds.s3.binders.BindACLToXMLPayload;
|
||||
import org.jclouds.s3.binders.BindAsHostPrefixIfConfigured;
|
||||
import org.jclouds.s3.binders.BindBucketLoggingToXmlPayload;
|
||||
import org.jclouds.s3.binders.BindNoBucketLoggingToXmlPayload;
|
||||
import org.jclouds.s3.binders.BindPayerToXmlPayload;
|
||||
import org.jclouds.s3.binders.BindS3ObjectMetadataToRequest;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
import org.jclouds.s3.domain.BucketLogging;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
|
@ -28,22 +68,34 @@ import org.jclouds.s3.domain.ListBucketResponse;
|
|||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.domain.Payer;
|
||||
import org.jclouds.s3.domain.S3Object;
|
||||
import org.jclouds.s3.fallbacks.FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists;
|
||||
import org.jclouds.s3.filters.RequestAuthorizeSignature;
|
||||
import org.jclouds.s3.functions.AssignCorrectHostnameForBucket;
|
||||
import org.jclouds.s3.functions.BindRegionToXmlPayload;
|
||||
import org.jclouds.s3.functions.DefaultEndpointThenInvalidateRegion;
|
||||
import org.jclouds.s3.functions.ObjectKey;
|
||||
import org.jclouds.s3.functions.ParseObjectFromHeadersAndHttpContent;
|
||||
import org.jclouds.s3.functions.ParseObjectMetadataFromHeaders;
|
||||
import org.jclouds.s3.options.CopyObjectOptions;
|
||||
import org.jclouds.s3.options.ListBucketOptions;
|
||||
import org.jclouds.s3.options.PutBucketOptions;
|
||||
import org.jclouds.s3.options.PutObjectOptions;
|
||||
import org.jclouds.s3.predicates.validators.BucketNameValidator;
|
||||
import org.jclouds.s3.xml.AccessControlListHandler;
|
||||
import org.jclouds.s3.xml.BucketLoggingHandler;
|
||||
import org.jclouds.s3.xml.CopyObjectHandler;
|
||||
import org.jclouds.s3.xml.ListAllMyBucketsHandler;
|
||||
import org.jclouds.s3.xml.ListBucketHandler;
|
||||
import org.jclouds.s3.xml.LocationConstraintHandler;
|
||||
import org.jclouds.s3.xml.PayerHandler;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Provides access to S3 via their REST API.
|
||||
* <p/>
|
||||
* All commands return a Future of the result from S3. Any exceptions incurred during
|
||||
* processing will be backend in an {@link ExecutionException} as documented in
|
||||
* {@link Future#get()}.
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAPI.html" />
|
||||
*/
|
||||
@RequestFilters(RequestAuthorizeSignature.class)
|
||||
@BlobScope(CONTAINER)
|
||||
public interface S3Client extends Closeable {
|
||||
|
||||
/**
|
||||
|
@ -60,14 +112,14 @@ public interface S3Client extends Closeable {
|
|||
* anonymous user, you can request the object without an authorization header.
|
||||
*
|
||||
* <p />
|
||||
* This command allows you to specify {@link GetObjectOptions} to control delivery of content.
|
||||
* This command allows you to specify {@link GetOptions} to control delivery of content.
|
||||
*
|
||||
* <h2>Note</h2>
|
||||
* If you specify any of the below options, you will receive partial content:
|
||||
* <ul>
|
||||
* <li>{@link GetObjectOptions#range}</li>
|
||||
* <li>{@link GetObjectOptions#startAt}</li>
|
||||
* <li>{@link GetObjectOptions#tail}</li>
|
||||
* <li>{@link GetOptions#range}</li>
|
||||
* <li>{@link GetOptions#startAt}</li>
|
||||
* <li>{@link GetOptions#tail}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param bucketName
|
||||
|
@ -75,20 +127,23 @@ public interface S3Client extends Closeable {
|
|||
* @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.
|
||||
* or null 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 GetObjectOptions
|
||||
*/
|
||||
S3Object getObject(String bucketName, String key, GetOptions... options);
|
||||
@Named("GetObject")
|
||||
@GET
|
||||
@Path("/{key}")
|
||||
@Fallback(NullOnKeyNotFound.class)
|
||||
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
|
||||
S3Object getObject(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key, GetOptions... options);
|
||||
|
||||
/**
|
||||
* Retrieves the {@link org.jclouds.s3.domain.internal.BucketListObjectMetadata metadata} of
|
||||
* the object associated with the key or
|
||||
* {@link org.jclouds.s3.domain.internal.BucketListObjectMetadata#NOT_FOUND} if not
|
||||
* available.
|
||||
* the object associated with the key or null if not available.
|
||||
*
|
||||
* <p/>
|
||||
* The HEAD operation is used to retrieve information about a specific object or object size,
|
||||
|
@ -96,21 +151,26 @@ public interface S3Client extends Closeable {
|
|||
* object metadata, and don't want to waste bandwidth on the object data.
|
||||
*
|
||||
*
|
||||
* @param bucketName
|
||||
* namespace of the metadata you are retrieving
|
||||
* @param key
|
||||
* unique key in the s3Bucket identifying the object
|
||||
* @return metadata associated with the key or
|
||||
* {@link org.jclouds.s3.domain.internal.BucketListObjectMetadata#NOT_FOUND} if not
|
||||
* present;
|
||||
* @see #getObject(String, String)
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectHEAD.html"
|
||||
* />
|
||||
* @param bucketName namespace of the metadata you are retrieving
|
||||
* @param key unique key in the s3Bucket identifying the object
|
||||
* @return metadata associated with the key or null if not present.
|
||||
*/
|
||||
ObjectMetadata headObject(String bucketName, String key);
|
||||
@Named("GetObject")
|
||||
@HEAD
|
||||
@Path("/{key}")
|
||||
@Fallback(NullOnKeyNotFound.class)
|
||||
@ResponseParser(ParseObjectMetadataFromHeaders.class)
|
||||
ObjectMetadata headObject(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key);
|
||||
|
||||
boolean objectExists(String bucketName, String key);
|
||||
@Named("GetObject")
|
||||
@HEAD
|
||||
@Path("/{key}")
|
||||
@Fallback(FalseOnKeyNotFound.class)
|
||||
boolean objectExists(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key);
|
||||
|
||||
/**
|
||||
* Removes the object and metadata associated with the key.
|
||||
|
@ -125,10 +185,14 @@ public interface S3Client extends Closeable {
|
|||
* unique key in the s3Bucket identifying the object
|
||||
* @throws org.jclouds.http.HttpResponseException
|
||||
* if the bucket is not available
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?
|
||||
* RESTObjectDELETE.html" />
|
||||
*/
|
||||
void deleteObject(String bucketName, String key);
|
||||
@Named("DeleteObject")
|
||||
@DELETE
|
||||
@Path("/{key}")
|
||||
@Fallback(VoidOnNotFoundOr404.class)
|
||||
void deleteObject(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key);
|
||||
|
||||
/**
|
||||
* Store data by creating or overwriting an object.
|
||||
|
@ -149,11 +213,16 @@ public interface S3Client extends Closeable {
|
|||
* @throws org.jclouds.http.HttpResponseException
|
||||
* if the conditions requested set are not satisfied by the object on the server.
|
||||
* @see org.jclouds.s3.domain.CannedAccessPolicy#PRIVATE
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT.html"
|
||||
* />
|
||||
*/
|
||||
String putObject(String bucketName, S3Object object, PutObjectOptions... options);
|
||||
@Named("PutObject")
|
||||
@PUT
|
||||
@Path("/{key}")
|
||||
@Headers(keys = EXPECT, values = "100-continue")
|
||||
@ResponseParser(ParseETagHeader.class)
|
||||
String putObject(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") @ParamParser(ObjectKey.class) @BinderParam(BindS3ObjectMetadataToRequest.class)
|
||||
S3Object object, PutObjectOptions... options);
|
||||
|
||||
/**
|
||||
* Create and name your own bucket in which to store your objects.
|
||||
|
@ -171,12 +240,15 @@ public interface S3Client extends Closeable {
|
|||
* @return true, if the bucket was created or false, if the container was already present
|
||||
*
|
||||
* @see PutBucketOptions
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT.html"
|
||||
* />
|
||||
*
|
||||
*/
|
||||
boolean putBucketInRegion(@Nullable String region, @Bucket String bucketName, PutBucketOptions... options);
|
||||
@Named("CreateBucket")
|
||||
@PUT
|
||||
@Path("/")
|
||||
@Endpoint(Bucket.class)
|
||||
@Fallback(FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists.class)
|
||||
boolean putBucketInRegion(@BinderParam(BindRegionToXmlPayload.class) @Nullable String region,
|
||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class)
|
||||
String bucketName, PutBucketOptions... options);
|
||||
|
||||
/**
|
||||
* Deletes the bucket, if it is empty.
|
||||
|
@ -187,20 +259,26 @@ public interface S3Client extends Closeable {
|
|||
* Only the owner of a bucket can delete it, regardless of the bucket's access control policy.
|
||||
*
|
||||
*
|
||||
* @param bucketName
|
||||
* what to delete
|
||||
* @param bucketName what to delete
|
||||
* @return false, if the bucket was not empty and therefore not deleted
|
||||
* @see org.jclouds.s3.commands.DeleteBucket
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketDELETE.html"
|
||||
* />
|
||||
*/
|
||||
boolean deleteBucketIfEmpty(String bucketName);
|
||||
@Named("DeleteBucket")
|
||||
@DELETE
|
||||
@Path("/")
|
||||
@Fallback(TrueOn404OrNotFoundFalseOnIllegalState.class)
|
||||
boolean deleteBucketIfEmpty(@Bucket @EndpointParam(parser = DefaultEndpointThenInvalidateRegion.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
|
||||
|
||||
/**
|
||||
* Issues a HEAD command to determine if the bucket exists or not.
|
||||
*/
|
||||
boolean bucketExists(String bucketName);
|
||||
@Named("BucketExists")
|
||||
@HEAD
|
||||
@Path("/")
|
||||
@Fallback(FalseOnContainerNotFound.class)
|
||||
boolean bucketExists(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
|
||||
/**
|
||||
* Retrieve a {@code S3Bucket} listing. A GET request operation using a bucket URI lists
|
||||
|
@ -210,53 +288,60 @@ public interface S3Client extends Closeable {
|
|||
* To list the keys of a bucket, you must have READ access to the bucket.
|
||||
* <p/>
|
||||
*
|
||||
* @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<ObjectMetadata>#NOT_FOUND} if not present.
|
||||
* @param bucketName namespace of the objects you wish to list
|
||||
* @return potentially empty or partial list of the bucket.
|
||||
* @see ListBucketOptions
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html"
|
||||
* />
|
||||
*/
|
||||
ListBucketResponse listBucket(String bucketName, ListBucketOptions... options);
|
||||
@Named("ListBucket")
|
||||
@GET
|
||||
@Path("/")
|
||||
@XMLResponseParser(ListBucketHandler.class)
|
||||
ListBucketResponse listBucket(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) 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 <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTServiceGET.html"
|
||||
* />
|
||||
*
|
||||
*/
|
||||
@Named("ListAllMyBuckets")
|
||||
@GET
|
||||
@XMLResponseParser(ListAllMyBucketsHandler.class)
|
||||
@Path("/")
|
||||
@VirtualHost
|
||||
Set<BucketMetadata> listOwnedBuckets();
|
||||
|
||||
|
||||
/**
|
||||
* Copies one object to another bucket, retaining UserMetadata from the source. The destination
|
||||
* will have a private acl. The copy operation creates a copy of an object that is already stored
|
||||
* in Amazon S3.
|
||||
* <p/>
|
||||
* When copying an object, you can preserve all metadata (default) or
|
||||
* {@link CopyObjectOptions#overrideMetadataWith(com.google.common.collect.Multimap) specify new
|
||||
* {@link CopyObjectOptions#overrideMetadataWith(java.util.Map)} specify new
|
||||
* metadata}. However, the ACL is not preserved and is set to private for the user making the
|
||||
* request. To override the default ACL setting,
|
||||
* {@link CopyObjectOptions#overrideAcl(org.jclouds.s3.domain.CannedAccessPolicy) specify a
|
||||
* new ACL} when generating a copy request.
|
||||
*
|
||||
* @return metadata populated with lastModified and eTag of the new object
|
||||
* @see org.jclouds.s3.commands.CopyObject
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectCOPY.html"
|
||||
* />
|
||||
* @throws org.jclouds.http.HttpResponseException
|
||||
* if the conditions requested set are not satisfied by the object on the server.
|
||||
* @see CopyObjectOptions
|
||||
* @see org.jclouds.s3.domain.CannedAccessPolicy
|
||||
*/
|
||||
ObjectMetadata copyObject(String sourceBucket, String sourceObject, String destinationBucket,
|
||||
String destinationObject, CopyObjectOptions... options);
|
||||
@Named("PutObject")
|
||||
@PUT
|
||||
@Path("/{destinationObject}")
|
||||
@Headers(keys = "x-amz-copy-source", values = "/{sourceBucket}/{sourceObject}")
|
||||
@XMLResponseParser(CopyObjectHandler.class)
|
||||
ObjectMetadata copyObject(@PathParam("sourceBucket") String sourceBucket,
|
||||
@PathParam("sourceObject") String sourceObject,
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String destinationBucket,
|
||||
@PathParam("destinationObject") String destinationObject, CopyObjectOptions... options);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -266,10 +351,16 @@ public interface S3Client extends Closeable {
|
|||
* To list a bucket's ACL, you must have READ_ACP access to the item.
|
||||
*
|
||||
* @return access permissions of the bucket
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html"/>
|
||||
*/
|
||||
AccessControlList getBucketACL(String bucketName);
|
||||
@Named("GetBucketAcl")
|
||||
@GET
|
||||
@QueryParams(keys = "acl")
|
||||
@XMLResponseParser(AccessControlListHandler.class)
|
||||
@Fallback(ThrowContainerNotFoundOn404.class)
|
||||
@Path("/")
|
||||
AccessControlList getBucketACL(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
|
||||
|
||||
/**
|
||||
* Update a bucket's Access Control List settings.
|
||||
|
@ -285,10 +376,14 @@ public interface S3Client extends Closeable {
|
|||
* the ACL to apply to the bucket. This acl object <strong>must</strong include a valid
|
||||
* owner identifier string in {@link AccessControlList#getOwner()}.
|
||||
* @return true if the bucket's Access Control List was updated successfully.
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html"/>
|
||||
*/
|
||||
boolean putBucketACL(String bucketName, AccessControlList acl);
|
||||
@Named("PutBucketAcl")
|
||||
@PUT
|
||||
@Path("/")
|
||||
@QueryParams(keys = "acl")
|
||||
boolean putBucketACL(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@BinderParam(BindACLToXMLPayload.class) AccessControlList acl);
|
||||
|
||||
/**
|
||||
* A GET request operation directed at an object or bucket URI with the "acl" parameter retrieves
|
||||
|
@ -297,10 +392,16 @@ public interface S3Client extends Closeable {
|
|||
* To list a object's ACL, you must have READ_ACP access to the item.
|
||||
*
|
||||
* @return access permissions of the object
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html"/>
|
||||
*/
|
||||
AccessControlList getObjectACL(String bucketName, String key);
|
||||
@Named("GetObjectAcl")
|
||||
@GET
|
||||
@QueryParams(keys = "acl")
|
||||
@Path("/{key}")
|
||||
@XMLResponseParser(AccessControlListHandler.class)
|
||||
@Fallback(ThrowKeyNotFoundOn404.class)
|
||||
AccessControlList getObjectACL(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key);
|
||||
|
||||
/**
|
||||
* Update an object's Access Control List settings.
|
||||
|
@ -310,18 +411,23 @@ public interface S3Client extends Closeable {
|
|||
* <p />
|
||||
* To set a bucket or object's ACL, you must have WRITE_ACP or FULL_CONTROL access to the item.
|
||||
*
|
||||
* @param bucket
|
||||
* @param bucketName
|
||||
* the bucket containing the object to be updated
|
||||
* @param objectKey
|
||||
* @param key
|
||||
* the key of the object whose Access Control List settings will be updated.
|
||||
* @param acl
|
||||
* the ACL to apply to the object. This acl object <strong>must</strong include a valid
|
||||
* owner identifier string in {@link AccessControlList#getOwner()}.
|
||||
* @return true if the object's Access Control List was updated successfully.
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html"/>
|
||||
*/
|
||||
boolean putObjectACL(String bucketName, String key, AccessControlList acl);
|
||||
@Named("PutObjectAcl")
|
||||
@PUT
|
||||
@QueryParams(keys = "acl")
|
||||
@Path("/{key}")
|
||||
boolean putObjectACL(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key, @BinderParam(BindACLToXMLPayload.class) AccessControlList acl);
|
||||
|
||||
|
||||
/**
|
||||
* A GET location request operation using a bucket URI lists the location constraint of the
|
||||
|
@ -329,16 +435,20 @@ public interface S3Client extends Closeable {
|
|||
* <p/>
|
||||
* To view the location constraint of a bucket, you must be the bucket owner.
|
||||
*
|
||||
* @param bucket
|
||||
* @param bucketName
|
||||
* the bucket you wish to know where exists
|
||||
*
|
||||
* @return location of the bucket
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AmazonS3/latest/index.html?RESTBucketLocationGET.html"
|
||||
* />
|
||||
*/
|
||||
String getBucketLocation(String bucketName);
|
||||
@Named("GetBucketLocation")
|
||||
@GET
|
||||
@QueryParams(keys = "location")
|
||||
@Path("/")
|
||||
@Endpoint(Bucket.class)
|
||||
@XMLResponseParser(LocationConstraintHandler.class)
|
||||
String getBucketLocation(@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(
|
||||
BucketNameValidator.class) String bucketName);
|
||||
|
||||
|
||||
/**
|
||||
* A GET request operation on a requestPayment resource returns the request payment configuration
|
||||
|
@ -349,14 +459,17 @@ public interface S3Client extends Closeable {
|
|||
* @param bucketName
|
||||
* the bucket you wish to know the payer status
|
||||
*
|
||||
* @return {@link Payer.REQUESTER} for a Requester Pays bucket, and {@link Payer.BUCKET_OWNER},
|
||||
* @return {@link Payer#REQUESTER} for a Requester Pays bucket, and {@link Payer#BUCKET_OWNER},
|
||||
* for a normal bucket.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AmazonS3/latest/index.html?RESTrequestPaymentGET.html"
|
||||
* />
|
||||
*/
|
||||
Payer getBucketPayer(String bucketName);
|
||||
@Named("GetBucketRequestPayment")
|
||||
@GET
|
||||
@QueryParams(keys = "requestPayment")
|
||||
@Path("/")
|
||||
@XMLResponseParser(PayerHandler.class)
|
||||
Payer getBucketPayer(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
|
||||
|
||||
/**
|
||||
* The PUT request operation with a requestPayment URI configures an existing bucket to be
|
||||
|
@ -371,14 +484,19 @@ public interface S3Client extends Closeable {
|
|||
* the bucket you wish to know the payer status
|
||||
*
|
||||
* @param payer
|
||||
* {@link Payer.REQUESTER} for a Requester Pays bucket, and {@link Payer.BUCKET_OWNER},
|
||||
* {@link Payer#REQUESTER} for a Requester Pays bucket, and {@link Payer#BUCKET_OWNER},
|
||||
* for a normal bucket.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AmazonS3/latest/index.html?RESTrequestPaymentPUT.html"
|
||||
* />
|
||||
*/
|
||||
void setBucketPayer(String bucketName, Payer payer);
|
||||
@Named("PutBucketRequestPayment")
|
||||
@PUT
|
||||
@QueryParams(keys = "requestPayment")
|
||||
@Path("/")
|
||||
void setBucketPayer(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@BinderParam(BindPayerToXmlPayload.class) Payer payer);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Inspects the logging status for a bucket.
|
||||
|
@ -387,11 +505,16 @@ public interface S3Client extends Closeable {
|
|||
* @param bucketName
|
||||
* the bucket you wish to know the logging status
|
||||
* @return bucketLogging configuration or null, if not configured
|
||||
*
|
||||
* @see <a href= "http://docs.amazonwebservices.com/AmazonS3/latest/index.html?ServerLogs.html"
|
||||
* />
|
||||
*/
|
||||
BucketLogging getBucketLogging(String bucketName);
|
||||
@Named("GetBucketLogging")
|
||||
@GET
|
||||
@QueryParams(keys = "logging")
|
||||
@XMLResponseParser(BucketLoggingHandler.class)
|
||||
@Fallback(ThrowContainerNotFoundOn404.class)
|
||||
@Path("/")
|
||||
BucketLogging getBucketLogging(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
|
||||
|
||||
/**
|
||||
* Enables logging for a bucket.
|
||||
|
@ -400,19 +523,26 @@ public interface S3Client extends Closeable {
|
|||
* the bucket you wish to enable logging for
|
||||
* @param logging
|
||||
* configuration including destination, prefix, and access rules
|
||||
* @see <a href= "http://docs.amazonwebservices.com/AmazonS3/latest/index.html?ServerLogs.html"
|
||||
* />
|
||||
*/
|
||||
void enableBucketLogging(String bucketName, BucketLogging logging);
|
||||
@Named("PutBucketLogging")
|
||||
@PUT
|
||||
@Path("/")
|
||||
@QueryParams(keys = "logging")
|
||||
void enableBucketLogging(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@BinderParam(BindBucketLoggingToXmlPayload.class) BucketLogging logging);
|
||||
|
||||
/**
|
||||
* Disables logging for a bucket.
|
||||
*
|
||||
* @param bucketName
|
||||
* the bucket you wish to disable logging for
|
||||
*
|
||||
* @see <a href= "http://docs.amazonwebservices.com/AmazonS3/latest/index.html?ServerLogs.html"
|
||||
* />
|
||||
*/
|
||||
void disableBucketLogging(String bucketName);
|
||||
@Named("PutBucketLogging")
|
||||
@PUT
|
||||
@Path("/")
|
||||
@QueryParams(keys = "logging")
|
||||
@Produces(MediaType.TEXT_XML)
|
||||
void disableBucketLogging(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindNoBucketLoggingToXmlPayload.class) @ParamValidators(BucketNameValidator.class) String bucketName);
|
||||
}
|
||||
|
|
|
@ -1,273 +0,0 @@
|
|||
/*
|
||||
* 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.s3.blobstore;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.util.concurrent.Futures.transform;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.domain.PageSet;
|
||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.blobstore.options.PutOptions;
|
||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
import org.jclouds.collect.Memoized;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.s3.blobstore.functions.BucketToResourceList;
|
||||
import org.jclouds.s3.blobstore.functions.ContainerToBucketListOptions;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlobMetadata;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
import org.jclouds.s3.domain.AccessControlList.GroupGranteeURI;
|
||||
import org.jclouds.s3.domain.AccessControlList.Permission;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
import org.jclouds.s3.domain.CannedAccessPolicy;
|
||||
import org.jclouds.s3.domain.ListBucketResponse;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.options.ListBucketOptions;
|
||||
import org.jclouds.s3.options.PutBucketOptions;
|
||||
import org.jclouds.s3.options.PutObjectOptions;
|
||||
import org.jclouds.s3.util.S3Utils;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated will be removed in jclouds 1.7, as async interfaces are no longer
|
||||
* supported. Please use {@link S3BlobStore}
|
||||
*/
|
||||
@Deprecated
|
||||
@Singleton
|
||||
public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
||||
|
||||
private final S3AsyncClient async;
|
||||
private final S3Client sync;
|
||||
private final Function<Set<BucketMetadata>, PageSet<? extends StorageMetadata>> convertBucketsToStorageMetadata;
|
||||
private final ContainerToBucketListOptions container2BucketListOptions;
|
||||
private final BlobToHttpGetOptions blob2ObjectGetOptions;
|
||||
private final BucketToResourceList bucket2ResourceList;
|
||||
private final ObjectToBlob object2Blob;
|
||||
private final BlobToObject blob2Object;
|
||||
private final ObjectToBlobMetadata object2BlobMd;
|
||||
private final Provider<FetchBlobMetadata> fetchBlobMetadataProvider;
|
||||
private final LoadingCache<String, AccessControlList> bucketAcls;
|
||||
|
||||
@Inject
|
||||
protected S3AsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, S3AsyncClient async, S3Client sync,
|
||||
Function<Set<BucketMetadata>, PageSet<? extends StorageMetadata>> convertBucketsToStorageMetadata,
|
||||
ContainerToBucketListOptions container2BucketListOptions, BucketToResourceList bucket2ResourceList,
|
||||
ObjectToBlob object2Blob, BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object,
|
||||
ObjectToBlobMetadata object2BlobMd, Provider<FetchBlobMetadata> fetchBlobMetadataProvider,
|
||||
LoadingCache<String, AccessControlList> bucketAcls) {
|
||||
super(context, blobUtils, userExecutor, defaultLocation, locations);
|
||||
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
||||
this.async = checkNotNull(async, "async");
|
||||
this.sync = checkNotNull(sync, "sync");
|
||||
this.convertBucketsToStorageMetadata = checkNotNull(convertBucketsToStorageMetadata, "convertBucketsToStorageMetadata");
|
||||
this.container2BucketListOptions = checkNotNull(container2BucketListOptions, "container2BucketListOptions");
|
||||
this.bucket2ResourceList = checkNotNull(bucket2ResourceList, "bucket2ResourceList");
|
||||
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
|
||||
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
|
||||
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
|
||||
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider");
|
||||
this.bucketAcls = checkNotNull(bucketAcls, "bucketAcls");
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation invokes {@link S3AsyncClient#listOwnedBuckets}
|
||||
*/
|
||||
@Override
|
||||
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
|
||||
return transform(async.listOwnedBuckets(),
|
||||
new Function<Set<BucketMetadata>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
|
||||
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(Set<BucketMetadata> from) {
|
||||
return convertBucketsToStorageMetadata.apply(from);
|
||||
}
|
||||
}, userExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation invokes {@link S3AsyncClient#bucketExists}
|
||||
*
|
||||
* @param container
|
||||
* bucket name
|
||||
*/
|
||||
@Override
|
||||
public ListenableFuture<Boolean> containerExists(String container) {
|
||||
return async.bucketExists(container);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation invokes {@link S3AsyncClient#putBucketInRegion}
|
||||
*
|
||||
* @param location
|
||||
* corresponds to Region
|
||||
* @param container
|
||||
* bucket name
|
||||
*/
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container) {
|
||||
return createContainerInLocation(location, container, CreateContainerOptions.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation invokes {@link S3AsyncClient#listBucket}
|
||||
*
|
||||
* @param container
|
||||
* bucket name
|
||||
*/
|
||||
@Override
|
||||
// TODO get rid of transform, as it serializes async results when the executor is single-threaded.
|
||||
public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container, ListContainerOptions options) {
|
||||
ListBucketOptions httpOptions = container2BucketListOptions.apply(options);
|
||||
ListenableFuture<ListBucketResponse> returnVal = async.listBucket(container, httpOptions);
|
||||
ListenableFuture<PageSet<? extends StorageMetadata>> list = transform(returnVal, bucket2ResourceList,
|
||||
userExecutor);
|
||||
return (options.isDetailed()) ? transform(list,
|
||||
fetchBlobMetadataProvider.get().setContainerName(container), userExecutor) : list;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation invokes {@link S3Utils#deleteAndVerifyContainerGone}
|
||||
*/
|
||||
protected boolean deleteAndVerifyContainerGone(final String container) {
|
||||
return S3Utils.deleteAndVerifyContainerGone(sync, container);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation invokes {@link S3AsyncClient#objectExists}
|
||||
*
|
||||
* @param container
|
||||
* bucket name
|
||||
* @param key
|
||||
* object key
|
||||
*/
|
||||
@Override
|
||||
public ListenableFuture<Boolean> blobExists(String container, String key) {
|
||||
return async.objectExists(container, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation invokes {@link S3AsyncClient#headObject}
|
||||
*
|
||||
* @param container
|
||||
* bucket name
|
||||
* @param key
|
||||
* object key
|
||||
*/
|
||||
@Override
|
||||
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
|
||||
return transform(async.headObject(container, key), new Function<ObjectMetadata, BlobMetadata>() {
|
||||
|
||||
@Override
|
||||
public BlobMetadata apply(ObjectMetadata from) {
|
||||
return object2BlobMd.apply(from);
|
||||
}
|
||||
|
||||
}, userExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation invokes {@link S3AsyncClient#getObject}
|
||||
*
|
||||
* @param container
|
||||
* bucket name
|
||||
* @param key
|
||||
* object key
|
||||
*/
|
||||
@Override
|
||||
public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) {
|
||||
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
|
||||
return transform(async.getObject(container, key, httpOptions), object2Blob, userExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation invokes {@link S3AsyncClient#putObject}
|
||||
*
|
||||
* @param container
|
||||
* bucket name
|
||||
* @param blob
|
||||
* object
|
||||
*/
|
||||
@Override
|
||||
public ListenableFuture<String> putBlob(String container, Blob blob) {
|
||||
return putBlob(container, blob, PutOptions.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<String> putBlob(String container, Blob blob, PutOptions overrides) {
|
||||
// TODO: Make use of options overrides
|
||||
PutObjectOptions options = new PutObjectOptions();
|
||||
try {
|
||||
AccessControlList acl = bucketAcls.getUnchecked(container);
|
||||
if (acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ))
|
||||
options.withAcl(CannedAccessPolicy.PUBLIC_READ);
|
||||
} catch (CacheLoader.InvalidCacheLoadException e) {
|
||||
// nulls not permitted from cache loader
|
||||
}
|
||||
return async.putObject(container, blob2Object.apply(blob), options);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation invokes {@link S3AsyncClient#deleteObject}
|
||||
*
|
||||
* @param container
|
||||
* bucket name
|
||||
* @param key
|
||||
* object key
|
||||
*/
|
||||
@Override
|
||||
public ListenableFuture<Void> removeBlob(String container, String key) {
|
||||
return async.deleteObject(container, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
|
||||
CreateContainerOptions options) {
|
||||
PutBucketOptions putBucketOptions = new PutBucketOptions();
|
||||
if (options.isPublicRead())
|
||||
putBucketOptions.withBucketAcl(CannedAccessPolicy.PUBLIC_READ);
|
||||
location = location != null ? location : defaultLocation.get();
|
||||
return async.putBucketInRegion(location.getId(), container, putBucketOptions);
|
||||
}
|
||||
|
||||
}
|
|
@ -30,7 +30,7 @@ import org.jclouds.http.HttpRequest;
|
|||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.reflect.Invocation;
|
||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.s3.domain.S3Object;
|
||||
import org.jclouds.s3.options.PutObjectOptions;
|
||||
|
@ -39,7 +39,7 @@ import com.google.common.collect.ImmutableList;
|
|||
import com.google.common.reflect.Invokable;
|
||||
|
||||
@Singleton
|
||||
public class S3BlobRequestSigner<T extends S3AsyncClient> implements BlobRequestSigner {
|
||||
public class S3BlobRequestSigner<T extends S3Client> implements BlobRequestSigner {
|
||||
protected final RestAnnotationProcessor processor;
|
||||
protected final BlobToObject blobToObject;
|
||||
protected final BlobToHttpGetOptions blob2HttpGetOptions;
|
||||
|
|
|
@ -26,7 +26,4 @@ public interface S3BlobStoreContext extends BlobStoreContext {
|
|||
|
||||
@Override
|
||||
S3BlobStore getBlobStore();
|
||||
|
||||
@Override
|
||||
S3AsyncBlobStore getAsyncBlobStore();
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ import org.jclouds.blobstore.AsyncBlobStore;
|
|||
import org.jclouds.blobstore.BlobRequestSigner;
|
||||
import org.jclouds.blobstore.BlobStore;
|
||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||
import org.jclouds.blobstore.internal.SubmissionAsyncBlobStore;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.blobstore.S3AsyncBlobStore;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.blobstore.S3BlobRequestSigner;
|
||||
import org.jclouds.s3.blobstore.S3BlobStore;
|
||||
import org.jclouds.s3.blobstore.functions.LocationFromBucketName;
|
||||
|
@ -42,15 +42,12 @@ import com.google.inject.AbstractModule;
|
|||
import com.google.inject.Provides;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* Configures the {@link S3BlobStoreContext}; requires {@link S3AsyncBlobStore} bound.
|
||||
*/
|
||||
public class S3BlobStoreContextModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL);
|
||||
bind(AsyncBlobStore.class).to(S3AsyncBlobStore.class).in(SINGLETON);
|
||||
bind(AsyncBlobStore.class).to(SubmissionAsyncBlobStore.class).in(SINGLETON);
|
||||
bind(BlobStore.class).to(S3BlobStore.class).in(SINGLETON);
|
||||
bind(new TypeLiteral<Function<String, Location>>() {
|
||||
}).to(LocationFromBucketName.class);
|
||||
|
@ -58,7 +55,7 @@ public class S3BlobStoreContextModule extends AbstractModule {
|
|||
}
|
||||
|
||||
protected void bindRequestSigner() {
|
||||
bind(BlobRequestSigner.class).to(new TypeLiteral<S3BlobRequestSigner<S3AsyncClient>>() {
|
||||
bind(BlobRequestSigner.class).to(new TypeLiteral<S3BlobRequestSigner<S3Client>>() {
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.jclouds.blobstore.attr.ConsistencyModel;
|
|||
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
||||
import org.jclouds.location.Provider;
|
||||
import org.jclouds.rest.Utils;
|
||||
import org.jclouds.s3.blobstore.S3AsyncBlobStore;
|
||||
import org.jclouds.s3.blobstore.S3BlobStore;
|
||||
import org.jclouds.s3.blobstore.S3BlobStoreContext;
|
||||
|
||||
|
@ -49,10 +48,4 @@ public class S3BlobStoreContextImpl extends BlobStoreContextImpl implements S3Bl
|
|||
public S3BlobStore getBlobStore() {
|
||||
return S3BlobStore.class.cast(super.getBlobStore());
|
||||
}
|
||||
|
||||
@Override
|
||||
public S3AsyncBlobStore getAsyncBlobStore() {
|
||||
return S3AsyncBlobStore.class.cast(super.getAsyncBlobStore());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.s3.config;
|
||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
|
@ -25,7 +24,7 @@ import javax.inject.Named;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.aws.config.AWSRestClientModule;
|
||||
import org.jclouds.aws.config.AWSHttpApiModule;
|
||||
import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
|
||||
import org.jclouds.aws.handlers.AWSServerErrorRetryHandler;
|
||||
import org.jclouds.blobstore.ContainerNotFoundException;
|
||||
|
@ -40,10 +39,9 @@ import org.jclouds.http.annotation.Redirection;
|
|||
import org.jclouds.http.annotation.ServerError;
|
||||
import org.jclouds.location.Region;
|
||||
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
import org.jclouds.rest.RequestSigner;
|
||||
import org.jclouds.s3.Bucket;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.blobstore.functions.BucketsToStorageMetadata;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
|
@ -60,7 +58,6 @@ import com.google.common.cache.CacheBuilder;
|
|||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Scopes;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
@ -68,16 +65,16 @@ import com.google.inject.TypeLiteral;
|
|||
/**
|
||||
* Configures the S3 connection, including logging and http transport.
|
||||
*/
|
||||
@ConfiguresRestClient
|
||||
public class S3RestClientModule<S extends S3Client, A extends S3AsyncClient> extends AWSRestClientModule<S, A> {
|
||||
@ConfiguresHttpApi
|
||||
public class S3HttpApiModule<S extends S3Client> extends AWSHttpApiModule<S> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public S3RestClientModule() {
|
||||
this(TypeToken.class.cast(typeToken(S3Client.class)), TypeToken.class.cast(typeToken(S3AsyncClient.class)));
|
||||
public S3HttpApiModule() {
|
||||
this(Class.class.cast(S3Client.class));
|
||||
}
|
||||
|
||||
protected S3RestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType) {
|
||||
super(syncClientType, asyncClientType);
|
||||
protected S3HttpApiModule(Class<S> syncClientType) {
|
||||
super(syncClientType);
|
||||
}
|
||||
|
||||
@Provides
|
|
@ -36,9 +36,6 @@ import com.google.common.collect.Sets;
|
|||
* has been granted to a specific {@link Grantee}. If an payload tries to access or modify an item
|
||||
* in S3, the operation will be denied unless the item has ACL settings that explicitly permit that
|
||||
* payload to perform that action.
|
||||
*
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html"/>
|
||||
*/
|
||||
public class AccessControlList {
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@ import com.google.common.collect.Sets;
|
|||
/**
|
||||
* Each Amazon S3 bucket has an associated XML sub-resource that you can read and write in order to
|
||||
* inspect or change the logging status for that bucket.
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/index.html?ServerLogs.html"/>
|
||||
*/
|
||||
public class BucketLogging {
|
||||
private final String targetBucket;
|
||||
|
|
|
@ -30,9 +30,6 @@ package org.jclouds.s3.domain;
|
|||
* is written with the private access control policy (even if, in the case of an
|
||||
* object, the object already exists with some other pre-existing access control
|
||||
* policy).
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?
|
||||
* RESTAccessPolicy.html" />
|
||||
*/
|
||||
public enum CannedAccessPolicy {
|
||||
|
||||
|
|
|
@ -21,9 +21,6 @@ package org.jclouds.s3.domain;
|
|||
* 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.
|
||||
* <p/>
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?
|
||||
* RESTAccessPolicy.html" />
|
||||
*/
|
||||
public class CanonicalUser {
|
||||
private final String id;
|
||||
|
@ -40,7 +37,7 @@ public class CanonicalUser {
|
|||
|
||||
/**
|
||||
* To locate the CanonicalUser ID for a user, the user must perform the
|
||||
* {@link org.jclouds.s3.blobstore.S3AsyncBlobStore#list(String)} and retrieve
|
||||
* {@link org.jclouds.s3.blobstore.S3BlobStore#list(String)} and retrieve
|
||||
* {@link BucketMetadata#getOwner()}
|
||||
*/
|
||||
public String getId() {
|
||||
|
|
|
@ -37,8 +37,6 @@ import java.util.Set;
|
|||
* 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?
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html" />
|
||||
*/
|
||||
public interface ListBucketResponse extends Set<ObjectMetadata> {
|
||||
|
||||
|
|
|
@ -26,14 +26,10 @@ import org.jclouds.s3.domain.internal.MutableObjectMetadataImpl;
|
|||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
* /** Amazon S3 is designed to store objects. Objects are stored in {@link S3BucketListing buckets}
|
||||
* and consist of a {@link org.jclouds.s3.domain.S3Object#getData() value}, a
|
||||
* {@link S3Object#getKey key}, {@link MutableObjectMetadata#getUserMetadata() metadata}, and an
|
||||
* /** Amazon S3 is designed to store objects. Objects are stored in {@link ListBucketResponse buckets}
|
||||
* and consist of a {@link S3Object#getPayload()} value}, a
|
||||
* {@link MutableObjectMetadata#getKey key}, {@link MutableObjectMetadata#getUserMetadata() metadata}, and an
|
||||
* access control policy.
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html"
|
||||
*
|
||||
* @see <a href= "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingMetadata.html" />
|
||||
*/
|
||||
@ImplementedBy(MutableObjectMetadataImpl.class)
|
||||
public interface MutableObjectMetadata extends ObjectMetadata {
|
||||
|
@ -42,8 +38,6 @@ public interface MutableObjectMetadata extends ObjectMetadata {
|
|||
* 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 <a href= "http://docs.amazonwebservices.com/AmazonHTTP/2006-03-01/UsingKeys.html" />
|
||||
*/
|
||||
void setKey(String key);
|
||||
|
||||
|
|
|
@ -27,10 +27,6 @@ import org.jclouds.io.ContentMetadata;
|
|||
* and consist of a {@link org.jclouds.s3.domain.S3Object#getData() value}, a
|
||||
* {@link S3Object#getKey key}, {@link ObjectMetadata#getUserMetadata() metadata}, and an access
|
||||
* control policy.
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html"
|
||||
*
|
||||
* @see <a href= "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingMetadata.html" />
|
||||
*/
|
||||
public interface ObjectMetadata extends Comparable<ObjectMetadata> {
|
||||
|
||||
|
|
|
@ -52,9 +52,6 @@ import com.google.common.base.CaseFormat;
|
|||
* You cannot use a Requester Pays bucket as the target bucket for end user logging, or vice versa.
|
||||
* However, you can turn on end user logging on a Requester Pays bucket where the target bucket is a
|
||||
* non Requester Pays bucket.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AmazonS3/latest/index.html?RESTrequestPaymentGET.html" />
|
||||
*/
|
||||
public enum Payer {
|
||||
REQUESTER, BUCKET_OWNER, UNRECOGNIZED;
|
||||
|
|
|
@ -23,11 +23,8 @@ import com.google.common.collect.Multimap;
|
|||
|
||||
/**
|
||||
* Amazon S3 is designed to store objects. Objects are stored in buckets and consist of a
|
||||
* {@link ObjectMetadataS3Object#getInput() value}, a {@link ObjectMetadata#getKey key},
|
||||
* {@link PayloadEnclosing#getPayload() value}, a {@link ObjectMetadata#getKey key},
|
||||
* {@link ObjectMetadata#getUserMetadata() metadata}, and an access control policy.
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html"
|
||||
* />
|
||||
*/
|
||||
public interface S3Object extends PayloadEnclosing, Comparable<S3Object> {
|
||||
public interface Factory {
|
||||
|
|
|
@ -16,6 +16,5 @@
|
|||
*/
|
||||
/**
|
||||
* This package contains the core components of S3.
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/Components.html" />
|
||||
*/
|
||||
package org.jclouds.s3.domain;
|
||||
|
|
|
@ -67,10 +67,6 @@ import com.google.common.net.HttpHeaders;
|
|||
|
||||
/**
|
||||
* Signs the S3 request.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/dev/index.html?RESTAuthentication.html"
|
||||
* />
|
||||
*/
|
||||
@Singleton
|
||||
public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSigner {
|
||||
|
|
|
@ -16,6 +16,5 @@
|
|||
*/
|
||||
/**
|
||||
* This package contains HttpRequestFilters needed to operate the REST api.
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html" />
|
||||
*/
|
||||
package org.jclouds.s3.filters;
|
||||
|
|
|
@ -37,12 +37,7 @@ import com.google.common.annotations.VisibleForTesting;
|
|||
import com.google.common.base.Function;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
/**
|
||||
* This parses @{link {@link org.jclouds.s3.domain.internal.MutableObjectMetadata} from HTTP
|
||||
* headers.
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTObjectGET.html" />
|
||||
*/
|
||||
/** This parses {@ link MutableObjectMetadata} from HTTP headers. */
|
||||
public class ParseObjectMetadataFromHeaders implements Function<HttpResponse, MutableObjectMetadata>,
|
||||
InvocationContext<ParseObjectMetadataFromHeaders> {
|
||||
private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
|
||||
|
@ -61,10 +56,7 @@ public class ParseObjectMetadataFromHeaders implements Function<HttpResponse, Mu
|
|||
// used as content-md5, so filter etags that contain hyphens
|
||||
static final Pattern MD5_FROM_ETAG = Pattern.compile("^\"?([0-9a-f]+)\"?$");
|
||||
|
||||
/**
|
||||
* parses the http response headers to create a new
|
||||
* {@link org.jclouds.s3.domain.internal.MutableObjectMetadata} object.
|
||||
*/
|
||||
/** parses the http response headers to create a new {@link MutableObjectMetadata} object. */
|
||||
public MutableObjectMetadata apply(HttpResponse from) {
|
||||
BlobMetadata base = blobMetadataParser.apply(from);
|
||||
MutableObjectMetadata to = blobToObjectMetadata.apply(base);
|
||||
|
|
|
@ -67,10 +67,6 @@ import com.google.common.collect.Multimap;
|
|||
* ifSourceModifiedSince(new Date().minusDays(1))
|
||||
* );
|
||||
* <code>
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectCOPY.html?"
|
||||
* />
|
||||
*/
|
||||
public class CopyObjectOptions extends BaseHttpRequestOptions {
|
||||
private static final DateService dateService = new SimpleDateFormatDateService();
|
||||
|
@ -121,7 +117,6 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
|||
* conditional copy headers.
|
||||
*
|
||||
* @return valid HTTP date
|
||||
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
|
||||
* @see CopyObjectOptions#ifSourceModifiedSince(Date)
|
||||
*/
|
||||
public String getIfModifiedSince() {
|
||||
|
@ -138,7 +133,6 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
|||
* conditional copy headers.
|
||||
*
|
||||
* @return valid HTTP date
|
||||
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
|
||||
* @see CopyObjectOptions#ifSourceUnmodifiedSince(Date)
|
||||
*/
|
||||
public String getIfUnmodifiedSince() {
|
||||
|
|
|
@ -31,12 +31,8 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
|
|||
* import static org.jclouds.s3.commands.options.GetBucketOptions.Builder.*
|
||||
* <p/>
|
||||
* S3Client connection = // get connection
|
||||
* Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
|
||||
* ListBucketResponse bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
|
||||
* <code>
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html?"
|
||||
* />
|
||||
*/
|
||||
public class ListBucketOptions extends BaseHttpRequestOptions implements Cloneable {
|
||||
public static final ListBucketOptions NONE = new ListBucketOptions();
|
||||
|
|
|
@ -44,12 +44,8 @@ import com.google.common.collect.Multimap;
|
|||
* import org.jclouds.s3.S3Client;
|
||||
* <p/>
|
||||
* S3Client connection = // get connection
|
||||
* Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
|
||||
* boolean createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
|
||||
* <code>
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT.html?"
|
||||
* />
|
||||
*/
|
||||
public class PutBucketOptions extends BaseHttpRequestOptions {
|
||||
private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE;
|
||||
|
|
|
@ -46,12 +46,8 @@ import com.google.common.collect.Multimap;
|
|||
* import org.jclouds.s3.S3Client;
|
||||
*
|
||||
* S3Client connection = // get connection
|
||||
* Future<Boolean> publicly readable = connection.putObject("bucketName",new S3Object("key","value"), withAcl(CannedAccessPolicy.PUBLIC_READ));
|
||||
* boolean publiclyReadable = connection.putObject("bucketName",new S3Object("key","value"), withAcl(CannedAccessPolicy.PUBLIC_READ));
|
||||
* <code>
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT.html?"
|
||||
* />
|
||||
*/
|
||||
public class PutObjectOptions extends BaseHttpRequestOptions {
|
||||
public static final PutObjectOptions NONE = new PutObjectOptions();
|
||||
|
|
|
@ -16,7 +16,5 @@
|
|||
*/
|
||||
/**
|
||||
* This package contains request options for S3 REST commands.
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAPI.html" />
|
||||
*/
|
||||
package org.jclouds.s3.options;
|
||||
|
|
|
@ -16,7 +16,5 @@
|
|||
*/
|
||||
/**
|
||||
* This package contains an Amazon S3 client implemented by {@link org.jclouds.http.HttpCommandExecutorService} commands.
|
||||
*
|
||||
* @see <a href="http://amazon.com/s3"/>
|
||||
*/
|
||||
package org.jclouds.s3;
|
||||
|
|
|
@ -16,13 +16,6 @@
|
|||
*/
|
||||
package org.jclouds.s3.reference;
|
||||
|
||||
/**
|
||||
* Additional headers specified by Amazon S3 REST API.
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/latest/index.html?RESTAuthentication.html"
|
||||
* />
|
||||
*/
|
||||
public interface S3Headers {
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,8 +33,6 @@ import org.xml.sax.Attributes;
|
|||
* Parses the following XML document:
|
||||
* <p/>
|
||||
* AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/"
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html"/>
|
||||
*/
|
||||
public class AccessControlListHandler extends ParseSax.HandlerWithResult<AccessControlList> {
|
||||
private AccessControlList acl = new AccessControlList();
|
||||
|
|
|
@ -36,8 +36,6 @@ import com.google.common.collect.Sets;
|
|||
* Parses the following XML document:
|
||||
* <p/>
|
||||
* BucketLoggingStatus xmlns="http://s3.amazonaws.com/doc/2006-03-01/"
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/index.html?ServerLogs.html"/>
|
||||
*/
|
||||
public class BucketLoggingHandler extends ParseSax.HandlerWithResult<BucketLogging> {
|
||||
private Set<Grant> targetGrants = Sets.newHashSet();
|
||||
|
|
|
@ -31,8 +31,6 @@ import org.jclouds.s3.domain.internal.CopyObjectResult;
|
|||
* Parses the response from Amazon S3 COPY Object command.
|
||||
* <p/>
|
||||
* CopyObjectResult is the document we expect to parse.
|
||||
*
|
||||
* @see <a href= "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTObjectCOPY.html" />
|
||||
*/
|
||||
public class CopyObjectHandler extends ParseSax.HandlerWithResult<ObjectMetadata> {
|
||||
|
||||
|
|
|
@ -34,10 +34,6 @@ import com.google.common.collect.Sets;
|
|||
* Parses the following XML document:
|
||||
* <p/>
|
||||
* SetAllMyBucketsResult xmlns="http://doc.s3.amazonaws.com/2006-03-01"
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTServiceGET.html"
|
||||
* />
|
||||
*/
|
||||
public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult<Set<BucketMetadata>> {
|
||||
|
||||
|
|
|
@ -41,10 +41,6 @@ import com.google.common.collect.ImmutableSet.Builder;
|
|||
* Parses the following XML document:
|
||||
* <p/>
|
||||
* ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01"
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html"
|
||||
* />
|
||||
*/
|
||||
public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResponse> {
|
||||
private Builder<ObjectMetadata> contents = ImmutableSet.builder();
|
||||
|
|
|
@ -33,10 +33,6 @@ import com.google.common.cache.LoadingCache;
|
|||
* Parses the response from Amazon S3 GET Bucket Location
|
||||
* <p/>
|
||||
* Region is the document we expect to parse.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AmazonS3/latest/RESTBucketLocationGET.html"
|
||||
* />
|
||||
*/
|
||||
public class LocationConstraintHandler extends ParseSax.HandlerWithResult<String> {
|
||||
private final LoadingCache<String, Optional<String>> bucketToRegion;
|
||||
|
|
|
@ -25,8 +25,6 @@ import org.jclouds.s3.domain.Payer;
|
|||
* Parses the response from Amazon S3 GET Request Payment
|
||||
* <p/>
|
||||
* RequestPaymentConfiguration is the document we expect to parse.
|
||||
*
|
||||
* @see <a href= "http://docs.amazonwebservices.com/AmazonS3/latest/RESTrequestPaymentGET.html" />
|
||||
*/
|
||||
public class PayerHandler extends ParseSax.HandlerWithResult<Payer> {
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
*/
|
||||
package org.jclouds.s3;
|
||||
|
||||
import static org.jclouds.s3.internal.StubS3AsyncClient.TEST_ACL_EMAIL;
|
||||
import static org.jclouds.s3.internal.StubS3AsyncClient.TEST_ACL_ID;
|
||||
import static org.jclouds.s3.options.CopyObjectOptions.Builder.ifSourceETagDoesntMatch;
|
||||
import static org.jclouds.s3.options.CopyObjectOptions.Builder.ifSourceETagMatches;
|
||||
import static org.jclouds.s3.options.CopyObjectOptions.Builder.ifSourceModifiedSince;
|
||||
|
@ -57,12 +55,16 @@ import com.google.common.collect.Maps;
|
|||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest {
|
||||
public static final String TEST_ACL_ID = "1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c";
|
||||
public static final String TEST_ACL_EMAIL = "james@misterm.org";
|
||||
public static final String DEFAULT_OWNER_ID = "abc123";
|
||||
|
||||
public S3ClientLiveTest() {
|
||||
this.provider = "s3";
|
||||
}
|
||||
|
||||
public S3Client getApi() {
|
||||
return view.unwrap(S3ApiMetadata.CONTEXT_TOKEN).getApi();
|
||||
return view.unwrapApi(S3Client.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,10 +35,10 @@ import org.jclouds.http.functions.ParseSax;
|
|||
import org.jclouds.http.functions.ReleasePayloadAndReturn;
|
||||
import org.jclouds.http.functions.ReturnTrueIf2xx;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.s3.S3Fallbacks.TrueOn404OrNotFoundFalseOnIllegalState;
|
||||
import org.jclouds.s3.config.S3RestClientModule;
|
||||
import org.jclouds.s3.config.S3HttpApiModule;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
import org.jclouds.s3.domain.AccessControlList.EmailAddressGrantee;
|
||||
import org.jclouds.s3.domain.AccessControlList.Grant;
|
||||
|
@ -50,7 +50,7 @@ import org.jclouds.s3.domain.S3Object;
|
|||
import org.jclouds.s3.fallbacks.FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists;
|
||||
import org.jclouds.s3.functions.ParseObjectFromHeadersAndHttpContent;
|
||||
import org.jclouds.s3.functions.ParseObjectMetadataFromHeaders;
|
||||
import org.jclouds.s3.internal.BaseS3AsyncClientTest;
|
||||
import org.jclouds.s3.internal.BaseS3ClientTest;
|
||||
import org.jclouds.s3.options.CopyObjectOptions;
|
||||
import org.jclouds.s3.options.ListBucketOptions;
|
||||
import org.jclouds.s3.options.PutBucketOptions;
|
||||
|
@ -72,16 +72,16 @@ import com.google.common.collect.Lists;
|
|||
import com.google.common.reflect.Invokable;
|
||||
import com.google.inject.Module;
|
||||
/**
|
||||
* Tests behavior of {@code S3AsyncClient}
|
||||
* Tests behavior of {@code S3Client}
|
||||
*/
|
||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
@Test(groups = "unit", testName = "S3AsyncClientTest")
|
||||
public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3AsyncClientTest<T> {
|
||||
@Test(groups = "unit", testName = "S3ClientTest")
|
||||
public abstract class S3ClientTest<T extends S3Client> extends BaseS3ClientTest<T> {
|
||||
|
||||
protected String url = "s3.amazonaws.com";
|
||||
|
||||
public void testAllRegions() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "putBucketInRegion", String.class, String.class,
|
||||
Invokable<?, ?> method = method(S3Client.class, "putBucketInRegion", String.class, String.class,
|
||||
PutBucketOptions[].class);
|
||||
for (String region : Region.DEFAULT_S3) {
|
||||
processor.createRequest(method, ImmutableList.<Object> of(region, "bucket-" + region));
|
||||
|
@ -89,7 +89,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testGetBucketLocation() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "getBucketLocation", String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "getBucketLocation", String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket"));
|
||||
|
||||
assertRequestLineEquals(request, "GET https://bucket." + url + "/?location HTTP/1.1");
|
||||
|
@ -112,7 +112,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testGetBucketPayer() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "getBucketPayer", String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "getBucketPayer", String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket"));
|
||||
|
||||
assertRequestLineEquals(request, "GET https://bucket." + url + "/?requestPayment HTTP/1.1");
|
||||
|
@ -127,7 +127,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testSetBucketPayerOwner() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "setBucketPayer", String.class, Payer.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "setBucketPayer", String.class, Payer.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", Payer.BUCKET_OWNER));
|
||||
|
||||
assertRequestLineEquals(request, "PUT https://bucket." + url + "/?requestPayment HTTP/1.1");
|
||||
|
@ -143,7 +143,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testSetBucketPayerRequester() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "setBucketPayer", String.class, Payer.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "setBucketPayer", String.class, Payer.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", Payer.REQUESTER));
|
||||
|
||||
assertRequestLineEquals(request, "PUT https://bucket." + url + "/?requestPayment HTTP/1.1");
|
||||
|
@ -159,7 +159,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testListBucket() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "listBucket", String.class,
|
||||
Invokable<?, ?> method = method(S3Client.class, "listBucket", String.class,
|
||||
ListBucketOptions[].class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket"));
|
||||
|
||||
|
@ -175,7 +175,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testBucketExists() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "bucketExists", String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "bucketExists", String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket"));
|
||||
|
||||
assertRequestLineEquals(request, "HEAD https://bucket." + url + "/ HTTP/1.1");
|
||||
|
@ -192,7 +192,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testCopyObjectInvalidName() throws ArrayIndexOutOfBoundsException, SecurityException,
|
||||
IllegalArgumentException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "copyObject", String.class, String.class, String.class,
|
||||
Invokable<?, ?> method = method(S3Client.class, "copyObject", String.class, String.class, String.class,
|
||||
String.class, CopyObjectOptions[].class);
|
||||
processor.createRequest(method, ImmutableList.<Object> of("sourceBucket", "sourceObject", "destinationBucket", "destinationObject"));
|
||||
|
||||
|
@ -200,7 +200,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
|
||||
public void testCopyObject() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||
NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "copyObject", String.class, String.class, String.class,
|
||||
Invokable<?, ?> method = method(S3Client.class, "copyObject", String.class, String.class, String.class,
|
||||
String.class, CopyObjectOptions[].class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("sourceBucket", "sourceObject", "destinationbucket",
|
||||
"destinationObject"));
|
||||
|
@ -218,7 +218,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testDeleteBucketIfEmpty() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "deleteBucketIfEmpty", String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "deleteBucketIfEmpty", String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket"));
|
||||
|
||||
assertRequestLineEquals(request, "DELETE https://bucket." + url + "/ HTTP/1.1");
|
||||
|
@ -233,7 +233,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testDeleteObject() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "deleteObject", String.class, String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "deleteObject", String.class, String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", "object"));
|
||||
|
||||
assertRequestLineEquals(request, "DELETE https://bucket." + url + "/object HTTP/1.1");
|
||||
|
@ -249,7 +249,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
|
||||
public void testGetBucketACL() throws SecurityException, NoSuchMethodException, IOException {
|
||||
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "getBucketACL", String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "getBucketACL", String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket"));
|
||||
|
||||
assertRequestLineEquals(request, "GET https://bucket." + url + "/?acl HTTP/1.1");
|
||||
|
@ -265,7 +265,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
|
||||
public void testGetObject() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||
NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "getObject", String.class, String.class, GetOptions[].class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "getObject", String.class, String.class, GetOptions[].class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", "object"));
|
||||
|
||||
assertRequestLineEquals(request, "GET https://bucket." + url + "/object HTTP/1.1");
|
||||
|
@ -281,7 +281,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
|
||||
public void testGetObjectACL() throws SecurityException, NoSuchMethodException, IOException {
|
||||
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "getObjectACL", String.class, String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "getObjectACL", String.class, String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", "object"));
|
||||
|
||||
assertRequestLineEquals(request, "GET https://bucket." + url + "/object?acl HTTP/1.1");
|
||||
|
@ -297,7 +297,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
|
||||
public void testObjectExists() throws SecurityException, NoSuchMethodException, IOException {
|
||||
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "objectExists", String.class, String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "objectExists", String.class, String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", "object"));
|
||||
|
||||
assertRequestLineEquals(request, "HEAD https://bucket." + url + "/object HTTP/1.1");
|
||||
|
@ -313,7 +313,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
|
||||
public void testHeadObject() throws SecurityException, NoSuchMethodException, IOException {
|
||||
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "headObject", String.class, String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "headObject", String.class, String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", "object"));
|
||||
|
||||
assertRequestLineEquals(request, "HEAD https://bucket." + url + "/object HTTP/1.1");
|
||||
|
@ -328,7 +328,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testListOwnedBuckets() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "listOwnedBuckets");
|
||||
Invokable<?, ?> method = method(S3Client.class, "listOwnedBuckets");
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
|
||||
|
||||
assertRequestLineEquals(request, "GET https://" + url + "/ HTTP/1.1");
|
||||
|
@ -343,12 +343,12 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testNewS3Object() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "newS3Object");
|
||||
Invokable<?, ?> method = method(S3Client.class, "newS3Object");
|
||||
assertEquals(method.getReturnType().getRawType(), S3Object.class);
|
||||
}
|
||||
|
||||
public void testPutBucketACL() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "putBucketACL", String.class, AccessControlList.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "putBucketACL", String.class, AccessControlList.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", AccessControlList.fromCannedAccessPolicy(
|
||||
CannedAccessPolicy.PRIVATE, "1234")));
|
||||
|
||||
|
@ -370,7 +370,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
|
||||
public void testPutBucketDefault() throws ArrayIndexOutOfBoundsException, SecurityException,
|
||||
IllegalArgumentException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "putBucketInRegion", String.class, String.class,
|
||||
Invokable<?, ?> method = method(S3Client.class, "putBucketInRegion", String.class, String.class,
|
||||
PutBucketOptions[].class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null, "bucket"));
|
||||
|
||||
|
@ -388,7 +388,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
public void testPutObject() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||
NoSuchMethodException, IOException {
|
||||
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "putObject", String.class, S3Object.class, PutObjectOptions[].class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "putObject", String.class, S3Object.class, PutObjectOptions[].class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", blobToS3Object
|
||||
.apply(BindBlobToMultipartFormTest.TEST_BLOB)));
|
||||
|
||||
|
@ -404,7 +404,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testPutObjectACL() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "putObjectACL", String.class, String.class, AccessControlList.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "putObjectACL", String.class, String.class, AccessControlList.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", "key", AccessControlList.fromCannedAccessPolicy(
|
||||
CannedAccessPolicy.PRIVATE, "1234")));
|
||||
|
||||
|
@ -425,7 +425,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testGetBucketLogging() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "getBucketLogging", String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "getBucketLogging", String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket"));
|
||||
|
||||
assertRequestLineEquals(request, "GET https://bucket." + url + "/?logging HTTP/1.1");
|
||||
|
@ -440,7 +440,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testDisableBucketLogging() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "disableBucketLogging", String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "disableBucketLogging", String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket"));
|
||||
|
||||
assertRequestLineEquals(request, "PUT https://bucket." + url + "/?logging HTTP/1.1");
|
||||
|
@ -456,7 +456,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
}
|
||||
|
||||
public void testEnableBucketLoggingOwner() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "enableBucketLogging", String.class, BucketLogging.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "enableBucketLogging", String.class, BucketLogging.class);
|
||||
GeneratedHttpRequest request = processor
|
||||
.createRequest(method, ImmutableList.<Object> of("bucket", new BucketLogging("mylogs", "access_log-", ImmutableSet
|
||||
.<Grant> of(new Grant(new EmailAddressGrantee("adrian@jclouds.org"), Permission.FULL_CONTROL)))));
|
||||
|
@ -473,8 +473,8 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
checkFilters(request);
|
||||
}
|
||||
|
||||
@ConfiguresRestClient
|
||||
private static final class TestS3RestClientModule extends S3RestClientModule<S3Client, S3AsyncClient> {
|
||||
@ConfiguresHttpApi
|
||||
private static final class TestS3HttpApiModule extends S3HttpApiModule<S3Client> {
|
||||
|
||||
@Override
|
||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||
|
@ -484,7 +484,7 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
|
|||
|
||||
@Override
|
||||
protected Module createModule() {
|
||||
return new TestS3RestClientModule();
|
||||
return new TestS3HttpApiModule();
|
||||
}
|
||||
|
||||
}
|
|
@ -22,8 +22,8 @@ import java.io.IOException;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.internal.BaseS3AsyncClientTest;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.internal.BaseS3ClientTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
@ -34,11 +34,11 @@ import com.google.common.reflect.Invokable;
|
|||
*/
|
||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
@Test(groups = "unit", testName = "BindAsHostPrefixIfConfiguredNoPathTest")
|
||||
public class BindAsHostPrefixIfConfiguredNoPathTest extends BaseS3AsyncClientTest<S3AsyncClient> {
|
||||
public class BindAsHostPrefixIfConfiguredNoPathTest extends BaseS3ClientTest<S3Client> {
|
||||
|
||||
public void testBucketWithHostnameStyle() throws IOException, SecurityException, NoSuchMethodException {
|
||||
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "deleteObject", String.class, String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "deleteObject", String.class, String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("testbucket.example.com", "test.jpg"));
|
||||
assertRequestLineEquals(request, "DELETE https://s3.amazonaws.com/testbucket.example.com/test.jpg HTTP/1.1");
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ import java.io.IOException;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.internal.BaseS3AsyncClientTest;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.internal.BaseS3ClientTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@ -37,7 +37,7 @@ import com.google.common.reflect.Invokable;
|
|||
*/
|
||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
@Test(groups = "unit", testName = "BindAsHostPrefixIfConfiguredTest")
|
||||
public class BindAsHostPrefixIfConfiguredTest extends BaseS3AsyncClientTest<S3AsyncClient> {
|
||||
public class BindAsHostPrefixIfConfiguredTest extends BaseS3ClientTest<S3Client> {
|
||||
|
||||
public void testBucket() throws IOException {
|
||||
|
||||
|
@ -57,7 +57,7 @@ public class BindAsHostPrefixIfConfiguredTest extends BaseS3AsyncClientTest<S3As
|
|||
request = binder.bindToRequest(request, "testbucket.example.com");
|
||||
assertEquals(request.getRequestLine(), "GET http://euc/services/Walrus/testbucket.example.com HTTP/1.1");
|
||||
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "deleteObject", String.class, String.class);
|
||||
Invokable<?, ?> method = method(S3Client.class, "deleteObject", String.class, String.class);
|
||||
request = processor.createRequest(method, ImmutableList.<Object> of("testbucket.example.com", "test.jpg"));
|
||||
|
||||
assertRequestLineEquals(request, "DELETE http://euc/services/Walrus/testbucket.example.com/test.jpg HTTP/1.1");
|
||||
|
|
|
@ -21,8 +21,8 @@ import static org.testng.Assert.assertEquals;
|
|||
import java.io.IOException;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.internal.BaseS3AsyncClientTest;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.internal.BaseS3ClientTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
|
@ -30,7 +30,7 @@ import org.testng.annotations.Test;
|
|||
*/
|
||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
@Test(groups = "unit", testName = "BindNoBucketLoggingToXmlPayloadTest")
|
||||
public class BindNoBucketLoggingToXmlPayloadTest extends BaseS3AsyncClientTest<S3AsyncClient> {
|
||||
public class BindNoBucketLoggingToXmlPayloadTest extends BaseS3ClientTest<S3Client> {
|
||||
|
||||
public void testApplyInputStream() throws IOException {
|
||||
|
||||
|
|
|
@ -25,9 +25,9 @@ import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.io.Payloads;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.domain.S3Object;
|
||||
import org.jclouds.s3.internal.BaseS3AsyncClientTest;
|
||||
import org.jclouds.s3.internal.BaseS3ClientTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
@ -38,7 +38,7 @@ import com.google.common.collect.ImmutableMultimap;
|
|||
*/
|
||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
@Test(groups = "unit", testName = "BindS3ObjectMetadataToRequestTest")
|
||||
public class BindS3ObjectMetadataToRequestTest extends BaseS3AsyncClientTest<S3AsyncClient> {
|
||||
public class BindS3ObjectMetadataToRequestTest extends BaseS3ClientTest<S3Client> {
|
||||
|
||||
@Test
|
||||
public void testPassWithMinimumDetailsAndPayload5GB() {
|
||||
|
|
|
@ -19,10 +19,9 @@ package org.jclouds.s3.blobstore;
|
|||
import org.jclouds.blobstore.internal.BaseBlobSignerExpectTest;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.config.S3RestClientModule;
|
||||
import org.jclouds.s3.config.S3HttpApiModule;
|
||||
import org.testng.SkipException;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@ -106,11 +105,11 @@ public class S3BlobSignerExpectTest extends BaseBlobSignerExpectTest {
|
|||
|
||||
@Override
|
||||
protected Module createModule() {
|
||||
return new TestS3RestClientModule();
|
||||
return new TestS3HttpApiModule();
|
||||
}
|
||||
|
||||
@ConfiguresRestClient
|
||||
private static final class TestS3RestClientModule extends S3RestClientModule<S3Client, S3AsyncClient> {
|
||||
@ConfiguresHttpApi
|
||||
private static final class TestS3HttpApiModule extends S3HttpApiModule<S3Client> {
|
||||
|
||||
@Override
|
||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||
|
|
|
@ -26,11 +26,11 @@ import java.util.Properties;
|
|||
import org.jclouds.blobstore.binders.BindBlobToMultipartFormTest;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
import org.jclouds.s3.domain.CannedAccessPolicy;
|
||||
import org.jclouds.s3.domain.S3Object;
|
||||
import org.jclouds.s3.internal.BaseS3AsyncClientTest;
|
||||
import org.jclouds.s3.internal.BaseS3ClientTest;
|
||||
import org.jclouds.s3.options.PutObjectOptions;
|
||||
import org.jclouds.s3.reference.S3Headers;
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
@ -45,7 +45,7 @@ import com.google.common.net.HttpHeaders;
|
|||
*/
|
||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
@Test(groups = "unit", testName = "RequestAuthorizeSignatureTest")
|
||||
public class RequestAuthorizeSignatureTest extends BaseS3AsyncClientTest<S3AsyncClient> {
|
||||
public class RequestAuthorizeSignatureTest extends BaseS3ClientTest<S3Client> {
|
||||
String bucketName = "bucket";
|
||||
|
||||
@DataProvider(parallel = true)
|
||||
|
@ -84,7 +84,7 @@ public class RequestAuthorizeSignatureTest extends BaseS3AsyncClientTest<S3Async
|
|||
@Test
|
||||
void testAppendBucketNameHostHeader() throws SecurityException, NoSuchMethodException {
|
||||
GeneratedHttpRequest request = processor.createRequest(
|
||||
method(S3AsyncClient.class, "getBucketLocation", String.class),
|
||||
method(S3Client.class, "getBucketLocation", String.class),
|
||||
ImmutableList.<Object> of("bucket"));
|
||||
StringBuilder builder = new StringBuilder();
|
||||
filter.appendBucketName(request, builder);
|
||||
|
@ -101,7 +101,7 @@ public class RequestAuthorizeSignatureTest extends BaseS3AsyncClientTest<S3Async
|
|||
|
||||
private GeneratedHttpRequest putBucketAcl() throws NoSuchMethodException {
|
||||
return processor.createRequest(
|
||||
method(S3AsyncClient.class, "putBucketACL", String.class, AccessControlList.class),
|
||||
method(S3Client.class, "putBucketACL", String.class, AccessControlList.class),
|
||||
ImmutableList.<Object> of("bucket",
|
||||
AccessControlList.fromCannedAccessPolicy(CannedAccessPolicy.PRIVATE, "1234")));
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ public class RequestAuthorizeSignatureTest extends BaseS3AsyncClientTest<S3Async
|
|||
}
|
||||
|
||||
private GeneratedHttpRequest listOwnedBuckets() throws NoSuchMethodException {
|
||||
return processor.createRequest(method(S3AsyncClient.class, "listOwnedBuckets"),
|
||||
return processor.createRequest(method(S3Client.class, "listOwnedBuckets"),
|
||||
ImmutableList.of());
|
||||
}
|
||||
|
||||
|
@ -134,14 +134,14 @@ public class RequestAuthorizeSignatureTest extends BaseS3AsyncClientTest<S3Async
|
|||
private HttpRequest putObject() throws NoSuchMethodException {
|
||||
S3Object object = blobToS3Object.apply(BindBlobToMultipartFormTest.TEST_BLOB);
|
||||
object.getMetadata().getUserMetadata().put("Adrian", "foo");
|
||||
return processor.createRequest(method(S3AsyncClient.class, "putObject", String.class,
|
||||
return processor.createRequest(method(S3Client.class, "putObject", String.class,
|
||||
S3Object.class, PutObjectOptions[].class), ImmutableList.<Object> of("bucket", object));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAppendBucketNameInURIPath() throws SecurityException, NoSuchMethodException {
|
||||
GeneratedHttpRequest request = processor.createRequest(
|
||||
method(S3AsyncClient.class, "getBucketLocation", String.class),
|
||||
method(S3Client.class, "getBucketLocation", String.class),
|
||||
ImmutableList.<Object> of(bucketName));
|
||||
URI uri = request.getEndpoint();
|
||||
assertEquals(uri.getHost(), "s3.amazonaws.com");
|
||||
|
|
|
@ -27,12 +27,11 @@ import org.jclouds.domain.Credentials;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.logging.config.NullLoggingModule;
|
||||
import org.jclouds.reflect.Invocation;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
import org.jclouds.rest.internal.BaseRestApiTest.MockModule;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.config.S3RestClientModule;
|
||||
import org.jclouds.s3.config.S3HttpApiModule;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
@ -50,11 +49,11 @@ public class RequestAuthorizeSignatureWithSessionCredentialsTest {
|
|||
public static Injector injector(Credentials creds) {
|
||||
return ContextBuilder.newBuilder("s3")
|
||||
.credentialsSupplier(Suppliers.<Credentials> ofInstance(creds))
|
||||
.modules(ImmutableList.<Module> of(new MockModule(), new NullLoggingModule(), new TestS3RestClientModule())).buildInjector();
|
||||
.modules(ImmutableList.<Module> of(new MockModule(), new NullLoggingModule(), new TestS3HttpApiModule())).buildInjector();
|
||||
}
|
||||
|
||||
@ConfiguresRestClient
|
||||
private static final class TestS3RestClientModule extends S3RestClientModule<S3Client, S3AsyncClient> {
|
||||
@ConfiguresHttpApi
|
||||
private static final class TestS3HttpApiModule extends S3HttpApiModule<S3Client> {
|
||||
|
||||
@Override
|
||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||
|
@ -72,7 +71,7 @@ public class RequestAuthorizeSignatureWithSessionCredentialsTest {
|
|||
.sessionToken("AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT")
|
||||
.expiration(new SimpleDateFormatDateService().iso8601DateParse("2011-07-11T19:55:29.611Z")).build();
|
||||
|
||||
Invocation invocation = Invocation.create(method(S3AsyncClient.class, "bucketExists", String.class),
|
||||
Invocation invocation = Invocation.create(method(S3Client.class, "bucketExists", String.class),
|
||||
ImmutableList.<Object> of("foo"));
|
||||
|
||||
HttpRequest bucketFooExists = GeneratedHttpRequest.builder().method("GET")
|
||||
|
|
|
@ -17,12 +17,11 @@
|
|||
package org.jclouds.s3.internal;
|
||||
|
||||
import org.jclouds.date.TimeStamp;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
import org.jclouds.rest.internal.BaseRestClientExpectTest;
|
||||
import org.jclouds.s3.S3ApiMetadata;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.config.S3RestClientModule;
|
||||
import org.jclouds.s3.config.S3HttpApiModule;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.Module;
|
||||
|
@ -31,8 +30,8 @@ public abstract class BaseS3ClientExpectTest extends BaseRestClientExpectTest<S3
|
|||
|
||||
protected static final String CONSTANT_DATE = "2009-11-08T15:54:08.897Z";
|
||||
|
||||
@ConfiguresRestClient
|
||||
private static final class TestS3RestClientModule extends S3RestClientModule<S3Client, S3AsyncClient> {
|
||||
@ConfiguresHttpApi
|
||||
private static final class TestS3HttpApiModule extends S3HttpApiModule<S3Client> {
|
||||
|
||||
@Override
|
||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||
|
@ -42,7 +41,7 @@ public abstract class BaseS3ClientExpectTest extends BaseRestClientExpectTest<S3
|
|||
|
||||
@Override
|
||||
protected Module createModule() {
|
||||
return new TestS3RestClientModule();
|
||||
return new TestS3HttpApiModule();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,14 +23,14 @@ import java.io.IOException;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.internal.BaseAsyncClientTest;
|
||||
import org.jclouds.s3.S3ApiMetadata;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.s3.filters.RequestAuthorizeSignature;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public abstract class BaseS3AsyncClientTest<T extends S3AsyncClient> extends BaseAsyncClientTest<T> {
|
||||
public abstract class BaseS3ClientTest<T extends S3Client> extends BaseAsyncClientTest<T> {
|
||||
|
||||
protected BlobToObject blobToS3Object;
|
||||
protected RequestAuthorizeSignature filter;
|
||||
|
@ -50,7 +50,7 @@ public abstract class BaseS3AsyncClientTest<T extends S3AsyncClient> extends Bas
|
|||
filter = injector.getInstance(RequestAuthorizeSignature.class);
|
||||
}
|
||||
|
||||
public BaseS3AsyncClientTest() {
|
||||
public BaseS3ClientTest() {
|
||||
super();
|
||||
}
|
||||
|
|
@ -1,342 +0,0 @@
|
|||
/*
|
||||
* 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.s3.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
|
||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||
import static com.google.common.util.concurrent.Futures.transform;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.aws.domain.Region;
|
||||
import org.jclouds.blobstore.AsyncBlobStore;
|
||||
import org.jclouds.blobstore.KeyNotFoundException;
|
||||
import org.jclouds.blobstore.LocalAsyncBlobStore;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.blobstore.util.BlobStoreUtils;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.domain.LocationBuilder;
|
||||
import org.jclouds.domain.LocationScope;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.lifecycle.Closer;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.s3.blobstore.functions.BlobToObjectMetadata;
|
||||
import org.jclouds.s3.blobstore.functions.BucketToContainerListOptions;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.s3.blobstore.functions.ResourceToBucketList;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
import org.jclouds.s3.domain.AccessControlList.CanonicalUserGrantee;
|
||||
import org.jclouds.s3.domain.AccessControlList.EmailAddressGrantee;
|
||||
import org.jclouds.s3.domain.AccessControlList.Grant;
|
||||
import org.jclouds.s3.domain.BucketLogging;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
import org.jclouds.s3.domain.CannedAccessPolicy;
|
||||
import org.jclouds.s3.domain.ListBucketResponse;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.domain.Payer;
|
||||
import org.jclouds.s3.domain.S3Object;
|
||||
import org.jclouds.s3.options.CopyObjectOptions;
|
||||
import org.jclouds.s3.options.ListBucketOptions;
|
||||
import org.jclouds.s3.options.PutBucketOptions;
|
||||
import org.jclouds.s3.options.PutObjectOptions;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
|
||||
/**
|
||||
* Implementation of {@link S3AsyncBlobStore} which keeps all data in a local Map object.
|
||||
*/
|
||||
@Singleton
|
||||
public class StubS3AsyncClient implements S3AsyncClient {
|
||||
private final DateService dateService;
|
||||
private final HttpGetOptionsListToGetOptions httpGetOptionsConverter;
|
||||
private final AsyncBlobStore blobStore;
|
||||
private final S3Object.Factory objectProvider;
|
||||
private final Blob.Factory blobProvider;
|
||||
private final ObjectToBlob object2Blob;
|
||||
private final BlobToObject blob2Object;
|
||||
private final BlobToObjectMetadata blob2ObjectMetadata;
|
||||
private final BucketToContainerListOptions bucket2ContainerListOptions;
|
||||
private final ResourceToBucketList resource2BucketList;
|
||||
private final ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs;
|
||||
private final ConcurrentMap<String, Location> containerToLocation;
|
||||
private final ListeningExecutorService userExecutor;
|
||||
private final Closer closer;
|
||||
|
||||
@Inject
|
||||
private StubS3AsyncClient(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
|
||||
LocalAsyncBlobStore blobStore, ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
|
||||
ConcurrentMap<String, Location> containerToLocation, DateService dateService,
|
||||
S3Object.Factory objectProvider, Blob.Factory blobProvider,
|
||||
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob, BlobToObject blob2Object,
|
||||
BlobToObjectMetadata blob2ObjectMetadata, BucketToContainerListOptions bucket2ContainerListOptions,
|
||||
ResourceToBucketList resource2BucketList, Closer closer) {
|
||||
this.userExecutor = userExecutor;
|
||||
this.containerToBlobs = containerToBlobs;
|
||||
this.containerToLocation = containerToLocation;
|
||||
this.blobStore = blobStore;
|
||||
this.objectProvider = objectProvider;
|
||||
this.blobProvider = blobProvider;
|
||||
this.dateService = dateService;
|
||||
this.httpGetOptionsConverter = httpGetOptionsConverter;
|
||||
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
|
||||
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
|
||||
this.blob2ObjectMetadata = checkNotNull(blob2ObjectMetadata, "blob2ObjectMetadata");
|
||||
this.bucket2ContainerListOptions = checkNotNull(bucket2ContainerListOptions, "bucket2ContainerListOptions");
|
||||
this.resource2BucketList = checkNotNull(resource2BucketList, "resource2BucketList");
|
||||
this.closer = checkNotNull(closer, "closer");
|
||||
}
|
||||
|
||||
public static final String TEST_ACL_ID = "1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c";
|
||||
public static final String TEST_ACL_EMAIL = "james@misterm.org";
|
||||
|
||||
/**
|
||||
* An S3 item's "ACL" may be a {@link CannedAccessPolicy} or an {@link AccessControlList}.
|
||||
*/
|
||||
private static Map<String, Object> keyToAcl = new ConcurrentHashMap<String, Object>();
|
||||
|
||||
public static final String DEFAULT_OWNER_ID = "abc123";
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> putBucketInRegion(@Nullable String region, String name,
|
||||
PutBucketOptions... optionsList) {
|
||||
region = region == null ? Region.US_STANDARD : region;
|
||||
final PutBucketOptions options = (optionsList.length == 0) ? new PutBucketOptions() : optionsList[0];
|
||||
keyToAcl.put(name, options.getAcl());
|
||||
return blobStore.createContainerInLocation(new LocationBuilder().scope(LocationScope.REGION).id(region)
|
||||
.description(region).build(), name);
|
||||
}
|
||||
|
||||
public ListenableFuture<ListBucketResponse> listBucket(final String name, ListBucketOptions... optionsList) {
|
||||
ListContainerOptions options = bucket2ContainerListOptions.apply(optionsList);
|
||||
return transform(blobStore.list(name, options), resource2BucketList, userExecutor);
|
||||
}
|
||||
|
||||
public ListenableFuture<ObjectMetadata> copyObject(final String sourceBucket, final String sourceObject,
|
||||
final String destinationBucket, final String destinationObject, CopyObjectOptions... nullableOptions) {
|
||||
final CopyObjectOptions options = (nullableOptions.length == 0) ? new CopyObjectOptions() : nullableOptions[0];
|
||||
ConcurrentMap<String, Blob> source = containerToBlobs.get(sourceBucket);
|
||||
ConcurrentMap<String, Blob> dest = containerToBlobs.get(destinationBucket);
|
||||
if (source.containsKey(sourceObject)) {
|
||||
Blob object = source.get(sourceObject);
|
||||
if (options.getIfMatch() != null) {
|
||||
if (!object.getMetadata().getETag().equals(options.getIfMatch()))
|
||||
return immediateFailedFuture(LocalAsyncBlobStore.returnResponseException(412));
|
||||
}
|
||||
if (options.getIfNoneMatch() != null) {
|
||||
if (object.getMetadata().getETag().equals(options.getIfNoneMatch()))
|
||||
return immediateFailedFuture(LocalAsyncBlobStore.returnResponseException(412));
|
||||
}
|
||||
if (options.getIfModifiedSince() != null) {
|
||||
Date modifiedSince = dateService.rfc822DateParse(options.getIfModifiedSince());
|
||||
if (modifiedSince.after(object.getMetadata().getLastModified()))
|
||||
return immediateFailedFuture(LocalAsyncBlobStore.returnResponseException(412));
|
||||
|
||||
}
|
||||
if (options.getIfUnmodifiedSince() != null) {
|
||||
Date unmodifiedSince = dateService.rfc822DateParse(options.getIfUnmodifiedSince());
|
||||
if (unmodifiedSince.before(object.getMetadata().getLastModified()))
|
||||
return immediateFailedFuture(LocalAsyncBlobStore.returnResponseException(412));
|
||||
}
|
||||
Blob sourceS3 = source.get(sourceObject);
|
||||
MutableBlobMetadata newMd = BlobStoreUtils.copy(sourceS3.getMetadata(), destinationObject);
|
||||
if (options.getAcl() != null)
|
||||
keyToAcl.put(destinationBucket + "/" + destinationObject, options.getAcl());
|
||||
|
||||
newMd.setLastModified(new Date());
|
||||
Blob newBlob = blobProvider.create(newMd);
|
||||
newBlob.setPayload(sourceS3.getPayload());
|
||||
dest.put(destinationObject, newBlob);
|
||||
return immediateFuture((ObjectMetadata) blob2ObjectMetadata.apply(BlobStoreUtils.copy(newMd)));
|
||||
}
|
||||
return immediateFailedFuture(new KeyNotFoundException(sourceBucket, sourceObject, sourceBucket + "/"
|
||||
+ sourceObject));
|
||||
}
|
||||
|
||||
public ListenableFuture<String> putObject(final String bucketName, final S3Object object,
|
||||
PutObjectOptions... nullableOptions) {
|
||||
final PutObjectOptions options = (nullableOptions.length == 0) ? new PutObjectOptions() : nullableOptions[0];
|
||||
if (options.getAcl() != null)
|
||||
keyToAcl.put(bucketName + "/" + object.getMetadata().getKey(), options.getAcl());
|
||||
return blobStore.putBlob(bucketName, object2Blob.apply(object));
|
||||
}
|
||||
|
||||
protected AccessControlList getACLforS3Item(String bucketAndObjectKey) {
|
||||
AccessControlList acl = null;
|
||||
Object aclObj = keyToAcl.get(bucketAndObjectKey);
|
||||
if (aclObj instanceof AccessControlList) {
|
||||
acl = (AccessControlList) aclObj;
|
||||
} else if (aclObj instanceof CannedAccessPolicy) {
|
||||
acl = AccessControlList.fromCannedAccessPolicy((CannedAccessPolicy) aclObj, DEFAULT_OWNER_ID);
|
||||
} else if (aclObj == null) {
|
||||
// Default to private access policy
|
||||
acl = AccessControlList.fromCannedAccessPolicy(CannedAccessPolicy.PRIVATE, DEFAULT_OWNER_ID);
|
||||
}
|
||||
return acl;
|
||||
}
|
||||
|
||||
public ListenableFuture<AccessControlList> getBucketACL(final String bucket) {
|
||||
return immediateFuture(getACLforS3Item(bucket));
|
||||
}
|
||||
|
||||
public ListenableFuture<AccessControlList> getObjectACL(final String bucket, final String objectKey) {
|
||||
return immediateFuture(getACLforS3Item(bucket + "/" + objectKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any AmazonCustomerByEmail grantees with a somewhat-arbitrary canonical user grantee,
|
||||
* to match S3 which substitutes each email address grantee with that user's corresponding ID. In
|
||||
* short, although you can PUT email address grantees, these are actually subsequently returned
|
||||
* by S3 as canonical user grantees.
|
||||
*
|
||||
* @param acl
|
||||
* @return
|
||||
*/
|
||||
protected AccessControlList sanitizeUploadedACL(AccessControlList acl) {
|
||||
// Replace any email address grantees with canonical user grantees, using
|
||||
// the acl's owner ID as the surrogate replacement.
|
||||
for (Grant grant : acl.getGrants()) {
|
||||
if (grant.getGrantee() instanceof EmailAddressGrantee) {
|
||||
EmailAddressGrantee emailGrantee = (EmailAddressGrantee) grant.getGrantee();
|
||||
String id = emailGrantee.getEmailAddress().equals(TEST_ACL_EMAIL) ? TEST_ACL_ID : acl.getOwner().getId();
|
||||
grant.setGrantee(new CanonicalUserGrantee(id, acl.getOwner().getDisplayName()));
|
||||
}
|
||||
}
|
||||
return acl;
|
||||
}
|
||||
|
||||
public ListenableFuture<Boolean> putBucketACL(final String bucket, final AccessControlList acl) {
|
||||
keyToAcl.put(bucket, sanitizeUploadedACL(acl));
|
||||
return immediateFuture(true);
|
||||
}
|
||||
|
||||
public ListenableFuture<Boolean> putObjectACL(final String bucket, final String objectKey,
|
||||
final AccessControlList acl) {
|
||||
keyToAcl.put(bucket + "/" + objectKey, sanitizeUploadedACL(acl));
|
||||
return immediateFuture(true);
|
||||
}
|
||||
|
||||
public ListenableFuture<Boolean> bucketExists(final String bucketName) {
|
||||
return immediateFuture(containerToBlobs.containsKey(bucketName));
|
||||
}
|
||||
|
||||
public ListenableFuture<Boolean> deleteBucketIfEmpty(String bucketName) {
|
||||
Boolean returnVal = true;
|
||||
if (containerToBlobs.containsKey(bucketName)) {
|
||||
if (containerToBlobs.get(bucketName).size() == 0)
|
||||
containerToBlobs.remove(bucketName);
|
||||
else
|
||||
returnVal = false;
|
||||
}
|
||||
return immediateFuture(returnVal);
|
||||
}
|
||||
|
||||
public ListenableFuture<Void> deleteObject(String bucketName, String key) {
|
||||
return blobStore.removeBlob(bucketName, key);
|
||||
}
|
||||
|
||||
public ListenableFuture<S3Object> getObject(final String bucketName, final String key, final GetOptions... options) {
|
||||
org.jclouds.blobstore.options.GetOptions getOptions = httpGetOptionsConverter.apply(options);
|
||||
return transform(blobStore.getBlob(bucketName, key, getOptions), blob2Object, userExecutor);
|
||||
}
|
||||
|
||||
public ListenableFuture<ObjectMetadata> headObject(String bucketName, String key) {
|
||||
return transform(blobStore.blobMetadata(bucketName, key), new Function<BlobMetadata, ObjectMetadata>() {
|
||||
public ObjectMetadata apply(BlobMetadata from) {
|
||||
return blob2ObjectMetadata.apply(from);
|
||||
}
|
||||
}, userExecutor);
|
||||
}
|
||||
|
||||
public ListenableFuture<? extends Set<BucketMetadata>> listOwnedBuckets() {
|
||||
return immediateFuture(Sets.newLinkedHashSet(Iterables.transform(containerToBlobs.keySet(),
|
||||
new Function<String, BucketMetadata>() {
|
||||
public BucketMetadata apply(String name) {
|
||||
return new BucketMetadata(name, null, null);
|
||||
}
|
||||
|
||||
})));
|
||||
}
|
||||
|
||||
public S3Object newS3Object() {
|
||||
return objectProvider.create(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<String> getBucketLocation(String bucketName) {
|
||||
Location location = containerToLocation.get(bucketName);
|
||||
return immediateFuture(location.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Payer> getBucketPayer(String bucketName) {
|
||||
return immediateFuture(Payer.BUCKET_OWNER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> setBucketPayer(String bucketName, Payer payer) {
|
||||
return immediateFuture(null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> disableBucketLogging(String bucketName) {
|
||||
return immediateFuture(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> enableBucketLogging(String bucketName, BucketLogging logging) {
|
||||
return immediateFuture(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<BucketLogging> getBucketLogging(String bucketName) {
|
||||
return immediateFuture(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> objectExists(String bucketName, String key) {
|
||||
return immediateFuture(containerToBlobs.get(bucketName).containsKey(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
closer.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -16,6 +16,18 @@
|
|||
*/
|
||||
package org.jclouds.s3.services;
|
||||
|
||||
import static org.jclouds.s3.S3ClientLiveTest.TEST_ACL_EMAIL;
|
||||
import static org.jclouds.s3.S3ClientLiveTest.TEST_ACL_ID;
|
||||
import static org.jclouds.s3.domain.AccessControlList.GroupGranteeURI.ALL_USERS;
|
||||
import static org.jclouds.s3.domain.AccessControlList.GroupGranteeURI.LOG_DELIVERY;
|
||||
import static org.jclouds.s3.domain.AccessControlList.Permission.FULL_CONTROL;
|
||||
import static org.jclouds.s3.domain.AccessControlList.Permission.READ;
|
||||
import static org.jclouds.s3.domain.AccessControlList.Permission.READ_ACP;
|
||||
import static org.jclouds.s3.domain.AccessControlList.Permission.WRITE;
|
||||
import static org.jclouds.s3.domain.AccessControlList.Permission.WRITE_ACP;
|
||||
import static org.jclouds.s3.domain.CannedAccessPolicy.PUBLIC_READ;
|
||||
import static org.jclouds.s3.domain.Payer.BUCKET_OWNER;
|
||||
import static org.jclouds.s3.domain.Payer.REQUESTER;
|
||||
import static org.jclouds.s3.options.ListBucketOptions.Builder.afterMarker;
|
||||
import static org.jclouds.s3.options.ListBucketOptions.Builder.delimiter;
|
||||
import static org.jclouds.s3.options.ListBucketOptions.Builder.maxResults;
|
||||
|
@ -34,21 +46,15 @@ import java.util.concurrent.ExecutionException;
|
|||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
|
||||
import org.jclouds.s3.S3ApiMetadata;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
import org.jclouds.s3.domain.AccessControlList.CanonicalUserGrantee;
|
||||
import org.jclouds.s3.domain.AccessControlList.EmailAddressGrantee;
|
||||
import org.jclouds.s3.domain.AccessControlList.Grant;
|
||||
import org.jclouds.s3.domain.AccessControlList.GroupGranteeURI;
|
||||
import org.jclouds.s3.domain.AccessControlList.Permission;
|
||||
import org.jclouds.s3.domain.BucketLogging;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
import org.jclouds.s3.domain.CannedAccessPolicy;
|
||||
import org.jclouds.s3.domain.ListBucketResponse;
|
||||
import org.jclouds.s3.domain.Payer;
|
||||
import org.jclouds.s3.domain.S3Object;
|
||||
import org.jclouds.s3.internal.StubS3AsyncClient;
|
||||
import org.jclouds.util.Strings2;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@ -58,13 +64,14 @@ import com.google.common.collect.Iterables;
|
|||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
|
||||
|
||||
public BucketsLiveTest() {
|
||||
this.provider = "s3";
|
||||
BaseBlobStoreIntegrationTest.SANITY_CHECK_RETURNED_BUCKET_NAME = true;
|
||||
}
|
||||
|
||||
public S3Client getApi() {
|
||||
return view.unwrap(S3ApiMetadata.CONTEXT_TOKEN).getApi();
|
||||
return view.unwrapApi(S3Client.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,7 +101,7 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
|
|||
assertEquals(acl.getGrants().size(), 1);
|
||||
assertNotNull(acl.getOwner());
|
||||
String ownerId = acl.getOwner().getId();
|
||||
assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL));
|
||||
assertTrue(acl.hasPermission(ownerId, FULL_CONTROL));
|
||||
} finally {
|
||||
returnContainer(bucketName);
|
||||
}
|
||||
|
@ -109,7 +116,7 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
|
|||
AccessControlList acl = getApi().getBucketACL(bucketName);
|
||||
String ownerId = acl.getOwner().getId();
|
||||
assertEquals(acl.getGrants().size(), 1);
|
||||
assertTrue(acl.hasPermission(ownerId, Permission.FULL_CONTROL));
|
||||
assertTrue(acl.hasPermission(ownerId, FULL_CONTROL));
|
||||
|
||||
addGrantsToACL(acl);
|
||||
assertEquals(acl.getGrants().size(), 4);
|
||||
|
@ -129,26 +136,26 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
|
|||
|
||||
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());
|
||||
assertTrue(acl.hasPermission(ownerId, FULL_CONTROL), acl.toString());
|
||||
assertTrue(acl.hasPermission(ALL_USERS, READ), acl.toString());
|
||||
assertTrue(acl.hasPermission(ownerId, WRITE_ACP), acl.toString());
|
||||
// EmailAddressGrantee is replaced by a CanonicalUserGrantee, so we cannot test by email addr
|
||||
assertTrue(acl.hasPermission(StubS3AsyncClient.TEST_ACL_ID, Permission.READ_ACP), acl.toString());
|
||||
assertTrue(acl.hasPermission(TEST_ACL_ID, 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(StubS3AsyncClient.TEST_ACL_EMAIL), Permission.READ_ACP);
|
||||
acl.addPermission(new CanonicalUserGrantee(ownerId), Permission.WRITE_ACP);
|
||||
acl.addPermission(ALL_USERS, READ);
|
||||
acl.addPermission(new EmailAddressGrantee(TEST_ACL_EMAIL), READ_ACP);
|
||||
acl.addPermission(new CanonicalUserGrantee(ownerId), WRITE_ACP);
|
||||
}
|
||||
|
||||
public void testPublicReadAccessPolicy() throws Exception {
|
||||
String bucketName = getScratchContainerName();
|
||||
try {
|
||||
getApi().putBucketInRegion(null, bucketName, withBucketAcl(CannedAccessPolicy.PUBLIC_READ));
|
||||
getApi().putBucketInRegion(null, bucketName, withBucketAcl(PUBLIC_READ));
|
||||
AccessControlList acl = getApi().getBucketACL(bucketName);
|
||||
assertTrue(acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ), acl.toString());
|
||||
assertTrue(acl.hasPermission(ALL_USERS, READ), acl.toString());
|
||||
// TODO: I believe that the following should work based on the above acl assertion passing.
|
||||
// However, it fails on 403
|
||||
// URL url = new URL(String.format("http://%s.s3.amazonaws.com", bucketName));
|
||||
|
@ -173,23 +180,23 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
|
|||
public void testBucketPayer() throws Exception {
|
||||
final String bucketName = getContainerName();
|
||||
try {
|
||||
assertEquals(Payer.BUCKET_OWNER, getApi().getBucketPayer(bucketName));
|
||||
getApi().setBucketPayer(bucketName, Payer.REQUESTER);
|
||||
assertEquals(BUCKET_OWNER, getApi().getBucketPayer(bucketName));
|
||||
getApi().setBucketPayer(bucketName, REQUESTER);
|
||||
assertConsistencyAware(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
assertEquals(Payer.REQUESTER, getApi().getBucketPayer(bucketName));
|
||||
assertEquals(REQUESTER, getApi().getBucketPayer(bucketName));
|
||||
|
||||
} catch (Exception e) {
|
||||
Throwables.propagateIfPossible(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
getApi().setBucketPayer(bucketName, Payer.BUCKET_OWNER);
|
||||
getApi().setBucketPayer(bucketName, BUCKET_OWNER);
|
||||
assertConsistencyAware(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
assertEquals(Payer.BUCKET_OWNER, getApi().getBucketPayer(bucketName));
|
||||
assertEquals(BUCKET_OWNER, getApi().getBucketPayer(bucketName));
|
||||
} catch (Exception e) {
|
||||
Throwables.propagateIfPossible(e);
|
||||
}
|
||||
|
@ -208,8 +215,7 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
|
|||
|
||||
setupAclForBucketLoggingTarget(targetBucket);
|
||||
final BucketLogging logging = new BucketLogging(targetBucket, "access_log-",
|
||||
ImmutableSet.<Grant> of(new Grant(new EmailAddressGrantee(StubS3AsyncClient.TEST_ACL_EMAIL),
|
||||
Permission.FULL_CONTROL)));
|
||||
ImmutableSet.<Grant> of(new Grant(new EmailAddressGrantee(TEST_ACL_EMAIL), FULL_CONTROL)));
|
||||
|
||||
getApi().enableBucketLogging(bucketName, logging);
|
||||
|
||||
|
@ -226,7 +232,7 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
|
|||
}
|
||||
// EmailAddressGrantee is replaced by a CanonicalUserGrantee, so we cannot test by
|
||||
// email addr
|
||||
assertTrue(acl.hasPermission(StubS3AsyncClient.TEST_ACL_ID, Permission.FULL_CONTROL), acl.toString());
|
||||
assertTrue(acl.hasPermission(TEST_ACL_ID, FULL_CONTROL), acl.toString());
|
||||
assertEquals(logging.getTargetBucket(), newLogging.getTargetBucket());
|
||||
assertEquals(logging.getTargetPrefix(), newLogging.getTargetPrefix());
|
||||
} catch (Exception e) {
|
||||
|
@ -251,10 +257,9 @@ public class BucketsLiveTest extends BaseBlobStoreIntegrationTest {
|
|||
}
|
||||
|
||||
private void setupAclForBucketLoggingTarget(final String targetBucket) {
|
||||
// http://docs.amazonwebservices.com/AmazonS3/latest/LoggingHowTo.html
|
||||
AccessControlList acl = getApi().getBucketACL(targetBucket);
|
||||
acl.addPermission(GroupGranteeURI.LOG_DELIVERY, Permission.WRITE);
|
||||
acl.addPermission(GroupGranteeURI.LOG_DELIVERY, Permission.READ_ACP);
|
||||
acl.addPermission(LOG_DELIVERY, WRITE);
|
||||
acl.addPermission(LOG_DELIVERY, READ_ACP);
|
||||
assertTrue(getApi().putBucketACL(targetBucket, acl));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
* 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.blobstore.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.blobstore.AsyncBlobStore;
|
||||
import org.jclouds.blobstore.BlobStore;
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.BlobBuilder;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.domain.PageSet;
|
||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.GetOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.blobstore.options.PutOptions;
|
||||
import org.jclouds.domain.Location;
|
||||
|
||||
import com.google.common.collect.ForwardingObject;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
|
||||
/**
|
||||
* Adapter that allows you to reuse an existing {@link BlobStore} to implement
|
||||
* the deprecated {@link AsyncBlobStore} interface.
|
||||
*
|
||||
* @deprecated will be removed in jclouds 2.0, as async interfaces are no longer
|
||||
* supported. Please use {@link BlobStore}
|
||||
*/
|
||||
@Deprecated
|
||||
public class SubmissionAsyncBlobStore extends ForwardingObject implements AsyncBlobStore {
|
||||
private final BlobStore blobstore;
|
||||
private final ListeningExecutorService executor;
|
||||
|
||||
@Inject
|
||||
public SubmissionAsyncBlobStore(BlobStore blobstore, @Named(PROPERTY_USER_THREADS) ListeningExecutorService executor) {
|
||||
this.blobstore = checkNotNull(blobstore, "blobstore");
|
||||
this.executor = checkNotNull(executor, "executor");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlobStore delegate() {
|
||||
return blobstore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlobStoreContext getContext() {
|
||||
return delegate().getContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlobBuilder blobBuilder(String name) {
|
||||
return delegate().blobBuilder(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Set<? extends Location>> listAssignableLocations() {
|
||||
return executor.submit(new Callable<Set<? extends Location>>() {
|
||||
public Set<? extends Location> call() {
|
||||
return delegate().listAssignableLocations();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
|
||||
return executor.submit(new Callable<PageSet<? extends StorageMetadata>>() {
|
||||
public PageSet<? extends StorageMetadata> call() {
|
||||
return delegate().list();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> containerExists(final String container) {
|
||||
return executor.submit(new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
return delegate().containerExists(container);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(final Location location, final String container) {
|
||||
return executor.submit(new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
return delegate().createContainerInLocation(location, container);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(final Location location, final String container,
|
||||
final CreateContainerOptions options) {
|
||||
return executor.submit(new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
return delegate().createContainerInLocation(location, container, options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<PageSet<? extends StorageMetadata>> list(final String container) {
|
||||
return executor.submit(new Callable<PageSet<? extends StorageMetadata>>() {
|
||||
public PageSet<? extends StorageMetadata> call() {
|
||||
return delegate().list(container);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<PageSet<? extends StorageMetadata>> list(final String container,
|
||||
final ListContainerOptions options) {
|
||||
return executor.submit(new Callable<PageSet<? extends StorageMetadata>>() {
|
||||
public PageSet<? extends StorageMetadata> call() {
|
||||
return delegate().list(container, options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> clearContainer(final String container) {
|
||||
return executor.submit(new Callable<Void>() {
|
||||
public Void call() {
|
||||
delegate().clearContainer(container);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> clearContainer(final String container, final ListContainerOptions options) {
|
||||
return executor.submit(new Callable<Void>() {
|
||||
public Void call() {
|
||||
delegate().clearContainer(container, options);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> deleteContainer(final String container) {
|
||||
return executor.submit(new Callable<Void>() {
|
||||
public Void call() {
|
||||
delegate().deleteContainer(container);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> deleteContainerIfEmpty(final String container) {
|
||||
return executor.submit(new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
return delegate().deleteContainerIfEmpty(container);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> directoryExists(final String container, final String directory) {
|
||||
return executor.submit(new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
return delegate().directoryExists(container, directory);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> createDirectory(final String container, final String directory) {
|
||||
return executor.submit(new Callable<Void>() {
|
||||
public Void call() {
|
||||
delegate().createDirectory(container, directory);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> deleteDirectory(final String containerName, final String name) {
|
||||
return executor.submit(new Callable<Void>() {
|
||||
public Void call() {
|
||||
delegate().deleteDirectory(containerName, name);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> blobExists(final String container, final String name) {
|
||||
return executor.submit(new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
return delegate().blobExists(container, name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<String> putBlob(final String container, final Blob blob) {
|
||||
return executor.submit(new Callable<String>() {
|
||||
public String call() {
|
||||
return delegate().putBlob(container, blob);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<String> putBlob(final String container, final Blob blob, final PutOptions options) {
|
||||
return executor.submit(new Callable<String>() {
|
||||
public String call() {
|
||||
return delegate().putBlob(container, blob, options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<BlobMetadata> blobMetadata(final String container, final String key) {
|
||||
return executor.submit(new Callable<BlobMetadata>() {
|
||||
public BlobMetadata call() {
|
||||
return delegate().blobMetadata(container, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Blob> getBlob(final String container, final String key) {
|
||||
return executor.submit(new Callable<Blob>() {
|
||||
public Blob call() {
|
||||
return delegate().getBlob(container, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Blob> getBlob(final String container, final String key, final GetOptions options) {
|
||||
return executor.submit(new Callable<Blob>() {
|
||||
public Blob call() {
|
||||
return delegate().getBlob(container, key, options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> removeBlob(final String container, final String key) {
|
||||
return executor.submit(new Callable<Void>() {
|
||||
public Void call() {
|
||||
delegate().removeBlob(container, key);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Long> countBlobs(final String container) {
|
||||
return executor.submit(new Callable<Long>() {
|
||||
public Long call() {
|
||||
return delegate().countBlobs(container);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Long> countBlobs(final String container, final ListContainerOptions options) {
|
||||
return executor.submit(new Callable<Long>() {
|
||||
public Long call() {
|
||||
return delegate().countBlobs(container, options);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -23,27 +23,17 @@ import java.util.Properties;
|
|||
|
||||
import org.jclouds.aws.s3.blobstore.AWSS3BlobStoreContext;
|
||||
import org.jclouds.aws.s3.blobstore.config.AWSS3BlobStoreContextModule;
|
||||
import org.jclouds.aws.s3.config.AWSS3RestClientModule;
|
||||
import org.jclouds.aws.s3.config.AWSS3HttpApiModule;
|
||||
import org.jclouds.s3.S3ApiMetadata;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* Implementation of {@link ApiMetadata} for the Amazon-specific S3 API
|
||||
* Implementation of {@link S3ApiMetadata} for the Amazon-specific S3 API
|
||||
*/
|
||||
public class AWSS3ApiMetadata extends S3ApiMetadata {
|
||||
|
||||
/**
|
||||
* @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(AWSS3Client.class)} as
|
||||
* {@link AWSS3AsyncClient} interface will be removed in jclouds 1.7.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final TypeToken<org.jclouds.rest.RestContext<AWSS3Client, AWSS3AsyncClient>> CONTEXT_TOKEN = new TypeToken<org.jclouds.rest.RestContext<AWSS3Client, AWSS3AsyncClient>>() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
};
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().fromApiMetadata(this);
|
||||
|
@ -63,16 +53,14 @@ public class AWSS3ApiMetadata extends S3ApiMetadata {
|
|||
return properties;
|
||||
}
|
||||
|
||||
public static class Builder extends S3ApiMetadata.Builder<Builder> {
|
||||
@SuppressWarnings("deprecation")
|
||||
public static class Builder extends S3ApiMetadata.Builder<AWSS3Client, Builder> {
|
||||
protected Builder() {
|
||||
super(AWSS3Client.class, AWSS3AsyncClient.class);
|
||||
super(AWSS3Client.class);
|
||||
id("aws-s3")
|
||||
.name("Amazon-specific S3 API")
|
||||
.defaultProperties(AWSS3ApiMetadata.defaultProperties())
|
||||
.context(CONTEXT_TOKEN)
|
||||
.view(typeToken(AWSS3BlobStoreContext.class))
|
||||
.defaultModules(ImmutableSet.<Class<? extends Module>>of(AWSS3RestClientModule.class, AWSS3BlobStoreContextModule.class));
|
||||
.defaultModules(ImmutableSet.<Class<? extends Module>>of(AWSS3HttpApiModule.class, AWSS3BlobStoreContextModule.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
* 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.blobstore.attr.BlobScopes.CONTAINER;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.QueryParam;
|
||||
|
||||
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
|
||||
import org.jclouds.aws.s3.binders.BindIterableAsPayloadToDeleteRequest;
|
||||
import org.jclouds.aws.s3.binders.BindObjectMetadataToRequest;
|
||||
import org.jclouds.aws.s3.binders.BindPartIdsAndETagsToRequest;
|
||||
import org.jclouds.aws.s3.domain.DeleteResult;
|
||||
import org.jclouds.aws.s3.functions.ETagFromHttpResponseViaRegex;
|
||||
import org.jclouds.aws.s3.functions.ObjectMetadataKey;
|
||||
import org.jclouds.aws.s3.functions.UploadIdFromHttpResponseViaRegex;
|
||||
import org.jclouds.aws.s3.xml.DeleteResultHandler;
|
||||
import org.jclouds.blobstore.attr.BlobScope;
|
||||
import org.jclouds.http.functions.ParseETagHeader;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
import org.jclouds.rest.annotations.ParamParser;
|
||||
import org.jclouds.rest.annotations.ParamValidators;
|
||||
import org.jclouds.rest.annotations.QueryParams;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.ResponseParser;
|
||||
import org.jclouds.rest.annotations.XMLResponseParser;
|
||||
import org.jclouds.s3.Bucket;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.binders.BindAsHostPrefixIfConfigured;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.filters.RequestAuthorizeSignature;
|
||||
import org.jclouds.s3.functions.AssignCorrectHostnameForBucket;
|
||||
import org.jclouds.s3.options.PutObjectOptions;
|
||||
import org.jclouds.s3.predicates.validators.BucketNameValidator;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* Provides access to amazon-specific S3 features
|
||||
*
|
||||
* @deprecated please use
|
||||
* {@code org.jclouds.ContextBuilder#buildApi(AWSS3Client.class)}
|
||||
* as {@link AWSS3AsyncClient} interface will be removed in jclouds 1.7.
|
||||
*/
|
||||
@RequestFilters(RequestAuthorizeSignature.class)
|
||||
@BlobScope(CONTAINER)
|
||||
@Deprecated
|
||||
public interface AWSS3AsyncClient extends S3AsyncClient {
|
||||
|
||||
/**
|
||||
* @see AWSS3Client#initiateMultipartUpload
|
||||
*/
|
||||
@Named("PutObject")
|
||||
@POST
|
||||
@QueryParams(keys = "uploads")
|
||||
@Path("/{key}")
|
||||
@ResponseParser(UploadIdFromHttpResponseViaRegex.class)
|
||||
ListenableFuture<String> initiateMultipartUpload(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") @ParamParser(ObjectMetadataKey.class) @BinderParam(BindObjectMetadataToRequest.class) ObjectMetadata objectMetadata,
|
||||
PutObjectOptions... options);
|
||||
|
||||
/**
|
||||
* @see AWSS3Client#abortMultipartUpload
|
||||
*/
|
||||
@Named("AbortMultipartUpload")
|
||||
@DELETE
|
||||
@Path("/{key}")
|
||||
@Fallback(VoidOnNotFoundOr404.class)
|
||||
ListenableFuture<Void> abortMultipartUpload(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key, @QueryParam("uploadId") String uploadId);
|
||||
|
||||
/**
|
||||
* @see AWSS3Client#uploadPart
|
||||
*/
|
||||
@Named("PutObject")
|
||||
@PUT
|
||||
@Path("/{key}")
|
||||
@ResponseParser(ParseETagHeader.class)
|
||||
ListenableFuture<String> uploadPart(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key, @QueryParam("partNumber") int partNumber,
|
||||
@QueryParam("uploadId") String uploadId, Payload part);
|
||||
|
||||
/**
|
||||
* @see AWSS3Client#completeMultipartUpload
|
||||
*/
|
||||
@Named("PutObject")
|
||||
@POST
|
||||
@Path("/{key}")
|
||||
@ResponseParser(ETagFromHttpResponseViaRegex.class)
|
||||
ListenableFuture<String> completeMultipartUpload(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key, @QueryParam("uploadId") String uploadId,
|
||||
@BinderParam(BindPartIdsAndETagsToRequest.class) Map<Integer, String> parts);
|
||||
|
||||
/**
|
||||
* @see AWSS3Client#deleteObjects
|
||||
*/
|
||||
@Named("DeleteObject")
|
||||
@POST
|
||||
@Path("/")
|
||||
@QueryParams(keys = "delete")
|
||||
@XMLResponseParser(DeleteResultHandler.class)
|
||||
ListenableFuture<DeleteResult> deleteObjects(
|
||||
@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@BinderParam(BindIterableAsPayloadToDeleteRequest.class) Iterable<String> keys);
|
||||
|
||||
}
|
|
@ -16,18 +16,53 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3;
|
||||
|
||||
import static org.jclouds.Fallbacks.VoidOnNotFoundOr404;
|
||||
import static org.jclouds.blobstore.attr.BlobScopes.CONTAINER;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.QueryParam;
|
||||
|
||||
import org.jclouds.aws.s3.binders.BindIterableAsPayloadToDeleteRequest;
|
||||
import org.jclouds.aws.s3.binders.BindObjectMetadataToRequest;
|
||||
import org.jclouds.aws.s3.binders.BindPartIdsAndETagsToRequest;
|
||||
import org.jclouds.aws.s3.domain.DeleteResult;
|
||||
import org.jclouds.aws.s3.functions.ETagFromHttpResponseViaRegex;
|
||||
import org.jclouds.aws.s3.functions.ObjectMetadataKey;
|
||||
import org.jclouds.aws.s3.functions.UploadIdFromHttpResponseViaRegex;
|
||||
import org.jclouds.aws.s3.xml.DeleteResultHandler;
|
||||
import org.jclouds.blobstore.attr.BlobScope;
|
||||
import org.jclouds.http.functions.ParseETagHeader;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
import org.jclouds.rest.annotations.ParamParser;
|
||||
import org.jclouds.rest.annotations.ParamValidators;
|
||||
import org.jclouds.rest.annotations.QueryParams;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.ResponseParser;
|
||||
import org.jclouds.rest.annotations.XMLResponseParser;
|
||||
import org.jclouds.s3.Bucket;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.binders.BindAsHostPrefixIfConfigured;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.filters.RequestAuthorizeSignature;
|
||||
import org.jclouds.s3.functions.AssignCorrectHostnameForBucket;
|
||||
import org.jclouds.s3.options.PutObjectOptions;
|
||||
import org.jclouds.s3.predicates.validators.BucketNameValidator;
|
||||
|
||||
/**
|
||||
* Provides access to amazon-specific S3 features
|
||||
*
|
||||
* @see AWSS3AsyncClient
|
||||
*/
|
||||
@RequestFilters(RequestAuthorizeSignature.class)
|
||||
@BlobScope(CONTAINER)
|
||||
public interface AWSS3Client extends S3Client {
|
||||
|
||||
/**
|
||||
|
@ -48,8 +83,15 @@ public interface AWSS3Client extends S3Client {
|
|||
* controls optional parameters such as canned ACL
|
||||
* @return ID for the initiated multipart upload.
|
||||
*/
|
||||
String initiateMultipartUpload(String bucketName, ObjectMetadata objectMetadata, PutObjectOptions... options);
|
||||
|
||||
@Named("PutObject")
|
||||
@POST
|
||||
@QueryParams(keys = "uploads")
|
||||
@Path("/{key}")
|
||||
@ResponseParser(UploadIdFromHttpResponseViaRegex.class)
|
||||
String initiateMultipartUpload(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") @ParamParser(ObjectMetadataKey.class) @BinderParam(BindObjectMetadataToRequest.class)
|
||||
ObjectMetadata objectMetadata, PutObjectOptions... options);
|
||||
|
||||
/**
|
||||
* This operation aborts a multipart upload. After a multipart upload is aborted, no additional
|
||||
|
@ -66,7 +108,13 @@ public interface AWSS3Client extends S3Client {
|
|||
* @param uploadId
|
||||
* id of the multipart upload in progress.
|
||||
*/
|
||||
void abortMultipartUpload(String bucketName, String key, String uploadId);
|
||||
@Named("AbortMultipartUpload")
|
||||
@DELETE
|
||||
@Path("/{key}")
|
||||
@Fallback(VoidOnNotFoundOr404.class)
|
||||
void abortMultipartUpload(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key, @QueryParam("uploadId") String uploadId);
|
||||
|
||||
/**
|
||||
* This operation uploads a part in a multipart upload. You must initiate a multipart upload (see
|
||||
|
@ -98,10 +146,15 @@ public interface AWSS3Client extends S3Client {
|
|||
* @param part
|
||||
* contains the data to create or overwrite
|
||||
* @return ETag of the content uploaded
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadUploadPart.html"
|
||||
* />
|
||||
*/
|
||||
String uploadPart(String bucketName, String key, int partNumber, String uploadId, Payload part);
|
||||
@Named("PutObject")
|
||||
@PUT
|
||||
@Path("/{key}")
|
||||
@ResponseParser(ParseETagHeader.class)
|
||||
String uploadPart(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key, @QueryParam("partNumber") int partNumber,
|
||||
@QueryParam("uploadId") String uploadId, Payload part);
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -135,7 +188,14 @@ public interface AWSS3Client extends S3Client {
|
|||
* a map of part id to eTag from the {@link #uploadPart} command.
|
||||
* @return ETag of the content uploaded
|
||||
*/
|
||||
String completeMultipartUpload(String bucketName, String key, String uploadId, Map<Integer, String> parts);
|
||||
@Named("PutObject")
|
||||
@POST
|
||||
@Path("/{key}")
|
||||
@ResponseParser(ETagFromHttpResponseViaRegex.class)
|
||||
String completeMultipartUpload(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@PathParam("key") String key, @QueryParam("uploadId") String uploadId,
|
||||
@BinderParam(BindPartIdsAndETagsToRequest.class) Map<Integer, String> parts);
|
||||
|
||||
/**
|
||||
* The Multi-Object Delete operation enables you to delete multiple objects from a bucket using a
|
||||
|
@ -151,11 +211,17 @@ public interface AWSS3Client extends S3Client {
|
|||
* By default, the operation uses verbose mode in which the response includes the result of
|
||||
* deletion of each key in your request.
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/API/multiobjectdeleteapi.html" />
|
||||
* @param bucketName
|
||||
* namespace of the objects you are deleting
|
||||
* @param keys
|
||||
* set of unique keys identifying objects
|
||||
*/
|
||||
DeleteResult deleteObjects(String bucketName, Iterable<String> keys);
|
||||
@Named("DeleteObject")
|
||||
@POST
|
||||
@Path("/")
|
||||
@QueryParams(keys = "delete")
|
||||
@XMLResponseParser(DeleteResultHandler.class)
|
||||
DeleteResult deleteObjects(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
|
||||
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
|
||||
@BinderParam(BindIterableAsPayloadToDeleteRequest.class) Iterable<String> keys);
|
||||
}
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
/*
|
||||
* 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.blobstore;
|
||||
|
||||
import static org.jclouds.s3.domain.ObjectMetadata.StorageClass.REDUCED_REDUNDANCY;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.aws.domain.Region;
|
||||
import org.jclouds.aws.s3.AWSS3ApiMetadata;
|
||||
import org.jclouds.aws.s3.AWSS3AsyncClient;
|
||||
import org.jclouds.aws.s3.AWSS3Client;
|
||||
import org.jclouds.aws.s3.blobstore.options.AWSS3PutObjectOptions;
|
||||
import org.jclouds.aws.s3.blobstore.options.AWSS3PutOptions;
|
||||
import org.jclouds.aws.s3.blobstore.strategy.AsyncMultipartUploadStrategy;
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.PageSet;
|
||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.PutOptions;
|
||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
import org.jclouds.collect.Memoized;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.s3.blobstore.S3AsyncBlobStore;
|
||||
import org.jclouds.s3.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.s3.blobstore.functions.BucketToResourceList;
|
||||
import org.jclouds.s3.blobstore.functions.ContainerToBucketListOptions;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlobMetadata;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
import org.jclouds.s3.domain.CannedAccessPolicy;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated will be removed in jclouds 1.7, as async interfaces are no longer
|
||||
* supported. Please use {@link AWSS3BlobStore}
|
||||
*/
|
||||
@Deprecated
|
||||
public class AWSS3AsyncBlobStore extends S3AsyncBlobStore {
|
||||
|
||||
private final Provider<AsyncMultipartUploadStrategy> multipartUploadStrategy;
|
||||
private final LoadingCache<String, AccessControlList> bucketAcls;
|
||||
private final BlobToObject blob2Object;
|
||||
|
||||
@Inject
|
||||
public AWSS3AsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, AWSS3AsyncClient async, AWSS3Client sync,
|
||||
Function<Set<BucketMetadata>, PageSet<? extends StorageMetadata>> convertBucketsToStorageMetadata,
|
||||
ContainerToBucketListOptions container2BucketListOptions, BucketToResourceList bucket2ResourceList,
|
||||
ObjectToBlob object2Blob, BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object,
|
||||
ObjectToBlobMetadata object2BlobMd, Provider<FetchBlobMetadata> fetchBlobMetadataProvider,
|
||||
LoadingCache<String, AccessControlList> bucketAcls,
|
||||
Provider<AsyncMultipartUploadStrategy> multipartUploadStrategy) {
|
||||
super(context, blobUtils, userExecutor, defaultLocation, locations, async, sync, convertBucketsToStorageMetadata,
|
||||
container2BucketListOptions, bucket2ResourceList, object2Blob, blob2ObjectGetOptions, blob2Object,
|
||||
object2BlobMd, fetchBlobMetadataProvider, bucketAcls);
|
||||
this.multipartUploadStrategy = multipartUploadStrategy;
|
||||
this.bucketAcls = bucketAcls;
|
||||
this.blob2Object = blob2Object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<String> putBlob(String container, Blob blob, PutOptions options) {
|
||||
if (options.isMultipart()) {
|
||||
// need to use a provider if the strategy object is stateful
|
||||
return multipartUploadStrategy.get().execute(container, blob, options);
|
||||
} else if (options instanceof AWSS3PutOptions &&
|
||||
((AWSS3PutOptions) options).getStorageClass() == REDUCED_REDUNDANCY) {
|
||||
return putBlobWithReducedRedundancy(container, blob);
|
||||
|
||||
} else {
|
||||
return super.putBlob(container, blob, options);
|
||||
}
|
||||
}
|
||||
|
||||
private ListenableFuture<String> putBlobWithReducedRedundancy(String container, Blob blob) {
|
||||
AWSS3PutObjectOptions options = new AWSS3PutObjectOptions();
|
||||
try {
|
||||
AccessControlList acl = bucketAcls.getUnchecked(container);
|
||||
if (acl != null && acl.hasPermission(AccessControlList.GroupGranteeURI.ALL_USERS,
|
||||
AccessControlList.Permission.READ)) {
|
||||
options.withAcl(CannedAccessPolicy.PUBLIC_READ);
|
||||
}
|
||||
options.storageClass(ObjectMetadata.StorageClass.REDUCED_REDUNDANCY);
|
||||
|
||||
} catch (CacheLoader.InvalidCacheLoadException e) {
|
||||
// nulls not permitted from cache loader
|
||||
}
|
||||
return getContext().unwrap(AWSS3ApiMetadata.CONTEXT_TOKEN).getAsyncApi().putObject(container,
|
||||
blob2Object.apply(blob), options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
|
||||
CreateContainerOptions options) {
|
||||
if ((location == null || location.getId().equals(Region.US_STANDARD)) &&
|
||||
Futures.getUnchecked(containerExists(container))) {
|
||||
// AWS-S3 returns the incorrect creation status when a container
|
||||
// already exists in the us-standard (or default) region. See
|
||||
// JCLOUDS-334 for details.
|
||||
// TODO: executing on the calling thread
|
||||
return Futures.immediateFuture(Boolean.FALSE);
|
||||
}
|
||||
return super.createContainerInLocation(location, container, options);
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ import java.net.URLEncoder;
|
|||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.aws.s3.AWSS3AsyncClient;
|
||||
import org.jclouds.aws.s3.AWSS3Client;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.date.DateService;
|
||||
|
@ -44,7 +44,7 @@ import com.google.common.net.HttpHeaders;
|
|||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
public class AWSS3BlobRequestSigner extends S3BlobRequestSigner<AWSS3AsyncClient> {
|
||||
public class AWSS3BlobRequestSigner extends S3BlobRequestSigner<AWSS3Client> {
|
||||
public static final String TEMPORARY_SIGNATURE_PARAM = "Signature";
|
||||
|
||||
private final RequestAuthorizeSignature authSigner;
|
||||
|
@ -54,7 +54,7 @@ public class AWSS3BlobRequestSigner extends S3BlobRequestSigner<AWSS3AsyncClient
|
|||
|
||||
@Inject
|
||||
public AWSS3BlobRequestSigner(RestAnnotationProcessor processor, BlobToObject blobToObject,
|
||||
BlobToHttpGetOptions blob2HttpGetOptions, Class<AWSS3AsyncClient> interfaceClass,
|
||||
BlobToHttpGetOptions blob2HttpGetOptions, Class<AWSS3Client> interfaceClass,
|
||||
@org.jclouds.location.Provider Supplier<Credentials> credentials,
|
||||
RequestAuthorizeSignature authSigner, @TimeStamp Provider<String> timeStampProvider,
|
||||
DateService dateService) throws SecurityException, NoSuchMethodException {
|
||||
|
|
|
@ -24,7 +24,6 @@ import javax.inject.Inject;
|
|||
import javax.inject.Provider;
|
||||
|
||||
import org.jclouds.aws.domain.Region;
|
||||
import org.jclouds.aws.s3.AWSS3ApiMetadata;
|
||||
import org.jclouds.aws.s3.AWSS3Client;
|
||||
import org.jclouds.aws.s3.blobstore.options.AWSS3PutObjectOptions;
|
||||
import org.jclouds.aws.s3.blobstore.options.AWSS3PutOptions;
|
||||
|
@ -110,8 +109,7 @@ public class AWSS3BlobStore extends S3BlobStore {
|
|||
} catch (CacheLoader.InvalidCacheLoadException e) {
|
||||
// nulls not permitted from cache loader
|
||||
}
|
||||
return getContext().unwrap(AWSS3ApiMetadata.CONTEXT_TOKEN).getApi().putObject(container, blob2Object.apply(blob),
|
||||
options);
|
||||
return getContext().unwrapApi(AWSS3Client.class).putObject(container, blob2Object.apply(blob), options);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,7 +26,4 @@ public interface AWSS3BlobStoreContext extends S3BlobStoreContext {
|
|||
|
||||
@Override
|
||||
AWSS3BlobStore getBlobStore();
|
||||
|
||||
@Override
|
||||
AWSS3AsyncBlobStore getAsyncBlobStore();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.blobstore.config;
|
||||
|
||||
import org.jclouds.aws.s3.blobstore.AWSS3AsyncBlobStore;
|
||||
import org.jclouds.aws.s3.blobstore.AWSS3BlobRequestSigner;
|
||||
import org.jclouds.aws.s3.blobstore.AWSS3BlobStore;
|
||||
import org.jclouds.aws.s3.blobstore.strategy.AsyncMultipartUploadStrategy;
|
||||
|
@ -24,7 +23,6 @@ import org.jclouds.aws.s3.blobstore.strategy.MultipartUploadStrategy;
|
|||
import org.jclouds.aws.s3.blobstore.strategy.internal.ParallelMultipartUploadStrategy;
|
||||
import org.jclouds.aws.s3.blobstore.strategy.internal.SequentialMultipartUploadStrategy;
|
||||
import org.jclouds.blobstore.BlobRequestSigner;
|
||||
import org.jclouds.s3.blobstore.S3AsyncBlobStore;
|
||||
import org.jclouds.s3.blobstore.S3BlobStore;
|
||||
import org.jclouds.s3.blobstore.config.S3BlobStoreContextModule;
|
||||
|
||||
|
@ -35,7 +33,6 @@ public class AWSS3BlobStoreContextModule extends S3BlobStoreContextModule {
|
|||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
bind(S3AsyncBlobStore.class).to(AWSS3AsyncBlobStore.class).in(Scopes.SINGLETON);
|
||||
bind(S3BlobStore.class).to(AWSS3BlobStore.class).in(Scopes.SINGLETON);
|
||||
bind(MultipartUploadStrategy.class).to(SequentialMultipartUploadStrategy.class);
|
||||
bind(AsyncMultipartUploadStrategy.class).to(ParallelMultipartUploadStrategy.class);
|
||||
|
|
|
@ -20,7 +20,6 @@ import javax.inject.Inject;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Context;
|
||||
import org.jclouds.aws.s3.blobstore.AWSS3AsyncBlobStore;
|
||||
import org.jclouds.aws.s3.blobstore.AWSS3BlobStore;
|
||||
import org.jclouds.aws.s3.blobstore.AWSS3BlobStoreContext;
|
||||
import org.jclouds.blobstore.AsyncBlobStore;
|
||||
|
@ -49,10 +48,4 @@ public class AWSS3BlobStoreContextImpl extends S3BlobStoreContextImpl implements
|
|||
public AWSS3BlobStore getBlobStore() {
|
||||
return AWSS3BlobStore.class.cast(super.getBlobStore());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AWSS3AsyncBlobStore getAsyncBlobStore() {
|
||||
return AWSS3AsyncBlobStore.class.cast(super.getAsyncBlobStore());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,9 +23,6 @@ import org.jclouds.blobstore.options.PutOptions;
|
|||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?qfacts.html">AWS Documentation</a>
|
||||
*/
|
||||
@ImplementedBy(ParallelMultipartUploadStrategy.class)
|
||||
public interface AsyncMultipartUploadStrategy extends MultipartUpload {
|
||||
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.blobstore.strategy;
|
||||
|
||||
/**
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?qfacts.html">AWS Documentation</a>
|
||||
*/
|
||||
public interface MultipartUpload {
|
||||
|
||||
/* Maximum number of parts per upload */
|
||||
|
|
|
@ -21,9 +21,6 @@ import org.jclouds.blobstore.domain.Blob;
|
|||
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?qfacts.html">AWS Documentation</a>
|
||||
*/
|
||||
@ImplementedBy(SequentialMultipartUploadStrategy.class)
|
||||
public interface MultipartUploadStrategy extends MultipartUpload {
|
||||
|
||||
|
|
|
@ -36,10 +36,8 @@ import javax.annotation.Resource;
|
|||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.aws.s3.AWSS3ApiMetadata;
|
||||
import org.jclouds.aws.s3.AWSS3AsyncClient;
|
||||
import org.jclouds.aws.s3.AWSS3Client;
|
||||
import org.jclouds.aws.s3.blobstore.AWSS3AsyncBlobStore;
|
||||
import org.jclouds.aws.s3.blobstore.AWSS3BlobStore;
|
||||
import org.jclouds.aws.s3.blobstore.strategy.AsyncMultipartUploadStrategy;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.internal.BlobRuntimeException;
|
||||
|
@ -93,13 +91,13 @@ public class ParallelMultipartUploadStrategy implements AsyncMultipartUploadStra
|
|||
@Named(Constants.PROPERTY_REQUEST_TIMEOUT)
|
||||
protected Long maxTime;
|
||||
|
||||
protected final AWSS3AsyncBlobStore ablobstore;
|
||||
protected final AWSS3BlobStore blobstore;
|
||||
protected final PayloadSlicer slicer;
|
||||
|
||||
@Inject
|
||||
public ParallelMultipartUploadStrategy(AWSS3AsyncBlobStore ablobstore, PayloadSlicer slicer,
|
||||
public ParallelMultipartUploadStrategy(AWSS3BlobStore blobstore, PayloadSlicer slicer,
|
||||
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor) {
|
||||
this.ablobstore = checkNotNull(ablobstore, "ablobstore");
|
||||
this.blobstore = checkNotNull(blobstore, "blobstore");
|
||||
this.slicer = checkNotNull(slicer, "slicer");
|
||||
this.ioExecutor = checkNotNull(ioExecutor, "ioExecutor");
|
||||
}
|
||||
|
@ -116,11 +114,15 @@ public class ParallelMultipartUploadStrategy implements AsyncMultipartUploadStra
|
|||
latch.countDown();
|
||||
return;
|
||||
}
|
||||
final AWSS3AsyncClient client = ablobstore.getContext().unwrap(AWSS3ApiMetadata.CONTEXT_TOKEN).getAsyncApi();
|
||||
Payload chunkedPart = slicer.slice(payload, offset, size);
|
||||
final AWSS3Client client = blobstore.getContext().unwrapApi(AWSS3Client.class);
|
||||
final Payload chunkedPart = slicer.slice(payload, offset, size);
|
||||
logger.debug(String.format("async uploading part %s of %s to container %s with uploadId %s", part, key, container, uploadId));
|
||||
final long start = System.currentTimeMillis();
|
||||
final ListenableFuture<String> futureETag = client.uploadPart(container, key, part, uploadId, chunkedPart);
|
||||
final ListenableFuture<String> futureETag = ioExecutor.submit(new Callable<String>() {
|
||||
@Override public String call() throws Exception {
|
||||
return client.uploadPart(container, key, part, uploadId, chunkedPart);
|
||||
}
|
||||
});
|
||||
futureETag.addListener(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -164,8 +166,7 @@ public class ParallelMultipartUploadStrategy implements AsyncMultipartUploadStra
|
|||
long chunkSize = algorithm.getChunkSize();
|
||||
long remaining = algorithm.getRemaining();
|
||||
if (parts > 0) {
|
||||
AWSS3Client client = ablobstore
|
||||
.getContext().unwrap(AWSS3ApiMetadata.CONTEXT_TOKEN).getApi();
|
||||
final AWSS3Client client = blobstore.getContext().unwrapApi(AWSS3Client.class);
|
||||
String uploadId = null;
|
||||
final Map<Integer, ListenableFuture<String>> futureParts =
|
||||
new ConcurrentHashMap<Integer, ListenableFuture<String>>();
|
||||
|
@ -240,8 +241,12 @@ public class ParallelMultipartUploadStrategy implements AsyncMultipartUploadStra
|
|||
// Issue 936: don't just call putBlob, as that will see options=multiPart and
|
||||
// recursively call this execute method again; instead mark as not multipart
|
||||
// because it can all fit in one go.
|
||||
PutOptions nonMultipartOptions = PutOptions.Builder.multipart(false);
|
||||
ListenableFuture<String> futureETag = ablobstore.putBlob(container, blob, nonMultipartOptions);
|
||||
final PutOptions nonMultipartOptions = PutOptions.Builder.multipart(false);
|
||||
ListenableFuture<String> futureETag = ioExecutor.submit(new Callable<String>() {
|
||||
@Override public String call() throws Exception {
|
||||
return blobstore.putBlob(container, blob, nonMultipartOptions);
|
||||
}
|
||||
});
|
||||
return maxTime != null ?
|
||||
futureETag.get(maxTime, TimeUnit.SECONDS) : futureETag.get();
|
||||
}
|
||||
|
|
|
@ -17,19 +17,16 @@
|
|||
package org.jclouds.aws.s3.config;
|
||||
|
||||
import static org.jclouds.aws.domain.Region.US_STANDARD;
|
||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.s3.AWSS3AsyncClient;
|
||||
import org.jclouds.aws.s3.AWSS3Client;
|
||||
import org.jclouds.aws.s3.filters.AWSRequestAuthorizeSignature;
|
||||
import org.jclouds.aws.s3.predicates.validators.AWSS3BucketNameValidator;
|
||||
import org.jclouds.location.Region;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.config.S3RestClientModule;
|
||||
import org.jclouds.s3.config.S3HttpApiModule;
|
||||
import org.jclouds.s3.filters.RequestAuthorizeSignature;
|
||||
import org.jclouds.s3.predicates.validators.BucketNameValidator;
|
||||
|
||||
|
@ -41,11 +38,11 @@ import com.google.inject.Scopes;
|
|||
/**
|
||||
* Configures the S3 connection.
|
||||
*/
|
||||
@ConfiguresRestClient
|
||||
public class AWSS3RestClientModule extends S3RestClientModule<AWSS3Client, AWSS3AsyncClient> {
|
||||
@ConfiguresHttpApi
|
||||
public class AWSS3HttpApiModule extends S3HttpApiModule<AWSS3Client> {
|
||||
|
||||
public AWSS3RestClientModule() {
|
||||
super(typeToken(AWSS3Client.class), typeToken(AWSS3AsyncClient.class));
|
||||
public AWSS3HttpApiModule() {
|
||||
super(AWSS3Client.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -69,10 +66,4 @@ public class AWSS3RestClientModule extends S3RestClientModule<AWSS3Client, AWSS3
|
|||
S3Client provide(AWSS3Client in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
S3AsyncClient provide(AWSS3AsyncClient in) {
|
||||
return in;
|
||||
}
|
||||
}
|
|
@ -16,22 +16,20 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ForwardingSet;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Multi-object delete API response
|
||||
* <p/>
|
||||
* Contains a list of the keys that were deleted
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/API/multiobjectdeleteapi.html" />
|
||||
*/
|
||||
public class DeleteResult extends ForwardingSet<String> {
|
||||
|
||||
|
|
|
@ -38,13 +38,7 @@ import org.jclouds.s3.filters.RequestAuthorizeSignature;
|
|||
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
/**
|
||||
* Signs the AWS S3 request, supporting temporary signatures.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/dev/index.html?RESTAuthentication.html"
|
||||
* />
|
||||
*/
|
||||
/** Signs the AWS S3 request, supporting temporary signatures. */
|
||||
@Singleton
|
||||
public class AWSRequestAuthorizeSignature extends RequestAuthorizeSignature {
|
||||
|
||||
|
|
|
@ -14,8 +14,5 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* This package contains HttpRequestFilters needed to operate the REST api.
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html" />
|
||||
*/
|
||||
/** This package contains HttpRequestFilters needed to operate the REST api. */
|
||||
package org.jclouds.aws.s3.filters;
|
||||
|
|
|
@ -27,9 +27,6 @@ import org.jclouds.http.functions.ReturnStringIf2xx;
|
|||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadComplete.html" />
|
||||
*/
|
||||
@Singleton
|
||||
public class ETagFromHttpResponseViaRegex implements Function<HttpResponse, String> {
|
||||
private static Pattern pattern = Pattern.compile("<ETag>([\\S&&[^<]]+)</ETag>");
|
||||
|
|
|
@ -27,11 +27,6 @@ import org.jclouds.http.functions.ReturnStringIf2xx;
|
|||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AmazonS3/latest/API/index.html?mpUploadInitiate.html"
|
||||
* />
|
||||
*/
|
||||
@Singleton
|
||||
public class UploadIdFromHttpResponseViaRegex implements Function<HttpResponse, String> {
|
||||
Pattern pattern = Pattern.compile("<UploadId>([\\S&&[^<]]+)</UploadId>");
|
||||
|
|
|
@ -16,14 +16,15 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.xml;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
|
||||
|
||||
import org.jclouds.aws.s3.domain.DeleteResult;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
public class DeleteResultHandler extends ParseSax.HandlerForGeneratedRequestWithResult<DeleteResult> {
|
||||
|
||||
|
|
|
@ -16,14 +16,15 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.xml;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.aws.s3.domain.DeleteResult;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
public class ErrorEntryHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Map.Entry<String, DeleteResult.Error>> {
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ public class AWSS3ClientLiveTest extends S3ClientLiveTest {
|
|||
|
||||
@Override
|
||||
public AWSS3Client getApi() {
|
||||
return view.unwrap(AWSS3ApiMetadata.CONTEXT_TOKEN).getApi();
|
||||
return view.unwrapApi(AWSS3Client.class);
|
||||
}
|
||||
|
||||
@BeforeClass(groups = { "integration", "live" })
|
||||
|
@ -171,7 +171,7 @@ public class AWSS3ClientLiveTest extends S3ClientLiveTest {
|
|||
blobStore.putBlob(containerName, blob,
|
||||
storageClass(StorageClass.REDUCED_REDUNDANCY));
|
||||
|
||||
S3Client s3Client = S3Client.class.cast(view.unwrap(AWSS3ApiMetadata.CONTEXT_TOKEN).getApi());
|
||||
S3Client s3Client = view.unwrapApi(S3Client.class);
|
||||
ListBucketResponse response = s3Client.listBucket(containerName, withPrefix(blobName));
|
||||
|
||||
ObjectMetadata metadata = response.iterator().next();
|
||||
|
|
|
@ -24,7 +24,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
|
||||
import org.jclouds.aws.s3.config.AWSS3RestClientModule;
|
||||
import org.jclouds.aws.s3.config.AWSS3HttpApiModule;
|
||||
import org.jclouds.aws.s3.filters.AWSRequestAuthorizeSignature;
|
||||
import org.jclouds.aws.s3.functions.ETagFromHttpResponseViaRegex;
|
||||
import org.jclouds.aws.s3.functions.UploadIdFromHttpResponseViaRegex;
|
||||
|
@ -39,11 +39,10 @@ import org.jclouds.http.functions.ReturnTrueIf2xx;
|
|||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.io.Payloads;
|
||||
import org.jclouds.location.Region;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.S3AsyncClientTest;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.S3ClientTest;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.domain.ObjectMetadataBuilder;
|
||||
import org.jclouds.s3.domain.S3Object;
|
||||
|
@ -65,8 +64,8 @@ import com.google.common.reflect.Invokable;
|
|||
import com.google.inject.Module;
|
||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during
|
||||
// surefire
|
||||
@Test(groups = "unit", testName = "AWSS3AsyncClientTest")
|
||||
public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
|
||||
@Test(groups = "unit", testName = "AWSS3ClientTest")
|
||||
public class AWSS3ClientTest extends S3ClientTest<AWSS3Client> {
|
||||
|
||||
@Override
|
||||
protected void checkFilters(HttpRequest request) {
|
||||
|
@ -78,14 +77,14 @@ public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
|
|||
public void testCopyObjectInvalidName() throws ArrayIndexOutOfBoundsException, SecurityException,
|
||||
IllegalArgumentException, NoSuchMethodException, IOException {
|
||||
// For AWS S3, S3AsyncClientTest#testCopyObjectInvalidName() will not throw an exception
|
||||
Invokable<?, ?> method = method(S3AsyncClient.class, "copyObject", String.class, String.class, String.class,
|
||||
Invokable<?, ?> method = method(AWSS3Client.class, "copyObject", String.class, String.class, String.class,
|
||||
String.class,
|
||||
CopyObjectOptions[].class);
|
||||
processor.createRequest(method, ImmutableList.<Object> of("sourceBucket", "sourceObject", "destinationbucket", "destinationObject"));
|
||||
}
|
||||
|
||||
public void testGetBucketLocationEUIsStillDefault() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(AWSS3AsyncClient.class, "getBucketLocation", String.class);
|
||||
Invokable<?, ?> method = method(AWSS3Client.class, "getBucketLocation", String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket-eu-west-1"));
|
||||
|
||||
assertRequestLineEquals(request, "GET https://bucket-eu-west-1.s3.amazonaws.com/?location HTTP/1.1");
|
||||
|
@ -103,7 +102,7 @@ public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
|
|||
public void testPutObject() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||
NoSuchMethodException, IOException {
|
||||
|
||||
Invokable<?, ?> method = method(AWSS3AsyncClient.class, "putObject", String.class, S3Object.class,
|
||||
Invokable<?, ?> method = method(AWSS3Client.class, "putObject", String.class, S3Object.class,
|
||||
PutObjectOptions[].class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket",
|
||||
blobToS3Object.apply(BindBlobToMultipartFormTest.TEST_BLOB)));
|
||||
|
@ -121,7 +120,7 @@ public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
|
|||
|
||||
@Override
|
||||
public void testGetBucketLocation() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(AWSS3AsyncClient.class, "getBucketLocation", String.class);
|
||||
Invokable<?, ?> method = method(AWSS3Client.class, "getBucketLocation", String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket"));
|
||||
|
||||
assertRequestLineEquals(request, "GET https://bucket.s3.amazonaws.com/?location HTTP/1.1");
|
||||
|
@ -146,7 +145,7 @@ public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
|
|||
@Override
|
||||
public void testPutBucketDefault() throws ArrayIndexOutOfBoundsException, SecurityException,
|
||||
IllegalArgumentException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(AWSS3AsyncClient.class, "putBucketInRegion", String.class, String.class,
|
||||
Invokable<?, ?> method = method(AWSS3Client.class, "putBucketInRegion", String.class, String.class,
|
||||
PutBucketOptions[].class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null, "bucket"));
|
||||
|
||||
|
@ -163,7 +162,7 @@ public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
|
|||
|
||||
public void testInitiateMultipartUpload() throws SecurityException, NegativeArraySizeException,
|
||||
NoSuchMethodException {
|
||||
Invokable<?, ?> method = method(AWSS3AsyncClient.class, "initiateMultipartUpload", String.class, ObjectMetadata.class,
|
||||
Invokable<?, ?> method = method(AWSS3Client.class, "initiateMultipartUpload", String.class, ObjectMetadata.class,
|
||||
PutObjectOptions[].class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", ObjectMetadataBuilder.create().key("foo")
|
||||
.contentMD5(new byte[] { 1, 2, 3, 4 }).build()));
|
||||
|
@ -192,7 +191,7 @@ public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
|
|||
}
|
||||
|
||||
public void testAbortMultipartUpload() throws SecurityException, NegativeArraySizeException, NoSuchMethodException {
|
||||
Invokable<?, ?> method = method(AWSS3AsyncClient.class, "abortMultipartUpload", String.class, String.class, String.class);
|
||||
Invokable<?, ?> method = method(AWSS3Client.class, "abortMultipartUpload", String.class, String.class, String.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", "foo", "asdsadasdas", 1,
|
||||
Payloads.newStringPayload("")));
|
||||
|
||||
|
@ -208,7 +207,7 @@ public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
|
|||
}
|
||||
|
||||
public void testUploadPart() throws SecurityException, NegativeArraySizeException, NoSuchMethodException {
|
||||
Invokable<?, ?> method = method(AWSS3AsyncClient.class, "uploadPart", String.class, String.class, int.class,
|
||||
Invokable<?, ?> method = method(AWSS3Client.class, "uploadPart", String.class, String.class, int.class,
|
||||
String.class, Payload.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", "foo", 1, "asdsadasdas",
|
||||
Payloads.newStringPayload("")));
|
||||
|
@ -226,7 +225,7 @@ public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
|
|||
|
||||
public void testCompleteMultipartUpload() throws SecurityException, NegativeArraySizeException,
|
||||
NoSuchMethodException {
|
||||
Invokable<?, ?> method = method(AWSS3AsyncClient.class, "completeMultipartUpload", String.class, String.class,
|
||||
Invokable<?, ?> method = method(AWSS3Client.class, "completeMultipartUpload", String.class, String.class,
|
||||
String.class, Map.class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", "foo", "asdsadasdas",
|
||||
ImmutableMap.<Integer, String> of(1, "\"a54357aff0632cce46d942af68356b38\"")));
|
||||
|
@ -247,7 +246,7 @@ public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
|
|||
|
||||
public void testPutBucketEu() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||
NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(AWSS3AsyncClient.class, "putBucketInRegion", String.class, String.class,
|
||||
Invokable<?, ?> method = method(AWSS3Client.class, "putBucketInRegion", String.class, String.class,
|
||||
PutBucketOptions[].class);
|
||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("EU", "bucket"));
|
||||
|
||||
|
@ -264,8 +263,8 @@ public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
|
|||
checkFilters(request);
|
||||
}
|
||||
|
||||
@ConfiguresRestClient
|
||||
private static final class TestAWSS3RestClientModule extends AWSS3RestClientModule {
|
||||
@ConfiguresHttpApi
|
||||
private static final class TestAWSS3HttpApiModule extends AWSS3HttpApiModule {
|
||||
|
||||
@Override
|
||||
protected CacheLoader<String, Optional<String>> bucketToRegion(@Region Supplier<Set<String>> regionSupplier,
|
||||
|
@ -292,7 +291,7 @@ public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> {
|
|||
|
||||
@Override
|
||||
protected Module createModule() {
|
||||
return new TestAWSS3RestClientModule();
|
||||
return new TestAWSS3HttpApiModule();
|
||||
}
|
||||
|
||||
@Override
|
|
@ -16,16 +16,17 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.binders;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.io.Payloads;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
public class BindIterableAsPayloadToDeleteRequestTest {
|
||||
|
||||
|
|
|
@ -22,10 +22,10 @@ import java.io.File;
|
|||
|
||||
import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.domain.ObjectMetadataBuilder;
|
||||
import org.jclouds.s3.internal.BaseS3AsyncClientTest;
|
||||
import org.jclouds.s3.internal.BaseS3ClientTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
@ -36,7 +36,7 @@ import com.google.common.collect.ImmutableMultimap;
|
|||
*/
|
||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
@Test(groups = "unit", testName = "BindObjectMetadataToRequestTest")
|
||||
public class BindObjectMetadataToRequestTest extends BaseS3AsyncClientTest<S3AsyncClient> {
|
||||
public class BindObjectMetadataToRequestTest extends BaseS3ClientTest<S3Client> {
|
||||
|
||||
@Test
|
||||
public void testPassWithMinimumDetailsAndPayload5GB() {
|
||||
|
|
|
@ -18,12 +18,12 @@ package org.jclouds.aws.s3.blobstore;
|
|||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.aws.s3.config.AWSS3RestClientModule;
|
||||
import org.jclouds.aws.s3.config.AWSS3HttpApiModule;
|
||||
import org.jclouds.blobstore.BlobStore;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
import org.jclouds.s3.blobstore.S3BlobSignerExpectTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@ -116,11 +116,11 @@ public class AWSS3BlobSignerExpectTest extends S3BlobSignerExpectTest {
|
|||
|
||||
@Override
|
||||
protected Module createModule() {
|
||||
return new TestAWSS3RestClientModule();
|
||||
return new TestAWSS3HttpApiModule();
|
||||
}
|
||||
|
||||
@ConfiguresRestClient
|
||||
private static final class TestAWSS3RestClientModule extends AWSS3RestClientModule {
|
||||
@ConfiguresHttpApi
|
||||
private static final class TestAWSS3HttpApiModule extends AWSS3HttpApiModule {
|
||||
@Override
|
||||
@TimeStamp
|
||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||
|
|
|
@ -18,10 +18,10 @@ package org.jclouds.aws.s3.internal;
|
|||
|
||||
import org.jclouds.aws.s3.AWSS3Client;
|
||||
import org.jclouds.aws.s3.AWSS3ProviderMetadata;
|
||||
import org.jclouds.aws.s3.config.AWSS3RestClientModule;
|
||||
import org.jclouds.aws.s3.config.AWSS3HttpApiModule;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
import org.jclouds.providers.ProviderMetadata;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
import org.jclouds.rest.internal.BaseRestClientExpectTest;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
@ -44,8 +44,8 @@ public class BaseAWSS3ClientExpectTest extends BaseRestClientExpectTest<AWSS3Cli
|
|||
return new AWSS3ProviderMetadata();
|
||||
}
|
||||
|
||||
@ConfiguresRestClient
|
||||
private static final class TestAWSS3RestClientModule extends AWSS3RestClientModule {
|
||||
@ConfiguresHttpApi
|
||||
private static final class TestAWSS3HttpApiModule extends AWSS3HttpApiModule {
|
||||
@Override
|
||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||
return CONSTANT_DATE;
|
||||
|
@ -54,7 +54,7 @@ public class BaseAWSS3ClientExpectTest extends BaseRestClientExpectTest<AWSS3Cli
|
|||
|
||||
@Override
|
||||
protected Module createModule() {
|
||||
return new TestAWSS3RestClientModule();
|
||||
return new TestAWSS3HttpApiModule();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.xml;
|
||||
|
||||
import org.jclouds.aws.s3.domain.DeleteResult;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import org.jclouds.aws.s3.domain.DeleteResult;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
@Test(groups = "unit", testName = "DeleteResultHandlerTest")
|
||||
|
|
Loading…
Reference in New Issue