diff --git a/apis/s3/src/main/java/org/jclouds/s3/Bucket.java b/apis/s3/src/main/java/org/jclouds/s3/Bucket.java index bc7a76c26d..819912163e 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/Bucket.java +++ b/apis/s3/src/main/java/org/jclouds/s3/Bucket.java @@ -18,16 +18,20 @@ */ package org.jclouds.s3; +import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import javax.inject.Qualifier; + /** * Annotates the parameter that this is a bucket. */ -@Target(PARAMETER) +@Target({ PARAMETER, METHOD }) @Retention(RUNTIME) +@Qualifier public @interface Bucket { } diff --git a/apis/s3/src/main/java/org/jclouds/s3/S3AsyncClient.java b/apis/s3/src/main/java/org/jclouds/s3/S3AsyncClient.java index faafe7b954..1f53e212cc 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/S3AsyncClient.java +++ b/apis/s3/src/main/java/org/jclouds/s3/S3AsyncClient.java @@ -33,6 +33,28 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; +import org.jclouds.blobstore.attr.BlobScope; +import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound; +import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound; +import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound; +import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404; +import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; +import org.jclouds.http.functions.ParseETagHeader; +import org.jclouds.http.options.GetOptions; +import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.EndpointParam; +import org.jclouds.rest.annotations.ExceptionParser; +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.SkipEncoding; +import org.jclouds.rest.annotations.VirtualHost; +import org.jclouds.rest.annotations.XMLResponseParser; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.s3.binders.BindACLToXMLPayload; import org.jclouds.s3.binders.BindAsHostPrefixIfConfigured; import org.jclouds.s3.binders.BindBucketLoggingToXmlPayload; @@ -65,26 +87,6 @@ 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 org.jclouds.blobstore.attr.BlobScope; -import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound; -import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound; -import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound; -import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404; -import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; -import org.jclouds.http.functions.ParseETagHeader; -import org.jclouds.http.options.GetOptions; -import org.jclouds.rest.annotations.BinderParam; -import org.jclouds.rest.annotations.ExceptionParser; -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.SkipEncoding; -import org.jclouds.rest.annotations.VirtualHost; -import org.jclouds.rest.annotations.XMLResponseParser; -import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import com.google.common.util.concurrent.ListenableFuture; import com.google.inject.Provides; @@ -121,8 +123,8 @@ public interface S3AsyncClient { @ExceptionParser(ReturnNullOnKeyNotFound.class) @ResponseParser(ParseObjectFromHeadersAndHttpContent.class) ListenableFuture getObject( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @PathParam("key") String key, GetOptions... options); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @PathParam("key") String key, GetOptions... options); /** * @see S3Client#headObject @@ -132,8 +134,8 @@ public interface S3AsyncClient { @ExceptionParser(ReturnNullOnKeyNotFound.class) @ResponseParser(ParseObjectMetadataFromHeaders.class) ListenableFuture headObject( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @PathParam("key") String key); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @PathParam("key") String key); /** * @see S3Client#objectExists @@ -142,8 +144,8 @@ public interface S3AsyncClient { @Path("/{key}") @ExceptionParser(ReturnFalseOnKeyNotFound.class) ListenableFuture objectExists( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @PathParam("key") String key); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @PathParam("key") String key); /** * @see S3Client#deleteObject @@ -152,8 +154,8 @@ public interface S3AsyncClient { @Path("/{key}") @ExceptionParser(ReturnVoidOnNotFoundOr404.class) ListenableFuture deleteObject( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @PathParam("key") String key); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @PathParam("key") String key); /** * @see S3Client#putObject @@ -162,9 +164,9 @@ public interface S3AsyncClient { @Path("/{key}") @ResponseParser(ParseETagHeader.class) ListenableFuture putObject( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @PathParam("key") @ParamParser(ObjectKey.class) @BinderParam(BindS3ObjectMetadataToRequest.class) S3Object object, - PutObjectOptions... options); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @PathParam("key") @ParamParser(ObjectKey.class) @BinderParam(BindS3ObjectMetadataToRequest.class) S3Object object, + PutObjectOptions... options); /** * @see S3Client#putBucketInRegion @@ -173,10 +175,9 @@ public interface S3AsyncClient { @Path("/") @ExceptionParser(ReturnFalseIfBucketAlreadyOwnedByYouOrIllegalState.class) ListenableFuture putBucketInRegion( - // TODO endpoint based on region - @BinderParam(BindRegionToXmlPayload.class) @Nullable String region, - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - PutBucketOptions... options); + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @BinderParam(BindRegionToXmlPayload.class) @Nullable String region, + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + PutBucketOptions... options); /** * @see S3Client#deleteBucketIfEmpty @@ -185,7 +186,7 @@ public interface S3AsyncClient { @Path("/") @ExceptionParser(ReturnTrueOn404OrNotFoundFalseOnIllegalState.class) ListenableFuture deleteBucketIfEmpty( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName); /** * @see S3Client#bucketExists @@ -195,7 +196,7 @@ public interface S3AsyncClient { @QueryParams(keys = "max-keys", values = "0") @ExceptionParser(ReturnFalseOnContainerNotFound.class) ListenableFuture bucketExists( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName); /** * @see S3Client#getBucketLocation @@ -205,7 +206,7 @@ public interface S3AsyncClient { @Path("/") @XMLResponseParser(LocationConstraintHandler.class) ListenableFuture getBucketLocation( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName); /** * @see S3Client#getBucketPayer @@ -215,7 +216,7 @@ public interface S3AsyncClient { @Path("/") @XMLResponseParser(PayerHandler.class) ListenableFuture getBucketPayer( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName); /** * @see S3Client#setBucketPayer @@ -224,8 +225,8 @@ public interface S3AsyncClient { @QueryParams(keys = "requestPayment") @Path("/") ListenableFuture setBucketPayer( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @BinderParam(BindPayerToXmlPayload.class) Payer payer); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @BinderParam(BindPayerToXmlPayload.class) Payer payer); /** * @see S3Client#listBucket @@ -234,8 +235,8 @@ public interface S3AsyncClient { @Path("/") @XMLResponseParser(ListBucketHandler.class) ListenableFuture listBucket( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - ListBucketOptions... options); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + ListBucketOptions... options); /** * @see S3Client#listOwnedBuckets @@ -254,10 +255,10 @@ public interface S3AsyncClient { @Headers(keys = "x-amz-copy-source", values = "/{sourceBucket}/{sourceObject}") @XMLResponseParser(CopyObjectHandler.class) ListenableFuture copyObject( - @PathParam("sourceBucket") String sourceBucket, - @PathParam("sourceObject") String sourceObject, - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String destinationBucket, - @PathParam("destinationObject") String destinationObject, CopyObjectOptions... options); + @PathParam("sourceBucket") String sourceBucket, + @PathParam("sourceObject") String sourceObject, + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String destinationBucket, + @PathParam("destinationObject") String destinationObject, CopyObjectOptions... options); /** * @see S3Client#getBucketACL @@ -268,7 +269,7 @@ public interface S3AsyncClient { @ExceptionParser(ThrowContainerNotFoundOn404.class) @Path("/") ListenableFuture getBucketACL( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName); /** * @see S3Client#putBucketACL @@ -277,8 +278,8 @@ public interface S3AsyncClient { @Path("/") @QueryParams(keys = "acl") ListenableFuture putBucketACL( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @BinderParam(BindACLToXMLPayload.class) AccessControlList acl); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @BinderParam(BindACLToXMLPayload.class) AccessControlList acl); /** * @see S3Client#getObjectACL @@ -289,8 +290,8 @@ public interface S3AsyncClient { @XMLResponseParser(AccessControlListHandler.class) @ExceptionParser(ThrowKeyNotFoundOn404.class) ListenableFuture getObjectACL( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @PathParam("key") String key); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @PathParam("key") String key); /** * @see S3Client#putObjectACL @@ -299,9 +300,8 @@ public interface S3AsyncClient { @QueryParams(keys = "acl") @Path("/{key}") ListenableFuture putObjectACL( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @PathParam("key") String key, - @BinderParam(BindACLToXMLPayload.class) AccessControlList acl); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @PathParam("key") String key, @BinderParam(BindACLToXMLPayload.class) AccessControlList acl); /** * @see S3Client#getBucketLogging @@ -312,7 +312,7 @@ public interface S3AsyncClient { @ExceptionParser(ThrowContainerNotFoundOn404.class) @Path("/") ListenableFuture getBucketLogging( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName); /** * @see S3Client#enableBucketLogging @@ -321,8 +321,8 @@ public interface S3AsyncClient { @Path("/") @QueryParams(keys = "logging") ListenableFuture enableBucketLogging( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @BinderParam(BindBucketLoggingToXmlPayload.class) BucketLogging logging); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @BinderParam(BindBucketLoggingToXmlPayload.class) BucketLogging logging); /** * @see S3Client#putBucketLogging @@ -332,6 +332,6 @@ public interface S3AsyncClient { @QueryParams(keys = "logging") @Produces(MediaType.TEXT_XML) ListenableFuture disableBucketLogging( - @Bucket @BinderParam(BindNoBucketLoggingToXmlPayload.class) @ParamValidators( { BucketNameValidator.class }) String bucketName); + @Bucket @BinderParam(BindNoBucketLoggingToXmlPayload.class) @ParamValidators({ BucketNameValidator.class }) String bucketName); } diff --git a/apis/s3/src/main/java/org/jclouds/s3/binders/BindAsHostPrefixIfConfigured.java b/apis/s3/src/main/java/org/jclouds/s3/binders/BindAsHostPrefixIfConfigured.java index 4699f5a626..f08c59e92a 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/binders/BindAsHostPrefixIfConfigured.java +++ b/apis/s3/src/main/java/org/jclouds/s3/binders/BindAsHostPrefixIfConfigured.java @@ -45,10 +45,10 @@ import com.google.common.collect.Maps; @Singleton public class BindAsHostPrefixIfConfigured implements Binder { - private final Provider uriBuilderProvider; - private final BindAsHostPrefix bindAsHostPrefix; - private final boolean isVhostStyle; - private final String servicePath; + protected final Provider uriBuilderProvider; + protected final BindAsHostPrefix bindAsHostPrefix; + protected final boolean isVhostStyle; + protected final String servicePath; @Inject public BindAsHostPrefixIfConfigured(BindAsHostPrefix bindAsHostPrefix, 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 index a70558c1a0..4efaf99ac4 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/config/S3RestClientModule.java +++ b/apis/s3/src/main/java/org/jclouds/s3/config/S3RestClientModule.java @@ -18,6 +18,7 @@ */ package org.jclouds.s3.config; +import java.util.Map; import java.util.concurrent.TimeUnit; import javax.inject.Named; @@ -34,6 +35,7 @@ import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; 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.filters.RequestAuthorizeSignature; @@ -41,6 +43,7 @@ import org.jclouds.s3.handlers.ParseS3ErrorFromXmlContent; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; +import com.google.common.collect.Maps; import com.google.inject.Provides; import com.google.inject.Scopes; @@ -60,6 +63,13 @@ public class S3RestClientModule ext super(sync, async); } + @Provides + @Bucket + @Singleton + protected Map bucketToRegion() { + return Maps.newConcurrentMap(); + } + @Override protected void configure() { install(new S3ObjectModule()); @@ -94,7 +104,7 @@ public class S3RestClientModule ext @TimeStamp @Singleton protected Supplier provideTimeStampCache(@Named(Constants.PROPERTY_SESSION_INTERVAL) long seconds, - final DateService dateService) { + final DateService dateService) { return Suppliers.memoizeWithExpiration(new Supplier() { public String get() { return dateService.rfc822DateFormat(); diff --git a/apis/s3/src/main/java/org/jclouds/s3/functions/BindRegionToXmlPayload.java b/apis/s3/src/main/java/org/jclouds/s3/functions/BindRegionToXmlPayload.java index 2a085bf311..4668ec06f9 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/functions/BindRegionToXmlPayload.java +++ b/apis/s3/src/main/java/org/jclouds/s3/functions/BindRegionToXmlPayload.java @@ -20,6 +20,8 @@ package org.jclouds.s3.functions; import static com.google.common.base.Preconditions.checkArgument; +import java.net.URI; +import java.util.Map; import java.util.Set; import javax.annotation.Nullable; diff --git a/apis/s3/src/main/java/org/jclouds/s3/xml/LocationConstraintHandler.java b/apis/s3/src/main/java/org/jclouds/s3/xml/LocationConstraintHandler.java index 7528d79a55..6d9f1c25f6 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/xml/LocationConstraintHandler.java +++ b/apis/s3/src/main/java/org/jclouds/s3/xml/LocationConstraintHandler.java @@ -20,8 +20,15 @@ package org.jclouds.s3.xml; import static org.jclouds.util.SaxUtils.currentOrNull; +import java.util.concurrent.ConcurrentMap; + +import javax.inject.Inject; + import org.jclouds.aws.domain.Region; +import org.jclouds.http.HttpRequest; import org.jclouds.http.functions.ParseSax; +import org.jclouds.rest.internal.GeneratedHttpRequest; +import org.jclouds.s3.Bucket; /** * Parses the response from Amazon S3 GET Bucket Location @@ -32,8 +39,15 @@ import org.jclouds.http.functions.ParseSax; * @author Adrian Cole */ public class LocationConstraintHandler extends ParseSax.HandlerWithResult { + private final ConcurrentMap bucketToRegion; private StringBuilder currentText = new StringBuilder(); private String region; + private String bucket; + + @Inject + public LocationConstraintHandler(@Bucket ConcurrentMap bucketToRegion) { + this.bucketToRegion = bucketToRegion; + } public String getResult() { return region; @@ -41,6 +55,18 @@ public class LocationConstraintHandler extends ParseSax.HandlerWithResult getVApp(@EndpointParam URI vApp); /** - * @see CommonVCloudClient#deployVApp + * @see VCloudExpressClient#deployVApp */ @POST @Consumes(TASK_XML) @@ -173,7 +174,7 @@ public interface VCloudExpressAsyncClient extends CommonVCloudAsyncClient { ListenableFuture deployVApp(@EndpointParam URI vAppId); /** - * @see CommonVCloudClient#undeployVApp + * @see VCloudExpressClient#undeployVApp */ @POST @Consumes(TASK_XML) @@ -182,7 +183,7 @@ public interface VCloudExpressAsyncClient extends CommonVCloudAsyncClient { ListenableFuture undeployVApp(@EndpointParam URI vAppId); /** - * @see CommonVCloudClient#powerOnVApp + * @see VCloudExpressClient#powerOnVApp */ @POST @Consumes(TASK_XML) @@ -191,7 +192,7 @@ public interface VCloudExpressAsyncClient extends CommonVCloudAsyncClient { ListenableFuture powerOnVApp(@EndpointParam URI vAppId); /** - * @see CommonVCloudClient#powerOffVApp + * @see VCloudExpressClient#powerOffVApp */ @POST @Consumes(TASK_XML) @@ -200,14 +201,14 @@ public interface VCloudExpressAsyncClient extends CommonVCloudAsyncClient { ListenableFuture powerOffVApp(@EndpointParam URI vAppId); /** - * @see CommonVCloudClient#shutdownVApp + * @see VCloudExpressClient#shutdownVApp */ @POST @Path("/power/action/shutdown") ListenableFuture shutdownVApp(@EndpointParam URI vAppId); /** - * @see CommonVCloudClient#resetVApp + * @see VCloudExpressClient#resetVApp */ @POST @Consumes(TASK_XML) @@ -216,7 +217,7 @@ public interface VCloudExpressAsyncClient extends CommonVCloudAsyncClient { ListenableFuture resetVApp(@EndpointParam URI vAppId); /** - * @see CommonVCloudClient#suspendVApp + * @see VCloudExpressClient#suspendVApp */ @POST @Consumes(TASK_XML) @@ -225,10 +226,10 @@ public interface VCloudExpressAsyncClient extends CommonVCloudAsyncClient { ListenableFuture suspendVApp(@EndpointParam URI vAppId); /** - * @see CommonVCloudClient#deleteVApp + * @see VCloudExpressClient#deleteVApp */ @DELETE - @ExceptionParser(ReturnVoidOnNotFoundOr404.class) - ListenableFuture deleteVApp(@EndpointParam URI vAppId); - + @ResponseParser(ParseTaskFromLocationHeader.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture deleteVApp(@EndpointParam URI vAppId); } diff --git a/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/VCloudExpressClient.java b/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/VCloudExpressClient.java index 808c473405..8c4138f5c8 100644 --- a/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/VCloudExpressClient.java +++ b/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/VCloudExpressClient.java @@ -42,7 +42,7 @@ import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions; public interface VCloudExpressClient extends CommonVCloudClient { VCloudExpressVApp instantiateVAppTemplateInVDC(URI vDC, URI template, String appName, - InstantiateVAppTemplateOptions... options); + InstantiateVAppTemplateOptions... options); Task cloneVAppInVDC(URI vDC, URI toClone, String newName, CloneVAppOptions... options); @@ -63,7 +63,7 @@ public interface VCloudExpressClient extends CommonVCloudClient { * if you specified an org, catalog, or catalog item name that isn't present */ VCloudExpressVAppTemplate findVAppTemplateInOrgCatalogNamed(@Nullable String orgName, @Nullable String catalogName, - String itemName); + String itemName); VCloudExpressVApp findVAppInOrgVDCNamed(@Nullable String orgName, @Nullable String catalogName, String vAppName); @@ -101,6 +101,6 @@ public interface VCloudExpressClient extends CommonVCloudClient { */ Task suspendVApp(URI vAppId); - void deleteVApp(URI vAppId); + Task deleteVApp(URI vAppId); } diff --git a/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/compute/functions/ParseOsFromVAppTemplateName.java b/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/compute/functions/ParseOsFromVAppTemplateName.java index a33c44a847..932d535739 100644 --- a/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/compute/functions/ParseOsFromVAppTemplateName.java +++ b/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/compute/functions/ParseOsFromVAppTemplateName.java @@ -29,7 +29,6 @@ import javax.inject.Inject; import javax.inject.Singleton; import org.jclouds.compute.domain.OperatingSystem; -import org.jclouds.compute.domain.OperatingSystemBuilder; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.util.ComputeServiceUtils; @@ -51,7 +50,7 @@ public class ParseOsFromVAppTemplateName implements Function> deleting vApp(%s)", vApp.getName()); - VCloudExpressClient.class.cast(client).deleteVApp(vApp.getHref()); + Task task = VCloudExpressClient.class.cast(client).deleteVApp(vApp.getHref()); + if (task != null) + if (!taskTester.apply(task.getHref())) + throw new RuntimeException(String.format("failed to %s %s: %s", "delete", vApp.getName(), task)); } @Override diff --git a/common/trmk/src/main/java/org/jclouds/vcloud/terremark/functions/ParseTaskFromLocationHeader.java b/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/functions/ParseTaskFromLocationHeader.java similarity index 97% rename from common/trmk/src/main/java/org/jclouds/vcloud/terremark/functions/ParseTaskFromLocationHeader.java rename to apis/vcloudexpress/src/main/java/org/jclouds/vcloud/functions/ParseTaskFromLocationHeader.java index 31e98d186a..388933f8ac 100644 --- a/common/trmk/src/main/java/org/jclouds/vcloud/terremark/functions/ParseTaskFromLocationHeader.java +++ b/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/functions/ParseTaskFromLocationHeader.java @@ -16,7 +16,8 @@ * limitations under the License. * ==================================================================== */ -package org.jclouds.vcloud.terremark.functions; + +package org.jclouds.vcloud.functions; import java.net.URI; import java.util.Date; diff --git a/apis/vcloudexpress/src/test/java/org/jclouds/vcloud/VCloudExpressAsyncClientTest.java b/apis/vcloudexpress/src/test/java/org/jclouds/vcloud/VCloudExpressAsyncClientTest.java index baaf3a9591..3dae72731f 100644 --- a/apis/vcloudexpress/src/test/java/org/jclouds/vcloud/VCloudExpressAsyncClientTest.java +++ b/apis/vcloudexpress/src/test/java/org/jclouds/vcloud/VCloudExpressAsyncClientTest.java @@ -44,7 +44,6 @@ import org.jclouds.rest.RestClientTest; import org.jclouds.rest.RestContextFactory; import org.jclouds.rest.RestContextSpec; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; -import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.util.Strings2; import org.jclouds.vcloud.config.VCloudExpressRestClientModule; @@ -60,6 +59,7 @@ import org.jclouds.vcloud.domain.internal.VDCImpl; import org.jclouds.vcloud.domain.network.FenceMode; import org.jclouds.vcloud.domain.network.NetworkConfig; import org.jclouds.vcloud.filters.SetVCloudTokenCookie; +import org.jclouds.vcloud.functions.ParseTaskFromLocationHeader; import org.jclouds.vcloud.options.CloneVAppOptions; import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions; import org.jclouds.vcloud.xml.CatalogHandler; @@ -500,9 +500,9 @@ public class VCloudExpressAsyncClientTest extends RestClientTest passwordGenerator, Predicate successTester, - Map vAppStatusToNodeState, Map credentialStore, - InternetServiceAndPublicIpAddressSupplier internetServiceAndPublicIpAddressSupplier) { + PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider, + @Named("PASSWORD") Provider passwordGenerator, Predicate successTester, + Map vAppStatusToNodeState, Map credentialStore, + InternetServiceAndPublicIpAddressSupplier internetServiceAndPublicIpAddressSupplier) { super(client, successTester, vAppStatusToNodeState); this.client = client; this.credentialsProvider = credentialsProvider; @@ -85,7 +85,7 @@ public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl @Override public VCloudExpressVApp start(@Nullable URI VDC, URI templateId, String name, - InstantiateVAppTemplateOptions options, int... portsToOpen) { + InstantiateVAppTemplateOptions options, int... portsToOpen) { if (options.getDiskSizeKilobytes() != null) { logger.warn("trmk does not support resizing the primary disk; unsetting disk size"); } @@ -95,7 +95,7 @@ public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl String password = null; VCloudExpressVAppTemplate template = client.getVAppTemplate(templateId); if (template.getDescription().indexOf("Windows") != -1 - && options instanceof TerremarkInstantiateVAppTemplateOptions) { + && options instanceof TerremarkInstantiateVAppTemplateOptions) { password = passwordGenerator.get(); TerremarkInstantiateVAppTemplateOptions.class.cast(options).getProperties().put("password", password); } @@ -104,7 +104,7 @@ public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl VCloudExpressVApp vAppResponse = super.start(VDC, templateId, name, options, portsToOpen); if (password != null) { credentialStore.put("node#" + vAppResponse.getHref().toASCIIString(), new Credentials( - defaultCredentials.identity, password)); + defaultCredentials.identity, password)); } if (portsToOpen.length > 0) createPublicAddressMappedToPorts(vAppResponse.getHref(), portsToOpen); @@ -119,37 +119,41 @@ public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl InternetService is = null; Protocol protocol; switch (port) { - case 22: - protocol = Protocol.TCP; - break; - case 80: - case 8080: - protocol = Protocol.HTTP; - break; - case 443: - protocol = Protocol.HTTPS; - break; - default: - protocol = Protocol.HTTP; - break; + case 22: + protocol = Protocol.TCP; + break; + case 80: + case 8080: + protocol = Protocol.HTTP; + break; + case 443: + protocol = Protocol.HTTPS; + break; + default: + protocol = Protocol.HTTP; + break; } if (ip == null) { Entry entry = internetServiceAndPublicIpAddressSupplier - .getNewInternetServiceAndIp(vApp, port, protocol); + .getNewInternetServiceAndIp(vApp, port, protocol); is = entry.getKey(); ip = entry.getValue(); } else { logger.debug(">> adding InternetService %s:%s:%d", ip.getAddress(), protocol, port); - is = client.addInternetServiceToExistingIp(ip.getId(), vApp.getName() + "-" + port, protocol, port, - withDescription(String.format("port %d access to serverId: %s name: %s", port, vApp.getName(), - vApp.getName()))); + is = client.addInternetServiceToExistingIp( + ip.getId(), + vApp.getName() + "-" + port, + protocol, + port, + withDescription(String.format("port %d access to serverId: %s name: %s", port, vApp.getName(), + vApp.getName()))); } - logger.debug("<< created InternetService(%s) %s:%s:%d", is.getName(), is.getPublicIpAddress().getAddress(), is - .getProtocol(), is.getPort()); + logger.debug("<< created InternetService(%s) %s:%s:%d", is.getName(), is.getPublicIpAddress().getAddress(), + is.getProtocol(), is.getPort()); logger.debug(">> adding Node %s:%d -> %s:%d", is.getPublicIpAddress().getAddress(), is.getPort(), - privateAddress, port); + privateAddress, port); Node node = client.addNode(is.getId(), privateAddress, vApp.getName() + "-" + port, port); logger.debug("<< added Node(%s)", node.getName()); } @@ -163,13 +167,13 @@ public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) { ipAddresses.add(service.getPublicIpAddress()); logger.debug(">> deleting Node(%s) %s:%d -> %s:%d", node.getName(), service.getPublicIpAddress() - .getAddress(), service.getPort(), node.getIpAddress(), node.getPort()); + .getAddress(), service.getPort(), node.getIpAddress(), node.getPort()); client.deleteNode(node.getId()); logger.debug("<< deleted Node(%s)", node.getName()); Set nodes = client.getNodes(service.getId()); if (nodes.size() == 0) { logger.debug(">> deleting InternetService(%s) %s:%d", service.getName(), service.getPublicIpAddress() - .getAddress(), service.getPort()); + .getAddress(), service.getPort()); client.deleteInternetService(service.getId()); logger.debug("<< deleted InternetService(%s)", service.getName()); continue SERVICE; diff --git a/core/src/main/java/org/jclouds/json/config/GsonModule.java b/core/src/main/java/org/jclouds/json/config/GsonModule.java index 1760798702..e0353efc7c 100644 --- a/core/src/main/java/org/jclouds/json/config/GsonModule.java +++ b/core/src/main/java/org/jclouds/json/config/GsonModule.java @@ -20,8 +20,10 @@ package org.jclouds.json.config; import java.lang.reflect.Type; import java.util.Date; +import java.util.Enumeration; import java.util.List; import java.util.Map; +import java.util.Properties; import javax.inject.Inject; import javax.inject.Singleton; @@ -33,6 +35,8 @@ import org.jclouds.json.Json; import org.jclouds.json.internal.EnumTypeAdapterThatReturnsFromValue; import org.jclouds.json.internal.GsonWrapper; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; import com.google.common.collect.Maps; import com.google.common.primitives.Bytes; import com.google.gson.Gson; @@ -51,6 +55,7 @@ import com.google.gson.reflect.TypeToken; import com.google.inject.AbstractModule; import com.google.inject.ImplementedBy; import com.google.inject.Provides; +import com.google.inject.TypeLiteral; /** * Contains logic for parsing objects from Strings. @@ -63,13 +68,15 @@ public class GsonModule extends AbstractModule { @Provides @Singleton Gson provideGson(JsonBallAdapter jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter, - ByteArrayAdapter byteArrayAdapter, JsonAdapterBindings bindings) throws ClassNotFoundException, Exception { + ByteArrayAdapter byteArrayAdapter, SerializePropertiesDefaults propertiesAdapter, JsonAdapterBindings bindings) + throws ClassNotFoundException, Exception { GsonBuilder builder = new GsonBuilder(); JcloudsGsonPackageAccessor.registerTypeHierarchyAdapter(builder, Enum.class, new EnumTypeAdapterThatReturnsFromValue()); JcloudsGsonPackageAccessor.registerTypeHierarchyAdapter(builder, Map.class, new MapTypeAdapter()); builder.registerTypeAdapter(JsonBall.class, jsonAdapter); builder.registerTypeAdapter(Date.class, adapter); + builder.registerTypeAdapter(Properties.class, propertiesAdapter); builder.registerTypeAdapter(new TypeToken>() { }.getType(), byteListAdapter); builder.registerTypeAdapter(byte[].class, byteArrayAdapter); @@ -169,6 +176,28 @@ public class GsonModule extends AbstractModule { } + @Singleton + public static class SerializePropertiesDefaults implements JsonSerializer { + private final Json json; + private final Type mapType = new TypeLiteral>() { + }.getRawType(); + + @Inject + public SerializePropertiesDefaults(Json json) { + this.json = json; + } + + public JsonElement serialize(Properties src, Type typeOfSrc, JsonSerializationContext context) { + Builder srcMap = ImmutableMap. builder(); + for (Enumeration propNames = src.propertyNames(); propNames.hasMoreElements();) { + String propName = (String) propNames.nextElement(); + srcMap.put(propName, src.getProperty(propName)); + } + return new JsonLiteral(json.toJson(srcMap.build(), mapType)); + } + + } + @Singleton public static class CDateAdapter implements DateAdapter { private final DateService dateService; diff --git a/core/src/test/java/org/jclouds/json/JsonTest.java b/core/src/test/java/org/jclouds/json/JsonTest.java index 5b7d8bcb49..9224822a84 100644 --- a/core/src/test/java/org/jclouds/json/JsonTest.java +++ b/core/src/test/java/org/jclouds/json/JsonTest.java @@ -21,6 +21,7 @@ package org.jclouds.json; import static org.testng.Assert.assertEquals; import java.util.Map; +import java.util.Properties; import org.jclouds.json.config.GsonModule; import org.testng.annotations.Test; @@ -44,6 +45,19 @@ public class JsonTest { private Test enumValue; } + public void testPropertiesSerializesDefaults() { + Properties props = new Properties(); + props.put("string", "string"); + props.put("number", "1"); + props.put("boolean", "true"); + assertEquals(json.toJson(props), "{\"string\":\"string\",\"boolean\":\"true\",\"number\":\"1\"}"); + Properties props3 = new Properties(props); + assertEquals(json.toJson(props3), "{\"string\":\"string\",\"boolean\":\"true\",\"number\":\"1\"}"); + Properties props2 = json.fromJson(json.toJson(props), Properties.class); + assertEquals(props2, props); + assertEquals(json.toJson(props2), json.toJson(props)); + } + public void testMapStringObjectWithAllValidValuesOneDeep() { Map map = Maps.newHashMap(); map.put("string", "string"); diff --git a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/AWSS3AsyncClient.java b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/AWSS3AsyncClient.java index 5c5ed564b2..1a0ea3e205 100644 --- a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/AWSS3AsyncClient.java +++ b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/AWSS3AsyncClient.java @@ -18,29 +18,13 @@ */ package org.jclouds.aws.s3; -/** - * - * - * ==================================================================== - * Licensed 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. - * ==================================================================== - */ - import static org.jclouds.blobstore.attr.BlobScopes.CONTAINER; import java.util.Map; +import javax.annotation.Nullable; import javax.ws.rs.DELETE; +import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; @@ -56,6 +40,7 @@ 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.Endpoint; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.ParamParser; import org.jclouds.rest.annotations.ParamValidators; @@ -63,14 +48,20 @@ import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.s3.Bucket; import org.jclouds.s3.S3AsyncClient; +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.BindRegionToXmlPayload; +import org.jclouds.s3.functions.ReturnFalseIfBucketAlreadyOwnedByYouOrIllegalState; +import org.jclouds.s3.options.PutBucketOptions; import org.jclouds.s3.options.PutObjectOptions; import org.jclouds.s3.predicates.validators.BucketNameValidator; +import org.jclouds.s3.xml.LocationConstraintHandler; import com.google.common.util.concurrent.ListenableFuture; @@ -83,6 +74,31 @@ import com.google.common.util.concurrent.ListenableFuture; @RequestFilters(RequestAuthorizeSignature.class) @BlobScope(CONTAINER) public interface AWSS3AsyncClient extends S3AsyncClient { + /** + * @see S3Client#putBucketInRegion + */ + @Override + @PUT + @Path("/") + @Endpoint(Bucket.class) + @ExceptionParser(ReturnFalseIfBucketAlreadyOwnedByYouOrIllegalState.class) + ListenableFuture putBucketInRegion( + @BinderParam(BindRegionToXmlPayload.class) @Nullable String region, + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + PutBucketOptions... options); + + /** + * @see S3Client#getBucketLocation + */ + @Override + @GET + @QueryParams(keys = "location") + @Path("/") + @Endpoint(Bucket.class) + @XMLResponseParser(LocationConstraintHandler.class) + ListenableFuture getBucketLocation( + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName); + /** * @see AWSS3Client#initiateMultipartUpload */ @@ -91,9 +107,9 @@ public interface AWSS3AsyncClient extends S3AsyncClient { @Path("/{key}") @ResponseParser(UploadIdFromHttpResponseViaRegex.class) ListenableFuture initiateMultipartUpload( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @PathParam("key") @ParamParser(ObjectMetadataKey.class) @BinderParam(BindObjectMetadataToRequest.class) ObjectMetadata objectMetadata, - PutObjectOptions... options); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @PathParam("key") @ParamParser(ObjectMetadataKey.class) @BinderParam(BindObjectMetadataToRequest.class) ObjectMetadata objectMetadata, + PutObjectOptions... options); /** * @see AWSS3Client#abortMultipartUpload @@ -102,8 +118,8 @@ public interface AWSS3AsyncClient extends S3AsyncClient { @Path("/{key}") @ExceptionParser(ReturnVoidOnNotFoundOr404.class) ListenableFuture abortMultipartUpload( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @PathParam("key") String key, @QueryParam("uploadId") String uploadId); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @PathParam("key") String key, @QueryParam("uploadId") String uploadId); /** * @see AWSS3Client#uploadPart @@ -112,9 +128,9 @@ public interface AWSS3AsyncClient extends S3AsyncClient { @Path("/{key}") @ResponseParser(ParseETagHeader.class) ListenableFuture uploadPart( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @PathParam("key") String key, @QueryParam("partNumber") int partNumber, - @QueryParam("uploadId") String uploadId, Payload part); + @Bucket @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 @@ -123,8 +139,8 @@ public interface AWSS3AsyncClient extends S3AsyncClient { @Path("/{key}") @ResponseParser(ETagFromHttpResponseViaRegex.class) ListenableFuture completeMultipartUpload( - @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName, - @PathParam("key") String key, @QueryParam("uploadId") String uploadId, - @BinderParam(BindPartIdsAndETagsToRequest.class) Map parts); + @Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators({ BucketNameValidator.class }) String bucketName, + @PathParam("key") String key, @QueryParam("uploadId") String uploadId, + @BinderParam(BindPartIdsAndETagsToRequest.class) Map parts); } diff --git a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java index fbd3933472..b2b8465fed 100644 --- a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java +++ b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java @@ -18,14 +18,24 @@ */ package org.jclouds.aws.s3.config; +import static org.jclouds.aws.domain.Region.US_STANDARD; +import static org.jclouds.location.reference.LocationConstants.ENDPOINT; +import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION; + +import java.net.URI; + +import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.aws.s3.AWSS3AsyncClient; import org.jclouds.aws.s3.AWSS3Client; +import org.jclouds.aws.s3.binders.AssignCorrectHostnameAndBindAsHostPrefixIfConfigured; import org.jclouds.http.RequiresHttp; import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.s3.Bucket; import org.jclouds.s3.S3AsyncClient; import org.jclouds.s3.S3Client; +import org.jclouds.s3.binders.BindAsHostPrefixIfConfigured; import org.jclouds.s3.config.S3RestClientModule; import com.google.inject.Provides; @@ -39,6 +49,19 @@ import com.google.inject.Provides; @ConfiguresRestClient public class AWSS3RestClientModule extends S3RestClientModule { + @Provides + @Singleton + @Bucket + protected URI provideLocationURI(@Named(PROPERTY_REGION + "." + US_STANDARD + "." + ENDPOINT) String endpoint) { + return URI.create(endpoint); + } + + @Override + protected void configure() { + bind(BindAsHostPrefixIfConfigured.class).to(AssignCorrectHostnameAndBindAsHostPrefixIfConfigured.class); + super.configure(); + } + public AWSS3RestClientModule() { super(AWSS3Client.class, AWSS3AsyncClient.class); } diff --git a/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3AsyncClientTest.java b/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3AsyncClientTest.java index 865c31c3a9..0ee634a309 100644 --- a/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3AsyncClientTest.java +++ b/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3AsyncClientTest.java @@ -21,8 +21,10 @@ package org.jclouds.aws.s3; import java.io.IOException; import java.lang.reflect.Array; import java.lang.reflect.Method; +import java.net.URI; import java.util.Map; import java.util.Properties; +import java.util.concurrent.ConcurrentMap; import org.jclouds.aws.s3.config.AWSS3RestClientModule; import org.jclouds.aws.s3.functions.ETagFromHttpResponseViaRegex; @@ -31,6 +33,7 @@ import org.jclouds.date.TimeStamp; import org.jclouds.http.HttpRequest; import org.jclouds.http.RequiresHttp; import org.jclouds.http.functions.ParseETagHeader; +import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ReleasePayloadAndReturn; import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.io.Payload; @@ -40,15 +43,18 @@ import org.jclouds.rest.RestContextFactory; import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.rest.internal.RestAnnotationProcessor; +import org.jclouds.s3.S3AsyncClient; import org.jclouds.s3.domain.ObjectMetadata; import org.jclouds.s3.domain.ObjectMetadataBuilder; import org.jclouds.s3.functions.ReturnFalseIfBucketAlreadyOwnedByYouOrIllegalState; import org.jclouds.s3.options.PutBucketOptions; import org.jclouds.s3.options.PutObjectOptions; +import org.jclouds.s3.xml.LocationConstraintHandler; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import com.google.inject.Module; import com.google.inject.TypeLiteral; @@ -63,6 +69,21 @@ public class AWSS3AsyncClientTest extends org.jclouds.s3.S3AsyncClientTest> createTypeLiteral() { return new TypeLiteral>() { @@ -75,15 +96,15 @@ public class AWSS3AsyncClientTest extends org.jclouds.s3.S3AsyncClientTest of(1, "\"a54357aff0632cce46d942af68356b38\"")); + String.class, Map.class); + HttpRequest request = processor.createRequest(method, "bucket", "foo", "asdsadasdas", + ImmutableMap. of(1, "\"a54357aff0632cce46d942af68356b38\"")); assertRequestLineEquals(request, "POST https://bucket." + url + "/foo?uploadId=asdsadasdas HTTP/1.1"); assertNonPayloadHeadersEqual(request, "Host: bucket." + url + "\n"); assertPayloadEquals( - request, - "1\"a54357aff0632cce46d942af68356b38\"", - "text/xml", false); + request, + "1\"a54357aff0632cce46d942af68356b38\"", + "text/xml", false); assertResponseParserClassEquals(method, request, ETagFromHttpResponseViaRegex.class); assertSaxResponseParserClassEquals(method, null); @@ -160,16 +180,16 @@ public class AWSS3AsyncClientTest extends org.jclouds.s3.S3AsyncClientTestEU", - "text/xml", false); + "EU", + "text/xml", false); assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class); assertSaxResponseParserClassEquals(method, null); @@ -186,6 +206,18 @@ public class AWSS3AsyncClientTest extends org.jclouds.s3.S3AsyncClientTest bucketToRegion() { + ConcurrentMap returnVal = Maps.newConcurrentMap(); + returnVal.put("eubucket", "EU"); + return returnVal; + } + + @Override + protected URI provideLocationURI(String endpoint) { + return URI.create("https://bucket"); + } + @Override protected String provideTimeStamp(@TimeStamp Supplier cache) { return "2009-11-08T15:54:08.897Z"; diff --git a/providers/trmk-ecloud/src/test/java/org/jclouds/vcloud/terremark/TerremarkECloudAsyncClientTest.java b/providers/trmk-ecloud/src/test/java/org/jclouds/vcloud/terremark/TerremarkECloudAsyncClientTest.java index 34b49a0880..6bf0e59cc5 100644 --- a/providers/trmk-ecloud/src/test/java/org/jclouds/vcloud/terremark/TerremarkECloudAsyncClientTest.java +++ b/providers/trmk-ecloud/src/test/java/org/jclouds/vcloud/terremark/TerremarkECloudAsyncClientTest.java @@ -48,9 +48,9 @@ import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.util.Strings2; import org.jclouds.vcloud.CommonVCloudClient; -import org.jclouds.vcloud.VCloudVersionsAsyncClient; import org.jclouds.vcloud.VCloudExpressAsyncClientTest.VCloudRestClientModuleExtension.TestOrgCatalogItemSupplier; import org.jclouds.vcloud.VCloudExpressAsyncClientTest.VCloudRestClientModuleExtension.TestOrgCatalogSupplier; +import org.jclouds.vcloud.VCloudVersionsAsyncClient; import org.jclouds.vcloud.config.CommonVCloudRestClientModule.OrgVDCSupplier; import org.jclouds.vcloud.domain.AllocationModel; import org.jclouds.vcloud.domain.Capacity; @@ -62,6 +62,7 @@ import org.jclouds.vcloud.domain.VDCStatus; import org.jclouds.vcloud.domain.internal.ReferenceTypeImpl; import org.jclouds.vcloud.domain.network.NetworkConfig; import org.jclouds.vcloud.filters.SetVCloudTokenCookie; +import org.jclouds.vcloud.functions.ParseTaskFromLocationHeader; import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions; import org.jclouds.vcloud.terremark.config.TerremarkECloudRestClientModule; import org.jclouds.vcloud.terremark.domain.Protocol; @@ -104,8 +105,8 @@ import com.google.inject.TypeLiteral; public class TerremarkECloudAsyncClientTest extends RestClientTest { public void testNetwork() throws SecurityException, NoSuchMethodException, IOException { Method method = TerremarkECloudAsyncClient.class.getMethod("getNetwork", URI.class); - HttpRequest request = processor.createRequest(method, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/vdcItem/2")); + HttpRequest request = processor.createRequest(method, + URI.create("https://vcloud.safesecureweb.com/api/v0.8/vdcItem/2")); assertRequestLineEquals(request, "GET https://vcloud.safesecureweb.com/api/v0.8/vdcItem/2 HTTP/1.1"); assertNonPayloadHeadersEqual(request, "Accept: application/vnd.vmware.vcloud.network+xml\n"); @@ -118,9 +119,25 @@ public class TerremarkECloudAsyncClientTest extends RestClientTestnametrueeggs", - "application/vnd.tmrk.vCloud.nodeService+xml", false); + request, + "nametrueeggs", + "application/vnd.tmrk.vCloud.nodeService+xml", false); assertResponseParserClassEquals(method, request, ParseSax.class); assertSaxResponseParserClassEquals(method, NodeHandler.class); assertExceptionParserClassEquals(method, null); @@ -390,16 +414,16 @@ public class TerremarkECloudAsyncClientTest extends RestClientTestnametrue", - "application/vnd.tmrk.vCloud.nodeService+xml", false); + request, + "nametrue", + "application/vnd.tmrk.vCloud.nodeService+xml", false); assertResponseParserClassEquals(method, request, ParseSax.class); assertSaxResponseParserClassEquals(method, NodeHandler.class); assertExceptionParserClassEquals(method, null); @@ -443,7 +467,7 @@ public class TerremarkECloudAsyncClientTest extends RestClientTest get() { - return ImmutableMap. of("org", new TerremarkOrgImpl("org", null, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/org/1"), null, ImmutableMap - . of("catalog", new ReferenceTypeImpl("catalog", - TerremarkECloudMediaType.CATALOG_XML, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/catalog/1"))), ImmutableMap - . of("vdc", new ReferenceTypeImpl("vdc", TerremarkECloudMediaType.VDC_XML, - URI.create("https://vcloud.safesecureweb.com/api/v0.8/vdc/1"))), ImmutableMap - . of(), new ReferenceTypeImpl("tasksList", - TerremarkECloudMediaType.TASKSLIST_XML, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/tasksList/1")), new ReferenceTypeImpl( - "keysList", TerremarkECloudMediaType.KEYSLIST_XML, URI + return ImmutableMap. of( + "org", + new TerremarkOrgImpl("org", null, URI.create("https://vcloud.safesecureweb.com/api/v0.8/org/1"), + null, ImmutableMap. of( + "catalog", + new ReferenceTypeImpl("catalog", TerremarkECloudMediaType.CATALOG_XML, URI + .create("https://vcloud.safesecureweb.com/api/v0.8/catalog/1"))), ImmutableMap + . of( + "vdc", + new ReferenceTypeImpl("vdc", TerremarkECloudMediaType.VDC_XML, URI + .create("https://vcloud.safesecureweb.com/api/v0.8/vdc/1"))), ImmutableMap + . of(), new ReferenceTypeImpl("tasksList", + TerremarkECloudMediaType.TASKSLIST_XML, URI + .create("https://vcloud.safesecureweb.com/api/v0.8/tasksList/1")), + new ReferenceTypeImpl("keysList", TerremarkECloudMediaType.KEYSLIST_XML, URI .create("https://vcloud.safesecureweb.com/api/v0.8/keysList/1")))); } } @@ -643,7 +670,7 @@ public class TerremarkECloudAsyncClientTest extends RestClientTest> vDCtoOrgSupplier) { + @org.jclouds.vcloud.endpoints.VDC Supplier> vDCtoOrgSupplier) { return "vdc"; } @@ -664,21 +691,25 @@ public class TerremarkECloudAsyncClientTest extends RestClientTest> get() { return ImmutableMap.> of("org", - ImmutableMap. of("vdc", new TerremarkVDCImpl("vdc", null, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/vdc/1"), VDCStatus.READY, null, "description", - ImmutableSet. of(), AllocationModel.UNRECOGNIZED, new Capacity("MB", 0, 0, 0, 0), new Capacity( - "MB", 0, 0, 0, 0), new Capacity("MB", 0, 0, 0, 0), ImmutableMap. of( - "vapp", new ReferenceTypeImpl("vapp", "application/vnd.vmware.vcloud.vApp+xml", URI - .create("https://vcloud.safesecureweb.com/api/v0.8/vApp/188849-1")), "network", + ImmutableMap. of( + "vdc", + new TerremarkVDCImpl("vdc", null, URI.create("https://vcloud.safesecureweb.com/api/v0.8/vdc/1"), + VDCStatus.READY, null, "description", ImmutableSet. of(), AllocationModel.UNRECOGNIZED, + new Capacity("MB", 0, 0, 0, 0), new Capacity("MB", 0, 0, 0, 0), new Capacity("MB", 0, 0, 0, 0), + ImmutableMap. of( + "vapp", + new ReferenceTypeImpl("vapp", "application/vnd.vmware.vcloud.vApp+xml", URI + .create("https://vcloud.safesecureweb.com/api/v0.8/vApp/188849-1")), + "network", new ReferenceTypeImpl("network", "application/vnd.vmware.vcloud.vAppTemplate+xml", URI - .create("https://vcloud.safesecureweb.com/api/v0.8/vdcItem/2"))), ImmutableMap + .create("https://vcloud.safesecureweb.com/api/v0.8/vdcItem/2"))), ImmutableMap . of(), 0, 0, 0, false, new ReferenceTypeImpl("catalog", TerremarkVCloudMediaType.CATALOG_XML, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/catalog/1")), - new ReferenceTypeImpl("publicIps", TerremarkVCloudMediaType.PUBLICIPSLIST_XML, URI + .create("https://vcloud.safesecureweb.com/api/v0.8/catalog/1")), + new ReferenceTypeImpl("publicIps", TerremarkVCloudMediaType.PUBLICIPSLIST_XML, URI .create("https://vcloud.safesecureweb.com/api/v0.8/publicIps/1")), new ReferenceTypeImpl( "internetServices", TerremarkVCloudMediaType.INTERNETSERVICESLIST_XML, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/internetServices/1"))))); + .create("https://vcloud.safesecureweb.com/api/v0.8/internetServices/1"))))); } } } diff --git a/providers/trmk-vcloudexpress/src/test/java/org/jclouds/vcloud/terremark/TerremarkVCloudExpressAsyncClientTest.java b/providers/trmk-vcloudexpress/src/test/java/org/jclouds/vcloud/terremark/TerremarkVCloudExpressAsyncClientTest.java index 08bbd70143..f92608bdb6 100644 --- a/providers/trmk-vcloudexpress/src/test/java/org/jclouds/vcloud/terremark/TerremarkVCloudExpressAsyncClientTest.java +++ b/providers/trmk-vcloudexpress/src/test/java/org/jclouds/vcloud/terremark/TerremarkVCloudExpressAsyncClientTest.java @@ -48,9 +48,9 @@ import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.util.Strings2; import org.jclouds.vcloud.CommonVCloudClient; -import org.jclouds.vcloud.VCloudVersionsAsyncClient; import org.jclouds.vcloud.VCloudExpressAsyncClientTest.VCloudRestClientModuleExtension.TestOrgCatalogItemSupplier; import org.jclouds.vcloud.VCloudExpressAsyncClientTest.VCloudRestClientModuleExtension.TestOrgCatalogSupplier; +import org.jclouds.vcloud.VCloudVersionsAsyncClient; import org.jclouds.vcloud.domain.AllocationModel; import org.jclouds.vcloud.domain.Capacity; import org.jclouds.vcloud.domain.Catalog; @@ -62,6 +62,7 @@ import org.jclouds.vcloud.domain.VDCStatus; import org.jclouds.vcloud.domain.internal.ReferenceTypeImpl; import org.jclouds.vcloud.domain.network.NetworkConfig; import org.jclouds.vcloud.filters.SetVCloudTokenCookie; +import org.jclouds.vcloud.functions.ParseTaskFromLocationHeader; import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions; import org.jclouds.vcloud.terremark.config.TerremarkVCloudExpressRestClientModule; import org.jclouds.vcloud.terremark.domain.Protocol; @@ -104,8 +105,8 @@ public class TerremarkVCloudExpressAsyncClientTest extends RestClientTestnametrueeggs", - "application/vnd.tmrk.vCloud.nodeService+xml", false); + request, + "nametrueeggs", + "application/vnd.tmrk.vCloud.nodeService+xml", false); assertResponseParserClassEquals(method, request, ParseSax.class); assertSaxResponseParserClassEquals(method, NodeHandler.class); assertExceptionParserClassEquals(method, null); @@ -404,16 +436,16 @@ public class TerremarkVCloudExpressAsyncClientTest extends RestClientTestnametrue", - "application/vnd.tmrk.vCloud.nodeService+xml", false); + request, + "nametrue", + "application/vnd.tmrk.vCloud.nodeService+xml", false); assertResponseParserClassEquals(method, request, ParseSax.class); assertSaxResponseParserClassEquals(method, NodeHandler.class); assertExceptionParserClassEquals(method, null); @@ -453,12 +485,12 @@ public class TerremarkVCloudExpressAsyncClientTest extends RestClientTest createContextSpec() { return new RestContextFactory().createContextSpec("trmk-vcloudexpress", "identity", "credential", - new Properties()); + new Properties()); } @RequiresHttp @@ -604,7 +636,7 @@ public class TerremarkVCloudExpressAsyncClientTest extends RestClientTest get() { - return ImmutableMap. of("org", new TerremarkOrgImpl("org", null, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/org/1"), null, ImmutableMap - . of("catalog", new ReferenceTypeImpl("catalog", - TerremarkVCloudExpressMediaType.CATALOG_XML, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/catalog/1"))), ImmutableMap - . of("vdc", new ReferenceTypeImpl("vdc", - TerremarkVCloudExpressMediaType.VDC_XML, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/vdc/1"))), ImmutableMap - . of(), new ReferenceTypeImpl("tasksList", - TerremarkVCloudExpressMediaType.TASKSLIST_XML, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/tasksList/1")), new ReferenceTypeImpl( - "keysList", TerremarkVCloudExpressMediaType.KEYSLIST_XML, URI + return ImmutableMap. of( + "org", + new TerremarkOrgImpl("org", null, URI.create("https://vcloud.safesecureweb.com/api/v0.8/org/1"), + null, ImmutableMap. of( + "catalog", + new ReferenceTypeImpl("catalog", TerremarkVCloudExpressMediaType.CATALOG_XML, URI + .create("https://vcloud.safesecureweb.com/api/v0.8/catalog/1"))), ImmutableMap + . of( + "vdc", + new ReferenceTypeImpl("vdc", TerremarkVCloudExpressMediaType.VDC_XML, URI + .create("https://vcloud.safesecureweb.com/api/v0.8/vdc/1"))), ImmutableMap + . of(), new ReferenceTypeImpl("tasksList", + TerremarkVCloudExpressMediaType.TASKSLIST_XML, URI + .create("https://vcloud.safesecureweb.com/api/v0.8/tasksList/1")), + new ReferenceTypeImpl("keysList", TerremarkVCloudExpressMediaType.KEYSLIST_XML, URI .create("https://vcloud.safesecureweb.com/api/v0.8/keysList/1")))); } } @@ -703,22 +738,25 @@ public class TerremarkVCloudExpressAsyncClientTest extends RestClientTest> get() { return ImmutableMap.> of("org", - ImmutableMap. of("vdc", new TerremarkVDCImpl("vdc", null, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/vdc/1"), VDCStatus.READY, null, "description", - ImmutableSet. of(), AllocationModel.UNRECOGNIZED, new Capacity("MB", 0, 0, 0, 0), - new Capacity("MB", 0, 0, 0, 0), new Capacity("MB", 0, 0, 0, 0), - ImmutableMap. of("vapp", new ReferenceTypeImpl("vapp", - "application/vnd.vmware.vcloud.vApp+xml", URI - .create("https://vcloud.safesecureweb.com/api/v0.8/vApp/188849-1")), "network", + ImmutableMap. of( + "vdc", + new TerremarkVDCImpl("vdc", null, URI.create("https://vcloud.safesecureweb.com/api/v0.8/vdc/1"), + VDCStatus.READY, null, "description", ImmutableSet. of(), AllocationModel.UNRECOGNIZED, + new Capacity("MB", 0, 0, 0, 0), new Capacity("MB", 0, 0, 0, 0), new Capacity("MB", 0, 0, 0, 0), + ImmutableMap. of( + "vapp", + new ReferenceTypeImpl("vapp", "application/vnd.vmware.vcloud.vApp+xml", URI + .create("https://vcloud.safesecureweb.com/api/v0.8/vApp/188849-1")), + "network", new ReferenceTypeImpl("network", "application/vnd.vmware.vcloud.vAppTemplate+xml", URI - .create("https://vcloud.safesecureweb.com/api/v0.8/vdcItem/2"))), ImmutableMap + .create("https://vcloud.safesecureweb.com/api/v0.8/vdcItem/2"))), ImmutableMap . of(), 0, 0, 0, false, new ReferenceTypeImpl("catalog", TerremarkVCloudExpressMediaType.CATALOG_XML, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/catalog/1")), - new ReferenceTypeImpl("publicIps", TerremarkVCloudExpressMediaType.PUBLICIPSLIST_XML, URI + .create("https://vcloud.safesecureweb.com/api/v0.8/catalog/1")), + new ReferenceTypeImpl("publicIps", TerremarkVCloudExpressMediaType.PUBLICIPSLIST_XML, URI .create("https://vcloud.safesecureweb.com/api/v0.8/publicIps/1")), new ReferenceTypeImpl( "internetServices", TerremarkVCloudExpressMediaType.INTERNETSERVICESLIST_XML, URI - .create("https://vcloud.safesecureweb.com/api/v0.8/internetServices/1"))))); + .create("https://vcloud.safesecureweb.com/api/v0.8/internetServices/1"))))); } } @@ -734,7 +772,7 @@ public class TerremarkVCloudExpressAsyncClientTest extends RestClientTest> vDCtoOrgSupplier) { + @org.jclouds.vcloud.endpoints.VDC Supplier> vDCtoOrgSupplier) { return "vdc"; }