You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ad...@apache.org on 2014/10/03 22:20:40 UTC

[4/4] git commit: JCLOUDS-150 add SubmissionAsyncBlobStore; unasync s3 and aws-s3

JCLOUDS-150 add SubmissionAsyncBlobStore; unasync s3 and aws-s3


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/b6497556
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/b6497556
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/b6497556

Branch: refs/heads/master
Commit: b6497556f69d07d87280bd8c38b79da384f79e04
Parents: 80d51f4
Author: Adrian Cole <ac...@twitter.com>
Authored: Fri Oct 3 13:14:00 2014 -0700
Committer: Adrian Cole <ad...@apache.org>
Committed: Fri Oct 3 13:18:29 2014 -0700

----------------------------------------------------------------------
 .../main/java/org/jclouds/s3/S3ApiMetadata.java |  40 +-
 .../main/java/org/jclouds/s3/S3AsyncClient.java | 363 --------------
 .../src/main/java/org/jclouds/s3/S3Client.java  | 356 +++++++++-----
 .../jclouds/s3/blobstore/S3AsyncBlobStore.java  | 273 -----------
 .../s3/blobstore/S3BlobRequestSigner.java       |   4 +-
 .../s3/blobstore/S3BlobStoreContext.java        |   3 -
 .../config/S3BlobStoreContextModule.java        |  11 +-
 .../internal/S3BlobStoreContextImpl.java        |   7 -
 .../org/jclouds/s3/config/S3HttpApiModule.java  | 211 ++++++++
 .../jclouds/s3/config/S3RestClientModule.java   | 214 --------
 .../jclouds/s3/domain/AccessControlList.java    |   3 -
 .../org/jclouds/s3/domain/BucketLogging.java    |   2 -
 .../jclouds/s3/domain/CannedAccessPolicy.java   |   3 -
 .../org/jclouds/s3/domain/CanonicalUser.java    |   5 +-
 .../jclouds/s3/domain/ListBucketResponse.java   |   2 -
 .../s3/domain/MutableObjectMetadata.java        |  14 +-
 .../org/jclouds/s3/domain/ObjectMetadata.java   |   4 -
 .../main/java/org/jclouds/s3/domain/Payer.java  |   3 -
 .../java/org/jclouds/s3/domain/S3Object.java    |   5 +-
 .../org/jclouds/s3/domain/package-info.java     |   1 -
 .../s3/filters/RequestAuthorizeSignature.java   |   4 -
 .../org/jclouds/s3/filters/package-info.java    |   1 -
 .../ParseObjectMetadataFromHeaders.java         |  12 +-
 .../jclouds/s3/options/CopyObjectOptions.java   |   6 -
 .../jclouds/s3/options/ListBucketOptions.java   |   6 +-
 .../jclouds/s3/options/PutBucketOptions.java    |   6 +-
 .../jclouds/s3/options/PutObjectOptions.java    |   6 +-
 .../org/jclouds/s3/options/package-info.java    |   2 -
 .../main/java/org/jclouds/s3/package-info.java  |   2 -
 .../org/jclouds/s3/reference/S3Headers.java     |   8 +-
 .../s3/xml/AccessControlListHandler.java        |   2 -
 .../jclouds/s3/xml/BucketLoggingHandler.java    |   2 -
 .../org/jclouds/s3/xml/CopyObjectHandler.java   |   2 -
 .../jclouds/s3/xml/ListAllMyBucketsHandler.java |   4 -
 .../org/jclouds/s3/xml/ListBucketHandler.java   |   4 -
 .../s3/xml/LocationConstraintHandler.java       |   4 -
 .../java/org/jclouds/s3/xml/PayerHandler.java   |   2 -
 .../java/org/jclouds/s3/S3AsyncClientTest.java  | 490 -------------------
 .../java/org/jclouds/s3/S3ClientLiveTest.java   |   8 +-
 .../test/java/org/jclouds/s3/S3ClientTest.java  | 490 +++++++++++++++++++
 .../BindAsHostPrefixIfConfiguredNoPathTest.java |   8 +-
 .../BindAsHostPrefixIfConfiguredTest.java       |   8 +-
 .../BindNoBucketLoggingToXmlPayloadTest.java    |   6 +-
 .../BindS3ObjectMetadataToRequestTest.java      |   6 +-
 .../s3/blobstore/S3BlobSignerExpectTest.java    |  11 +-
 .../filters/RequestAuthorizeSignatureTest.java  |  16 +-
 ...rizeSignatureWithSessionCredentialsTest.java |  13 +-
 .../s3/internal/BaseS3AsyncClientTest.java      |  62 ---
 .../s3/internal/BaseS3ClientExpectTest.java     |  11 +-
 .../jclouds/s3/internal/BaseS3ClientTest.java   |  62 +++
 .../jclouds/s3/internal/StubS3AsyncClient.java  | 343 -------------
 .../jclouds/s3/services/BucketsLiveTest.java    |  63 +--
 .../internal/SubmissionAsyncBlobStore.java      | 293 +++++++++++
 .../org/jclouds/aws/s3/AWSS3ApiMetadata.java    |  22 +-
 .../org/jclouds/aws/s3/AWSS3AsyncClient.java    | 135 -----
 .../java/org/jclouds/aws/s3/AWSS3Client.java    |  88 +++-
 .../aws/s3/blobstore/AWSS3AsyncBlobStore.java   | 139 ------
 .../s3/blobstore/AWSS3BlobRequestSigner.java    |   6 +-
 .../aws/s3/blobstore/AWSS3BlobStore.java        |   4 +-
 .../aws/s3/blobstore/AWSS3BlobStoreContext.java |   3 -
 .../config/AWSS3BlobStoreContextModule.java     |   3 -
 .../internal/AWSS3BlobStoreContextImpl.java     |   7 -
 .../strategy/AsyncMultipartUploadStrategy.java  |   3 -
 .../s3/blobstore/strategy/MultipartUpload.java  |   3 -
 .../strategy/MultipartUploadStrategy.java       |   3 -
 .../ParallelMultipartUploadStrategy.java        |  31 +-
 .../aws/s3/config/AWSS3HttpApiModule.java       |  69 +++
 .../aws/s3/config/AWSS3RestClientModule.java    |  78 ---
 .../org/jclouds/aws/s3/domain/DeleteResult.java |  12 +-
 .../filters/AWSRequestAuthorizeSignature.java   |   8 +-
 .../jclouds/aws/s3/filters/package-info.java    |   5 +-
 .../functions/ETagFromHttpResponseViaRegex.java |   3 -
 .../UploadIdFromHttpResponseViaRegex.java       |   5 -
 .../jclouds/aws/s3/xml/DeleteResultHandler.java |   7 +-
 .../jclouds/aws/s3/xml/ErrorEntryHandler.java   |   9 +-
 .../jclouds/aws/s3/AWSS3AsyncClientTest.java    | 308 ------------
 .../org/jclouds/aws/s3/AWSS3ClientLiveTest.java |   4 +-
 .../org/jclouds/aws/s3/AWSS3ClientTest.java     | 307 ++++++++++++
 ...indIterableAsPayloadToDeleteRequestTest.java |  11 +-
 .../BindObjectMetadataToRequestTest.java        |   6 +-
 .../s3/blobstore/AWSS3BlobSignerExpectTest.java |  10 +-
 .../s3/internal/BaseAWSS3ClientExpectTest.java  |  10 +-
 .../aws/s3/xml/DeleteResultHandlerTest.java     |   8 +-
 83 files changed, 1930 insertions(+), 2864 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/b6497556/apis/s3/src/main/java/org/jclouds/s3/S3ApiMetadata.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/S3ApiMetadata.java b/apis/s3/src/main/java/org/jclouds/s3/S3ApiMetadata.java
