Issue 76: added support for @Produces and @Consumes, replaced @EntityBinder with @DecoratorParam so that we can manipulate more things then just entities; organized rest module

git-svn-id: http://jclouds.googlecode.com/svn/trunk@1952 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-10-10 00:18:34 +00:00
parent b3a9e76d21
commit 5b7878b0ea
117 changed files with 1248 additions and 829 deletions

View File

@ -34,7 +34,7 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.aws.s3.binders.S3ObjectBinder; import org.jclouds.aws.s3.decorators.AddS3ObjectEntity;
import org.jclouds.aws.s3.domain.BucketMetadata; import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ListBucketResponse; import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.domain.ObjectMetadata; import org.jclouds.aws.s3.domain.ObjectMetadata;
@ -55,17 +55,17 @@ import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.functions.ReturnFalseOn404; import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.EntityParam; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.HostPrefixParam; import org.jclouds.rest.annotations.HostPrefixParam;
import org.jclouds.rest.ParamParser; import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.QueryParams; import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.VirtualHost; import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
/** /**
* Provides access to S3 via their REST API. * Provides access to S3 via their REST API.
@ -181,7 +181,7 @@ public interface S3BlobStore extends BlobStore<BucketMetadata, ObjectMetadata, S
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<byte[]> putBlob( Future<byte[]> putBlob(
@HostPrefixParam String bucketName, @HostPrefixParam String bucketName,
@PathParam("key") @ParamParser(BlobKey.class) @EntityParam(S3ObjectBinder.class) S3Object object); @PathParam("key") @ParamParser(BlobKey.class) @DecoratorParam(AddS3ObjectEntity.class) S3Object object);
@PUT @PUT
@Path("/") @Path("/")

View File

@ -34,8 +34,8 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.aws.s3.binders.AccessControlListBinder; import org.jclouds.aws.s3.decorators.AddACLAsXMLEntity;
import org.jclouds.aws.s3.binders.S3ObjectBinder; import org.jclouds.aws.s3.decorators.AddS3ObjectEntity;
import org.jclouds.aws.s3.domain.AccessControlList; import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.domain.BucketMetadata; import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ListBucketResponse; import org.jclouds.aws.s3.domain.ListBucketResponse;
@ -62,21 +62,18 @@ import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.functions.ReturnFalseOn404; import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.EntityParam; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.HostPrefixParam; import org.jclouds.rest.annotations.HostPrefixParam;
import org.jclouds.rest.ParamParser; import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.QueryParams; import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.VirtualHost; import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.binders.HttpRequestOptionsBinder;
import com.google.inject.internal.Nullable;
/** /**
* Provides access to S3 via their REST API. * Provides access to S3 via their REST API.
@ -209,7 +206,7 @@ public interface S3Connection {
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<byte[]> putObject( Future<byte[]> putObject(
@HostPrefixParam String bucketName, @HostPrefixParam String bucketName,
@PathParam("key") @ParamParser(BlobKey.class) @EntityParam(S3ObjectBinder.class) S3Object object, @PathParam("key") @ParamParser(BlobKey.class) @DecoratorParam(AddS3ObjectEntity.class) S3Object object,
PutObjectOptions... options); PutObjectOptions... options);
/** /**
@ -237,7 +234,7 @@ public interface S3Connection {
@Path("/") @Path("/")
@ExceptionParser(ReturnTrueIfBucketAlreadyOwnedByYou.class) @ExceptionParser(ReturnTrueIfBucketAlreadyOwnedByYou.class)
Future<Boolean> putBucketIfNotExists(@HostPrefixParam String bucketName, Future<Boolean> putBucketIfNotExists(@HostPrefixParam String bucketName,
@Nullable @EntityParam(HttpRequestOptionsBinder.class) PutBucketOptions... options); PutBucketOptions... options);
/** /**
* Deletes the bucket, if it is empty. * Deletes the bucket, if it is empty.
@ -378,7 +375,7 @@ public interface S3Connection {
@Path("/") @Path("/")
@QueryParams(keys = "acl") @QueryParams(keys = "acl")
Future<Boolean> putBucketACL(@HostPrefixParam String bucketName, Future<Boolean> putBucketACL(@HostPrefixParam String bucketName,
@EntityParam(AccessControlListBinder.class) AccessControlList acl); @DecoratorParam(AddACLAsXMLEntity.class) AccessControlList acl);
/** /**
* A GET request operation directed at an object or bucket URI with the "acl" parameter retrieves * A GET request operation directed at an object or bucket URI with the "acl" parameter retrieves
@ -421,6 +418,6 @@ public interface S3Connection {
@QueryParams(keys = "acl") @QueryParams(keys = "acl")
@Path("{key}") @Path("{key}")
Future<Boolean> putObjectACL(@HostPrefixParam String bucketName, @PathParam("key") String key, Future<Boolean> putObjectACL(@HostPrefixParam String bucketName, @PathParam("key") String key,
@EntityParam(AccessControlListBinder.class) AccessControlList acl); @DecoratorParam(AddACLAsXMLEntity.class) AccessControlList acl);
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.aws.s3.binders; package org.jclouds.aws.s3.decorators;
import java.util.Properties; import java.util.Properties;
@ -37,14 +37,14 @@ import org.jclouds.aws.s3.domain.AccessControlList.Grant;
import org.jclouds.aws.s3.domain.AccessControlList.GroupGrantee; import org.jclouds.aws.s3.domain.AccessControlList.GroupGrantee;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.EntityBinder; import org.jclouds.rest.decorators.RequestDecorator;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.jamesmurty.utils.XMLBuilder; import com.jamesmurty.utils.XMLBuilder;
public class AccessControlListBinder implements EntityBinder { public class AddACLAsXMLEntity implements RequestDecorator {
public void addEntityToRequest(Object entity, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object entity) {
AccessControlList from = (AccessControlList) entity; AccessControlList from = (AccessControlList) entity;
Properties outputProperties = new Properties(); Properties outputProperties = new Properties();
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes"); outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
@ -57,6 +57,7 @@ public class AccessControlListBinder implements EntityBinder {
Utils.rethrowIfRuntime(e); Utils.rethrowIfRuntime(e);
throw new RuntimeException("error transforming acl: " + from, e); throw new RuntimeException("error transforming acl: " + from, e);
} }
return request;
} }
protected XMLBuilder generateBuilder(AccessControlList acl) throws ParserConfigurationException, protected XMLBuilder generateBuilder(AccessControlList acl) throws ParserConfigurationException,

View File

@ -21,28 +21,27 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.aws.s3.binders; package org.jclouds.aws.s3.decorators;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX; import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.binders.BlobBinder; import org.jclouds.blobstore.decorators.AddBlobEntity;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import javax.inject.Inject; public class AddS3ObjectEntity extends AddBlobEntity {
import javax.inject.Named;
public class S3ObjectBinder extends BlobBinder {
@Inject @Inject
public S3ObjectBinder(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) { public AddS3ObjectEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
super(metadataPrefix); super(metadataPrefix);
} }
public void addEntityToRequest(Object entity, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object entity) {
Blob<?> object = (Blob<?>) entity; Blob<?> object = (Blob<?>) entity;
checkArgument(object.getMetadata().getSize() >= 0, "size must be set"); checkArgument(object.getMetadata().getSize() >= 0, "size must be set");
checkArgument(object.getContentLength() <= 5 * 1024 * 1024 * 1024, checkArgument(object.getContentLength() <= 5 * 1024 * 1024 * 1024,
@ -64,6 +63,6 @@ public class S3ObjectBinder extends BlobBinder {
s3Object.getMetadata().getContentEncoding()); s3Object.getMetadata().getContentEncoding());
} }
} }
super.addEntityToRequest(entity, request); return super.decorateRequest(request, entity);
} }
} }

View File

@ -48,7 +48,7 @@ import java.util.SortedSet;
* @author Adrian Cole * @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html" /> * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html" />
*/ */
public interface ListBucketResponse extends org.jclouds.rest.BoundedSortedSet<ObjectMetadata> { public interface ListBucketResponse extends org.jclouds.rest.internal.BoundedSortedSet<ObjectMetadata> {
/** /**
* Example: * Example:

View File

@ -30,7 +30,7 @@ import java.util.SortedSet;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class TreeSetListBucketResponse extends org.jclouds.rest.BoundedTreeSet<ObjectMetadata> public class TreeSetListBucketResponse extends org.jclouds.rest.internal.BoundedTreeSet<ObjectMetadata>
implements ListBucketResponse { implements ListBucketResponse {
/** The serialVersionUID */ /** The serialVersionUID */
private static final long serialVersionUID = -4475709781001190244L; private static final long serialVersionUID = -4475709781001190244L;

View File

@ -50,24 +50,24 @@ import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.filters.SharedKeyAuthentication; import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
import org.jclouds.azure.storage.options.ListOptions; import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.reference.AzureStorageHeaders; import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.blobstore.binders.BlobBinder; import org.jclouds.blobstore.decorators.AddBlobEntity;
import org.jclouds.blobstore.binders.UserMetadataBinder; import org.jclouds.blobstore.decorators.AddHeadersWithPrefix;
import org.jclouds.blobstore.functions.BlobKey; import org.jclouds.blobstore.functions.BlobKey;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.functions.ReturnTrueOn404; import org.jclouds.http.functions.ReturnTrueOn404;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.EntityParam; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.ParamParser; import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.QueryParams; import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -144,7 +144,7 @@ public interface AzureBlobConnection {
@Path("{container}") @Path("{container}")
@QueryParams(keys = { "restype", "comp" }, values = { "container", "metadata" }) @QueryParams(keys = { "restype", "comp" }, values = { "container", "metadata" })
void setContainerMetadata(@PathParam("container") String container, void setContainerMetadata(@PathParam("container") String container,
@EntityParam(UserMetadataBinder.class) Multimap<String, String> metadata); @DecoratorParam(AddHeadersWithPrefix.class) Multimap<String, String> metadata);
/** /**
* The Delete Container operation marks the specified container for deletion. The container and * The Delete Container operation marks the specified container for deletion. The container and
@ -272,7 +272,7 @@ public interface AzureBlobConnection {
@Path("{container}/{key}") @Path("{container}/{key}")
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<byte[]> putBlob(@PathParam("container") String container, Future<byte[]> putBlob(@PathParam("container") String container,
@PathParam("key") @ParamParser(BlobKey.class) @EntityParam(BlobBinder.class) Blob object); @PathParam("key") @ParamParser(BlobKey.class) @DecoratorParam(AddBlobEntity.class) Blob object);
/** /**
* The Get Blob operation reads or downloads a blob from the system, including its metadata and * The Get Blob operation reads or downloads a blob from the system, including its metadata and
@ -302,7 +302,7 @@ public interface AzureBlobConnection {
@Path("{container}/{key}") @Path("{container}/{key}")
@QueryParams(keys = { "comp" }, values = { "metadata" }) @QueryParams(keys = { "comp" }, values = { "metadata" })
void setBlobMetadata(@PathParam("container") String container, @PathParam("key") String key, void setBlobMetadata(@PathParam("container") String container, @PathParam("key") String key,
@EntityParam(UserMetadataBinder.class) Multimap<String, String> metadata); @DecoratorParam(AddHeadersWithPrefix.class) Multimap<String, String> metadata);
/** /**
* The Delete Blob operation marks the specified blob for deletion. The blob is later deleted * The Delete Blob operation marks the specified blob for deletion. The blob is later deleted

View File

@ -35,11 +35,11 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.azure.storage.AzureBlob; import org.jclouds.azure.storage.AzureBlob;
import org.jclouds.azure.storage.blob.decorators.GenerateMD5AndAddBlobEntity;
import org.jclouds.azure.storage.blob.domain.Blob; import org.jclouds.azure.storage.blob.domain.Blob;
import org.jclouds.azure.storage.blob.domain.BlobMetadata; import org.jclouds.azure.storage.blob.domain.BlobMetadata;
import org.jclouds.azure.storage.blob.domain.ContainerMetadata; import org.jclouds.azure.storage.blob.domain.ContainerMetadata;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse; import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.functions.MD5EnforcingBlobBinder;
import org.jclouds.azure.storage.blob.functions.ParseBlobFromHeadersAndHttpContent; import org.jclouds.azure.storage.blob.functions.ParseBlobFromHeadersAndHttpContent;
import org.jclouds.azure.storage.blob.functions.ParseBlobMetadataFromHeaders; import org.jclouds.azure.storage.blob.functions.ParseBlobMetadataFromHeaders;
import org.jclouds.azure.storage.blob.functions.ReturnTrueIfContainerAlreadyExists; import org.jclouds.azure.storage.blob.functions.ReturnTrueIfContainerAlreadyExists;
@ -56,16 +56,16 @@ import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.functions.ReturnFalseOn404; import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.EntityParam; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.ParamParser; import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.QueryParams; import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
/** /**
* Provides access to Azure Blob via their REST API. * Provides access to Azure Blob via their REST API.
@ -149,7 +149,7 @@ public interface AzureBlobStore extends BlobStore<ContainerMetadata, BlobMetadat
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<byte[]> putBlob( Future<byte[]> putBlob(
@PathParam("container") String container, @PathParam("container") String container,
@PathParam("key") @ParamParser(BlobKey.class) @EntityParam(MD5EnforcingBlobBinder.class) Blob object); @PathParam("key") @ParamParser(BlobKey.class) @DecoratorParam(GenerateMD5AndAddBlobEntity.class) Blob object);
@GET @GET
@ResponseParser(ParseBlobFromHeadersAndHttpContent.class) @ResponseParser(ParseBlobFromHeadersAndHttpContent.class)

View File

@ -33,12 +33,12 @@ import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
import org.jclouds.azure.storage.reference.AzureStorageHeaders; import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseContentMD5FromHeaders; import org.jclouds.http.functions.ParseContentMD5FromHeaders;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
/** /**
* Helper functions needed to to derive BlobStore values * Helper functions needed to to derive BlobStore values

View File

@ -21,27 +21,27 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.azure.storage.blob.binders; package org.jclouds.azure.storage.blob.decorators;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX; import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.azure.storage.blob.domain.BlobMetadata; import org.jclouds.azure.storage.blob.domain.BlobMetadata;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import javax.inject.Inject; public class AddBlobEntity extends org.jclouds.blobstore.decorators.AddBlobEntity {
import javax.inject.Named;
public class BlobBinder extends org.jclouds.blobstore.binders.BlobBinder {
@Inject @Inject
public BlobBinder(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) { public AddBlobEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
super(metadataPrefix); super(metadataPrefix);
} }
public void addEntityToRequest(Object entity, HttpRequest request) { @Override
public HttpRequest decorateRequest(HttpRequest request, Object entity) {
Blob<?> object = (Blob<?>) entity; Blob<?> object = (Blob<?>) entity;
checkArgument(object.getMetadata().getSize() >= 0, "size must be set"); checkArgument(object.getMetadata().getSize() >= 0, "size must be set");
checkArgument(object.getContentLength() <= 64 * 1024 * 1024, checkArgument(object.getContentLength() <= 64 * 1024 * 1024,
@ -57,6 +57,6 @@ public class BlobBinder extends org.jclouds.blobstore.binders.BlobBinder {
request.getHeaders().put(HttpHeaders.CONTENT_ENCODING, md.getContentEncoding()); request.getHeaders().put(HttpHeaders.CONTENT_ENCODING, md.getContentEncoding());
} }
} }
super.addEntityToRequest(entity, request); return super.decorateRequest(request, entity);
} }
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.azure.storage.blob.functions; package org.jclouds.azure.storage.blob.decorators;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX; import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
@ -30,18 +30,18 @@ import java.io.IOException;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import org.jclouds.azure.storage.blob.binders.BlobBinder;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
public class MD5EnforcingBlobBinder extends BlobBinder { public class GenerateMD5AndAddBlobEntity extends AddBlobEntity {
@Inject @Inject
public MD5EnforcingBlobBinder(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) { public GenerateMD5AndAddBlobEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
super(metadataPrefix); super(metadataPrefix);
} }
public void addEntityToRequest(Object entity, HttpRequest request) { @Override
public HttpRequest decorateRequest(HttpRequest request, Object entity) {
Blob<?> object = (Blob<?>) entity; Blob<?> object = (Blob<?>) entity;
if (object.getMetadata().getContentMD5() == null) { if (object.getMetadata().getContentMD5() == null) {
try { try {
@ -50,6 +50,6 @@ public class MD5EnforcingBlobBinder extends BlobBinder {
throw new RuntimeException("Could not generate MD5 for " + object.getKey(), e); throw new RuntimeException("Could not generate MD5 for " + object.getKey(), e);
} }
} }
super.addEntityToRequest(entity, request); return super.decorateRequest(request, entity);
} }
} }

View File

@ -36,7 +36,7 @@ import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.rest.RestContext; import org.jclouds.rest.InvocationContext;
import org.jclouds.util.DateService; import org.jclouds.util.DateService;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -50,7 +50,7 @@ import com.google.common.base.Function;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ParseContainerMetadataFromHeaders implements public class ParseContainerMetadataFromHeaders implements
Function<HttpResponse, ContainerMetadata>, RestContext { Function<HttpResponse, ContainerMetadata>, InvocationContext {
private final DateService dateParser; private final DateService dateParser;
private final String metadataPrefix; private final String metadataPrefix;

View File

@ -33,6 +33,7 @@ import java.net.URI;
import java.util.Collections; import java.util.Collections;
import javax.ws.rs.HttpMethod; import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.azure.storage.AzureBlob; import org.jclouds.azure.storage.AzureBlob;
import org.jclouds.azure.storage.blob.functions.ParseContainerMetadataFromHeaders; import org.jclouds.azure.storage.blob.functions.ParseContainerMetadataFromHeaders;
@ -52,8 +53,8 @@ import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.ReturnTrueOn404; import org.jclouds.http.functions.ReturnTrueOn404;
import org.jclouds.http.functions.ReturnVoidIf2xx; import org.jclouds.http.functions.ReturnVoidIf2xx;
import org.jclouds.rest.JaxrsAnnotationProcessor; import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.config.JaxrsModule; import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -300,7 +301,9 @@ public class AzureBlobConnectionTest {
assertEquals(httpMethod.getEndpoint().getPath(), "/container"); assertEquals(httpMethod.getEndpoint().getPath(), "/container");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container&comp=metadata"); assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container&comp=metadata");
assertEquals(httpMethod.getMethod(), HttpMethod.PUT); assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 2); assertEquals(httpMethod.getHeaders().size(), 3);
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList("0"));
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17")); .singletonList("2009-07-17"));
assertEquals(httpMethod.getHeaders().get("x-ms-meta-key"), Collections.singletonList("value")); assertEquals(httpMethod.getHeaders().get("x-ms-meta-key"), Collections.singletonList("value"));
@ -319,9 +322,11 @@ public class AzureBlobConnectionTest {
assertEquals(httpMethod.getEndpoint().getPath(), "/container/blob"); assertEquals(httpMethod.getEndpoint().getPath(), "/container/blob");
assertEquals(httpMethod.getEndpoint().getQuery(), "comp=metadata"); assertEquals(httpMethod.getEndpoint().getQuery(), "comp=metadata");
assertEquals(httpMethod.getMethod(), HttpMethod.PUT); assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 2); assertEquals(httpMethod.getHeaders().size(), 3);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17")); .singletonList("2009-07-17"));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList("0"));
assertEquals(httpMethod.getHeaders().get("x-ms-meta-key"), Collections.singletonList("value")); assertEquals(httpMethod.getHeaders().get("x-ms-meta-key"), Collections.singletonList("value"));
assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(),
@ -346,12 +351,12 @@ public class AzureBlobConnectionTest {
Jsr330.named(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX)).to( Jsr330.named(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX)).to(
"x-ms-meta-"); "x-ms-meta-");
} }
}, new JaxrsModule(), new ExecutorServiceModule(new WithinThreadExecutorService()), }, new RestModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule()); new JavaUrlHttpCommandExecutorServiceModule());
processor = injector.getInstance(Key processor = injector.getInstance(Key
.get(new TypeLiteral<JaxrsAnnotationProcessor<AzureBlobConnection>>() { .get(new TypeLiteral<RestAnnotationProcessor<AzureBlobConnection>>() {
})); }));
} }
JaxrsAnnotationProcessor<AzureBlobConnection> processor; RestAnnotationProcessor<AzureBlobConnection> processor;
} }

View File

@ -49,8 +49,8 @@ import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.ReturnVoidIf2xx; import org.jclouds.http.functions.ReturnVoidIf2xx;
import org.jclouds.rest.JaxrsAnnotationProcessor; import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.config.JaxrsModule; import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -195,12 +195,12 @@ public class AzureBlobStoreTest {
}; };
} }
}, new JaxrsModule(), new ExecutorServiceModule(new WithinThreadExecutorService()), }, new RestModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule()); new JavaUrlHttpCommandExecutorServiceModule());
processor = injector.getInstance(Key processor = injector.getInstance(Key
.get(new TypeLiteral<JaxrsAnnotationProcessor<AzureBlobStore>>() { .get(new TypeLiteral<RestAnnotationProcessor<AzureBlobStore>>() {
})); }));
} }
JaxrsAnnotationProcessor<AzureBlobStore> processor; RestAnnotationProcessor<AzureBlobStore> processor;
} }

View File

@ -28,7 +28,7 @@ package org.jclouds.azure.storage.domain;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public interface BoundedSortedSet<T> extends org.jclouds.rest.BoundedSortedSet<T> { public interface BoundedSortedSet<T> extends org.jclouds.rest.internal.BoundedSortedSet<T> {
String getNextMarker(); String getNextMarker();

View File

@ -30,7 +30,7 @@ import java.util.SortedSet;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class BoundedTreeSet<T> extends org.jclouds.rest.BoundedTreeSet<T> implements public class BoundedTreeSet<T> extends org.jclouds.rest.internal.BoundedTreeSet<T> implements
BoundedSortedSet<T> { BoundedSortedSet<T> {
/** The serialVersionUID */ /** The serialVersionUID */
private static final long serialVersionUID = -4475709781001190244L; private static final long serialVersionUID = -4475709781001190244L;

View File

@ -37,11 +37,11 @@ import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.Endpoint;
import org.jclouds.rest.QueryParams;
import org.jclouds.rest.RequestFilters;
import org.jclouds.rest.RestClientFactory; import org.jclouds.rest.RestClientFactory;
import org.jclouds.rest.config.JaxrsModule; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.config.RestModule;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -96,7 +96,7 @@ public class SharedKeyAuthenticationLiveTest {
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY)).to(key); Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY)).to(key);
} }
}, new JaxrsModule(), new Log4JLoggingModule(), new ExecutorServiceModule( }, new RestModule(), new Log4JLoggingModule(), new ExecutorServiceModule(
new WithinThreadExecutorService()), new JavaUrlHttpCommandExecutorServiceModule()); new WithinThreadExecutorService()), new JavaUrlHttpCommandExecutorServiceModule());
RestClientFactory factory = injector.getInstance(RestClientFactory.class); RestClientFactory factory = injector.getInstance(RestClientFactory.class);
client = factory.create(IntegrationTestClient.class); client = factory.create(IntegrationTestClient.class);