index 5e6fd0b..2923c15 100644
--- a/apis/s3/src/main/java/org/jclouds/s3/S3ApiMetadata.java
+++ b/apis/s3/src/main/java/org/jclouds/s3/S3ApiMetadata.java
@@ -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;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b6497556/apis/s3/src/main/java/org/jclouds/s3/S3AsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/S3AsyncClient.java b/apis/s3/src/main/java/org/jclouds/s3/S3AsyncClient.java
deleted file mode 100644
index f119461..0000000
--- a/apis/s3/src/main/java/org/jclouds/s3/S3AsyncClient.java
+++ /dev/null
@@ -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 {
-   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);
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b6497556/apis/s3/src/main/java/org/jclouds/s3/S3Client.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/S3Client.java b/apis/s3/src/main/java/org/jclouds/s3/S3Client.java
index 34ae0f0..ba11992 100644
--- a/apis/s3/src/main/java/org/jclouds/s3/S3Client.java
+++ b/apis/s3/src/main/java/org/jclouds/s3/S3Client.java
@@ -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);
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b6497556/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3AsyncBlobStore.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3AsyncBlobStore.java b/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3AsyncBlobStore.java
deleted file mode 100644
index 3725d0a..0000000
--- a/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3AsyncBlobStore.java
+++ /dev/null
@@ -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);
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b6497556/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobRequestSigner.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobRequestSigner.java b/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobRequestSigner.java
index 2ba56f4..a335754 100644
--- a/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobRequestSigner.java
+++ b/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobRequestSigner.java
@@ -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;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b6497556/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStoreContext.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStoreContext.java b/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStoreContext.java
index d4bcd4f..9f32ce8 100644
--- a/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStoreContext.java
+++ b/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStoreContext.java
@@ -26,7 +26,4 @@ public interface S3BlobStoreContext extends BlobStoreContext {
 
    @Override
    S3BlobStore getBlobStore();
-
-   @Override
-   S3AsyncBlobStore getAsyncBlobStore();
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b6497556/apis/s3/src/main/java/org/jclouds/s3/blobstore/config/S3BlobStoreContextModule.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/blobstore/config/S3BlobStoreContextModule.java b/apis/s3/src/main/java/org/jclouds/s3/blobstore/config/S3BlobStoreContextModule.java
index 3b42159..525f9bd 100644
--- a/apis/s3/src/main/java/org/jclouds/s3/blobstore/config/S3BlobStoreContextModule.java
+++ b/apis/s3/src/main/java/org/jclouds/s3/blobstore/config/S3BlobStoreContextModule.java
@@ -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>>() {
       });
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b6497556/apis/s3/src/main/java/org/jclouds/s3/blobstore/internal/S3BlobStoreContextImpl.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/blobstore/internal/S3BlobStoreContextImpl.java b/apis/s3/src/main/java/org/jclouds/s3/blobstore/internal/S3BlobStoreContextImpl.java
index 79bc913..a2aaf9a 100644
--- a/apis/s3/src/main/java/org/jclouds/s3/blobstore/internal/S3BlobStoreContextImpl.java
+++ b/apis/s3/src/main/java/org/jclouds/s3/blobstore/internal/S3BlobStoreContextImpl.java
@@ -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());
-   }
-
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b6497556/apis/s3/src/main/java/org/jclouds/s3/config/S3HttpApiModule.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/config/S3HttpApiModule.java b/apis/s3/src/main/java/org/jclouds/s3/config/S3HttpApiModule.java
new file mode 100644
index 0000000..3841865
--- /dev/null
+++ b/apis/s3/src/main/java/org/jclouds/s3/config/S3HttpApiModule.java
@@ -0,0 +1,211 @@
+/*
+ * 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.config;
+
+import java.net.URI;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.Constants;
+import org.jclouds.aws.config.AWSHttpApiModule;
+import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
+import org.jclouds.aws.handlers.AWSServerErrorRetryHandler;
+import org.jclouds.blobstore.ContainerNotFoundException;
+import org.jclouds.blobstore.domain.PageSet;
+import org.jclouds.blobstore.domain.StorageMetadata;
+import org.jclouds.date.DateService;
+import org.jclouds.date.TimeStamp;
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.HttpRetryHandler;
+import org.jclouds.http.annotation.ClientError;
+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.ConfiguresHttpApi;
+import org.jclouds.rest.RequestSigner;
+import org.jclouds.s3.Bucket;
+import org.jclouds.s3.S3Client;
+import org.jclouds.s3.blobstore.functions.BucketsToStorageMetadata;
+import org.jclouds.s3.domain.BucketMetadata;
+import org.jclouds.s3.filters.RequestAuthorizeSignature;
+import org.jclouds.s3.functions.GetRegionForBucket;
+import org.jclouds.s3.handlers.ParseS3ErrorFromXmlContent;
+import org.jclouds.s3.handlers.S3RedirectionRetryHandler;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+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.inject.Provides;
+import com.google.inject.Scopes;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Configures the S3 connection, including logging and http transport.
+ */
+@ConfiguresHttpApi
+public class S3HttpApiModule<S extends S3Client> extends AWSHttpApiModule<S> {
+
+   @SuppressWarnings("unchecked")
+   public S3HttpApiModule() {
+      this(Class.class.cast(S3Client.class));
+   }
+
+   protected S3HttpApiModule(Class<S> syncClientType) {
+      super(syncClientType);
+   }
+
+   @Provides
+   @Bucket
+   @Singleton
+   protected CacheLoader<String, Optional<String>> bucketToRegion(@Region Supplier<Set<String>> regionSupplier,
+            final S3Client client) {
+      Set<String> regions = regionSupplier.get();
+      if (regions.isEmpty()) {
+         return new CacheLoader<String, Optional<String>>() {
+
+            @Override
+            public Optional<String> load(String bucket) {
+               return Optional.absent();
+            }
+
+            @Override
+            public String toString() {
+               return "noRegions()";
+            }
+         };
+      } else if (regions.size() == 1) {
+         final String onlyRegion = Iterables.getOnlyElement(regions);
+         return new CacheLoader<String, Optional<String>>() {
+            Optional<String> onlyRegionOption = Optional.of(onlyRegion);
+
+            @Override
+            public Optional<String> load(String bucket) {
+               return onlyRegionOption;
+            }
+
+            @Override
+            public String toString() {
+               return "onlyRegion(" + onlyRegion + ")";
+            }
+         };
+      } else {
+         return new CacheLoader<String, Optional<String>>() {
+            @Override
+            public Optional<String> load(String bucket) {
+               try {
+                  return Optional.fromNullable(client.getBucketLocation(bucket));
+               } catch (ContainerNotFoundException e) {
+                  return Optional.absent();
+               }
+            }
+
+            @Override
+            public String toString() {
+               return "bucketToRegion()";
+            }
+         };
+      }
+   }
+
+   @Provides
+   @Bucket
+   @Singleton
+   protected LoadingCache<String, Optional<String>> bucketToRegion(@Bucket CacheLoader<String, Optional<String>> loader) {
+      return CacheBuilder.newBuilder().build(loader);
+   }
+
+   @Provides
+   @Bucket
+   @Singleton
+   protected Supplier<String> defaultRegionForBucket(@Region Supplier<String> defaultRegion) {
+      return defaultRegion;
+   }
+
+   @Provides
+   @Singleton
+   @Bucket
+   protected Supplier<URI> provideBucketURI(@Bucket Supplier<String> defaultRegion,
+            RegionToEndpointOrProviderIfNull regionToEndpoint) {
+      return Suppliers.compose(regionToEndpoint, defaultRegion);
+   }
+
+   @Override
+   protected void configure() {
+      super.configure();
+      install(new S3ObjectModule());
+      install(new S3ParserModule());
+      bindRequestSigner();
+      bind(new TypeLiteral<Function<String, Optional<String>>>() {
+      }).annotatedWith(Bucket.class).to(GetRegionForBucket.class);
+      bind(new TypeLiteral<Function<Set<BucketMetadata>, PageSet<? extends StorageMetadata>>>() {
+      }).to(BucketsToStorageMetadata.class);
+   }
+
+   @Override
+   protected void bindErrorHandlers() {
+      bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseS3ErrorFromXmlContent.class);
+      bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseS3ErrorFromXmlContent.class);
+      bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseS3ErrorFromXmlContent.class);
+   }
+
+   protected void bindRequestSigner() {
+      bind(RequestAuthorizeSignature.class).in(Scopes.SINGLETON);
+   }
+
+   @Provides
+   @Singleton
+   protected RequestSigner provideRequestSigner(RequestAuthorizeSignature in) {
+      return in;
+   }
+
+   @Override
+   protected void bindRetryHandlers() {
+      bind(HttpRetryHandler.class).annotatedWith(Redirection.class).to(S3RedirectionRetryHandler.class);
+      bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(AWSClientErrorRetryHandler.class);
+      bind(HttpRetryHandler.class).annotatedWith(ServerError.class).to(AWSServerErrorRetryHandler.class);
+   }
+
+   @Provides
+   @TimeStamp
+   protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
+      return cache.get();
+   }
+
+   /**
+    * borrowing concurrency code to ensure that caching takes place properly
+    */
+   @Provides
+   @TimeStamp
+   @Singleton
+   protected Supplier<String> provideTimeStampCache(@Named(Constants.PROPERTY_SESSION_INTERVAL) long seconds,
+            final DateService dateService) {
+      return Suppliers.memoizeWithExpiration(new Supplier<String>() {
+         public String get() {
+            return dateService.rfc822DateFormat();
+         }
+      }, seconds, TimeUnit.SECONDS);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b6497556/apis/s3/src/main/java/org/jclouds/s3/config/S3RestClientModule.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/config/S3RestClientModule.java b/apis/s3/src/main/java/org/jclouds/s3/config/S3RestClientModule.java
deleted file mode 100644
index 23cf033..0000000
--- a/apis/s3/src/main/java/org/jclouds/s3/config/S3RestClientModule.java
+++ /dev/null
@@ -1,214 +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.config;
-import static org.jclouds.reflect.Reflection2.typeToken;
-
-import java.net.URI;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-import org.jclouds.Constants;
-import org.jclouds.aws.config.AWSRestClientModule;
-import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
-import org.jclouds.aws.handlers.AWSServerErrorRetryHandler;
-import org.jclouds.blobstore.ContainerNotFoundException;
-import org.jclouds.blobstore.domain.PageSet;
-import org.jclouds.blobstore.domain.StorageMetadata;
-import org.jclouds.date.DateService;
-import org.jclouds.date.TimeStamp;
-import org.jclouds.http.HttpErrorHandler;
-import org.jclouds.http.HttpRetryHandler;
-import org.jclouds.http.annotation.ClientError;
-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.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;
-import org.jclouds.s3.filters.RequestAuthorizeSignature;
-import org.jclouds.s3.functions.GetRegionForBucket;
-import org.jclouds.s3.handlers.ParseS3ErrorFromXmlContent;
-import org.jclouds.s3.handlers.S3RedirectionRetryHandler;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-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;
-
-/**
- * Configures the S3 connection, including logging and http transport.
- */
-@ConfiguresRestClient
-public class S3RestClientModule<S extends S3Client, A extends S3AsyncClient> extends AWSRestClientModule<S, A> {
-
-   @SuppressWarnings("unchecked")
-   public S3RestClientModule() {
-      this(TypeToken.class.cast(typeToken(S3Client.class)), TypeToken.class.cast(typeToken(S3AsyncClient.class)));
-   }
-
-   protected S3RestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType) {
-      super(syncClientType, asyncClientType);
-   }
-
-   @Provides
-   @Bucket
-   @Singleton
-   protected CacheLoader<String, Optional<String>> bucketToRegion(@Region Supplier<Set<String>> regionSupplier,
-            final S3Client client) {
-      Set<String> regions = regionSupplier.get();
-      if (regions.isEmpty()) {
-         return new CacheLoader<String, Optional<String>>() {
-
-            @Override
-            public Optional<String> load(String bucket) {
-               return Optional.absent();
-            }
-
-            @Override
-            public String toString() {
-               return "noRegions()";
-            }
-         };
-      } else if (regions.size() == 1) {
-         final String onlyRegion = Iterables.getOnlyElement(regions);
-         return new CacheLoader<String, Optional<String>>() {
-            Optional<String> onlyRegionOption = Optional.of(onlyRegion);
-
-            @Override
-            public Optional<String> load(String bucket) {
-               return onlyRegionOption;
-            }
-
-            @Override
-            public String toString() {
-               return "onlyRegion(" + onlyRegion + ")";
-            }
-         };
-      } else {
-         return new CacheLoader<String, Optional<String>>() {
-            @Override
-            public Optional<String> load(String bucket) {
-               try {
-                  return Optional.fromNullable(client.getBucketLocation(bucket));
-               } catch (ContainerNotFoundException e) {
-                  return Optional.absent();
-               }
-            }
-
-            @Override
-            public String toString() {
-               return "bucketToRegion()";
-            }
-         };
-      }
-   }
-
-   @Provides
-   @Bucket
-   @Singleton
-   protected LoadingCache<String, Optional<String>> bucketToRegion(@Bucket CacheLoader<String, Optional<String>> loader) {
-      return CacheBuilder.newBuilder().build(loader);
-   }
-
-   @Provides
-   @Bucket
-   @Singleton
-   protected Supplier<String> defaultRegionForBucket(@Region Supplier<String> defaultRegion) {
-      return defaultRegion;
-   }
-
-   @Provides
-   @Singleton
-   @Bucket
-   protected Supplier<URI> provideBucketURI(@Bucket Supplier<String> defaultRegion,
-            RegionToEndpointOrProviderIfNull regionToEndpoint) {
-      return Suppliers.compose(regionToEndpoint, defaultRegion);
-   }
-
-   @Override
-   protected void configure() {
-      super.configure();
-      install(new S3ObjectModule());
-      install(new S3ParserModule());
-      bindRequestSigner();
-      bind(new TypeLiteral<Function<String, Optional<String>>>() {
-      }).annotatedWith(Bucket.class).to(GetRegionForBucket.class);
-      bind(new TypeLiteral<Function<Set<BucketMetadata>, PageSet<? extends StorageMetadata>>>() {
-      }).to(BucketsToStorageMetadata.class);
-   }
-
-   @Override
-   protected void bindErrorHandlers() {
-      bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseS3ErrorFromXmlContent.class);
-      bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseS3ErrorFromXmlContent.class);
-      bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseS3ErrorFromXmlContent.class);
-   }
-
-   protected void bindRequestSigner() {
-      bind(RequestAuthorizeSignature.class).in(Scopes.SINGLETON);
-   }
-
-   @Provides
-   @Singleton
-   protected RequestSigner provideRequestSigner(RequestAuthorizeSignature in) {
-      return in;
-   }
-
-   @Override
-   protected void bindRetryHandlers() {
-      bind(HttpRetryHandler.class).annotatedWith(Redirection.class).to(S3RedirectionRetryHandler.class);
-      bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(AWSClientErrorRetryHandler.class);
-      bind(HttpRetryHandler.class).annotatedWith(ServerError.class).to(AWSServerErrorRetryHandler.class);
-   }
-
-   @Provides
-   @TimeStamp
-   protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
-      return cache.get();
-   }
-
-   /**
-    * borrowing concurrency code to ensure that caching takes place properly
-    */
-   @Provides
-   @TimeStamp
-   @Singleton
-   protected Supplier<String> provideTimeStampCache(@Named(Constants.PROPERTY_SESSION_INTERVAL) long seconds,
-            final DateService dateService) {
-      return Suppliers.memoizeWithExpiration(new Supplier<String>() {
-         public String get() {
-            return dateService.rfc822DateFormat();
-         }
-      }, seconds, TimeUnit.SECONDS);
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b6497556/apis/s3/src/main/java/org/jclouds/s3/domain/AccessControlList.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/domain/AccessControlList.java b/apis/s3/src/main/java/org/jclouds/s3/domain/AccessControlList.java
index 0faaa38..7450f30 100644
--- a/apis/s3/src/main/java/org/jclouds/s3/domain/AccessControlList.java
+++ b/apis/s3/src/main/java/org/jclouds/s3/domain/AccessControlList.java
@@ -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 {
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/b6497556/apis/s3/src/main/java/org/jclouds/s3/domain/BucketLogging.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/domain/BucketLogging.java b/apis/s3/src/main/java/org/jclouds/s3/domain/BucketLogging.java
index 3d50a44..1470441 100644
--- a/apis/s3/src/main/java/org/jclouds/s3/domain/BucketLogging.java
+++ b/apis/s3/src/main/java/org/jclouds/s3/domain/BucketLogging.java
@@ -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;