View File

@ -40,12 +40,12 @@ import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.queue.domain.QueueMetadata; import org.jclouds.azure.storage.queue.domain.QueueMetadata;
import org.jclouds.azure.storage.queue.xml.AccountNameEnumerationResultsHandler; import org.jclouds.azure.storage.queue.xml.AccountNameEnumerationResultsHandler;
import org.jclouds.azure.storage.reference.AzureStorageHeaders; import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.QueryParams; import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
/** /**
* Provides access to Azure Queue via their REST API. * Provides access to Azure Queue via their REST API.

View File

@ -44,8 +44,8 @@ import org.jclouds.http.HttpUtils;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.rest.JaxrsAnnotationProcessor; import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.config.JaxrsModule; import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -177,12 +177,12 @@ public class AzureQueueConnectionTest {
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY)).to( Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY)).to(
HttpUtils.toBase64String("key".getBytes())); HttpUtils.toBase64String("key".getBytes()));
} }
}, new JaxrsModule(), new ExecutorServiceModule(new WithinThreadExecutorService()), }, new RestModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule()); new JavaUrlHttpCommandExecutorServiceModule());
processor = injector.getInstance(Key processor = injector.getInstance(Key
.get(new TypeLiteral<JaxrsAnnotationProcessor<AzureQueueConnection>>() { .get(new TypeLiteral<RestAnnotationProcessor<AzureQueueConnection>>() {
})); }));
} }
JaxrsAnnotationProcessor<AzureQueueConnection> processor; RestAnnotationProcessor<AzureQueueConnection> processor;
} }

View File

@ -21,9 +21,9 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.blobstore.binders; package org.jclouds.blobstore.decorators;
import static com.google.common.base.Preconditions.*; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX; import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import javax.inject.Inject; import javax.inject.Inject;
@ -33,17 +33,17 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.rest.binders.EntityBinder; import org.jclouds.rest.decorators.RequestDecorator;
public class BlobBinder implements EntityBinder { public class AddBlobEntity implements RequestDecorator {
private final String metadataPrefix; private final String metadataPrefix;
@Inject @Inject
public BlobBinder(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) { public AddBlobEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
this.metadataPrefix = metadataPrefix; this.metadataPrefix = metadataPrefix;
} }
public void addEntityToRequest(Object entity, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object entity) {
Blob<?> object = (Blob<?>) entity; Blob<?> object = (Blob<?>) entity;
for (String key : object.getMetadata().getUserMetadata().keySet()) { for (String key : object.getMetadata().getUserMetadata().keySet()) {
@ -63,6 +63,6 @@ public class BlobBinder implements EntityBinder {
request.getHeaders().put("Content-MD5", request.getHeaders().put("Content-MD5",
HttpUtils.toBase64String(object.getMetadata().getContentMD5())); HttpUtils.toBase64String(object.getMetadata().getContentMD5()));
} }
return request;
} }
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.mezeo.pcs2.binders; package org.jclouds.blobstore.decorators;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -32,12 +32,12 @@ import java.io.InputStream;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.MultipartForm; import org.jclouds.http.MultipartForm;
import org.jclouds.http.MultipartForm.Part; import org.jclouds.http.MultipartForm.Part;
import org.jclouds.mezeo.pcs2.functions.Key; import org.jclouds.rest.decorators.RequestDecorator;
import org.jclouds.mezeo.pcs2.util.PCSUtils;
import org.jclouds.rest.binders.EntityBinder;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -46,13 +46,13 @@ import com.google.common.collect.Multimap;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class PCSFileAsMultipartFormBinder implements EntityBinder { public class AddBlobEntityAsMultipartForm implements RequestDecorator {
public static final String BOUNDARY = "--PCS--"; public static final String BOUNDARY = "--JCLOUDS--";
public void addEntityToRequest(Object entity, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object entity) {
Blob<?> object = (Blob<?>) entity; Blob<?> object = (Blob<?>) entity;
Key key = PCSUtils.parseKey(new Key("junk", object.getKey())); Key key = BlobStoreUtils.parseKey(new Key("junk", object.getKey()));
Multimap<String, String> partHeaders = ImmutableMultimap.of("Content-Disposition", String Multimap<String, String> partHeaders = ImmutableMultimap.of("Content-Disposition", String
.format("form-data; name=\"%s\"; filename=\"%s\"", key.getKey(), key.getKey()), .format("form-data; name=\"%s\"; filename=\"%s\"", key.getKey(), key.getKey()),
HttpHeaders.CONTENT_TYPE, checkNotNull(object.getMetadata().getContentType(), HttpHeaders.CONTENT_TYPE, checkNotNull(object.getMetadata().getContentType(),
@ -84,6 +84,6 @@ public class PCSFileAsMultipartFormBinder implements EntityBinder {
"multipart/form-data; boundary=" + BOUNDARY); "multipart/form-data; boundary=" + BOUNDARY);
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, form.getSize() + ""); request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, form.getSize() + "");
return request;
} }
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.blobstore.binders; package org.jclouds.blobstore.decorators;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX; import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
@ -31,20 +31,20 @@ import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.EntityBinder; import org.jclouds.rest.decorators.RequestDecorator;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
public class UserMetadataBinder implements EntityBinder { public class AddHeadersWithPrefix implements RequestDecorator {
private final String metadataPrefix; private final String metadataPrefix;
@Inject @Inject
public UserMetadataBinder(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) { public AddHeadersWithPrefix(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
this.metadataPrefix = metadataPrefix; this.metadataPrefix = metadataPrefix;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void addEntityToRequest(Object entity, HttpRequest request) { public HttpRequest decorateRequest( HttpRequest request, Object entity) {
Multimap<String, String> userMetadata = (Multimap<String, String>) entity; Multimap<String, String> userMetadata = (Multimap<String, String>) entity;
for (Entry<String, String> entry : userMetadata.entries()) { for (Entry<String, String> entry : userMetadata.entries()) {
if (entry.getKey().startsWith(metadataPrefix)) { if (entry.getKey().startsWith(metadataPrefix)) {
@ -54,6 +54,7 @@ public class UserMetadataBinder implements EntityBinder {
entry.getValue()); entry.getValue());
} }
} }
return request;
} }
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.mezeo.pcs2.functions; package org.jclouds.blobstore.domain;
public class Key { public class Key {
private final String container; private final String container;

View File

@ -38,13 +38,13 @@ import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.blobstore.strategy.ClearContainerStrategy; import org.jclouds.blobstore.strategy.ClearContainerStrategy;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.RestContext; import org.jclouds.rest.InvocationContext;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.base.Function; import com.google.common.base.Function;
public class ClearAndDeleteIfNotEmpty<C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>> public class ClearAndDeleteIfNotEmpty<C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>>
implements Function<Exception, Void>, RestContext { implements Function<Exception, Void>, InvocationContext {
static final Void v; static final Void v;
static { static {
Constructor<Void> cv; Constructor<Void> cv;

View File

@ -32,7 +32,7 @@ import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.rest.RestContext; import org.jclouds.rest.InvocationContext;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -44,7 +44,7 @@ import com.google.common.base.Function;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ParseBlobFromHeadersAndHttpContent<M extends BlobMetadata, B extends Blob<M>> public class ParseBlobFromHeadersAndHttpContent<M extends BlobMetadata, B extends Blob<M>>
implements Function<HttpResponse, B>, RestContext { implements Function<HttpResponse, B>, InvocationContext {
private final ParseContentTypeFromHeaders<M> metadataParser; private final ParseContentTypeFromHeaders<M> metadataParser;
private final Provider<B> blobFactory; private final Provider<B> blobFactory;

View File

@ -31,7 +31,7 @@ import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.rest.RestContext; import org.jclouds.rest.InvocationContext;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -40,7 +40,7 @@ import com.google.common.base.Function;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ParseContentTypeFromHeaders<M extends BlobMetadata> implements public class ParseContentTypeFromHeaders<M extends BlobMetadata> implements
Function<HttpResponse, M>, RestContext { Function<HttpResponse, M>, InvocationContext {
private final Provider<M> metadataFactory; private final Provider<M> metadataFactory;
private HttpRequest request; private HttpRequest request;
private Object[] args; private Object[] args;

View File

@ -44,7 +44,7 @@ import org.jclouds.blobstore.strategy.ContainerCountStrategy;
import org.jclouds.blobstore.strategy.ContainsValueStrategy; import org.jclouds.blobstore.strategy.ContainsValueStrategy;
import org.jclouds.blobstore.strategy.GetAllBlobMetadataStrategy; import org.jclouds.blobstore.strategy.GetAllBlobMetadataStrategy;
import org.jclouds.blobstore.strategy.GetAllBlobsStrategy; import org.jclouds.blobstore.strategy.GetAllBlobsStrategy;
import org.jclouds.rest.BoundedSortedSet; import org.jclouds.rest.internal.BoundedSortedSet;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;

View File

@ -30,6 +30,7 @@ import java.io.InputStream;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
/** /**
@ -39,6 +40,17 @@ import org.jclouds.util.Utils;
*/ */
public class BlobStoreUtils { public class BlobStoreUtils {
public static Key parseKey(Key key) {
if (key.getKey().indexOf('/') != -1) {
String container = key.getContainer() + '/'
+ key.getKey().substring(0, key.getKey().lastIndexOf('/'));
String newKey = key.getKey().substring(key.getKey().lastIndexOf('/') + 1);
key = new Key(container.replaceAll("//", "/"), newKey);
}
return key;
}
public static String getContentAsStringAndClose(Blob<? extends BlobMetadata> object) public static String getContentAsStringAndClose(Blob<? extends BlobMetadata> object)
throws IOException { throws IOException {
checkNotNull(object, "s3Object"); checkNotNull(object, "s3Object");

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.mezeo.pcs2.binders; package org.jclouds.blobstore.decorators;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -32,8 +32,10 @@ import java.net.URI;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import org.jclouds.blobstore.decorators.AddBlobEntityAsMultipartForm;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.mezeo.pcs2.domain.PCSFile;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -42,34 +44,34 @@ import org.testng.annotations.Test;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(testName = "pcs2.PCSFileAsMultipartFormBinderTest") @Test(testName = "blobstore.AddBlobEntityAsMultipartFormTest")
public class PCSFileAsMultipartFormBinderTest { public class AddBlobEntityAsMultipartFormTest {
public static String BOUNDRY = PCSFileAsMultipartFormBinder.BOUNDARY; public static String BOUNDRY = AddBlobEntityAsMultipartForm.BOUNDARY;
public static final String EXPECTS; public static final String EXPECTS;
public static final PCSFile TEST_BLOB; public static final Blob<BlobMetadata> TEST_BLOB;
static { static {
StringBuilder builder = new StringBuilder("--"); StringBuilder builder = new StringBuilder("--");
addData(BOUNDRY, "hello", builder); addData(BOUNDRY, "hello", builder);
builder.append("--").append(BOUNDRY).append("--").append("\r\n"); builder.append("--").append(BOUNDRY).append("--").append("\r\n");
EXPECTS = builder.toString(); EXPECTS = builder.toString();
TEST_BLOB = new PCSFile("hello"); TEST_BLOB = new Blob<BlobMetadata>("hello");
TEST_BLOB.setData("hello"); TEST_BLOB.setData("hello");
TEST_BLOB.getMetadata().setContentType(MediaType.TEXT_PLAIN); TEST_BLOB.getMetadata().setContentType(MediaType.TEXT_PLAIN);
} }
public void testSinglePart() throws IOException { public void testSinglePart() throws IOException {
assertEquals(EXPECTS.length(), 123); assertEquals(EXPECTS.length(), 131);
PCSFileAsMultipartFormBinder binder = new PCSFileAsMultipartFormBinder(); AddBlobEntityAsMultipartForm binder = new AddBlobEntityAsMultipartForm();
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost:8001")); HttpRequest request = new HttpRequest("GET", URI.create("http://localhost:8001"));
binder.addEntityToRequest(TEST_BLOB, request); binder.decorateRequest(request, TEST_BLOB);
assertEquals(Utils.toStringAndClose((InputStream) request.getEntity()), EXPECTS); assertEquals(Utils.toStringAndClose((InputStream) request.getEntity()), EXPECTS);
assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH), 123 + ""); assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH), 131 + "");
assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE),
"multipart/form-data; boundary=" + BOUNDRY); "multipart/form-data; boundary=" + BOUNDRY);

View File

@ -0,0 +1,28 @@
package org.jclouds.blobstore.util;
import static org.testng.Assert.assertEquals;
import org.jclouds.blobstore.domain.Key;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code BlobStoreUtils}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "blobstore.BlobStoreUtilsTest")
public class BlobStoreUtilsTest {
public void testParseKey() {
Key key = BlobStoreUtils.parseKey(new Key("container", "key"));
assertEquals(key.getContainer(), "container");
assertEquals(key.getKey(), "key");
key = BlobStoreUtils.parseKey(new Key("container", "container/key"));
assertEquals(key.getContainer(), "container/container");
assertEquals(key.getKey(), "key");
key = BlobStoreUtils.parseKey(new Key("container", "/container/key"));
assertEquals(key.getContainer(), "container/container");
assertEquals(key.getKey(), "key");
}
}

View File

@ -52,7 +52,7 @@ import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.config.LoggingModule; import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule; import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.config.JaxrsModule; import org.jclouds.rest.config.RestModule;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -218,7 +218,7 @@ public abstract class CloudContextBuilder<C> {
} }
})) { })) {
modules.add(new JaxrsModule()); modules.add(new RestModule());
} }
} }

View File

@ -30,14 +30,14 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.RestContext; import org.jclouds.rest.InvocationContext;
import com.google.common.base.Function; import com.google.common.base.Function;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]>, RestContext { public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]>, InvocationContext {
public static class NoContentMD5Exception extends RuntimeException { public static class NoContentMD5Exception extends RuntimeException {

View File

@ -75,7 +75,7 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
try { try {
logger.trace("%s - filtering request %s", request.getEndpoint(), request); logger.trace("%s - filtering request %s", request.getEndpoint(), request);
for (HttpRequestFilter filter : request.getFilters()) { for (HttpRequestFilter filter : request.getFilters()) {
filter.filter(request); request = filter.filter(request);
} }
logger.trace("%s - request now %s", request.getEndpoint(), request); logger.trace("%s - request now %s", request.getEndpoint(), request);
nativeRequest = convert(request); nativeRequest = convert(request);

View File

@ -34,7 +34,7 @@ import org.jclouds.http.HttpRequest;
* @see PathParam * @see PathParam
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface RestContext { public interface InvocationContext {
void setContext(HttpRequest request, Object[] args); void setContext(HttpRequest request, Object[] args);
Object[] getArgs(); Object[] getArgs();

View File

@ -28,6 +28,8 @@ import java.lang.reflect.Proxy;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.rest.internal.RestClientProxy;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
@ -29,20 +29,20 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.jclouds.rest.binders.EntityBinder; import org.jclouds.rest.decorators.RequestDecorator;
import org.jclouds.rest.binders.ToStringEntityBinder;
/** /**
* Designates that this parameter will hold the entity for a PUT or POST command. * Designates that this parameter will modify the request, possibly including adding an entity to
* it.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Target(PARAMETER) @Target(PARAMETER)
@Retention(RUNTIME) @Retention(RUNTIME)
public @interface EntityParam { public @interface DecoratorParam {
/** /**
* how to persist this entity. * how to persist this entity.
*/ */
Class<? extends EntityBinder> value() default ToStringEntityBinder.class; Class<? extends RequestDecorator> value();
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.PARAMETER;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.TYPE;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
@ -29,7 +29,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.jclouds.rest.binders.MapEntityBinder; import org.jclouds.rest.decorators.MapRequestDecorator;
/** /**
* Designates that this parameter will hold the entity for a PUT or POST command. * Designates that this parameter will hold the entity for a PUT or POST command.
@ -41,8 +41,8 @@ import org.jclouds.rest.binders.MapEntityBinder;
public @interface MapBinder { public @interface MapBinder {
/** /**
* How to bind {@link MapEntityParam} values, if there is no {@link MapEntityBinder} in the method * How to bind {@link MapEntityParam} values, if there is no {@link MapRequestDecorator} in the method
* definition * definition
*/ */
Class<? extends MapEntityBinder> value(); Class<? extends MapRequestDecorator> value();
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
@ -39,7 +39,7 @@ import java.lang.annotation.Target;
public @interface MapEntityParam { public @interface MapEntityParam {
/** /**
* The key used in a map passed to the {@link MapEntityBinder} associated with the request. * The key used in a map passed to the {@link MapRequestDecorator} associated with the request.
*/ */
String value(); String value();
} }

View File

@ -0,0 +1,50 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.rest.annotations;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.ws.rs.MatrixParam;
/**
* Designates that a matrix param will be added to the request.
*
* @see MatrixParam
* @author Adrian Cole
*/
@Target( { TYPE, METHOD })
@Retention(RUNTIME)
public @interface MatrixParams {
public static final String NULL = "MATRIX_NULL";
String[] keys();
String[] values() default NULL;
}

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.PARAMETER;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.*; import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.TYPE;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.annotations;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;

View File

@ -1,49 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.rest.binders;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.options.HttpRequestOptions;
import javax.inject.Singleton;
/**
* Adds an entity to a request.
*
* @author Adrian Cole
*/
@Singleton
public class HttpRequestOptionsBinder implements EntityBinder {
public void addEntityToRequest(Object entity, HttpRequest request) {
HttpRequestOptions options = (HttpRequestOptions) entity;
String stringEntity = options.buildStringEntity();
if (stringEntity != null) {
request.getHeaders().put(HttpHeaders.CONTENT_TYPE, "application/unknown");
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, stringEntity.getBytes().length + "");
request.setEntity(stringEntity);
}
}
}

View File

@ -28,7 +28,7 @@ import javax.ws.rs.ext.RuntimeDelegate;
import org.jclouds.http.TransformingHttpCommand; import org.jclouds.http.TransformingHttpCommand;
import org.jclouds.http.TransformingHttpCommandImpl; import org.jclouds.http.TransformingHttpCommandImpl;
import org.jclouds.http.functions.config.ParserModule; import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.rest.RuntimeDelegateImpl; import org.jclouds.rest.internal.RuntimeDelegateImpl;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -38,7 +38,7 @@ import com.google.inject.assistedinject.FactoryProvider;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class JaxrsModule extends AbstractModule { public class RestModule extends AbstractModule {
private final static TypeLiteral<TransformingHttpCommand.Factory> httpCommandFactoryLiteral = new TypeLiteral<TransformingHttpCommand.Factory>() { private final static TypeLiteral<TransformingHttpCommand.Factory> httpCommandFactoryLiteral = new TypeLiteral<TransformingHttpCommand.Factory>() {
}; };

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest.binders; package org.jclouds.rest.decorators;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
@ -42,16 +42,16 @@ import com.google.gson.Gson;
* @author Adrian Cole * @author Adrian Cole
* @since 4.0 * @since 4.0
*/ */
public class JsonBinder implements MapEntityBinder { public class AddAsJsonEntity implements MapRequestDecorator {
@Inject @Inject
protected Gson gson; protected Gson gson;
public void addEntityToRequest(Map<String, String> postParams, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Map<String, String> postParams) {
addEntityToRequest((Object) postParams, request); return decorateRequest(request, (Object) postParams);
} }
public void addEntityToRequest(Object toBind, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object toBind) {
checkState(gson != null, "Program error: gson should have been injected at this point"); checkState(gson != null, "Program error: gson should have been injected at this point");
String json = gson.toJson(toBind); String json = gson.toJson(toBind);
request.setEntity(json); request.setEntity(json);
@ -59,6 +59,7 @@ public class JsonBinder implements MapEntityBinder {
Collections.singletonList(json.getBytes().length + "")); Collections.singletonList(json.getBytes().length + ""));
request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE, request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE,
Collections.singletonList(MediaType.APPLICATION_JSON)); Collections.singletonList(MediaType.APPLICATION_JSON));
return request;
} }
} }

View File

@ -21,25 +21,26 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest.binders; package org.jclouds.rest.decorators;
import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import javax.inject.Singleton;
/** /**
* Adds an entity to a request. * Adds an entity to a request.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class ToStringEntityBinder implements EntityBinder { public class AddAsStringEntity implements RequestDecorator {
public void addEntityToRequest(Object entity, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object entity) {
String stringEntity = entity.toString(); String stringEntity = entity.toString();
request.getHeaders().put(HttpHeaders.CONTENT_TYPE, "application/unknown"); if (request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE) == null)
request.getHeaders().put(HttpHeaders.CONTENT_TYPE, "application/unknown");
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, stringEntity.getBytes().length + ""); request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, stringEntity.getBytes().length + "");
request.setEntity(stringEntity); request.setEntity(stringEntity);
return request;
} }
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest.binders; package org.jclouds.rest.decorators;
import java.util.Map; import java.util.Map;
@ -33,13 +33,13 @@ import org.jclouds.http.HttpRequest;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public interface MapEntityBinder extends EntityBinder { public interface MapRequestDecorator extends RequestDecorator {
/** /**
* creates and binds the POST entity to the request using parameters specified. * creates and binds the POST entity to the request using parameters specified.
* *
* @see MapEntityParam * @see MapEntityParam
*/ */
public void addEntityToRequest(Map<String,String> postParams, HttpRequest request); public HttpRequest decorateRequest(HttpRequest request, Map<String, String> postParams);
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest.binders; package org.jclouds.rest.decorators;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
@ -30,6 +30,6 @@ import org.jclouds.http.HttpRequest;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface EntityBinder { public interface RequestDecorator {
public void addEntityToRequest(Object toBind, HttpRequest request); public HttpRequest decorateRequest(HttpRequest request, Object input);
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.internal;
import java.util.SortedSet; import java.util.SortedSet;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.internal;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.internal;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -33,7 +33,9 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URI; import java.net.URI;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -45,8 +47,11 @@ import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.HeaderParam; import javax.ws.rs.HeaderParam;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;
@ -65,9 +70,24 @@ import org.jclouds.http.functions.ReturnVoidIf2xx;
import org.jclouds.http.functions.ParseSax.HandlerWithResult; import org.jclouds.http.functions.ParseSax.HandlerWithResult;
import org.jclouds.http.options.HttpRequestOptions; import org.jclouds.http.options.HttpRequestOptions;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.binders.EntityBinder; import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.binders.HttpRequestOptionsBinder; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.binders.MapEntityBinder; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.HostPrefixParam;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.MapEntityParam;
import org.jclouds.rest.annotations.MatrixParams;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.decorators.MapRequestDecorator;
import org.jclouds.rest.decorators.RequestDecorator;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -89,17 +109,18 @@ import com.google.inject.internal.Lists;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class JaxrsAnnotationProcessor<T> { public class RestAnnotationProcessor<T> {
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final Class<T> declaring; private final Class<T> declaring;
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToEntityAnnotation = createMethodToIndexOfParamToAnnotation(EntityParam.class); private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToDecoratorParamAnnotation = createMethodToIndexOfParamToAnnotation(DecoratorParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToHeaderParamAnnotations = createMethodToIndexOfParamToAnnotation(HeaderParam.class); private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToHeaderParamAnnotations = createMethodToIndexOfParamToAnnotation(HeaderParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToHostPrefixParamAnnotations = createMethodToIndexOfParamToAnnotation(HostPrefixParam.class); private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToHostPrefixParamAnnotations = createMethodToIndexOfParamToAnnotation(HostPrefixParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToindexOfParamToEndpointAnnotations = createMethodToIndexOfParamToAnnotation(Endpoint.class); private final Map<Method, Map<Integer, Set<Annotation>>> methodToindexOfParamToEndpointAnnotations = createMethodToIndexOfParamToAnnotation(Endpoint.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToindexOfParamToMatrixParamAnnotations = createMethodToIndexOfParamToAnnotation(MatrixParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToindexOfParamToQueryParamAnnotations = createMethodToIndexOfParamToAnnotation(QueryParam.class); private final Map<Method, Map<Integer, Set<Annotation>>> methodToindexOfParamToQueryParamAnnotations = createMethodToIndexOfParamToAnnotation(QueryParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToindexOfParamToPathParamAnnotations = createMethodToIndexOfParamToAnnotation(PathParam.class); private final Map<Method, Map<Integer, Set<Annotation>>> methodToindexOfParamToPathParamAnnotations = createMethodToIndexOfParamToAnnotation(PathParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToindexOfParamToPostParamAnnotations = createMethodToIndexOfParamToAnnotation(MapEntityParam.class); private final Map<Method, Map<Integer, Set<Annotation>>> methodToindexOfParamToPostParamAnnotations = createMethodToIndexOfParamToAnnotation(MapEntityParam.class);
@ -172,8 +193,8 @@ public class JaxrsAnnotationProcessor<T> {
} else { } else {
transformer = injector.getInstance(getParserOrThrowException(method)); transformer = injector.getInstance(getParserOrThrowException(method));
} }
if (transformer instanceof RestContext) { if (transformer instanceof InvocationContext) {
((RestContext) transformer).setContext(request, args); ((InvocationContext) transformer).setContext(request, args);
} }
return transformer; return transformer;
} }
@ -189,16 +210,15 @@ public class JaxrsAnnotationProcessor<T> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Inject @Inject
public JaxrsAnnotationProcessor(Injector injector, ParseSax.Factory parserFactory, public RestAnnotationProcessor(Injector injector, ParseSax.Factory parserFactory,
TypeLiteral<T> typeLiteral) { TypeLiteral<T> typeLiteral) {
this.declaring = (Class<T>) typeLiteral.getRawType(); this.declaring = (Class<T>) typeLiteral.getRawType();
this.injector = injector; this.injector = injector;
this.parserFactory = parserFactory; this.parserFactory = parserFactory;
this.optionsBinder = injector.getInstance(HttpRequestOptionsBinder.class);
seedCache(declaring); seedCache(declaring);
} }
protected Method getDelegateOrNull(Method in) { public Method getDelegateOrNull(Method in) {
return delegationMap.get(new MethodKey(in)); return delegationMap.get(new MethodKey(in));
} }
@ -208,9 +228,10 @@ public class JaxrsAnnotationProcessor<T> {
for (Method method : methods) { for (Method method : methods) {
if (isHttpMethod(method)) { if (isHttpMethod(method)) {
for (int index = 0; index < method.getParameterTypes().length; index++) { for (int index = 0; index < method.getParameterTypes().length; index++) {
methodToIndexOfParamToEntityAnnotation.get(method).get(index); methodToIndexOfParamToDecoratorParamAnnotation.get(method).get(index);
methodToIndexOfParamToHeaderParamAnnotations.get(method).get(index); methodToIndexOfParamToHeaderParamAnnotations.get(method).get(index);
methodToIndexOfParamToHostPrefixParamAnnotations.get(method).get(index); methodToIndexOfParamToHostPrefixParamAnnotations.get(method).get(index);
methodToindexOfParamToMatrixParamAnnotations.get(method).get(index);
methodToindexOfParamToQueryParamAnnotations.get(method).get(index); methodToindexOfParamToQueryParamAnnotations.get(method).get(index);
methodToindexOfParamToEndpointAnnotations.get(method).get(index); methodToindexOfParamToEndpointAnnotations.get(method).get(index);
methodToindexOfParamToPathParamAnnotations.get(method).get(index); methodToindexOfParamToPathParamAnnotations.get(method).get(index);
@ -272,8 +293,6 @@ public class JaxrsAnnotationProcessor<T> {
final Injector injector; final Injector injector;
private HttpRequestOptionsBinder optionsBinder;
public HttpRequest createRequest(Method method, Object[] args) { public HttpRequest createRequest(Method method, Object[] args) {
URI endpoint = getEndpointFor(method, args); URI endpoint = getEndpointFor(method, args);
@ -283,68 +302,116 @@ public class JaxrsAnnotationProcessor<T> {
builder.path(declaring); builder.path(declaring);
builder.path(method); builder.path(method);
if (declaring.isAnnotationPresent(QueryParams.class)) { Multimap<String, String> tokenValues;
QueryParams query = declaring.getAnnotation(QueryParams.class); if (declaring.isAnnotationPresent(SkipEncoding.class)) {
addQuery(builder, query); tokenValues = encodeValues(getPathParamKeyValues(method, args), declaring.getAnnotation(
SkipEncoding.class).value());
} else {
tokenValues = encodeValues(getPathParamKeyValues(method, args));
} }
if (method.isAnnotationPresent(QueryParams.class)) { addQueryParams(method, args, builder, tokenValues.entries());
QueryParams query = method.getAnnotation(QueryParams.class); addMatrixParams(method, args, builder, tokenValues.entries());
addQuery(builder, query);
}
for (Entry<String, String> query : getQueryParamKeyValues(method, args).entrySet()) { Multimap<String, String> headers = buildHeaders(method, args, tokenValues.entries());
builder.queryParam(query.getKey(), query.getValue());
}
Multimap<String, String> headers = buildHeaders(method, args);
String stringEntity = null;
HttpRequestOptions options = findOptionsIn(method, args); HttpRequestOptions options = findOptionsIn(method, args);
if (options != null) { if (options != null) {
injector.injectMembers(options);// TODO test case injector.injectMembers(options);// TODO test case
headers.putAll(options.buildRequestHeaders()); for (Entry<String, String> header : options.buildRequestHeaders().entries()) {
headers.put(header.getKey(), replaceTokens(header.getValue(), tokenValues.entries()));
}
for (Entry<String, String> query : options.buildQueryParameters().entries()) { for (Entry<String, String> query : options.buildQueryParameters().entries()) {
builder.queryParam(query.getKey(), query.getValue()); builder.queryParam(query.getKey(), replaceTokens(query.getValue(), tokenValues
.entries()));
} }
for (Entry<String, String> matrix : options.buildMatrixParameters().entries()) { for (Entry<String, String> matrix : options.buildMatrixParameters().entries()) {
builder.matrixParam(matrix.getKey(), matrix.getValue()); builder.matrixParam(matrix.getKey(), replaceTokens(matrix.getValue(), tokenValues
.entries()));
} }
String pathSuffix = options.buildPathSuffix(); String pathSuffix = options.buildPathSuffix();
if (pathSuffix != null) { if (pathSuffix != null) {
builder.path(pathSuffix); builder.path(pathSuffix);
} }
stringEntity = options.buildStringEntity();
if (stringEntity != null) {
headers.put(HttpHeaders.CONTENT_LENGTH, stringEntity.getBytes().length + "");
}
} }
URI endPoint; URI endPoint;
try { try {
addHeaderIfAnnotationPresentOnMethod(headers, method, args); endPoint = builder.buildFromEncodedMap(convertUnsafe(tokenValues));
if (declaring.isAnnotationPresent(SkipEncoding.class)) {
endPoint = builder.buildFromEncodedMap(getEncodedPathParamKeyValues(method, args,
declaring.getAnnotation(SkipEncoding.class).value()));
} else {
endPoint = builder.buildFromEncodedMap(getEncodedPathParamKeyValues(method, args));
}
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} catch (UriBuilderException e) { } catch (UriBuilderException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(e);
} }
HttpRequest request = new HttpRequest(httpMethod, endPoint, headers); HttpRequest request = new HttpRequest(httpMethod, endPoint, headers);
addHostHeaderIfAnnotatedWithVirtualHost(headers, request.getEndpoint().getHost(), method); addHostHeaderIfAnnotatedWithVirtualHost(headers, request.getEndpoint().getHost(), method);
addFiltersIfAnnotated(method, request); addFiltersIfAnnotated(method, request);
if (stringEntity != null) {
buildEntityIfPostOrPutRequest(method, args, request); request.setEntity(stringEntity);
return request; if (headers.get(HttpHeaders.CONTENT_TYPE) != null)
headers.put(HttpHeaders.CONTENT_TYPE, "application/unknown");
}
return decorateRequest(method, args, request);
} }
private void addQuery(UriBuilder builder, QueryParams query) { private void addMatrixParams(Method method, Object[] args, UriBuilder builder,
Collection<Entry<String, String>> tokenValues) {
if (declaring.isAnnotationPresent(MatrixParams.class)) {
MatrixParams query = declaring.getAnnotation(MatrixParams.class);
addMatrix(builder, query, tokenValues);
}
if (method.isAnnotationPresent(MatrixParams.class)) {
MatrixParams query = method.getAnnotation(MatrixParams.class);
addMatrix(builder, query, tokenValues);
}
for (Entry<String, String> query : getMatrixParamKeyValues(method, args).entries()) {
builder.queryParam(query.getKey(), replaceTokens(query.getValue(), tokenValues));
}
}
private void addQueryParams(Method method, Object[] args, UriBuilder builder,
Collection<Entry<String, String>> tokenValues) {
if (declaring.isAnnotationPresent(QueryParams.class)) {
QueryParams query = declaring.getAnnotation(QueryParams.class);
addQuery(builder, query, tokenValues);
}
if (method.isAnnotationPresent(QueryParams.class)) {
QueryParams query = method.getAnnotation(QueryParams.class);
addQuery(builder, query, tokenValues);
}
for (Entry<String, String> query : getQueryParamKeyValues(method, args).entries()) {
builder.queryParam(query.getKey(), replaceTokens(query.getValue(), tokenValues));
}
}
private void addQuery(UriBuilder builder, QueryParams query,
Collection<Entry<String, String>> tokenValues) {
for (int i = 0; i < query.keys().length; i++) { for (int i = 0; i < query.keys().length; i++) {
if (query.values()[i].equals(QueryParams.NULL)) { if (query.values()[i].equals(QueryParams.NULL)) {
builder.replaceQuery(query.keys()[i]); builder.replaceQuery(query.keys()[i]);
} else { } else {
builder.queryParam(query.keys()[i], query.values()[i]); builder.queryParam(query.keys()[i], replaceTokens(query.values()[i], tokenValues));
}
}
}
private void addMatrix(UriBuilder builder, MatrixParams matrix,
Collection<Entry<String, String>> tokenValues) {
for (int i = 0; i < matrix.keys().length; i++) {
if (matrix.values()[i].equals(MatrixParams.NULL)) {
builder.replaceMatrix(matrix.keys()[i]);
} else {
builder.matrixParam(matrix.keys()[i], replaceTokens(matrix.values()[i], tokenValues));
} }
} }
} }
@ -461,27 +528,27 @@ public class JaxrsAnnotationProcessor<T> {
return null; return null;
} }
public MapEntityBinder getMapEntityBinderOrNull(Method method, Object[] args) { public MapRequestDecorator getMapEntityBinderOrNull(Method method, Object[] args) {
if (args != null) { if (args != null) {
for (Object arg : args) { for (Object arg : args) {
if (arg instanceof Object[]) { if (arg instanceof Object[]) {
Object[] postBinders = (Object[]) arg; Object[] postBinders = (Object[]) arg;
if (postBinders.length == 0) { if (postBinders.length == 0) {
} else if (postBinders.length == 1) { } else if (postBinders.length == 1) {
if (postBinders[0] instanceof MapEntityBinder) { if (postBinders[0] instanceof MapRequestDecorator) {
MapEntityBinder binder = (MapEntityBinder) postBinders[0]; MapRequestDecorator binder = (MapRequestDecorator) postBinders[0];
injector.injectMembers(binder); injector.injectMembers(binder);
return binder; return binder;
} }
} else { } else {
if (postBinders[0] instanceof MapEntityBinder) { if (postBinders[0] instanceof MapRequestDecorator) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"we currently do not support multiple varargs postBinders in: " "we currently do not support multiple varargs postBinders in: "
+ method.getName()); + method.getName());
} }
} }
} else if (arg instanceof MapEntityBinder) { } else if (arg instanceof MapRequestDecorator) {
MapEntityBinder binder = (MapEntityBinder) arg; MapRequestDecorator binder = (MapRequestDecorator) arg;
injector.injectMembers(binder); injector.injectMembers(binder);
return binder; return binder;
} }
@ -494,7 +561,7 @@ public class JaxrsAnnotationProcessor<T> {
return null; return null;
} }
private Map<String, String> constants = Maps.newHashMap(); private Multimap<String, String> constants = HashMultimap.create();
public boolean isHttpMethod(Method method) { public boolean isHttpMethod(Method method) {
return IsHttpMethod.getHttpMethods(method) != null; return IsHttpMethod.getHttpMethods(method) != null;
@ -528,49 +595,41 @@ public class JaxrsAnnotationProcessor<T> {
} }
} }
public HttpRequest buildEntityIfPostOrPutRequest(Method method, Object[] args, public HttpRequest decorateRequest(Method method, Object[] args, HttpRequest request) {
HttpRequest request) { MapRequestDecorator mapBinder = getMapEntityBinderOrNull(method, args);
OUTER: if (request.getMethod().toUpperCase().equals("POST") Map<String, String> mapParams = buildPostParams(method, args);
|| request.getMethod().toUpperCase().equals("PUT")) { // MapEntityBinder is only useful if there are parameters. We guard here in case the
MapEntityBinder mapBinder = getMapEntityBinderOrNull(method, args); // MapEntityBinder is also an EntityBinder. If so, it can be used with or without
Map<String, String> mapParams = buildPostParams(method, args); // parameters.
// MapEntityBinder is only useful if there are parameters. We guard here in case the if (mapBinder != null) {
// MapEntityBinder is also an EntityBinder. If so, it can be used with or without mapBinder.decorateRequest(request, mapParams);
// parameters. return request;
if (mapBinder != null) { }
mapBinder.addEntityToRequest(mapParams, request);
break OUTER;
}
HttpRequestOptions options = findOptionsIn(method, args);
if (options != null) {
optionsBinder.addEntityToRequest(options, request);
}
if (request.getEntity() == null) {
Map<Integer, Set<Annotation>> indexToEntityAnnotation = indexWithOnlyOneAnnotation( for (Entry<Integer, Set<Annotation>> entry : Maps.filterValues(
method, "@Entity", methodToIndexOfParamToEntityAnnotation); methodToIndexOfParamToDecoratorParamAnnotation.get(method),
new Predicate<Set<Annotation>>() {
if (indexToEntityAnnotation.size() == 1) { public boolean apply(Set<Annotation> input) {
Entry<Integer, Set<Annotation>> entry = indexToEntityAnnotation.entrySet() return input.size() >= 1;
.iterator().next(); }
EntityParam entityAnnotation = (EntityParam) entry.getValue().iterator().next(); }).entrySet()) {
DecoratorParam entityAnnotation = (DecoratorParam) entry.getValue().iterator().next();
EntityBinder binder = injector.getInstance(entityAnnotation.value()); RequestDecorator binder = injector.getInstance(entityAnnotation.value());
Object entity = args[entry.getKey()]; Object input = args[entry.getKey()];
if (entity.getClass().isArray()) { if (input.getClass().isArray()) {
Object[] entityArray = (Object[]) entity; Object[] entityArray = (Object[]) input;
entity = entityArray.length > 0 ? entityArray[0] : null; input = entityArray.length > 0 ? entityArray[0] : null;
}
if (entity != null)
binder.addEntityToRequest(entity, request);
} else if (indexToEntityAnnotation.size() > 1) {
throw new IllegalStateException("cannot have multiple @Entity annotations on "
+ method);
} else {
request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,
Lists.newArrayList("0"));
}
} }
Object oldEntity = request.getEntity();
request = binder.decorateRequest(request, input);
if (oldEntity != null && !oldEntity.equals(request.getEntity())) {
throw new IllegalStateException(String.format(
"binder %s replaced the previous entity on request: %s", binder, request));
}
}
if (request.getMethod().equals("PUT") && request.getEntity() == null) {
request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,
Collections.singletonList(0 + ""));
} }
return request; return request;
} }
@ -619,46 +678,85 @@ public class JaxrsAnnotationProcessor<T> {
return null; return null;
} }
public Multimap<String, String> buildHeaders(Method method, final Object[] args) { public Multimap<String, String> buildHeaders(Method method, final Object[] args,
Collection<Entry<String, String>> tokenValues) {
Multimap<String, String> headers = HashMultimap.create(); Multimap<String, String> headers = HashMultimap.create();
addHeaderIfAnnotationPresentOnMethod(headers, method, tokenValues);
Map<Integer, Set<Annotation>> indexToHeaderParam = methodToIndexOfParamToHeaderParamAnnotations Map<Integer, Set<Annotation>> indexToHeaderParam = methodToIndexOfParamToHeaderParamAnnotations
.get(method); .get(method);
for (Entry<Integer, Set<Annotation>> entry : indexToHeaderParam.entrySet()) { for (Entry<Integer, Set<Annotation>> entry : indexToHeaderParam.entrySet()) {
for (Annotation key : entry.getValue()) { for (Annotation key : entry.getValue()) {
headers.put(((HeaderParam) key).value(), args[entry.getKey()].toString()); String value = args[entry.getKey()].toString();
value = replaceTokens(value, tokenValues);
headers.put(((HeaderParam) key).value(), value);
} }
} }
addProducesIfPresentOnTypeOrMethod(headers, method);
addConsumesIfPresentOnTypeOrMethod(headers, method);
return headers; return headers;
} }
public void addHeaderIfAnnotationPresentOnMethod(Multimap<String, String> headers, void addConsumesIfPresentOnTypeOrMethod(Multimap<String, String> headers, Method method) {
Method method, Object[] args, char... skipEncode) throws UnsupportedEncodingException { if (declaring.isAnnotationPresent(Consumes.class)) {
if (declaring.isAnnotationPresent(Headers.class)) { Consumes header = declaring.getAnnotation(Consumes.class);
Headers header = declaring.getAnnotation(Headers.class); headers.replaceValues(HttpHeaders.ACCEPT, Arrays.asList(header.value()));
addHeader(headers, method, args, header);
} }
if (method.isAnnotationPresent(Headers.class)) { if (method.isAnnotationPresent(Consumes.class)) {
Headers header = method.getAnnotation(Headers.class); Consumes header = method.getAnnotation(Consumes.class);
addHeader(headers, method, args, header); headers.replaceValues(HttpHeaders.ACCEPT, Arrays.asList(header.value()));
} }
} }
private void addHeader(Multimap<String, String> headers, Method method, Object[] args, void addProducesIfPresentOnTypeOrMethod(Multimap<String, String> headers, Method method) {
Headers header) throws UnsupportedEncodingException { if (declaring.isAnnotationPresent(Produces.class)) {
Produces header = declaring.getAnnotation(Produces.class);
headers.replaceValues(HttpHeaders.CONTENT_TYPE, Arrays.asList(header.value()));
}
if (method.isAnnotationPresent(Produces.class)) {
Produces header = method.getAnnotation(Produces.class);
headers.replaceValues(HttpHeaders.CONTENT_TYPE, Arrays.asList(header.value()));
}
}
public void addHeaderIfAnnotationPresentOnMethod(Multimap<String, String> headers,
Method method, Collection<Entry<String, String>> tokenValues) {
if (declaring.isAnnotationPresent(Headers.class)) {
Headers header = declaring.getAnnotation(Headers.class);
addHeader(headers, header, tokenValues);
}
if (method.isAnnotationPresent(Headers.class)) {
Headers header = method.getAnnotation(Headers.class);
addHeader(headers, header, tokenValues);
}
}
private void addHeader(Multimap<String, String> headers, Headers header,
Collection<Entry<String, String>> tokenValues) {
for (int i = 0; i < header.keys().length; i++) { for (int i = 0; i < header.keys().length; i++) {
String value = header.values()[i]; String value = header.values()[i];
for (Entry<String, String> tokenValue : getEncodedPathParamKeyValues(method, args) value = replaceTokens(value, tokenValues);
.entrySet()) {
value = value.replaceAll("\\{" + tokenValue.getKey() + "\\}", tokenValue.getValue());
}
headers.put(header.keys()[i], value); headers.put(header.keys()[i], value);
} }
} }
private Map<String, String> getEncodedPathParamKeyValues(Method method, Object[] args, private String replaceTokens(String value, Collection<Entry<String, String>> tokenValues) {
final char... skipEncode) throws UnsupportedEncodingException { for (Entry<String, String> tokenValue : tokenValues) {
Map<String, String> pathParamValues = Maps.newHashMap(); value = value.replaceAll("\\{" + tokenValue.getKey() + "\\}", tokenValue.getValue());
}
return value;
}
private Map<String, String> convertUnsafe(Multimap<String, String> in) {
Map<String, String> out = Maps.newHashMap();
for (Entry<String, String> entry : in.entries()) {
out.put(entry.getKey(), entry.getValue());
}
return out;
}
private Multimap<String, String> getPathParamKeyValues(Method method, Object[] args) {
Multimap<String, String> pathParamValues = HashMultimap.create();
pathParamValues.putAll(constants); pathParamValues.putAll(constants);
Map<Integer, Set<Annotation>> indexToPathParam = methodToindexOfParamToPathParamAnnotations Map<Integer, Set<Annotation>> indexToPathParam = methodToindexOfParamToPathParamAnnotations
.get(method); .get(method);
@ -686,30 +784,50 @@ public class JaxrsAnnotationProcessor<T> {
String paramValue = injector.getInstance(method.getAnnotation(ParamParser.class).value()) String paramValue = injector.getInstance(method.getAnnotation(ParamParser.class).value())
.apply(args); .apply(args);
pathParamValues.put(paramKey, paramValue); pathParamValues.put(paramKey, paramValue);
}
return Maps.transformValues(pathParamValues, new Function<String, String>() { }
public String apply(String paramValue) { return pathParamValues;
try {
paramValue = URLEncoder.encode(paramValue, "UTF-8");
// Web browsers do not always handle '+' characters well, use the well-supported
// '%20' instead.
paramValue = paramValue.replaceAll("\\+", "%20");
for (char c : skipEncode) {
String value = Character.toString(c);
String encoded = URLEncoder.encode(value, "UTF-8");
paramValue = paramValue.replaceAll(encoded, value);
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("jclouds only supports UTF-8", e);
}
return paramValue;
}
});
} }
private Map<String, String> getQueryParamKeyValues(Method method, Object[] args) { private Multimap<String, String> encodeValues(Multimap<String, String> unencoded,
Map<String, String> queryParamValues = Maps.newHashMap(); final char... skipEncode) {
Multimap<String, String> encoded = HashMultimap.create();
for (Entry<String, String> entry : unencoded.entries()) {
try {
String value = URLEncoder.encode(entry.getValue(), "UTF-8");
// Web browsers do not always handle '+' characters well, use the well-supported
// '%20' instead.
value = value.replaceAll("\\+", "%20");
for (char c : skipEncode) {
String toSkip = Character.toString(c);
String encodedValueToSkip = URLEncoder.encode(toSkip, "UTF-8");
value = value.replaceAll(encodedValueToSkip, toSkip);
}
encoded.put(entry.getKey(), value);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("jclouds only supports UTF-8", e);
}
}
return encoded;
}
private Multimap<String, String> getMatrixParamKeyValues(Method method, Object[] args) {
Multimap<String, String> queryParamValues = HashMultimap.create();
queryParamValues.putAll(constants);
Map<Integer, Set<Annotation>> indexToMatrixParam = methodToindexOfParamToMatrixParamAnnotations
.get(method);
for (Entry<Integer, Set<Annotation>> entry : indexToMatrixParam.entrySet()) {
for (Annotation key : entry.getValue()) {
String paramKey = ((MatrixParam) key).value();
String paramValue = args[entry.getKey()].toString();
queryParamValues.put(paramKey, paramValue);
}
}
return queryParamValues;
}
private Multimap<String, String> getQueryParamKeyValues(Method method, Object[] args) {
Multimap<String, String> queryParamValues = HashMultimap.create();
queryParamValues.putAll(constants); queryParamValues.putAll(constants);
Map<Integer, Set<Annotation>> indexToQueryParam = methodToindexOfParamToQueryParamAnnotations Map<Integer, Set<Annotation>> indexToQueryParam = methodToindexOfParamToQueryParamAnnotations
.get(method); .get(method);

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.internal;
/** /**
* Generates RESTful clients from appropriately annotated interfaces. * Generates RESTful clients from appropriately annotated interfaces.
@ -46,13 +46,14 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.TransformingHttpCommand; import org.jclouds.http.TransformingHttpCommand;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.InvocationContext;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@Singleton @Singleton
public class RestClientProxy<T> implements InvocationHandler { public class RestClientProxy<T> implements InvocationHandler {
private final JaxrsAnnotationProcessor<T> util; private final RestAnnotationProcessor<T> util;
private final Class<T> declaring; private final Class<T> declaring;
private final TransformingHttpCommand.Factory commandFactory; private final TransformingHttpCommand.Factory commandFactory;
@ -69,7 +70,7 @@ public class RestClientProxy<T> implements InvocationHandler {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Inject @Inject
public RestClientProxy(TransformingHttpCommand.Factory factory, public RestClientProxy(TransformingHttpCommand.Factory factory,
JaxrsAnnotationProcessor<T> util, TypeLiteral<T> typeLiteral) { RestAnnotationProcessor<T> util, TypeLiteral<T> typeLiteral) {
this.util = util; this.util = util;
this.declaring = (Class<T>) typeLiteral.getRawType(); this.declaring = (Class<T>) typeLiteral.getRawType();
this.commandFactory = factory; this.commandFactory = factory;
@ -87,14 +88,14 @@ public class RestClientProxy<T> implements InvocationHandler {
Function<Exception, ?> exceptionParser = util Function<Exception, ?> exceptionParser = util
.createExceptionParserOrNullIfNotFound(method); .createExceptionParserOrNullIfNotFound(method);
// in case there is an exception creating the request, we should at least pass in args // in case there is an exception creating the request, we should at least pass in args
if (exceptionParser instanceof RestContext) { if (exceptionParser instanceof InvocationContext) {
((RestContext) exceptionParser).setContext(null, args); ((InvocationContext) exceptionParser).setContext(null, args);
} }
HttpRequest request; HttpRequest request;
try { try {
request = util.createRequest(method, args); request = util.createRequest(method, args);
if (exceptionParser instanceof RestContext) { if (exceptionParser instanceof InvocationContext) {
((RestContext) exceptionParser).setContext(request, args); ((InvocationContext) exceptionParser).setContext(request, args);
} }
} catch (RuntimeException e) { } catch (RuntimeException e) {
if (exceptionParser != null) { if (exceptionParser != null) {

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rest; package org.jclouds.rest.internal;
import javax.ws.rs.core.Application; import javax.ws.rs.core.Application;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;

View File

@ -41,7 +41,7 @@ import org.jclouds.cloud.ConfiguresCloudConnection;
import org.jclouds.cloud.internal.CloudContextImpl; import org.jclouds.cloud.internal.CloudContextImpl;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.rest.RestClientFactory; import org.jclouds.rest.RestClientFactory;
import org.jclouds.rest.JaxrsAnnotationProcessorTest.Localhost; import org.jclouds.rest.RestAnnotationProcessorTest.Localhost;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import org.mortbay.jetty.Handler; import org.mortbay.jetty.Handler;

View File

@ -33,17 +33,18 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.rest.binders.JsonBinder;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.options.HttpRequestOptions; import org.jclouds.http.options.HttpRequestOptions;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.RestAnnotationProcessorTest.Localhost;
import org.jclouds.rest.EntityParam; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.ExceptionParser; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.MapBinder; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.MapEntityParam; import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.MapEntityParam;
import org.jclouds.rest.XMLResponseParser; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.JaxrsAnnotationProcessorTest.Localhost; import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.decorators.AddAsJsonEntity;
import org.jclouds.rest.decorators.AddAsStringEntity;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -87,15 +88,15 @@ public interface IntegrationTestClient {
@PUT @PUT
@Path("objects/{id}") @Path("objects/{id}")
Future<String> upload(@PathParam("id") String id, @EntityParam String toPut); Future<String> upload(@PathParam("id") String id, @DecoratorParam(AddAsStringEntity.class) String toPut);
@POST @POST
@Path("objects/{id}") @Path("objects/{id}")
Future<String> post(@PathParam("id") String id, @EntityParam String toPut); Future<String> post(@PathParam("id") String id, @DecoratorParam(AddAsStringEntity.class) String toPut);
@POST @POST
@Path("objects/{id}") @Path("objects/{id}")
@MapBinder(JsonBinder.class) @MapBinder(AddAsJsonEntity.class)
Future<String> postJson(@PathParam("id") String id, @MapEntityParam("key") String toPut); Future<String> postJson(@PathParam("id") String id, @MapEntityParam("key") String toPut);
@GET @GET

View File

@ -43,6 +43,7 @@ import java.util.concurrent.Future;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Qualifier; import javax.inject.Qualifier;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam; import javax.ws.rs.HeaderParam;
import javax.ws.rs.HttpMethod; import javax.ws.rs.HttpMethod;
@ -50,7 +51,9 @@ import javax.ws.rs.POST;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.concurrent.WithinThreadExecutorService; import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.concurrent.config.ExecutorServiceModule;
@ -67,10 +70,25 @@ import org.jclouds.http.functions.ReturnVoidIf2xx;
import org.jclouds.http.options.BaseHttpRequestOptions; import org.jclouds.http.options.BaseHttpRequestOptions;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
import org.jclouds.http.options.HttpRequestOptions; import org.jclouds.http.options.HttpRequestOptions;
import org.jclouds.rest.binders.HttpRequestOptionsBinder; import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.binders.JsonBinder; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.binders.MapEntityBinder; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.config.JaxrsModule; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.HostPrefixParam;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.MapEntityParam;
import org.jclouds.rest.annotations.MatrixParams;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.decorators.AddAsJsonEntity;
import org.jclouds.rest.decorators.AddAsStringEntity;
import org.jclouds.rest.decorators.MapRequestDecorator;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.DateService; import org.jclouds.util.DateService;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -81,6 +99,7 @@ import org.testng.annotations.Test;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Guice; import com.google.inject.Guice;
@ -95,7 +114,7 @@ import com.google.inject.util.Types;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "jaxrs.JaxrsUtilTest") @Test(groups = "unit", testName = "jaxrs.JaxrsUtilTest")
public class JaxrsAnnotationProcessorTest { public class RestAnnotationProcessorTest {
@Target( { ElementType.METHOD }) @Target( { ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@javax.ws.rs.HttpMethod("FOO") @javax.ws.rs.HttpMethod("FOO")
@ -166,12 +185,11 @@ public class JaxrsAnnotationProcessorTest {
@Endpoint(Localhost.class) @Endpoint(Localhost.class)
public class TestEntityParamVarargs { public class TestEntityParamVarargs {
@POST @POST
public void varargs( public void varargs(HttpRequestOptions... options) {
@EntityParam(HttpRequestOptionsBinder.class) HttpRequestOptions... options) {
} }
@POST @POST
public void post(@EntityParam(HttpRequestOptionsBinder.class) HttpRequestOptions options) { public void post(HttpRequestOptions options) {
} }
} }
@ -293,22 +311,22 @@ public class JaxrsAnnotationProcessorTest {
@Endpoint(Localhost.class) @Endpoint(Localhost.class)
public class TestPost { public class TestPost {
@POST @POST
public void post(@EntityParam String content) { public void post(@DecoratorParam(AddAsStringEntity.class) String content) {
} }
@POST @POST
public void postAsJson(@EntityParam(JsonBinder.class) String content) { public void postAsJson(@DecoratorParam(AddAsJsonEntity.class) String content) {
} }
@POST @POST
@Path("{foo}") @Path("{foo}")
public void postWithPath(@PathParam("foo") @MapEntityParam("fooble") String path, public void postWithPath(@PathParam("foo") @MapEntityParam("fooble") String path,
MapEntityBinder content) { MapRequestDecorator content) {
} }
@POST @POST
@Path("{foo}") @Path("{foo}")
@MapBinder(JsonBinder.class) @MapBinder(AddAsJsonEntity.class)
public void postWithMethodBinder(@PathParam("foo") @MapEntityParam("fooble") String path) { public void postWithMethodBinder(@PathParam("foo") @MapEntityParam("fooble") String path) {
} }
} }
@ -344,14 +362,17 @@ public class JaxrsAnnotationProcessorTest {
} }
public void testCreatePostWithPathRequest() throws SecurityException, NoSuchMethodException { public void testCreatePostWithPathRequest() throws SecurityException, NoSuchMethodException {
Method method = TestPost.class.getMethod("postWithPath", String.class, MapEntityBinder.class); Method method = TestPost.class.getMethod("postWithPath", String.class,
MapRequestDecorator.class);
HttpRequest httpMethod = factory(TestPost.class).createRequest(method, HttpRequest httpMethod = factory(TestPost.class).createRequest(method,
new Object[] { "data", new MapEntityBinder() { new Object[] { "data", new MapRequestDecorator() {
public void addEntityToRequest(Map<String, String> postParams, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request,
Map<String, String> postParams) {
request.setEntity(postParams.get("fooble")); request.setEntity(postParams.get("fooble"));
return request;
} }
public void addEntityToRequest(Object toBind, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object toBind) {
throw new RuntimeException("this shouldn't be used in POST"); throw new RuntimeException("this shouldn't be used in POST");
} }
} }); } });
@ -382,9 +403,24 @@ public class JaxrsAnnotationProcessorTest {
public class TestPut { public class TestPut {
@PUT @PUT
@Path("{foo}") @Path("{foo}")
@MapBinder(JsonBinder.class) @MapBinder(AddAsJsonEntity.class)
public void putWithMethodBinder(@PathParam("foo") @MapEntityParam("fooble") String path) { public void putWithMethodBinder(@PathParam("foo") @MapEntityParam("fooble") String path) {
} }
@PUT
@Path("{foo}")
@Produces(MediaType.TEXT_PLAIN)
public void putWithMethodBinderProduces(
@PathParam("foo") @DecoratorParam(AddAsStringEntity.class) String path) {
}
@PUT
@Path("{foo}")
@MapBinder(AddAsJsonEntity.class)
@Consumes(MediaType.APPLICATION_JSON)
public void putWithMethodBinderConsumes(
@PathParam("foo") @MapEntityParam("fooble") String path) {
}
} }
public void testCreatePutWithMethodBinder() throws SecurityException, NoSuchMethodException { public void testCreatePutWithMethodBinder() throws SecurityException, NoSuchMethodException {
@ -402,6 +438,40 @@ public class JaxrsAnnotationProcessorTest {
.singletonList(expected.getBytes().length + "")); .singletonList(expected.getBytes().length + ""));
assertEquals(httpMethod.getEntity(), expected); assertEquals(httpMethod.getEntity(), expected);
} }
public void testCreatePutWithMethodProduces() throws SecurityException, NoSuchMethodException {
Method method = TestPut.class.getMethod("putWithMethodBinderProduces", String.class);
HttpRequest httpMethod = factory(TestPut.class).createRequest(method,
new Object[] { "data", });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/data");
assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 2);
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
.singletonList("text/plain"));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList("data".getBytes().length + ""));
assertEquals(httpMethod.getEntity(), "data");
}
public void testCreatePutWithMethodConsumes() throws SecurityException, NoSuchMethodException {
Method method = TestPut.class.getMethod("putWithMethodBinderConsumes", String.class);
HttpRequest httpMethod = factory(TestPut.class).createRequest(method,
new Object[] { "data", });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/data");
assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 3);
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
.singletonList("application/json"));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.ACCEPT), Collections
.singletonList("application/json"));
String expected = "{\"fooble\":\"data\"}";
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList(expected.getBytes().length + ""));
assertEquals(httpMethod.getEntity(), expected);
}
static class TestRequestFilter1 implements HttpRequestFilter { static class TestRequestFilter1 implements HttpRequestFilter {
public HttpRequest filter(HttpRequest request) throws HttpException { public HttpRequest filter(HttpRequest request) throws HttpException {
@ -578,9 +648,8 @@ public class JaxrsAnnotationProcessorTest {
public void testBuildTwoHeader() throws SecurityException, NoSuchMethodException, public void testBuildTwoHeader() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException { UnsupportedEncodingException {
Method oneHeader = TestHeader.class.getMethod("twoHeader", String.class); Method oneHeader = TestHeader.class.getMethod("twoHeader", String.class);
Multimap<String, String> headers = HashMultimap.create(); Multimap<String, String> headers = factory(TestHeader.class).createRequest(oneHeader,
factory(TestHeader.class).addHeaderIfAnnotationPresentOnMethod(headers, oneHeader, new Object[] { "robot" }).getHeaders();
new Object[] { "robot" });
assertEquals(headers.size(), 2); assertEquals(headers.size(), 2);
assertEquals(headers.get("slash"), Collections.singletonList("/robot")); assertEquals(headers.get("slash"), Collections.singletonList("/robot"));
assertEquals(headers.get("hyphen"), Collections.singletonList("-robot")); assertEquals(headers.get("hyphen"), Collections.singletonList("-robot"));
@ -598,9 +667,8 @@ public class JaxrsAnnotationProcessorTest {
public void testBuildOneClassHeader() throws SecurityException, NoSuchMethodException, public void testBuildOneClassHeader() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException { UnsupportedEncodingException {
Method oneHeader = TestClassHeader.class.getMethod("oneHeader", String.class); Method oneHeader = TestClassHeader.class.getMethod("oneHeader", String.class);
Multimap<String, String> headers = HashMultimap.create(); Multimap<String, String> headers = factory(TestClassHeader.class).createRequest(oneHeader,
factory(TestClassHeader.class).addHeaderIfAnnotationPresentOnMethod(headers, oneHeader, new Object[] { "robot" }).getHeaders();
new Object[] { "robot" });
assertEquals(headers.size(), 1); assertEquals(headers.size(), 1);
assertEquals(headers.get("x-amz-copy-source"), Collections.singletonList("/robot")); assertEquals(headers.get("x-amz-copy-source"), Collections.singletonList("/robot"));
} }
@ -609,9 +677,8 @@ public class JaxrsAnnotationProcessorTest {
public void testBuildOneHeader() throws SecurityException, NoSuchMethodException, public void testBuildOneHeader() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException { UnsupportedEncodingException {
Method oneHeader = TestHeader.class.getMethod("oneHeader", String.class); Method oneHeader = TestHeader.class.getMethod("oneHeader", String.class);
Multimap<String, String> headers = HashMultimap.create(); Multimap<String, String> headers = factory(TestHeader.class).createRequest(oneHeader,
factory(TestHeader.class).addHeaderIfAnnotationPresentOnMethod(headers, oneHeader, new Object[] { "robot" }).getHeaders();
new Object[] { "robot" });
assertEquals(headers.size(), 1); assertEquals(headers.size(), 1);
assertEquals(headers.get("x-amz-copy-source"), Collections.singletonList("/robot")); assertEquals(headers.get("x-amz-copy-source"), Collections.singletonList("/robot"));
} }
@ -620,9 +687,8 @@ public class JaxrsAnnotationProcessorTest {
public void testBuildTwoHeaders() throws SecurityException, NoSuchMethodException, public void testBuildTwoHeaders() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException { UnsupportedEncodingException {
Method twoHeaders = TestHeader.class.getMethod("twoHeaders", String.class, String.class); Method twoHeaders = TestHeader.class.getMethod("twoHeaders", String.class, String.class);
Multimap<String, String> headers = HashMultimap.create(); Multimap<String, String> headers = factory(TestHeader.class).createRequest(twoHeaders,
factory(TestHeader.class).addHeaderIfAnnotationPresentOnMethod(headers, twoHeaders, new Object[] { "robot", "eggs" }).getHeaders();
new Object[] { "robot", "eggs" });
assertEquals(headers.size(), 1); assertEquals(headers.size(), 1);
assertEquals(headers.get("x-amz-copy-source"), Collections.singletonList("/robot/eggs")); assertEquals(headers.get("x-amz-copy-source"), Collections.singletonList("/robot/eggs"));
} }
@ -632,13 +698,213 @@ public class JaxrsAnnotationProcessorTest {
UnsupportedEncodingException { UnsupportedEncodingException {
Method twoHeadersOutOfOrder = TestHeader.class.getMethod("twoHeadersOutOfOrder", Method twoHeadersOutOfOrder = TestHeader.class.getMethod("twoHeadersOutOfOrder",
String.class, String.class); String.class, String.class);
Multimap<String, String> headers = HashMultimap.create(); Multimap<String, String> headers = factory(TestHeader.class).createRequest(
factory(TestHeader.class).addHeaderIfAnnotationPresentOnMethod(headers, twoHeadersOutOfOrder, twoHeadersOutOfOrder, new Object[] { "robot", "eggs" }).getHeaders();
new Object[] { "robot", "eggs" });
assertEquals(headers.size(), 1); assertEquals(headers.size(), 1);
assertEquals(headers.get("x-amz-copy-source"), Collections.singletonList("/eggs/robot")); assertEquals(headers.get("x-amz-copy-source"), Collections.singletonList("/eggs/robot"));
} }
public class TestReplaceQueryOptions extends BaseHttpRequestOptions {
public TestReplaceQueryOptions() {
this.queryParameters.put("x-amz-copy-source", "/{bucket}");
}
}
@Test
public void testQueryInOptions() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Method oneQuery = TestQueryReplace.class.getMethod("queryInOptions", String.class,
TestReplaceQueryOptions.class);
String query = factory(TestQueryReplace.class).createRequest(oneQuery,
new Object[] { "robot", new TestReplaceQueryOptions() }).getEndpoint().getQuery();
assertEquals(query, "x-amz-copy-source=/robot");
}
@Endpoint(Localhost.class)
public class TestQueryReplace {
@GET
public void queryInOptions(@PathParam("bucket") String path, TestReplaceQueryOptions options) {
}
@GET
@QueryParams(keys = "x-amz-copy-source", values = "/{bucket}")
public void oneQuery(@PathParam("bucket") String path) {
}
@GET
@QueryParams(keys = { "slash", "hyphen" }, values = { "/{bucket}", "-{bucket}" })
public void twoQuery(@PathParam("bucket") String path) {
}
@GET
@QueryParams(keys = "x-amz-copy-source", values = "/{bucket}/{key}")
public void twoQuerys(@PathParam("bucket") String path, @PathParam("key") String path2) {
}
@GET
@QueryParams(keys = "x-amz-copy-source", values = "/{bucket}/{key}")
public void twoQuerysOutOfOrder(@PathParam("key") String path,
@PathParam("bucket") String path2) {
}
}
@Test
public void testBuildTwoQuery() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Method oneQuery = TestQueryReplace.class.getMethod("twoQuery", String.class);
String query = factory(TestQueryReplace.class).createRequest(oneQuery,
new Object[] { "robot" }).getEndpoint().getQuery();
assertEquals(query, "slash=/robot&hyphen=-robot");
}
@QueryParams(keys = "x-amz-copy-source", values = "/{bucket}")
@Endpoint(Localhost.class)
public class TestClassQuery {
@GET
public void oneQuery(@PathParam("bucket") String path) {
}
}
@Test
public void testBuildOneClassQuery() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Method oneQuery = TestClassQuery.class.getMethod("oneQuery", String.class);
String query = factory(TestClassQuery.class)
.createRequest(oneQuery, new Object[] { "robot" }).getEndpoint().getQuery();
assertEquals(query, "x-amz-copy-source=/robot");
}
@Test
public void testBuildOneQuery() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Method oneQuery = TestQueryReplace.class.getMethod("oneQuery", String.class);
String query = factory(TestQueryReplace.class).createRequest(oneQuery,
new Object[] { "robot" }).getEndpoint().getQuery();
assertEquals(query, "x-amz-copy-source=/robot");
}
@Test
public void testBuildTwoQuerys() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Method twoQuerys = TestQueryReplace.class.getMethod("twoQuerys", String.class, String.class);
String query = factory(TestQueryReplace.class).createRequest(twoQuerys,
new Object[] { "robot", "eggs" }).getEndpoint().getQuery();
assertEquals(query, "x-amz-copy-source=/robot/eggs");
}
@Test
public void testBuildTwoQuerysOutOfOrder() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Method twoQuerysOutOfOrder = TestQueryReplace.class.getMethod("twoQuerysOutOfOrder",
String.class, String.class);
String query = factory(TestQueryReplace.class).createRequest(twoQuerysOutOfOrder,
new Object[] { "robot", "eggs" }).getEndpoint().getQuery();
assertEquals(query, "x-amz-copy-source=/eggs/robot");
}
public class TestReplaceMatrixOptions extends BaseHttpRequestOptions {
public TestReplaceMatrixOptions() {
this.matrixParameters.put("x-amz-copy-source", "/{bucket}");
}
}
@Test
public void testMatrixInOptions() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Method oneMatrix = TestMatrixReplace.class.getMethod("matrixInOptions", String.class,
TestReplaceMatrixOptions.class);
String path = factory(TestMatrixReplace.class).createRequest(oneMatrix,
new Object[] { "robot", new TestReplaceMatrixOptions() }).getEndpoint().getPath();
assertEquals(path, "/;x-amz-copy-source=/robot");
}
@Endpoint(Localhost.class)
@Path("/")
public class TestMatrixReplace {
@GET
public void matrixInOptions(@PathParam("bucket") String path, TestReplaceMatrixOptions options) {
}
@GET
@MatrixParams(keys = "x-amz-copy-source", values = "/{bucket}")
public void oneMatrix(@PathParam("bucket") String path) {
}
@GET
@MatrixParams(keys = { "slash", "hyphen" }, values = { "/{bucket}", "-{bucket}" })
public void twoMatrix(@PathParam("bucket") String path) {
}
@GET
@MatrixParams(keys = "x-amz-copy-source", values = "/{bucket}/{key}")
public void twoMatrixs(@PathParam("bucket") String path, @PathParam("key") String path2) {
}
@GET
@MatrixParams(keys = "x-amz-copy-source", values = "/{bucket}/{key}")
public void twoMatrixsOutOfOrder(@PathParam("key") String path,
@PathParam("bucket") String path2) {
}
}
@Test
public void testBuildTwoMatrix() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Method oneMatrix = TestMatrixReplace.class.getMethod("twoMatrix", String.class);
String path = factory(TestMatrixReplace.class).createRequest(oneMatrix,
new Object[] { "robot" }).getEndpoint().getPath();
assertEquals(path, "/;slash=/robot;hyphen=-robot");
}
@MatrixParams(keys = "x-amz-copy-source", values = "/{bucket}")
@Endpoint(Localhost.class)
@Path("/")
public class TestClassMatrix {
@GET
public void oneMatrix(@PathParam("bucket") String path) {
}
}
@Test
public void testBuildOneClassMatrix() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Method oneMatrix = TestClassMatrix.class.getMethod("oneMatrix", String.class);
String path = factory(TestClassMatrix.class).createRequest(oneMatrix,
new Object[] { "robot" }).getEndpoint().getPath();
assertEquals(path, "/;x-amz-copy-source=/robot");
}
@Test
public void testBuildOneMatrix() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Method oneMatrix = TestMatrixReplace.class.getMethod("oneMatrix", String.class);
String path = factory(TestMatrixReplace.class).createRequest(oneMatrix,
new Object[] { "robot" }).getEndpoint().getPath();
assertEquals(path, "/;x-amz-copy-source=/robot");
}
@Test
public void testBuildTwoMatrixs() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Method twoMatrixs = TestMatrixReplace.class.getMethod("twoMatrixs", String.class,
String.class);
String path = factory(TestMatrixReplace.class).createRequest(twoMatrixs,
new Object[] { "robot", "eggs" }).getEndpoint().getPath();
assertEquals(path, "/;x-amz-copy-source=/robot/eggs");
}
@Test
public void testBuildTwoMatrixsOutOfOrder() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Method twoMatrixsOutOfOrder = TestMatrixReplace.class.getMethod("twoMatrixsOutOfOrder",
String.class, String.class);
String path = factory(TestMatrixReplace.class).createRequest(twoMatrixsOutOfOrder,
new Object[] { "robot", "eggs" }).getEndpoint().getPath();
assertEquals(path, "/;x-amz-copy-source=/eggs/robot");
}
@Endpoint(Localhost.class) @Endpoint(Localhost.class)
public interface TestTransformers { public interface TestTransformers {
@GET @GET
@ -697,7 +963,7 @@ public class JaxrsAnnotationProcessorTest {
assertEquals(transformer, ParseURIList.class); assertEquals(transformer, ParseURIList.class);
} }
public static class ReturnStringIf200Context extends ReturnStringIf200 implements RestContext { public static class ReturnStringIf200Context extends ReturnStringIf200 implements InvocationContext {
private Object[] args; private Object[] args;
private HttpRequest request; private HttpRequest request;
@ -783,7 +1049,7 @@ public class JaxrsAnnotationProcessorTest {
@PUT @PUT
@Path("/{id}") @Path("/{id}")
public Future<String> put(@PathParam("id") @ParamParser(FirstCharacter.class) String id, public Future<String> put(@PathParam("id") @ParamParser(FirstCharacter.class) String id,
@EntityParam String payload) { @DecoratorParam(AddAsStringEntity.class) String payload) {
return null; return null;
} }
@ -798,7 +1064,8 @@ public class JaxrsAnnotationProcessorTest {
@Path("/{id}") @Path("/{id}")
@Headers(keys = "foo", values = "--{id}--") @Headers(keys = "foo", values = "--{id}--")
@ResponseParser(ReturnTrueIf2xx.class) @ResponseParser(ReturnTrueIf2xx.class)
public Future<String> putHeader(@PathParam("id") String id, @EntityParam String payload) { public Future<String> putHeader(@PathParam("id") String id,
@DecoratorParam(AddAsStringEntity.class) String payload) {
return null; return null;
} }
} }
@ -1080,7 +1347,7 @@ public class JaxrsAnnotationProcessorTest {
public void testOneHeader() throws SecurityException, NoSuchMethodException { public void testOneHeader() throws SecurityException, NoSuchMethodException {
Method method = TestHeaders.class.getMethod("oneHeader", String.class); Method method = TestHeaders.class.getMethod("oneHeader", String.class);
Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(method, Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(method,
new Object[] { "robot" }); new Object[] { "robot" }, ImmutableMultimap.<String, String> of().entries());
assertEquals(headers.size(), 1); assertEquals(headers.size(), 1);
assertEquals(headers.get("header"), Collections.singletonList("robot")); assertEquals(headers.get("header"), Collections.singletonList("robot"));
} }
@ -1089,7 +1356,7 @@ public class JaxrsAnnotationProcessorTest {
public void testOneIntHeader() throws SecurityException, NoSuchMethodException { public void testOneIntHeader() throws SecurityException, NoSuchMethodException {
Method method = TestHeaders.class.getMethod("oneIntHeader", int.class); Method method = TestHeaders.class.getMethod("oneIntHeader", int.class);
Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(method, Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(method,
new Object[] { 1 }); new Object[] { 1 }, ImmutableMultimap.<String, String> of().entries());
assertEquals(headers.size(), 1); assertEquals(headers.size(), 1);
assertEquals(headers.get("header"), Collections.singletonList("1")); assertEquals(headers.get("header"), Collections.singletonList("1"));
} }
@ -1099,7 +1366,7 @@ public class JaxrsAnnotationProcessorTest {
Method method = TestHeaders.class Method method = TestHeaders.class
.getMethod("twoDifferentHeaders", String.class, String.class); .getMethod("twoDifferentHeaders", String.class, String.class);
Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(method, Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(method,
new Object[] { "robot", "egg" }); new Object[] { "robot", "egg" }, ImmutableMultimap.<String, String> of().entries());
assertEquals(headers.size(), 2); assertEquals(headers.size(), 2);
assertEquals(headers.get("header1"), Collections.singletonList("robot")); assertEquals(headers.get("header1"), Collections.singletonList("robot"));
assertEquals(headers.get("header2"), Collections.singletonList("egg")); assertEquals(headers.get("header2"), Collections.singletonList("egg"));
@ -1109,7 +1376,7 @@ public class JaxrsAnnotationProcessorTest {
public void testTwoSameHeaders() throws SecurityException, NoSuchMethodException { public void testTwoSameHeaders() throws SecurityException, NoSuchMethodException {
Method method = TestHeaders.class.getMethod("twoSameHeaders", String.class, String.class); Method method = TestHeaders.class.getMethod("twoSameHeaders", String.class, String.class);
Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(method, Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(method,
new Object[] { "robot", "egg" }); new Object[] { "robot", "egg" }, ImmutableMultimap.<String, String> of().entries());
assertEquals(headers.size(), 2); assertEquals(headers.size(), 2);
Collection<String> values = headers.get("header"); Collection<String> values = headers.get("header");
assert values.contains("robot"); assert values.contains("robot");
@ -1119,22 +1386,23 @@ public class JaxrsAnnotationProcessorTest {
@Endpoint(Localhost.class) @Endpoint(Localhost.class)
public interface TestEntity { public interface TestEntity {
@PUT @PUT
public void put(@EntityParam String content); public void put(@DecoratorParam(AddAsStringEntity.class) String content);
@PUT @PUT
@Path("{foo}") @Path("{foo}")
public Future<Void> putWithPath(@PathParam("foo") String path, @EntityParam String content); public Future<Void> putWithPath(@PathParam("foo") String path,
@DecoratorParam(AddAsStringEntity.class) String content);
@PUT @PUT
public void twoEntities(@EntityParam String entity1, @EntityParam String entity2); public void twoEntities(@DecoratorParam(AddAsStringEntity.class) String entity1,
@DecoratorParam(AddAsStringEntity.class) String entity2);
} }
@Test @Test
public void testPut() throws SecurityException, NoSuchMethodException { public void testPut() throws SecurityException, NoSuchMethodException {
Method method = TestEntity.class.getMethod("put", String.class); Method method = TestEntity.class.getMethod("put", String.class);
HttpRequest request = new HttpRequest(HttpMethod.PUT, URI.create("http://localhost:8080")); HttpRequest request = new HttpRequest(HttpMethod.PUT, URI.create("http://localhost:8080"));
factory(TestEntity.class).buildEntityIfPostOrPutRequest(method, new Object[] { "test" }, factory(TestEntity.class).decorateRequest(method, new Object[] { "test" }, request);
request);
assertEquals(request.getEntity(), "test"); assertEquals(request.getEntity(), "test");
assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
.singletonList("application/unknown")); .singletonList("application/unknown"));
@ -1149,8 +1417,7 @@ public class JaxrsAnnotationProcessorTest {
public void putWithPath() throws SecurityException, NoSuchMethodException { public void putWithPath() throws SecurityException, NoSuchMethodException {
Method method = TestEntity.class.getMethod("putWithPath", String.class, String.class); Method method = TestEntity.class.getMethod("putWithPath", String.class, String.class);
HttpRequest request = new HttpRequest(HttpMethod.PUT, URI.create("http://localhost:8080")); HttpRequest request = new HttpRequest(HttpMethod.PUT, URI.create("http://localhost:8080"));
factory(TestEntity.class).buildEntityIfPostOrPutRequest(method, factory(TestEntity.class).decorateRequest(method, new Object[] { "rabble", "test" }, request);
new Object[] { "rabble", "test" }, request);
assertEquals(request.getEntity(), "test"); assertEquals(request.getEntity(), "test");
assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
.singletonList("application/unknown")); .singletonList("application/unknown"));
@ -1162,14 +1429,14 @@ public class JaxrsAnnotationProcessorTest {
public void testPutTwoEntities() throws SecurityException, NoSuchMethodException { public void testPutTwoEntities() throws SecurityException, NoSuchMethodException {
Method method = TestEntity.class.getMethod("twoEntities", String.class, String.class); Method method = TestEntity.class.getMethod("twoEntities", String.class, String.class);
HttpRequest request = new HttpRequest(HttpMethod.PUT, URI.create("http://localhost:8080")); HttpRequest request = new HttpRequest(HttpMethod.PUT, URI.create("http://localhost:8080"));
factory(TestEntity.class).buildEntityIfPostOrPutRequest(method, factory(TestEntity.class)
new Object[] { "test", "ralphie" }, request); .decorateRequest(method, new Object[] { "test", "ralphie" }, request);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T> JaxrsAnnotationProcessor<T> factory(Class<T> clazz) { private <T> RestAnnotationProcessor<T> factory(Class<T> clazz) {
return ((JaxrsAnnotationProcessor<T>) injector.getInstance(Key.get(TypeLiteral.get(Types return ((RestAnnotationProcessor<T>) injector.getInstance(Key.get(TypeLiteral.get(Types
.newParameterizedType(JaxrsAnnotationProcessor.class, clazz))))); .newParameterizedType(RestAnnotationProcessor.class, clazz)))));
} }
Injector injector; Injector injector;
@ -1186,7 +1453,7 @@ public class JaxrsAnnotationProcessorTest {
bind(URI.class).annotatedWith(Localhost2.class).toInstance( bind(URI.class).annotatedWith(Localhost2.class).toInstance(
URI.create("http://localhost:8081")); URI.create("http://localhost:8081"));
} }
}, new JaxrsModule(), new ExecutorServiceModule(new WithinThreadExecutorService()), }, new RestModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule()); new JavaUrlHttpCommandExecutorServiceModule());
} }

View File

@ -85,7 +85,7 @@ public class NioHttpCommandExecutionHandler implements NHttpRequestExecutionHand
if (rendezvous != null) { if (rendezvous != null) {
HttpRequest request = rendezvous.getCommand().getRequest(); HttpRequest request = rendezvous.getCommand().getRequest();
for (HttpRequestFilter filter : request.getFilters()) { for (HttpRequestFilter filter : request.getFilters()) {
filter.filter(request); request = filter.filter(request);
} }
return NioHttpUtils.convertToApacheRequest(request); return NioHttpUtils.convertToApacheRequest(request);
} }

View File

@ -38,8 +38,8 @@ import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
import org.jclouds.mezeo.pcs2.binders.BlockBinder; import org.jclouds.mezeo.pcs2.decorators.AddDataAndLength;
import org.jclouds.mezeo.pcs2.binders.CreateContainerBinder; import org.jclouds.mezeo.pcs2.decorators.AddContainerNameAsXmlEntity;
import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; import org.jclouds.mezeo.pcs2.domain.ContainerMetadata;
import org.jclouds.mezeo.pcs2.domain.FileMetadata; import org.jclouds.mezeo.pcs2.domain.FileMetadata;
import org.jclouds.mezeo.pcs2.domain.PCSFile; import org.jclouds.mezeo.pcs2.domain.PCSFile;
@ -57,15 +57,15 @@ import org.jclouds.mezeo.pcs2.functions.ReturnTrueIfContainerAlreadyExists;
import org.jclouds.mezeo.pcs2.xml.CachingFileListToContainerMetadataListHandler; import org.jclouds.mezeo.pcs2.xml.CachingFileListToContainerMetadataListHandler;
import org.jclouds.mezeo.pcs2.xml.FileListToFileMetadataListHandler; import org.jclouds.mezeo.pcs2.xml.FileListToFileMetadataListHandler;
import org.jclouds.mezeo.pcs2.xml.FileMetadataHandler; import org.jclouds.mezeo.pcs2.xml.FileMetadataHandler;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.EntityParam; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.ParamParser; import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
/** /**
* Provides access to Mezeo PCS v2 via their REST API. * Provides access to Mezeo PCS v2 via their REST API.
@ -98,7 +98,7 @@ public interface PCSBlobStore extends BlobStore<ContainerMetadata, FileMetadata,
@Path("/contents") @Path("/contents")
@Endpoint(RootContainer.class) @Endpoint(RootContainer.class)
@ExceptionParser(ReturnTrueIfContainerAlreadyExists.class) @ExceptionParser(ReturnTrueIfContainerAlreadyExists.class)
Future<Boolean> createContainer(@EntityParam(CreateContainerBinder.class) String container); Future<Boolean> createContainer(@DecoratorParam(AddContainerNameAsXmlEntity.class) String container);
@DELETE @DELETE
@ExceptionParser(ReturnVoidOnNotFoundOr404.class) @ExceptionParser(ReturnVoidOnNotFoundOr404.class)
@ -124,7 +124,7 @@ public interface PCSBlobStore extends BlobStore<ContainerMetadata, FileMetadata,
@PathParam("fileResourceId") @PathParam("fileResourceId")
@ParamParser(CreateSubFolderIfNotExistsAndNewFileResource.class) @ParamParser(CreateSubFolderIfNotExistsAndNewFileResource.class)
Future<byte[]> putBlob(String containerName, Future<byte[]> putBlob(String containerName,
@EntityParam(BlockBinder.class) PCSFile object); @DecoratorParam(AddDataAndLength.class) PCSFile object);
// @POST // @POST
// @Path("/containers/{containerResourceId}/contents") // @Path("/containers/{containerResourceId}/contents")
@ -133,7 +133,7 @@ public interface PCSBlobStore extends BlobStore<ContainerMetadata, FileMetadata,
// @PathParam("containerResourceId") // @PathParam("containerResourceId")
// @ParamParser(CreateSubFolderIfNotExistsAndGetResourceId.class) // @ParamParser(CreateSubFolderIfNotExistsAndGetResourceId.class)
// Future<byte[]> putBlob(String containerName, // Future<byte[]> putBlob(String containerName,
// @EntityParam(PCSFileAsMultipartFormBinder.class) PCSFile object); // @EntityParam(BlobAsMultipartFormBinder.class) PCSFile object);
@DELETE @DELETE
@ExceptionParser(ReturnVoidOnNotFoundOr404.class) @ExceptionParser(ReturnVoidOnNotFoundOr404.class)

View File

@ -37,9 +37,9 @@ import org.jclouds.mezeo.pcs2.endpoints.RootContainer;
import org.jclouds.mezeo.pcs2.endpoints.Shares; import org.jclouds.mezeo.pcs2.endpoints.Shares;
import org.jclouds.mezeo.pcs2.endpoints.Tags; import org.jclouds.mezeo.pcs2.endpoints.Tags;
import org.jclouds.mezeo.pcs2.xml.CloudXlinkHandler; import org.jclouds.mezeo.pcs2.xml.CloudXlinkHandler;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
/** /**
* Provides URIs to PCS services via their REST API. * Provides URIs to PCS services via their REST API.

View File

@ -34,13 +34,13 @@ import javax.ws.rs.POST;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import org.jclouds.blobstore.decorators.AddBlobEntityAsMultipartForm;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.mezeo.pcs2.binders.BlockBinder; import org.jclouds.mezeo.pcs2.decorators.AddDataAndLength;
import org.jclouds.mezeo.pcs2.binders.CreateContainerBinder; import org.jclouds.mezeo.pcs2.decorators.AddContainerNameAsXmlEntity;
import org.jclouds.mezeo.pcs2.binders.CreateFileBinder; import org.jclouds.mezeo.pcs2.decorators.AddFileInfoAsXmlEntity;
import org.jclouds.mezeo.pcs2.binders.PCSFileAsMultipartFormBinder;
import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; import org.jclouds.mezeo.pcs2.domain.ContainerMetadata;
import org.jclouds.mezeo.pcs2.domain.FileMetadata; import org.jclouds.mezeo.pcs2.domain.FileMetadata;
import org.jclouds.mezeo.pcs2.domain.PCSFile; import org.jclouds.mezeo.pcs2.domain.PCSFile;
@ -48,13 +48,13 @@ import org.jclouds.mezeo.pcs2.endpoints.RootContainer;
import org.jclouds.mezeo.pcs2.options.PutBlockOptions; import org.jclouds.mezeo.pcs2.options.PutBlockOptions;
import org.jclouds.mezeo.pcs2.xml.FileListToContainerMetadataListHandler; import org.jclouds.mezeo.pcs2.xml.FileListToContainerMetadataListHandler;
import org.jclouds.mezeo.pcs2.xml.FileListToFileMetadataListHandler; import org.jclouds.mezeo.pcs2.xml.FileListToFileMetadataListHandler;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.EntityParam; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
/** /**
* Provides access to Mezeo PCS v2 via their REST API. * Provides access to Mezeo PCS v2 via their REST API.
@ -79,12 +79,12 @@ public interface PCSConnection {
@POST @POST
@Path("/contents") @Path("/contents")
@Endpoint(RootContainer.class) @Endpoint(RootContainer.class)
Future<URI> createContainer(@EntityParam(CreateContainerBinder.class) String container); Future<URI> createContainer(@DecoratorParam(AddContainerNameAsXmlEntity.class) String container);
@POST @POST
@Path("/contents") @Path("/contents")
Future<URI> createContainer(@Endpoint URI parent, Future<URI> createContainer(@Endpoint URI parent,
@EntityParam(CreateContainerBinder.class) String container); @DecoratorParam(AddContainerNameAsXmlEntity.class) String container);
@DELETE @DELETE
@ExceptionParser(ReturnVoidOnNotFoundOr404.class) @ExceptionParser(ReturnVoidOnNotFoundOr404.class)
@ -105,17 +105,17 @@ public interface PCSConnection {
@POST @POST
@Path("/contents") @Path("/contents")
Future<URI> uploadFile(@Endpoint URI container, Future<URI> uploadFile(@Endpoint URI container,
@EntityParam(PCSFileAsMultipartFormBinder.class) PCSFile object); @DecoratorParam(AddBlobEntityAsMultipartForm.class) PCSFile object);
@POST @POST
@Path("/contents") @Path("/contents")
Future<URI> createFile(@Endpoint URI container, Future<URI> createFile(@Endpoint URI container,
@EntityParam(CreateFileBinder.class) PCSFile object); @DecoratorParam(AddFileInfoAsXmlEntity.class) PCSFile object);
@PUT @PUT
@Path("/content") @Path("/content")
Future<Void> uploadBlock(@Endpoint URI file, Future<Void> uploadBlock(@Endpoint URI file,
@EntityParam(BlockBinder.class) PCSFile object, PutBlockOptions ... options); @DecoratorParam(AddDataAndLength.class) PCSFile object, PutBlockOptions ... options);
@DELETE @DELETE
@ExceptionParser(ReturnVoidOnNotFoundOr404.class) @ExceptionParser(ReturnVoidOnNotFoundOr404.class)

View File

@ -33,11 +33,12 @@ import javax.ws.rs.PathParam;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.mezeo.pcs2.functions.AddEntryIntoMultiMap; import org.jclouds.mezeo.pcs2.functions.AddEntryIntoMultiMap;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.EntityParam; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.decorators.AddAsStringEntity;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -58,7 +59,7 @@ public interface PCSUtil {
@Endpoint(PCS.class) @Endpoint(PCS.class)
@Path("/files/{fileResourceId}/metadata/{key}") @Path("/files/{fileResourceId}/metadata/{key}")
Future<Void> putMetadata(@PathParam("fileResourceId") String resourceId, Future<Void> putMetadata(@PathParam("fileResourceId") String resourceId,
@PathParam("key") String key, @EntityParam String value); @PathParam("key") String key, @DecoratorParam(AddAsStringEntity.class) String value);
@GET @GET
@ResponseParser(AddEntryIntoMultiMap.class) @ResponseParser(AddEntryIntoMultiMap.class)

View File

@ -35,6 +35,7 @@ import javax.inject.Singleton;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.BlobStoreContextImpl; import org.jclouds.blobstore.BlobStoreContextImpl;
import org.jclouds.blobstore.BlobMap.Factory; import org.jclouds.blobstore.BlobMap.Factory;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.mezeo.pcs2.PCS; import org.jclouds.mezeo.pcs2.PCS;
import org.jclouds.mezeo.pcs2.PCSConnection; import org.jclouds.mezeo.pcs2.PCSConnection;
@ -44,7 +45,6 @@ import org.jclouds.mezeo.pcs2.domain.FileMetadata;
import org.jclouds.mezeo.pcs2.domain.PCSFile; import org.jclouds.mezeo.pcs2.domain.PCSFile;
import org.jclouds.mezeo.pcs2.functions.FindIdInContainerList; import org.jclouds.mezeo.pcs2.functions.FindIdInContainerList;
import org.jclouds.mezeo.pcs2.functions.FindIdInFileList; import org.jclouds.mezeo.pcs2.functions.FindIdInFileList;
import org.jclouds.mezeo.pcs2.functions.Key;
import org.jclouds.mezeo.pcs2.reference.PCSConstants; import org.jclouds.mezeo.pcs2.reference.PCSConstants;
import com.google.common.base.Function; import com.google.common.base.Function;

View File

@ -21,28 +21,29 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.mezeo.pcs2.binders; package org.jclouds.mezeo.pcs2.decorators;
import java.util.Collections; import java.util.Collections;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.EntityBinder; import org.jclouds.rest.decorators.RequestDecorator;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class CreateContainerBinder implements EntityBinder { public class AddContainerNameAsXmlEntity implements RequestDecorator {
public void addEntityToRequest(Object toBind, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object toBind) {
String container = String.format("<container><name>%s</name></container>", toBind); String container = String.format("<container><name>%s</name></container>", toBind);
request.setEntity(container); request.setEntity(container);
request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH, request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,
Collections.singletonList(container.getBytes().length + "")); Collections.singletonList(container.getBytes().length + ""));
request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE, request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE,
Collections.singletonList("application/vnd.csp.container-info+xml")); Collections.singletonList("application/vnd.csp.container-info+xml"));
return request;
} }
} }

View File

@ -1,4 +1,4 @@
package org.jclouds.mezeo.pcs2.binders; package org.jclouds.mezeo.pcs2.decorators;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -6,13 +6,14 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.EntityBinder; import org.jclouds.rest.decorators.RequestDecorator;
public class BlockBinder implements EntityBinder { public class AddDataAndLength implements RequestDecorator {
public void addEntityToRequest(Object entity, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object entity) {
Blob<?> object = (Blob<?>) entity; Blob<?> object = (Blob<?>) entity;
request.setEntity(checkNotNull(object.getData(), "object.getContent()")); request.setEntity(checkNotNull(object.getData(), "object.getContent()"));
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, object.getMetadata().getSize() + ""); request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, object.getMetadata().getSize() + "");
return request;
} }
} }

View File

@ -21,28 +21,28 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.mezeo.pcs2.binders; package org.jclouds.mezeo.pcs2.decorators;
import java.util.Collections; import java.util.Collections;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.mezeo.pcs2.functions.Key; import org.jclouds.rest.decorators.RequestDecorator;
import org.jclouds.mezeo.pcs2.util.PCSUtils;
import org.jclouds.rest.binders.EntityBinder;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class CreateFileBinder implements EntityBinder { public class AddFileInfoAsXmlEntity implements RequestDecorator {
public void addEntityToRequest(Object toBind, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object toBind) {
Blob<?> blob = (Blob<?>) toBind; Blob<?> blob = (Blob<?>) toBind;
String bareKey = PCSUtils.parseKey(new Key("trash", blob.getKey())).getKey(); String bareKey = BlobStoreUtils.parseKey(new Key("trash", blob.getKey())).getKey();
String file = String.format( String file = String.format(
"<file><name>%s</name><mime_type>%s</mime_type><public>false</public></file>", "<file><name>%s</name><mime_type>%s</mime_type><public>false</public></file>",
bareKey, blob.getMetadata().getContentType()); bareKey, blob.getMetadata().getContentType());
@ -51,5 +51,6 @@ public class CreateFileBinder implements EntityBinder {
Collections.singletonList(file.getBytes().length + "")); Collections.singletonList(file.getBytes().length + ""));
request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE, request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE,
Collections.singletonList("application/vnd.csp.file-info+xml")); Collections.singletonList("application/vnd.csp.file-info+xml"));
return request;
} }
} }

View File

@ -9,7 +9,7 @@ import javax.inject.Inject;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ReturnStringIf200; import org.jclouds.http.functions.ReturnStringIf200;
import org.jclouds.rest.RestContext; import org.jclouds.rest.InvocationContext;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -18,7 +18,7 @@ import com.google.common.collect.Multimap;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class AddEntryIntoMultiMap implements Function<HttpResponse, Void>, RestContext { public class AddEntryIntoMultiMap implements Function<HttpResponse, Void>, InvocationContext {
ReturnStringIf200 returnIf200; ReturnStringIf200 returnIf200;
@Inject @Inject

View File

@ -38,6 +38,7 @@ import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.blobstore.internal.BlobRuntimeException; import org.jclouds.blobstore.internal.BlobRuntimeException;
import org.jclouds.blobstore.reference.BlobStoreConstants; import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
@ -46,7 +47,7 @@ import org.jclouds.logging.Logger;
import org.jclouds.mezeo.pcs2.PCSUtil; import org.jclouds.mezeo.pcs2.PCSUtil;
import org.jclouds.mezeo.pcs2.domain.PCSFile; import org.jclouds.mezeo.pcs2.domain.PCSFile;
import org.jclouds.mezeo.pcs2.util.PCSUtils; import org.jclouds.mezeo.pcs2.util.PCSUtils;
import org.jclouds.rest.RestContext; import org.jclouds.rest.InvocationContext;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -58,7 +59,7 @@ import com.google.common.collect.Sets;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class AddMetadataAndParseResourceIdIntoBytes implements Function<HttpResponse, byte[]>, public class AddMetadataAndParseResourceIdIntoBytes implements Function<HttpResponse, byte[]>,
RestContext { InvocationContext {
private final PCSUtil util; private final PCSUtil util;
private final ConcurrentMap<Key, String> fileCache; private final ConcurrentMap<Key, String> fileCache;

View File

@ -27,12 +27,13 @@ import java.util.concurrent.ConcurrentMap;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.blobstore.functions.ParseContentTypeFromHeaders; import org.jclouds.blobstore.functions.ParseContentTypeFromHeaders;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.mezeo.pcs2.domain.FileMetadata; import org.jclouds.mezeo.pcs2.domain.FileMetadata;
import org.jclouds.mezeo.pcs2.domain.PCSFile; import org.jclouds.mezeo.pcs2.domain.PCSFile;
import org.jclouds.rest.RestContext; import org.jclouds.rest.InvocationContext;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -43,7 +44,7 @@ import com.google.common.base.Function;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class AssembleBlobFromContentAndMetadataCache implements Function<HttpResponse, PCSFile>, public class AssembleBlobFromContentAndMetadataCache implements Function<HttpResponse, PCSFile>,
RestContext { InvocationContext {
private final ConcurrentMap<Key, FileMetadata> cache; private final ConcurrentMap<Key, FileMetadata> cache;
private HttpRequest request; private HttpRequest request;

View File

@ -34,6 +34,7 @@ import javax.inject.Singleton;
import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.base.Function; import com.google.common.base.Function;

View File

@ -40,8 +40,10 @@ import javax.inject.Singleton;
import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.blobstore.internal.BlobRuntimeException; import org.jclouds.blobstore.internal.BlobRuntimeException;
import org.jclouds.blobstore.reference.BlobStoreConstants; import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.mezeo.pcs2.PCSConnection; import org.jclouds.mezeo.pcs2.PCSConnection;
import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; import org.jclouds.mezeo.pcs2.domain.ContainerMetadata;
import org.jclouds.mezeo.pcs2.endpoints.RootContainer; import org.jclouds.mezeo.pcs2.endpoints.RootContainer;
@ -85,7 +87,7 @@ public class CreateSubFolderIfNotExistsAndGetResourceId implements Function<Obje
Object[] args = (Object[]) from; Object[] args = (Object[]) from;
checkArgument(args[0] instanceof String, "arg[0] must be a container name"); checkArgument(args[0] instanceof String, "arg[0] must be a container name");
checkArgument(args[1] instanceof Blob, "arg[1] must be a pcsfile"); checkArgument(args[1] instanceof Blob, "arg[1] must be a pcsfile");
Key key = PCSUtils.parseKey(new Key(args[0].toString(), ((Blob) args[1]).getKey())); Key key = BlobStoreUtils.parseKey(new Key(args[0].toString(), ((Blob) args[1]).getKey()));
try { try {
return finder.get(key.getContainer()); return finder.get(key.getContainer());
} catch (ComputationException e) { } catch (ComputationException e) {
@ -95,12 +97,12 @@ public class CreateSubFolderIfNotExistsAndGetResourceId implements Function<Obje
SortedSet<ContainerMetadata> response = blobStore.listContainers(); SortedSet<ContainerMetadata> response = blobStore.listContainers();
URI containerUri; URI containerUri;
try { try {
containerUri = urlForNameInListOrCreate(rootContainer, containerTree[0], containerUri = urlForNameInListOrCreate(rootContainer, containerTree[0], response);
response);
} catch (Exception e1) { } catch (Exception e1) {
Utils.<ContainerNotFoundException> rethrowIfRuntimeOrSameType(e1); Utils.<ContainerNotFoundException> rethrowIfRuntimeOrSameType(e1);
throw new BlobRuntimeException("error creating container at: " + containerTree[0], e1); throw new BlobRuntimeException("error creating container at: " + containerTree[0],
e1);
} }
if (containerTree.length != 1) { if (containerTree.length != 1) {
for (int i = 1; i < containerTree.length; i++) { for (int i = 1; i < containerTree.length; i++) {

View File

@ -38,6 +38,7 @@ import javax.ws.rs.core.UriBuilder;
import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.blobstore.internal.BlobRuntimeException; import org.jclouds.blobstore.internal.BlobRuntimeException;
import org.jclouds.blobstore.reference.BlobStoreConstants; import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.mezeo.pcs2.PCS; import org.jclouds.mezeo.pcs2.PCS;

View File

@ -32,11 +32,12 @@ import javax.inject.Inject;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; import org.jclouds.mezeo.pcs2.domain.ContainerMetadata;
import org.jclouds.mezeo.pcs2.domain.FileMetadata; import org.jclouds.mezeo.pcs2.domain.FileMetadata;
import org.jclouds.mezeo.pcs2.domain.PCSFile; import org.jclouds.mezeo.pcs2.domain.PCSFile;
import org.jclouds.mezeo.pcs2.util.PCSUtils;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -51,7 +52,7 @@ public class FindIdInFileList implements Function<Key, String> {
} }
public String apply(Key key) { public String apply(Key key) {
key = PCSUtils.parseKey(key); key = BlobStoreUtils.parseKey(key);
SortedSet<FileMetadata> response; SortedSet<FileMetadata> response;
try { try {
response = connection.listBlobs(key.getContainer()).get(10, TimeUnit.SECONDS); response = connection.listBlobs(key.getContainer()).get(10, TimeUnit.SECONDS);

View File

@ -30,7 +30,7 @@ import javax.inject.Inject;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.rest.RestContext; import org.jclouds.rest.InvocationContext;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -40,7 +40,7 @@ import com.google.common.base.Function;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class InvalidateContainerNameCacheAndReturnTrueIf2xx implements Function<HttpResponse, Boolean>, public class InvalidateContainerNameCacheAndReturnTrueIf2xx implements Function<HttpResponse, Boolean>,
RestContext { InvocationContext {
private final ConcurrentMap<String, String> cache; private final ConcurrentMap<String, String> cache;
private HttpRequest request; private HttpRequest request;
private Object[] args; private Object[] args;

View File

@ -28,10 +28,11 @@ import java.util.concurrent.ConcurrentMap;
import javax.inject.Inject; import javax.inject.Inject;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.mezeo.pcs2.domain.FileMetadata; import org.jclouds.mezeo.pcs2.domain.FileMetadata;
import org.jclouds.rest.RestContext; import org.jclouds.rest.InvocationContext;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -41,7 +42,7 @@ import com.google.common.base.Function;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class InvalidatePCSKeyCacheAndReturnVoidIf2xx implements Function<HttpResponse, Void>, public class InvalidatePCSKeyCacheAndReturnVoidIf2xx implements Function<HttpResponse, Void>,
RestContext { InvocationContext {
private final ConcurrentMap<Key, String> cache; private final ConcurrentMap<Key, String> cache;
private final ConcurrentMap<Key, FileMetadata> mdCache; private final ConcurrentMap<Key, FileMetadata> mdCache;
private HttpRequest request; private HttpRequest request;

View File

@ -26,7 +26,6 @@ package org.jclouds.mezeo.pcs2.util;
import java.net.URI; import java.net.URI;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.mezeo.pcs2.functions.Key;
/** /**
* Utilities for PCS connections. * Utilities for PCS connections.
@ -49,17 +48,6 @@ public class PCSUtils {
return eTag; return eTag;
} }
public static Key parseKey(Key key) {
if (key.getKey().indexOf('/') != -1) {
String container = key.getContainer() + '/'
+ key.getKey().substring(0, key.getKey().lastIndexOf('/'));
String newKey = key.getKey().substring(key.getKey().lastIndexOf('/') + 1);
key = new Key(container.replaceAll("//", "/"), newKey);
}
return key;
}
public static String getContainerId(URI url) { public static String getContainerId(URI url) {
String path = url.getPath(); String path = url.getPath();
int indexAfterContainersSlash = path.indexOf("containers/") + "containers/".length(); int indexAfterContainersSlash = path.indexOf("containers/") + "containers/".length();

View File

@ -54,7 +54,6 @@ import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.ReturnVoidIf2xx; import org.jclouds.http.functions.ReturnVoidIf2xx;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
import org.jclouds.mezeo.pcs2.binders.PCSFileAsMultipartFormBinderTest;
import org.jclouds.mezeo.pcs2.domain.ContainerMetadata; import org.jclouds.mezeo.pcs2.domain.ContainerMetadata;
import org.jclouds.mezeo.pcs2.domain.FileMetadata; import org.jclouds.mezeo.pcs2.domain.FileMetadata;
import org.jclouds.mezeo.pcs2.domain.PCSFile; import org.jclouds.mezeo.pcs2.domain.PCSFile;
@ -67,8 +66,8 @@ import org.jclouds.mezeo.pcs2.functions.InvalidateContainerNameCacheAndReturnTru
import org.jclouds.mezeo.pcs2.functions.InvalidatePCSKeyCacheAndReturnVoidIf2xx; import org.jclouds.mezeo.pcs2.functions.InvalidatePCSKeyCacheAndReturnVoidIf2xx;
import org.jclouds.mezeo.pcs2.functions.ReturnFalseIfContainerNotFound; import org.jclouds.mezeo.pcs2.functions.ReturnFalseIfContainerNotFound;
import org.jclouds.mezeo.pcs2.options.PutBlockOptions; import org.jclouds.mezeo.pcs2.options.PutBlockOptions;
import org.jclouds.rest.JaxrsAnnotationProcessor; import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.config.JaxrsModule; import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.DateService; import org.jclouds.util.DateService;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -298,19 +297,18 @@ public class PCSBlobStoreTest {
public void testPutBlob() throws SecurityException, NoSuchMethodException, IOException { public void testPutBlob() throws SecurityException, NoSuchMethodException, IOException {
Method method = PCSBlobStore.class.getMethod("putBlob", String.class, PCSFile.class); Method method = PCSBlobStore.class.getMethod("putBlob", String.class, PCSFile.class);
PCSFile file = new PCSFile("hello");
HttpRequest httpMethod = processor.createRequest(method, new Object[] { "mycontainer", file.setData("wonkers");
PCSFileAsMultipartFormBinderTest.TEST_BLOB }); HttpRequest httpMethod = processor
.createRequest(method, new Object[] { "mycontainer", file });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/files/o/content"); assertEquals(httpMethod.getEndpoint().getPath(), "/files/o/content");
assertEquals(httpMethod.getEndpoint().getQuery(), null); assertEquals(httpMethod.getEndpoint().getQuery(), null);
assertEquals(httpMethod.getMethod(), HttpMethod.PUT); assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 1); assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList(PCSFileAsMultipartFormBinderTest.TEST_BLOB.getData().toString() .singletonList(file.getData().toString().getBytes().length + ""));
.getBytes().length assertEquals(httpMethod.getEntity(), file.getData());
+ ""));
assertEquals(httpMethod.getEntity(), PCSFileAsMultipartFormBinderTest.TEST_BLOB.getData());
assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(),
AddMetadataAndParseResourceIdIntoBytes.class); AddMetadataAndParseResourceIdIntoBytes.class);
} }
@ -419,8 +417,8 @@ public class PCSBlobStoreTest {
AddEntryIntoMultiMap.class); AddEntryIntoMultiMap.class);
} }
JaxrsAnnotationProcessor<PCSBlobStore> processor; RestAnnotationProcessor<PCSBlobStore> processor;
private JaxrsAnnotationProcessor<PCSUtil> utilProcessor; private RestAnnotationProcessor<PCSUtil> utilProcessor;
@BeforeClass @BeforeClass
void setupFactory() { void setupFactory() {
@ -459,22 +457,20 @@ public class PCSBlobStoreTest {
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Provides @Provides
@Singleton @Singleton
ConcurrentMap<org.jclouds.mezeo.pcs2.functions.Key, String> giveMap() { ConcurrentMap<org.jclouds.blobstore.domain.Key, String> giveMap() {
ConcurrentHashMap<org.jclouds.mezeo.pcs2.functions.Key, String> map = new ConcurrentHashMap<org.jclouds.mezeo.pcs2.functions.Key, String>(); ConcurrentHashMap<org.jclouds.blobstore.domain.Key, String> map = new ConcurrentHashMap<org.jclouds.blobstore.domain.Key, String>();
map.put( map.put(new org.jclouds.blobstore.domain.Key("mycontainer", "testfile.txt"),
new org.jclouds.mezeo.pcs2.functions.Key("mycontainer", "9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3");
"testfile.txt"), "9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3");
return map; return map;
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Provides @Provides
@Singleton @Singleton
ConcurrentMap<org.jclouds.mezeo.pcs2.functions.Key, FileMetadata> giveMap2() { ConcurrentMap<org.jclouds.blobstore.domain.Key, FileMetadata> giveMap2() {
ConcurrentHashMap<org.jclouds.mezeo.pcs2.functions.Key, FileMetadata> map = new ConcurrentHashMap<org.jclouds.mezeo.pcs2.functions.Key, FileMetadata>(); ConcurrentHashMap<org.jclouds.blobstore.domain.Key, FileMetadata> map = new ConcurrentHashMap<org.jclouds.blobstore.domain.Key, FileMetadata>();
map.put( map.put(new org.jclouds.blobstore.domain.Key("mycontainer", "testfile.txt"),
new org.jclouds.mezeo.pcs2.functions.Key("mycontainer", new FileMetadata("testfile.txt"));
"testfile.txt"), new FileMetadata("testfile.txt"));
return map; return map;
} }
@ -494,14 +490,14 @@ public class PCSBlobStoreTest {
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
return new BasicAuthentication("foo", "bar"); return new BasicAuthentication("foo", "bar");
} }
}, new JaxrsModule(), new ExecutorServiceModule(new WithinThreadExecutorService()), }, new RestModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule()); new JavaUrlHttpCommandExecutorServiceModule());
processor = injector.getInstance(Key processor = injector.getInstance(Key
.get(new TypeLiteral<JaxrsAnnotationProcessor<PCSBlobStore>>() { .get(new TypeLiteral<RestAnnotationProcessor<PCSBlobStore>>() {
})); }));
utilProcessor = injector.getInstance(Key utilProcessor = injector.getInstance(Key
.get(new TypeLiteral<JaxrsAnnotationProcessor<PCSUtil>>() { .get(new TypeLiteral<RestAnnotationProcessor<PCSUtil>>() {
})); }));
} }
} }

View File

@ -37,7 +37,7 @@ import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.mezeo.pcs2.PCSCloud.Response; import org.jclouds.mezeo.pcs2.PCSCloud.Response;
import org.jclouds.rest.RestClientFactory; import org.jclouds.rest.RestClientFactory;
import org.jclouds.rest.config.JaxrsModule; import org.jclouds.rest.config.RestModule;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -97,7 +97,7 @@ public class PCSCloudLiveTest {
protected PCSCloud provideCloud(RestClientFactory factory) { protected PCSCloud provideCloud(RestClientFactory factory) {
return factory.create(PCSCloud.class); return factory.create(PCSCloud.class);
} }
}, new JaxrsModule(), new ExecutorServiceModule(new WithinThreadExecutorService()), }, new RestModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule()); new JavaUrlHttpCommandExecutorServiceModule());
} }
} }

View File

@ -39,6 +39,7 @@ import javax.inject.Singleton;
import javax.ws.rs.HttpMethod; import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.decorators.AddBlobEntityAsMultipartFormTest;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.concurrent.WithinThreadExecutorService; import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.concurrent.config.ExecutorServiceModule;
@ -49,12 +50,11 @@ import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ParseURIList; import org.jclouds.http.functions.ParseURIList;
import org.jclouds.http.functions.ReturnInputStream; import org.jclouds.http.functions.ReturnInputStream;
import org.jclouds.http.functions.ReturnVoidIf2xx; import org.jclouds.http.functions.ReturnVoidIf2xx;
import org.jclouds.mezeo.pcs2.binders.PCSFileAsMultipartFormBinderTest;
import org.jclouds.mezeo.pcs2.domain.FileMetadata; import org.jclouds.mezeo.pcs2.domain.FileMetadata;
import org.jclouds.mezeo.pcs2.domain.PCSFile; import org.jclouds.mezeo.pcs2.domain.PCSFile;
import org.jclouds.mezeo.pcs2.endpoints.RootContainer; import org.jclouds.mezeo.pcs2.endpoints.RootContainer;
import org.jclouds.rest.JaxrsAnnotationProcessor; import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.config.JaxrsModule; import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -165,19 +165,19 @@ public class PCSConnectionTest {
HttpRequest httpMethod = processor.createRequest(method, new Object[] { HttpRequest httpMethod = processor.createRequest(method, new Object[] {
URI.create("http://localhost/mycontainer"), URI.create("http://localhost/mycontainer"),
PCSFileAsMultipartFormBinderTest.TEST_BLOB }); AddBlobEntityAsMultipartFormTest.TEST_BLOB });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost"); assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/mycontainer/contents"); assertEquals(httpMethod.getEndpoint().getPath(), "/mycontainer/contents");
assertEquals(httpMethod.getEndpoint().getQuery(), null); assertEquals(httpMethod.getEndpoint().getQuery(), null);
assertEquals(httpMethod.getMethod(), HttpMethod.POST); assertEquals(httpMethod.getMethod(), HttpMethod.POST);
assertEquals(httpMethod.getHeaders().size(), 2); assertEquals(httpMethod.getHeaders().size(), 2);
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList(PCSFileAsMultipartFormBinderTest.EXPECTS.length() + "")); .singletonList(AddBlobEntityAsMultipartFormTest.EXPECTS.length() + ""));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
.singletonList("multipart/form-data; boundary=" .singletonList("multipart/form-data; boundary="
+ PCSFileAsMultipartFormBinderTest.BOUNDRY)); + AddBlobEntityAsMultipartFormTest.BOUNDRY));
assertEquals(Utils.toStringAndClose((InputStream) httpMethod.getEntity()), assertEquals(Utils.toStringAndClose((InputStream) httpMethod.getEntity()),
PCSFileAsMultipartFormBinderTest.EXPECTS); AddBlobEntityAsMultipartFormTest.EXPECTS);
assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(), assertEquals(processor.createResponseParser(method, httpMethod, null).getClass(),
ParseURIList.class); ParseURIList.class);
} }
@ -212,7 +212,7 @@ public class PCSConnectionTest {
ReturnVoidOnNotFoundOr404.class); ReturnVoidOnNotFoundOr404.class);
} }
JaxrsAnnotationProcessor<PCSConnection> processor; RestAnnotationProcessor<PCSConnection> processor;
@BeforeClass @BeforeClass
void setupFactory() { void setupFactory() {
@ -248,22 +248,20 @@ public class PCSConnectionTest {
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Provides @Provides
@Singleton @Singleton
ConcurrentMap<org.jclouds.mezeo.pcs2.functions.Key, String> giveMap() { ConcurrentMap<org.jclouds.blobstore.domain.Key, String> giveMap() {
ConcurrentHashMap<org.jclouds.mezeo.pcs2.functions.Key, String> map = new ConcurrentHashMap<org.jclouds.mezeo.pcs2.functions.Key, String>(); ConcurrentHashMap<org.jclouds.blobstore.domain.Key, String> map = new ConcurrentHashMap<org.jclouds.blobstore.domain.Key, String>();
map.put( map.put(new org.jclouds.blobstore.domain.Key("mycontainer", "testfile.txt"),
new org.jclouds.mezeo.pcs2.functions.Key("mycontainer", "9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3");
"testfile.txt"), "9E4C5AFA-A98B-11DE-8B4C-C3884B4A2DA3");
return map; return map;
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Provides @Provides
@Singleton @Singleton
ConcurrentMap<org.jclouds.mezeo.pcs2.functions.Key, FileMetadata> giveMap2() { ConcurrentMap<org.jclouds.blobstore.domain.Key, FileMetadata> giveMap2() {
ConcurrentHashMap<org.jclouds.mezeo.pcs2.functions.Key, FileMetadata> map = new ConcurrentHashMap<org.jclouds.mezeo.pcs2.functions.Key, FileMetadata>(); ConcurrentHashMap<org.jclouds.blobstore.domain.Key, FileMetadata> map = new ConcurrentHashMap<org.jclouds.blobstore.domain.Key, FileMetadata>();
map.put( map.put(new org.jclouds.blobstore.domain.Key("mycontainer", "testfile.txt"),
new org.jclouds.mezeo.pcs2.functions.Key("mycontainer", new FileMetadata("testfile.txt"));
"testfile.txt"), new FileMetadata("testfile.txt"));
return map; return map;
} }
@ -283,11 +281,11 @@ public class PCSConnectionTest {
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
return new BasicAuthentication("foo", "bar"); return new BasicAuthentication("foo", "bar");
} }
}, new JaxrsModule(), new ExecutorServiceModule(new WithinThreadExecutorService()), }, new RestModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule()); new JavaUrlHttpCommandExecutorServiceModule());
processor = injector.getInstance(Key processor = injector.getInstance(Key
.get(new TypeLiteral<JaxrsAnnotationProcessor<PCSConnection>>() { .get(new TypeLiteral<RestAnnotationProcessor<PCSConnection>>() {
})); }));
} }
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.mezeo.pcs2.binders; package org.jclouds.mezeo.pcs2.decorators;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -33,17 +33,17 @@ import org.jclouds.http.HttpRequest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
* Tests behavior of {@code ParseFlavorListFromGsonResponseTest} * Tests behavior of {@code AddContainerNameAsXmlEntity}
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "pcs2.CreateContainerBinderTest") @Test(groups = "unit", testName = "pcs2.AddContainerNameAsXmlEntityTest")
public class CreateContainerBinderTest { public class AddContainerNameAsXmlEntityTest {
public void test() { public void test() {
CreateContainerBinder binder = new CreateContainerBinder(); AddContainerNameAsXmlEntity binder = new AddContainerNameAsXmlEntity();
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost")); HttpRequest request = new HttpRequest("GET", URI.create("http://localhost"));
binder.addEntityToRequest("foo", request); binder.decorateRequest(request, "foo");
assertEquals(request.getEntity(), "<container><name>foo</name></container>"); assertEquals(request.getEntity(), "<container><name>foo</name></container>");
assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH), assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH),
"<container><name>foo</name></container>".getBytes().length + ""); "<container><name>foo</name></container>".getBytes().length + "");

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.mezeo.pcs2.binders; package org.jclouds.mezeo.pcs2.decorators;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -34,18 +34,18 @@ import org.jclouds.mezeo.pcs2.domain.PCSFile;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
* Tests behavior of {@code CreateFileBinder} * Tests behavior of {@code AddFileInfoAsXmlEntity}
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "pcs2.CreateFileBinderTest") @Test(groups = "unit", testName = "pcs2.AddFileInfoAsXmlEntityTest")
public class CreateFileBinderTest { public class AddFileInfoAsXmlEntityTest {
public void test() { public void test() {
CreateFileBinder binder = new CreateFileBinder(); AddFileInfoAsXmlEntity binder = new AddFileInfoAsXmlEntity();
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost")); HttpRequest request = new HttpRequest("GET", URI.create("http://localhost"));
PCSFile file = new PCSFile("foo"); PCSFile file = new PCSFile("foo");
binder.addEntityToRequest(file, request); binder.decorateRequest(request, file);
assertEquals( assertEquals(
request.getEntity(), request.getEntity(),
"<file><name>foo</name><mime_type>application/octet-stream</mime_type><public>false</public></file>"); "<file><name>foo</name><mime_type>application/octet-stream</mime_type><public>false</public></file>");
@ -58,13 +58,12 @@ public class CreateFileBinderTest {
"application/vnd.csp.file-info+xml"); "application/vnd.csp.file-info+xml");
} }
public void testCompound() { public void testCompound() {
CreateFileBinder binder = new CreateFileBinder(); AddFileInfoAsXmlEntity binder = new AddFileInfoAsXmlEntity();
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost")); HttpRequest request = new HttpRequest("GET", URI.create("http://localhost"));
PCSFile file = new PCSFile("subdir/foo"); PCSFile file = new PCSFile("subdir/foo");
binder.addEntityToRequest(file, request); binder.decorateRequest(request, file);
assertEquals( assertEquals(
request.getEntity(), request.getEntity(),
"<file><name>foo</name><mime_type>application/octet-stream</mime_type><public>false</public></file>"); "<file><name>foo</name><mime_type>application/octet-stream</mime_type><public>false</public></file>");

View File

@ -38,12 +38,13 @@ import java.util.concurrent.Future;
import javax.ws.rs.ext.RuntimeDelegate; import javax.ws.rs.ext.RuntimeDelegate;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.mezeo.pcs2.PCSUtil; import org.jclouds.mezeo.pcs2.PCSUtil;
import org.jclouds.mezeo.pcs2.domain.PCSFile; import org.jclouds.mezeo.pcs2.domain.PCSFile;
import org.jclouds.rest.RuntimeDelegateImpl; import org.jclouds.rest.internal.RuntimeDelegateImpl;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;

View File

@ -31,6 +31,7 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream; import java.io.InputStream;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import org.jclouds.blobstore.domain.Key;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.mezeo.pcs2.domain.FileMetadata; import org.jclouds.mezeo.pcs2.domain.FileMetadata;

View File

@ -28,7 +28,6 @@ import static org.testng.Assert.assertEquals;
import java.net.URI; import java.net.URI;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.mezeo.pcs2.functions.Key;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
@ -45,17 +44,4 @@ public class PCSUtilsTest {
.create("http://localhost/contents/7F143552-AAF5-11DE-BBB0-0BC388ED913B")); .create("http://localhost/contents/7F143552-AAF5-11DE-BBB0-0BC388ED913B"));
assertEquals(eTag, expected); assertEquals(eTag, expected);
} }
public void testParseKey() {
Key key = PCSUtils.parseKey(new Key("container", "key"));
assertEquals(key.getContainer(), "container");
assertEquals(key.getKey(), "key");
key = PCSUtils.parseKey(new Key("container", "container/key"));
assertEquals(key.getContainer(), "container/container");
assertEquals(key.getKey(), "key");
key = PCSUtils.parseKey(new Key("container", "/container/key"));
assertEquals(key.getContainer(), "container/container");
assertEquals(key.getKey(), "key");
}
} }

View File

@ -35,7 +35,7 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.binders.BlobBinder; import org.jclouds.blobstore.decorators.AddBlobEntity;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.functions.BlobKey; import org.jclouds.blobstore.functions.BlobKey;
@ -53,14 +53,14 @@ import org.jclouds.rackspace.cloudfiles.functions.ParseObjectFromHeadersAndHttpC
import org.jclouds.rackspace.cloudfiles.functions.ParseObjectMetadataFromHeaders; import org.jclouds.rackspace.cloudfiles.functions.ParseObjectMetadataFromHeaders;
import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions; import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions;
import org.jclouds.rackspace.filters.AuthenticateRequest; import org.jclouds.rackspace.filters.AuthenticateRequest;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.EntityParam; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.ParamParser; import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.QueryParams; import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
/** /**
* Provides access to Cloud Files via their REST API. * Provides access to Cloud Files via their REST API.
@ -113,7 +113,7 @@ public interface CloudFilesBlobStore extends
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<byte[]> putBlob( Future<byte[]> putBlob(
@PathParam("container") String container, @PathParam("container") String container,
@PathParam("key") @ParamParser(BlobKey.class) @EntityParam(BlobBinder.class) Blob<BlobMetadata> object); @PathParam("key") @ParamParser(BlobKey.class) @DecoratorParam(AddBlobEntity.class) Blob<BlobMetadata> object);
@GET @GET
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class) @ResponseParser(ParseObjectFromHeadersAndHttpContent.class)

View File

@ -36,8 +36,8 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.blobstore.binders.BlobBinder; import org.jclouds.blobstore.decorators.AddBlobEntity;
import org.jclouds.blobstore.binders.UserMetadataBinder; import org.jclouds.blobstore.decorators.AddHeadersWithPrefix;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.functions.BlobKey; import org.jclouds.blobstore.functions.BlobKey;
@ -64,15 +64,15 @@ import org.jclouds.rackspace.cloudfiles.options.ListCdnContainerOptions;
import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions; import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions;
import org.jclouds.rackspace.cloudfiles.reference.CloudFilesHeaders; import org.jclouds.rackspace.cloudfiles.reference.CloudFilesHeaders;
import org.jclouds.rackspace.filters.AuthenticateRequest; import org.jclouds.rackspace.filters.AuthenticateRequest;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.EntityParam; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.ParamParser; import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.QueryParams; import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -141,7 +141,7 @@ public interface CloudFilesConnection {
@Path("{container}/{key}") @Path("{container}/{key}")
boolean setObjectMetadata(@PathParam("container") String container, boolean setObjectMetadata(@PathParam("container") String container,
@PathParam("key") String key, @PathParam("key") String key,
@EntityParam(UserMetadataBinder.class) Multimap<String, String> userMetadata); @DecoratorParam(AddHeadersWithPrefix.class) Multimap<String, String> userMetadata);
@GET @GET
@ResponseParser(ParseContainerCDNMetadataListFromGsonResponse.class) @ResponseParser(ParseContainerCDNMetadataListFromGsonResponse.class)
@ -205,7 +205,7 @@ public interface CloudFilesConnection {
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<byte[]> putObject( Future<byte[]> putObject(
@PathParam("container") String container, @PathParam("container") String container,
@PathParam("key") @ParamParser(BlobKey.class) @EntityParam(BlobBinder.class) Blob<BlobMetadata> object); @PathParam("key") @ParamParser(BlobKey.class) @DecoratorParam(AddBlobEntity.class) Blob<BlobMetadata> object);
@GET @GET
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class) @ResponseParser(ParseObjectFromHeadersAndHttpContent.class)

View File

@ -21,28 +21,27 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rackspace.cloudfiles.binders; package org.jclouds.rackspace.cloudfiles.decorators;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX; import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.binders.BlobBinder; import org.jclouds.blobstore.decorators.AddBlobEntity;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import javax.inject.Inject; public class AddCFObjectEntity extends AddBlobEntity {
import javax.inject.Named;
public class CFObjectBinder extends BlobBinder {
@Inject @Inject
public CFObjectBinder(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) { public AddCFObjectEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
super(metadataPrefix); super(metadataPrefix);
} }
public void addEntityToRequest(Object entity, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object entity) {
Blob<?> object = (Blob<?>) entity; Blob<?> object = (Blob<?>) entity;
if (object.getMetadata().getSize() >= 0) { if (object.getMetadata().getSize() >= 0) {
checkArgument(object.getContentLength() <= 5 * 1024 * 1024 * 1024, checkArgument(object.getContentLength() <= 5 * 1024 * 1024 * 1024,
@ -59,6 +58,6 @@ public class CFObjectBinder extends BlobBinder {
request.getHeaders().put(HttpHeaders.ETAG, request.getHeaders().put(HttpHeaders.ETAG,
HttpUtils.toBase64String(object.getMetadata().getContentMD5())); HttpUtils.toBase64String(object.getMetadata().getContentMD5()));
} }
super.addEntityToRequest(entity, request); return super.decorateRequest(request, entity);
} }
} }

View File

@ -37,15 +37,15 @@ import javax.ws.rs.PathParam;
import org.jclouds.http.functions.ReturnFalseOn404; import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.rackspace.CloudServers; import org.jclouds.rackspace.CloudServers;
import org.jclouds.rackspace.cloudservers.binders.BackupScheduleBinder; import org.jclouds.rackspace.cloudservers.decorators.AddBackupScheduleAsJsonEntity;
import org.jclouds.rackspace.cloudservers.binders.ChangeAdminPassBinder; import org.jclouds.rackspace.cloudservers.decorators.AddAdminPassAsJsonEntity;
import org.jclouds.rackspace.cloudservers.binders.ChangeServerNameBinder; import org.jclouds.rackspace.cloudservers.decorators.AddServerNameAsJsonEntity;
import org.jclouds.rackspace.cloudservers.binders.ConfirmResizeBinder; import org.jclouds.rackspace.cloudservers.decorators.AddConfirmResizeAsJsonEntity;
import org.jclouds.rackspace.cloudservers.binders.CreateImageBinder; import org.jclouds.rackspace.cloudservers.decorators.AddCreateImageAsJsonEntity;
import org.jclouds.rackspace.cloudservers.binders.RebootTypeBinder; import org.jclouds.rackspace.cloudservers.decorators.AddRebootTypeAsJsonEntity;
import org.jclouds.rackspace.cloudservers.binders.ResizeBinder; import org.jclouds.rackspace.cloudservers.decorators.AddResizeFlavorAsJsonEntity;
import org.jclouds.rackspace.cloudservers.binders.RevertResizeBinder; import org.jclouds.rackspace.cloudservers.decorators.AddRevertResizeAsJsonEntity;
import org.jclouds.rackspace.cloudservers.binders.ShareIpBinder; import org.jclouds.rackspace.cloudservers.decorators.AddSharedIpGroupAsJsonEntity;
import org.jclouds.rackspace.cloudservers.domain.Addresses; import org.jclouds.rackspace.cloudservers.domain.Addresses;
import org.jclouds.rackspace.cloudservers.domain.BackupSchedule; import org.jclouds.rackspace.cloudservers.domain.BackupSchedule;
import org.jclouds.rackspace.cloudservers.domain.Flavor; import org.jclouds.rackspace.cloudservers.domain.Flavor;
@ -74,16 +74,16 @@ import org.jclouds.rackspace.cloudservers.options.CreateSharedIpGroupOptions;
import org.jclouds.rackspace.cloudservers.options.ListOptions; import org.jclouds.rackspace.cloudservers.options.ListOptions;
import org.jclouds.rackspace.cloudservers.options.RebuildServerOptions; import org.jclouds.rackspace.cloudservers.options.RebuildServerOptions;
import org.jclouds.rackspace.filters.AuthenticateRequest; import org.jclouds.rackspace.filters.AuthenticateRequest;
import org.jclouds.rest.Endpoint; import org.jclouds.rest.annotations.DecoratorParam;
import org.jclouds.rest.EntityParam; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.MapBinder; import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.MapEntityParam; import org.jclouds.rest.annotations.MapEntityParam;
import org.jclouds.rest.ParamParser; import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.QueryParams; import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
/** /**
* Provides access to Cloud Servers via their REST API. * Provides access to Cloud Servers via their REST API.
@ -170,7 +170,7 @@ public interface CloudServersConnection {
// TODO:cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest // TODO:cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400), badMediaType(415),buildInProgress (409), overLimit (403) // (400), badMediaType(415),buildInProgress (409), overLimit (403)
boolean rebootServer(@PathParam("id") int id, boolean rebootServer(@PathParam("id") int id,
@EntityParam(RebootTypeBinder.class) RebootType rebootType); @DecoratorParam(AddRebootTypeAsJsonEntity.class) RebootType rebootType);
/** /**
* The resize function converts an existing server to a different flavor, in essence, scaling the * The resize function converts an existing server to a different flavor, in essence, scaling the
@ -192,7 +192,7 @@ public interface CloudServersConnection {
// TODO:cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest // TODO:cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400), badMediaType(415), itemNotFound (404), buildInProgress (409), serverCapacityUnavailable // (400), badMediaType(415), itemNotFound (404), buildInProgress (409), serverCapacityUnavailable
// (503), overLimit (413), resizeNotAllowed (403) // (503), overLimit (413), resizeNotAllowed (403)
boolean resizeServer(@PathParam("id") int id, @EntityParam(ResizeBinder.class) int flavorId); boolean resizeServer(@PathParam("id") int id, @DecoratorParam(AddResizeFlavorAsJsonEntity.class) int flavorId);
/** /**
* The resize function converts an existing server to a different flavor, in essence, scaling the * The resize function converts an existing server to a different flavor, in essence, scaling the
@ -212,7 +212,7 @@ public interface CloudServersConnection {
// TODO:cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest // TODO:cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400), badMediaType(415), itemNotFound (404), buildInProgress (409), serverCapacityUnavailable // (400), badMediaType(415), itemNotFound (404), buildInProgress (409), serverCapacityUnavailable
// (503), overLimit (413), resizeNotAllowed (403) // (503), overLimit (413), resizeNotAllowed (403)
boolean confirmResizeServer(@PathParam("id") @EntityParam(ConfirmResizeBinder.class) int id); boolean confirmResizeServer(@PathParam("id") @DecoratorParam(AddConfirmResizeAsJsonEntity.class) int id);
/** /**
* The resize function converts an existing server to a different flavor, in essence, scaling the * The resize function converts an existing server to a different flavor, in essence, scaling the
@ -232,7 +232,7 @@ public interface CloudServersConnection {
// TODO:cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest // TODO:cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400), badMediaType(415), itemNotFound (404), buildInProgress (409), serverCapacityUnavailable // (400), badMediaType(415), itemNotFound (404), buildInProgress (409), serverCapacityUnavailable
// (503), overLimit (413), resizeNotAllowed (403) // (503), overLimit (413), resizeNotAllowed (403)
boolean revertResizeServer(@PathParam("id") @EntityParam(RevertResizeBinder.class) int id); boolean revertResizeServer(@PathParam("id") @DecoratorParam(AddRevertResizeAsJsonEntity.class) int id);
/** /**
* This operation asynchronously provisions a new server. The progress of this operation depends * This operation asynchronously provisions a new server. The progress of this operation depends
@ -304,7 +304,7 @@ public interface CloudServersConnection {
@PUT @PUT
@ExceptionParser(ReturnFalseOn404.class) @ExceptionParser(ReturnFalseOn404.class)
@Path("/servers/{id}/ips/public/{address}") @Path("/servers/{id}/ips/public/{address}")
@MapBinder(ShareIpBinder.class) @MapBinder(AddSharedIpGroupAsJsonEntity.class)
// TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest // TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400), badMediaType(415), buildInProgress (409), overLimit (413) // (400), badMediaType(415), buildInProgress (409), overLimit (413)
boolean shareIp(@PathParam("address") @ParamParser(IpAddress.class) InetAddress addressToShare, boolean shareIp(@PathParam("address") @ParamParser(IpAddress.class) InetAddress addressToShare,
@ -344,7 +344,7 @@ public interface CloudServersConnection {
// TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest // TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400), badMediaType(415), buildInProgress (409), overLimit (413) // (400), badMediaType(415), buildInProgress (409), overLimit (413)
boolean changeAdminPass(@PathParam("id") int id, boolean changeAdminPass(@PathParam("id") int id,
@EntityParam(ChangeAdminPassBinder.class) String adminPass); @DecoratorParam(AddAdminPassAsJsonEntity.class) String adminPass);
/** /**
* This operation allows you to update the name of the server. This operation changes the name of * This operation allows you to update the name of the server. This operation changes the name of
@ -360,7 +360,7 @@ public interface CloudServersConnection {
// TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest // TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400), badMediaType(415), buildInProgress (409), overLimit (413) // (400), badMediaType(415), buildInProgress (409), overLimit (413)
boolean renameServer(@PathParam("id") int id, boolean renameServer(@PathParam("id") int id,
@EntityParam(ChangeServerNameBinder.class) String newName); @DecoratorParam(AddServerNameAsJsonEntity.class) String newName);
/** /**
* *
@ -447,7 +447,7 @@ public interface CloudServersConnection {
@ResponseParser(ParseImageFromJsonResponse.class) @ResponseParser(ParseImageFromJsonResponse.class)
@QueryParams(keys = "format", values = "json") @QueryParams(keys = "format", values = "json")
@ExceptionParser(ReturnImageNotFoundOn404.class) @ExceptionParser(ReturnImageNotFoundOn404.class)
@MapBinder(CreateImageBinder.class) @MapBinder(AddCreateImageAsJsonEntity.class)
@Path("/images") @Path("/images")
// TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest // TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
// (400), badMediaType(415), buildInProgress (409), serverCapacityUnavailable (503), overLimit // (400), badMediaType(415), buildInProgress (409), serverCapacityUnavailable (503), overLimit
@ -554,7 +554,7 @@ public interface CloudServersConnection {
// (400), badMediaType(415), buildInProgress (409), serverCapacityUnavailable (503), // (400), badMediaType(415), buildInProgress (409), serverCapacityUnavailable (503),
// backupOrResizeInProgress(409), resizeNotAllowed (403). overLimit (413) // backupOrResizeInProgress(409), resizeNotAllowed (403). overLimit (413)
boolean replaceBackupSchedule(@PathParam("id") int id, boolean replaceBackupSchedule(@PathParam("id") int id,
@EntityParam(BackupScheduleBinder.class) BackupSchedule backupSchedule); @DecoratorParam(AddBackupScheduleAsJsonEntity.class) BackupSchedule backupSchedule);
/** /**
* List all server addresses * List all server addresses

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rackspace.cloudservers.binders; package org.jclouds.rackspace.cloudservers.decorators;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -29,7 +29,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.JsonBinder; import org.jclouds.rest.decorators.AddAsJsonEntity;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -38,17 +38,17 @@ import com.google.common.collect.ImmutableMap;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class ChangeAdminPassBinder extends JsonBinder { public class AddAdminPassAsJsonEntity extends AddAsJsonEntity {
@Override @Override
public void addEntityToRequest(Map<String, String> postParams, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Map<String, String> postParams) {
throw new IllegalStateException("Change Admin Pass is a PUT operation"); throw new IllegalStateException("Change Admin Pass is a PUT operation");
} }
@Override @Override
public void addEntityToRequest(Object toBind, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object toBind) {
checkArgument(toBind instanceof String, "this binder is only valid for Strings!"); checkArgument(toBind instanceof String, "this binder is only valid for Strings!");
super.addEntityToRequest(ImmutableMap.of("server", ImmutableMap.of("adminPass", checkNotNull( return super.decorateRequest(request, ImmutableMap.of("server", ImmutableMap.of("adminPass",
toBind, "adminPass"))), request); checkNotNull(toBind, "adminPass"))));
} }
} }

View File

@ -21,15 +21,15 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rackspace.cloudservers.binders; package org.jclouds.rackspace.cloudservers.decorators;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import java.util.Map; import java.util.Map;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.JsonBinder;
import org.jclouds.rackspace.cloudservers.domain.BackupSchedule; import org.jclouds.rackspace.cloudservers.domain.BackupSchedule;
import org.jclouds.rest.decorators.AddAsJsonEntity;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -38,18 +38,18 @@ import com.google.common.collect.ImmutableMap;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class BackupScheduleBinder extends JsonBinder { public class AddBackupScheduleAsJsonEntity extends AddAsJsonEntity {
@Override @Override
public void addEntityToRequest(Map<String, String> postParams, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Map<String, String> postParams) {
throw new IllegalStateException( throw new IllegalStateException(
"Replace Backup Schedule needs an BackupSchedule object, not a Map"); "Replace Backup Schedule needs an BackupSchedule object, not a Map");
} }
@Override @Override
public void addEntityToRequest(Object toBind, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object toBind) {
checkArgument(toBind instanceof BackupSchedule, checkArgument(toBind instanceof BackupSchedule,
"this binder is only valid for BackupSchedules!"); "this binder is only valid for BackupSchedules!");
super.addEntityToRequest(ImmutableMap.of("backupSchedule", toBind), request); return super.decorateRequest(request, ImmutableMap.of("backupSchedule", toBind));
} }
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rackspace.cloudservers.binders; package org.jclouds.rackspace.cloudservers.decorators;
import java.util.Collections; import java.util.Collections;
@ -29,20 +29,21 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.EntityBinder; import org.jclouds.rest.decorators.RequestDecorator;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class ConfirmResizeBinder implements EntityBinder { public class AddConfirmResizeAsJsonEntity implements RequestDecorator {
public void addEntityToRequest(Object toBind, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object toBind) {
request.setEntity("{\"confirmResize\":null}"); request.setEntity("{\"confirmResize\":null}");
request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH, request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,
Collections.singletonList("{\"confirmResize\":null}".getBytes().length + "")); Collections.singletonList("{\"confirmResize\":null}".getBytes().length + ""));
request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE, request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE,
Collections.singletonList(MediaType.APPLICATION_JSON)); Collections.singletonList(MediaType.APPLICATION_JSON));
return request;
} }
} }

View File

@ -21,14 +21,14 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rackspace.cloudservers.binders; package org.jclouds.rackspace.cloudservers.decorators;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.JsonBinder; import org.jclouds.rest.decorators.AddAsJsonEntity;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -37,7 +37,7 @@ import com.google.common.collect.ImmutableMap;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class CreateImageBinder extends JsonBinder { public class AddCreateImageAsJsonEntity extends AddAsJsonEntity {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private class CreateImageRequest { private class CreateImageRequest {
@ -52,15 +52,15 @@ public class CreateImageBinder extends JsonBinder {
} }
@Override @Override
public void addEntityToRequest(Map<String, String> postParams, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Map<String, String> postParams) {
CreateImageRequest createRequest = new CreateImageRequest(Integer CreateImageRequest createRequest = new CreateImageRequest(Integer
.parseInt(checkNotNull(postParams.get("serverId"))), checkNotNull(postParams .parseInt(checkNotNull(postParams.get("serverId"))), checkNotNull(postParams
.get("imageName"))); .get("imageName")));
super.addEntityToRequest(ImmutableMap.of("image", createRequest), request); return super.decorateRequest(request, ImmutableMap.of("image", createRequest));
} }
@Override @Override
public void addEntityToRequest(Object toBind, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object toBind) {
throw new IllegalArgumentException("image is needs parameters"); throw new IllegalArgumentException("image is needs parameters");
} }
} }

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rackspace.cloudservers.binders; package org.jclouds.rackspace.cloudservers.decorators;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -29,8 +29,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.JsonBinder;
import org.jclouds.rackspace.cloudservers.domain.RebootType; import org.jclouds.rackspace.cloudservers.domain.RebootType;
import org.jclouds.rest.decorators.AddAsJsonEntity;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -39,17 +39,17 @@ import com.google.common.collect.ImmutableMap;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class RebootTypeBinder extends JsonBinder { public class AddRebootTypeAsJsonEntity extends AddAsJsonEntity {
@Override @Override
public void addEntityToRequest(Map<String, String> postParams, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Map<String, String> postParams) {
throw new IllegalStateException("Reboot doesn't take map parameters"); throw new IllegalStateException("Reboot doesn't take map parameters");
} }
@Override @Override
public void addEntityToRequest(Object toBind, HttpRequest request) { public HttpRequest decorateRequest(HttpRequest request, Object toBind) {
checkArgument(toBind instanceof RebootType, "this binder is only valid for RebootTypes!"); checkArgument(toBind instanceof RebootType, "this binder is only valid for RebootTypes!");
super.addEntityToRequest(ImmutableMap.of("reboot", ImmutableMap.of("type", checkNotNull( return super.decorateRequest(request, ImmutableMap.of("reboot", ImmutableMap.of("type",
toBind, "type"))), request); checkNotNull(toBind, "type"))));
} }
} }

Some files were not shown because too many files have changed in this diff Show More