converted http methods to enums

git-svn-id: http://jclouds.googlecode.com/svn/trunk@1449 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-06-21 00:22:04 +00:00
parent 3f7833c2c3
commit 8bd15c7fc9
28 changed files with 412 additions and 359 deletions

View File

@ -177,7 +177,7 @@ public abstract class BaseEC2RequestOptions<T extends EC2RequestOptions> extends
// 4. Separate the name-value pairs with an ampersand. // 4. Separate the name-value pairs with an ampersand.
// -- buildQueryString() does this. // -- buildQueryString() does this.
StringBuilder toSign = new StringBuilder(); StringBuilder toSign = new StringBuilder();
toSign.append("GET").append("\n").append(host.toLowerCase()).append("\n").append("/").append( toSign.append(HttpMethod.GET).append("\n").append(host.toLowerCase()).append("\n").append("/").append(
"\n"); "\n");
String canonicalizedQueryString = super.buildQueryString().replaceFirst("\\?", ""); String canonicalizedQueryString = super.buildQueryString().replaceFirst("\\?", "");
toSign.append(canonicalizedQueryString); toSign.append(canonicalizedQueryString);

View File

@ -29,6 +29,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx; import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
@ -45,42 +46,39 @@ import com.google.inject.name.Named;
*/ */
public class BucketExists extends S3FutureCommand<Boolean> { public class BucketExists extends S3FutureCommand<Boolean> {
@Inject @Inject
public BucketExists(@Named("jclouds.http.address") String amazonHost, public BucketExists(@Named("jclouds.http.address") String amazonHost, ReturnTrueIf2xx callable,
ReturnTrueIf2xx callable, @Assisted String s3Bucket) { @Assisted String s3Bucket) {
super("HEAD", "/" + maxResults(0).buildQueryString(), callable, super(HttpMethod.HEAD, "/" + maxResults(0).buildQueryString(), callable, amazonHost, s3Bucket);
amazonHost, s3Bucket); }
}
@Override @Override
public Boolean get() throws InterruptedException, ExecutionException { public Boolean get() throws InterruptedException, ExecutionException {
try { try {
return super.get(); return super.get();
} catch (ExecutionException e) { } catch (ExecutionException e) {
return attemptNotFound(e); return attemptNotFound(e);
} }
} }
@VisibleForTesting @VisibleForTesting
Boolean attemptNotFound(ExecutionException e) throws ExecutionException { Boolean attemptNotFound(ExecutionException e) throws ExecutionException {
if (e.getCause() != null if (e.getCause() != null && e.getCause() instanceof HttpResponseException) {
&& e.getCause() instanceof HttpResponseException) { HttpResponseException responseException = (HttpResponseException) e.getCause();
HttpResponseException responseException = (HttpResponseException) e if (responseException.getResponse().getStatusCode() == 404) {
.getCause(); return false;
if (responseException.getResponse().getStatusCode() == 404) { }
return false; }
} throw e;
} }
throw e;
}
@Override @Override
public Boolean get(long l, TimeUnit timeUnit) throws InterruptedException, public Boolean get(long l, TimeUnit timeUnit) throws InterruptedException, ExecutionException,
ExecutionException, TimeoutException { TimeoutException {
try { try {
return super.get(l, timeUnit); return super.get(l, timeUnit);
} catch (ExecutionException e) { } catch (ExecutionException e) {
return attemptNotFound(e); return attemptNotFound(e);
} }
} }
} }

View File

@ -28,6 +28,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.aws.s3.commands.options.CopyObjectOptions; import org.jclouds.aws.s3.commands.options.CopyObjectOptions;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.xml.CopyObjectHandler; import org.jclouds.aws.s3.xml.CopyObjectHandler;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
@ -63,7 +64,7 @@ public class CopyObject extends S3FutureCommand<S3Object.Metadata> {
@Assisted("destinationObject") String destinationObject, @Assisted("destinationObject") String destinationObject,
@Assisted CopyObjectOptions options) @Assisted CopyObjectOptions options)
{ {
super("PUT", super(HttpMethod.PUT,
"/" + checkNotNull(destinationObject, "destinationObject"), "/" + checkNotNull(destinationObject, "destinationObject"),
callable, amazonHost, destinationBucket); callable, amazonHost, destinationBucket);
CopyObjectHandler handler = (CopyObjectHandler) callable.getHandler(); CopyObjectHandler handler = (CopyObjectHandler) callable.getHandler();

View File

@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.AWSResponseException;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx; import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -51,7 +52,7 @@ public class DeleteBucket extends S3FutureCommand<Boolean> {
@Inject @Inject
public DeleteBucket(@Named("jclouds.http.address") String amazonHost, ReturnTrueIf2xx callable, public DeleteBucket(@Named("jclouds.http.address") String amazonHost, ReturnTrueIf2xx callable,
@Assisted String s3Bucket) { @Assisted String s3Bucket) {
super("DELETE", "/", callable, amazonHost, s3Bucket); super(HttpMethod.DELETE, "/", callable, amazonHost, s3Bucket);
} }
@Override @Override

View File

@ -25,6 +25,7 @@ package org.jclouds.aws.s3.commands;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx; import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -32,8 +33,8 @@ import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named; import com.google.inject.name.Named;
/** /**
* The DELETE request operation removes the specified object from Amazon S3. * The DELETE request operation removes the specified object from Amazon S3. Once deleted, there is
* Once deleted, there is no method to restore or undelete an object. * no method to restore or undelete an object.
* *
* @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?
* RESTObjectDELETE.html" /> * RESTObjectDELETE.html" />
@ -41,10 +42,9 @@ import com.google.inject.name.Named;
*/ */
public class DeleteObject extends S3FutureCommand<Boolean> { public class DeleteObject extends S3FutureCommand<Boolean> {
@Inject @Inject
public DeleteObject(@Named("jclouds.http.address") String amazonHost, public DeleteObject(@Named("jclouds.http.address") String amazonHost, ReturnTrueIf2xx callable,
ReturnTrueIf2xx callable, @Assisted("bucketName") String bucket, @Assisted("bucketName") String bucket, @Assisted("key") String key) {
@Assisted("key") String key) { super(HttpMethod.DELETE, "/" + checkNotNull(key), callable, amazonHost, bucket);
super("DELETE", "/" + checkNotNull(key), callable, amazonHost, bucket); }
}
} }

View File

@ -29,6 +29,7 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.s3.domain.AccessControlList; import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -51,14 +52,14 @@ public class GetAccessControlList extends S3FutureCommand<AccessControlList> {
public GetAccessControlList(@Named("jclouds.http.address") String amazonHost, public GetAccessControlList(@Named("jclouds.http.address") String amazonHost,
ParseSax<AccessControlList> accessControlListParser, ParseSax<AccessControlList> accessControlListParser,
@Assisted("bucketName") String bucket) { @Assisted("bucketName") String bucket) {
super("GET", "/?acl", accessControlListParser, amazonHost, bucket); super(HttpMethod.GET, "/?acl", accessControlListParser, amazonHost, bucket);
} }
@Inject @Inject
public GetAccessControlList(@Named("jclouds.http.address") String amazonHost, public GetAccessControlList(@Named("jclouds.http.address") String amazonHost,
ParseSax<AccessControlList> accessControlListParser, ParseSax<AccessControlList> accessControlListParser,
@Assisted("bucketName") String bucket, @Assisted("objectKey") String objectKey) { @Assisted("bucketName") String bucket, @Assisted("objectKey") String objectKey) {
super("GET", "/" + objectKey + "?acl", accessControlListParser, amazonHost, bucket); super(HttpMethod.GET, "/" + objectKey + "?acl", accessControlListParser, amazonHost, bucket);
} }
@Override @Override

View File

@ -33,6 +33,7 @@ import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.s3.commands.callables.ParseObjectFromHeadersAndHttpContent; import org.jclouds.aws.s3.commands.callables.ParseObjectFromHeadersAndHttpContent;
import org.jclouds.aws.s3.commands.options.GetObjectOptions; import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.http.HttpMethod;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -68,7 +69,7 @@ public class GetObject extends S3FutureCommand<S3Object> {
public GetObject(@Named("jclouds.http.address") String amazonHost, public GetObject(@Named("jclouds.http.address") String amazonHost,
ParseObjectFromHeadersAndHttpContent callable, @Assisted("bucketName") String s3Bucket, ParseObjectFromHeadersAndHttpContent callable, @Assisted("bucketName") String s3Bucket,
@Assisted("key") String key, @Assisted GetObjectOptions options) { @Assisted("key") String key, @Assisted GetObjectOptions options) {
super("GET", "/" + checkNotNull(key), callable, amazonHost, s3Bucket); super(HttpMethod.GET, "/" + checkNotNull(key), callable, amazonHost, s3Bucket);
this.getRequest().getHeaders().putAll(options.buildRequestHeaders()); this.getRequest().getHeaders().putAll(options.buildRequestHeaders());
callable.setKey(key); callable.setKey(key);
} }

View File

@ -31,6 +31,7 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.commands.callables.ParseMetadataFromHeaders; import org.jclouds.aws.s3.commands.callables.ParseMetadataFromHeaders;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -43,58 +44,54 @@ import com.google.inject.name.Named;
* {@link org.jclouds.aws.s3.domain.S3Object.Metadata#NOT_FOUND} if not available. * {@link org.jclouds.aws.s3.domain.S3Object.Metadata#NOT_FOUND} if not available.
* *
* <p/> * <p/>
* The HEAD operation is used to retrieve information about a specific object or * The HEAD operation is used to retrieve information about a specific object or object size,
* object size, without actually fetching the object itself. This is useful if * without actually fetching the object itself. This is useful if you're only interested in the
* you're only interested in the object metadata, and don't want to waste * object metadata, and don't want to waste bandwidth on the object data.
* bandwidth on the object data.
* *
* @see GetObject * @see GetObject
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectHEAD.html" * @see <a
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectHEAD.html"
* /> * />
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class HeadObject extends S3FutureCommand<S3Object.Metadata> { public class HeadObject extends S3FutureCommand<S3Object.Metadata> {
@Inject @Inject
public HeadObject(@Named("jclouds.http.address") String amazonHost, public HeadObject(@Named("jclouds.http.address") String amazonHost,
ParseMetadataFromHeaders callable, ParseMetadataFromHeaders callable, @Assisted("bucketName") String bucket,
@Assisted("bucketName") String bucket, @Assisted("key") String key) { @Assisted("key") String key) {
super("HEAD", "/" + checkNotNull(key), callable, amazonHost, bucket); super(HttpMethod.HEAD, "/" + checkNotNull(key), callable, amazonHost, bucket);
callable.setKey(key); callable.setKey(key);
} }
@Override @Override
public S3Object.Metadata get() throws InterruptedException, public S3Object.Metadata get() throws InterruptedException, ExecutionException {
ExecutionException { try {
try { return super.get();
return super.get(); } catch (ExecutionException e) {
} catch (ExecutionException e) { return attemptNotFound(e);
return attemptNotFound(e); }
} }
}
@VisibleForTesting @VisibleForTesting
S3Object.Metadata attemptNotFound(ExecutionException e) S3Object.Metadata attemptNotFound(ExecutionException e) throws ExecutionException {
throws ExecutionException { if (e.getCause() != null && e.getCause() instanceof HttpResponseException) {
if (e.getCause() != null HttpResponseException responseException = (HttpResponseException) e.getCause();
&& e.getCause() instanceof HttpResponseException) { if (responseException.getResponse().getStatusCode() == 404) {
HttpResponseException responseException = (HttpResponseException) e return S3Object.Metadata.NOT_FOUND;
.getCause(); }
if (responseException.getResponse().getStatusCode() == 404) { }
return S3Object.Metadata.NOT_FOUND; throw e;
} }
}
throw e;
}
@Override @Override
public S3Object.Metadata get(long l, TimeUnit timeUnit) public S3Object.Metadata get(long l, TimeUnit timeUnit) throws InterruptedException,
throws InterruptedException, ExecutionException, TimeoutException { ExecutionException, TimeoutException {
try { try {
return super.get(l, timeUnit); return super.get(l, timeUnit);
} catch (ExecutionException e) { } catch (ExecutionException e) {
return attemptNotFound(e); return attemptNotFound(e);
} }
} }
} }

View File

@ -31,6 +31,7 @@ import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.s3.commands.options.ListBucketOptions; import org.jclouds.aws.s3.commands.options.ListBucketOptions;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.xml.ListBucketHandler; import org.jclouds.aws.s3.xml.ListBucketHandler;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -58,7 +59,7 @@ public class ListBucket extends S3FutureCommand<S3Bucket> {
public ListBucket(@Named("jclouds.http.address") String amazonHost, public ListBucket(@Named("jclouds.http.address") String amazonHost,
ParseSax<S3Bucket> bucketParser, @Assisted String bucket, ParseSax<S3Bucket> bucketParser, @Assisted String bucket,
@Assisted ListBucketOptions options) { @Assisted ListBucketOptions options) {
super("GET", "/" + options.buildQueryString(), bucketParser, amazonHost, bucket); super(HttpMethod.GET, "/" + options.buildQueryString(), bucketParser, amazonHost, bucket);
ListBucketHandler handler = (ListBucketHandler) bucketParser.getHandler(); ListBucketHandler handler = (ListBucketHandler) bucketParser.getHandler();
handler.setBucketName(bucket); handler.setBucketName(bucket);
} }

View File

@ -26,26 +26,27 @@ package org.jclouds.aws.s3.commands;
import java.util.List; import java.util.List;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.name.Named; import com.google.inject.name.Named;
/** /**
* Returns a list of all of the buckets owned by the authenticated sender of the * Returns a list of all of the buckets owned by the authenticated sender of the request.
* request.
* *
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTServiceGET.html" * @see <a
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTServiceGET.html"
* /> * />
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class ListOwnedBuckets extends S3FutureCommand<List<S3Bucket.Metadata>> { public class ListOwnedBuckets extends S3FutureCommand<List<S3Bucket.Metadata>> {
@Inject @Inject
public ListOwnedBuckets(@Named("jclouds.http.address") String amazonHost, public ListOwnedBuckets(@Named("jclouds.http.address") String amazonHost,
ParseSax<List<S3Bucket.Metadata>> callable) { ParseSax<List<S3Bucket.Metadata>> callable) {
super("GET", "/", callable, amazonHost); super(HttpMethod.GET, "/", callable, amazonHost);
} }
} }

View File

@ -31,6 +31,7 @@ import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.s3.commands.options.PutBucketOptions; import org.jclouds.aws.s3.commands.options.PutBucketOptions;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpHeaders; import org.jclouds.http.HttpHeaders;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx; import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -58,7 +59,7 @@ public class PutBucket extends S3FutureCommand<Boolean> {
@Inject @Inject
public PutBucket(@Named("jclouds.http.address") String amazonHost, ReturnTrueIf2xx callable, public PutBucket(@Named("jclouds.http.address") String amazonHost, ReturnTrueIf2xx callable,
@Assisted String bucketName, @Assisted PutBucketOptions options) { @Assisted String bucketName, @Assisted PutBucketOptions options) {
super("PUT", "/", callable, amazonHost, S3Utils.validateBucketName(bucketName)); super(HttpMethod.PUT, "/", callable, amazonHost, S3Utils.validateBucketName(bucketName));
getRequest().getHeaders().putAll(options.buildRequestHeaders()); getRequest().getHeaders().putAll(options.buildRequestHeaders());
String payload = options.buildPayload(); String payload = options.buildPayload();
if (payload != null) { if (payload != null) {
@ -77,7 +78,8 @@ public class PutBucket extends S3FutureCommand<Boolean> {
} }
@VisibleForTesting @VisibleForTesting
static Boolean eventualConsistencyAlreadyOwnedIsOk(ExecutionException e) throws ExecutionException { static Boolean eventualConsistencyAlreadyOwnedIsOk(ExecutionException e)
throws ExecutionException {
if (e.getCause() != null && e.getCause() instanceof AWSResponseException) { if (e.getCause() != null && e.getCause() instanceof AWSResponseException) {
AWSResponseException responseException = (AWSResponseException) e.getCause(); AWSResponseException responseException = (AWSResponseException) e.getCause();
if ("BucketAlreadyOwnedByYou".equals(responseException.getError().getCode())) { if ("BucketAlreadyOwnedByYou".equals(responseException.getError().getCode())) {

View File

@ -28,6 +28,7 @@ import javax.annotation.Resource;
import org.jclouds.aws.s3.domain.AccessControlList; import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.xml.AccessControlListBuilder; import org.jclouds.aws.s3.xml.AccessControlListBuilder;
import org.jclouds.http.HttpHeaders; import org.jclouds.http.HttpHeaders;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx; import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -52,7 +53,7 @@ public class PutBucketAccessControlList extends S3FutureCommand<Boolean> {
public PutBucketAccessControlList(@Named("jclouds.http.address") String amazonHost, public PutBucketAccessControlList(@Named("jclouds.http.address") String amazonHost,
ReturnTrueIf2xx callable, @Assisted("bucketName") String bucket, ReturnTrueIf2xx callable, @Assisted("bucketName") String bucket,
@Assisted AccessControlList acl) { @Assisted AccessControlList acl) {
super("PUT", "/?acl", callable, amazonHost, bucket); super(HttpMethod.PUT, "/?acl", callable, amazonHost, bucket);
String aclPayload = ""; String aclPayload = "";
try { try {

View File

@ -31,6 +31,7 @@ import org.jclouds.aws.s3.commands.options.PutObjectOptions;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpHeaders; import org.jclouds.http.HttpHeaders;
import org.jclouds.http.HttpMethod;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
@ -43,56 +44,54 @@ import com.google.inject.name.Named;
* This returns a byte[] of the md5 hash of what Amazon S3 received * This returns a byte[] of the md5 hash of what Amazon S3 received
* <p /> * <p />
* <p/> * <p/>
* This command allows you to specify {@link PutObjectOptions} to control * This command allows you to specify {@link PutObjectOptions} to control delivery of content.
* delivery of content.
* *
* *
* @see PutObjectOptions * @see PutObjectOptions
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT.html" * @see <a
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT.html"
* /> * />
* @author Adrian Cole * @author Adrian Cole
*/ */
public class PutObject extends S3FutureCommand<byte[]> { public class PutObject extends S3FutureCommand<byte[]> {
@Inject @Inject
public PutObject(@Named("jclouds.http.address") String amazonHost, public PutObject(@Named("jclouds.http.address") String amazonHost,
ParseMd5FromETagHeader callable, @Assisted String s3Bucket, ParseMd5FromETagHeader callable, @Assisted String s3Bucket, @Assisted S3Object object,
@Assisted S3Object object, @Assisted PutObjectOptions options) { @Assisted PutObjectOptions options) {
super("PUT", "/" + checkNotNull(object.getKey()), callable, amazonHost, super(HttpMethod.PUT, "/" + checkNotNull(object.getKey()), callable, amazonHost, s3Bucket);
s3Bucket); checkArgument(object.getMetadata().getSize() >= 0, "size must be set");
checkArgument(object.getMetadata().getSize() >= 0, "size must be set");
getRequest().setPayload( getRequest().setPayload(checkNotNull(object.getData(), "object.getContent()"));
checkNotNull(object.getData(), "object.getContent()"));
getRequest().getHeaders().put( getRequest().getHeaders()
HttpHeaders.CONTENT_TYPE, .put(
checkNotNull(object.getMetadata().getContentType(), HttpHeaders.CONTENT_TYPE,
"object.metadata.contentType()")); checkNotNull(object.getMetadata().getContentType(),
"object.metadata.contentType()"));
getRequest().getHeaders().put(HttpHeaders.CONTENT_LENGTH, getRequest().getHeaders()
object.getMetadata().getSize() + ""); .put(HttpHeaders.CONTENT_LENGTH, object.getMetadata().getSize() + "");
if (object.getMetadata().getCacheControl() != null) { if (object.getMetadata().getCacheControl() != null) {
getRequest().getHeaders().put(HttpHeaders.CACHE_CONTROL, getRequest().getHeaders().put(HttpHeaders.CACHE_CONTROL,
object.getMetadata().getCacheControl()); object.getMetadata().getCacheControl());
} }
if (object.getMetadata().getContentDisposition() != null) { if (object.getMetadata().getContentDisposition() != null) {
getRequest().getHeaders().put(HttpHeaders.CONTENT_DISPOSITION, getRequest().getHeaders().put(HttpHeaders.CONTENT_DISPOSITION,
object.getMetadata().getContentDisposition()); object.getMetadata().getContentDisposition());
} }
if (object.getMetadata().getContentEncoding() != null) { if (object.getMetadata().getContentEncoding() != null) {
getRequest().getHeaders().put(HttpHeaders.CONTENT_ENCODING, getRequest().getHeaders().put(HttpHeaders.CONTENT_ENCODING,
object.getMetadata().getContentEncoding()); object.getMetadata().getContentEncoding());
} }
if (object.getMetadata().getMd5() != null) if (object.getMetadata().getMd5() != null)
getRequest().getHeaders().put(HttpHeaders.CONTENT_MD5, getRequest().getHeaders().put(HttpHeaders.CONTENT_MD5,
S3Utils.toBase64String(object.getMetadata().getMd5())); S3Utils.toBase64String(object.getMetadata().getMd5()));
getRequest().getHeaders() getRequest().getHeaders().putAll(object.getMetadata().getUserMetadata());
.putAll(object.getMetadata().getUserMetadata()); getRequest().getHeaders().putAll(options.buildRequestHeaders());
getRequest().getHeaders().putAll(options.buildRequestHeaders());
} }
} }

View File

@ -28,6 +28,7 @@ import javax.annotation.Resource;
import org.jclouds.aws.s3.domain.AccessControlList; import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.xml.AccessControlListBuilder; import org.jclouds.aws.s3.xml.AccessControlListBuilder;
import org.jclouds.http.HttpHeaders; import org.jclouds.http.HttpHeaders;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx; import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -36,8 +37,8 @@ import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named; import com.google.inject.name.Named;
/** /**
* A PUT request operation directed at an object URI with the "acl" parameter * A PUT request operation directed at an object URI with the "acl" parameter sets the Access
* sets the Access Control List (ACL) settings for that S3 item. * Control List (ACL) settings for that S3 item.
* <p /> * <p />
* To set a bucket or object's ACL, you must have WRITE_ACP or FULL_CONTROL access to the item. * To set a bucket or object's ACL, you must have WRITE_ACP or FULL_CONTROL access to the item.
* *
@ -50,11 +51,10 @@ public class PutObjectAccessControlList extends S3FutureCommand<Boolean> {
@Inject @Inject
public PutObjectAccessControlList(@Named("jclouds.http.address") String amazonHost, public PutObjectAccessControlList(@Named("jclouds.http.address") String amazonHost,
ReturnTrueIf2xx callable, @Assisted("bucketName") String bucket, ReturnTrueIf2xx callable, @Assisted("bucketName") String bucket,
@Assisted("key") String objectKey, @Assisted AccessControlList acl) @Assisted("key") String objectKey, @Assisted AccessControlList acl) {
{ super(HttpMethod.PUT, "/" + objectKey + "?acl", callable, amazonHost, bucket);
super("PUT", "/" + objectKey + "?acl", callable, amazonHost, bucket);
String aclPayload = ""; String aclPayload = "";
try { try {
aclPayload = (new AccessControlListBuilder(acl)).getXmlString(); aclPayload = (new AccessControlListBuilder(acl)).getXmlString();
@ -63,8 +63,7 @@ public class PutObjectAccessControlList extends S3FutureCommand<Boolean> {
logger.error(e, "Unable to build XML document for Access Control List: " + acl); logger.error(e, "Unable to build XML document for Access Control List: " + acl);
} }
getRequest().setPayload(aclPayload); getRequest().setPayload(aclPayload);
getRequest().getHeaders().put( getRequest().getHeaders().put(HttpHeaders.CONTENT_LENGTH, aclPayload.getBytes().length + "");
HttpHeaders.CONTENT_LENGTH, aclPayload.getBytes().length + "");
} }
} }

View File

@ -26,6 +26,7 @@ package org.jclouds.aws.s3.commands;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.http.HttpFutureCommand; import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpMethod;
/** /**
* Conditionally adds the amazon host header to requests. * Conditionally adds the amazon host header to requests.
@ -36,13 +37,13 @@ import org.jclouds.http.HttpFutureCommand;
*/ */
public class S3FutureCommand<T> extends HttpFutureCommand<T> { public class S3FutureCommand<T> extends HttpFutureCommand<T> {
public S3FutureCommand(String method, String uri, ResponseCallable<T> responseCallable, public S3FutureCommand(HttpMethod method, String uri, ResponseCallable<T> responseCallable,
String amazonHost, String bucketName) { String amazonHost, String bucketName) {
super(method, uri, responseCallable); super(method, uri, responseCallable);
addHostHeader(checkNotNull(amazonHost, "amazonHost"), checkNotNull(bucketName, "bucketName")); addHostHeader(checkNotNull(amazonHost, "amazonHost"), checkNotNull(bucketName, "bucketName"));
} }
public S3FutureCommand(String method, String uri, ResponseCallable<T> responseCallable, public S3FutureCommand(HttpMethod method, String uri, ResponseCallable<T> responseCallable,
String amazonHost) { String amazonHost) {
super(method, uri, responseCallable); super(method, uri, responseCallable);
addHostHeader(checkNotNull(amazonHost, "amazonHost")); addHostHeader(checkNotNull(amazonHost, "amazonHost"));

View File

@ -39,7 +39,7 @@ import org.jclouds.logging.Logger;
*/ */
public class HttpFutureCommand<T> extends FutureCommand<HttpRequest, HttpResponse, T> { public class HttpFutureCommand<T> extends FutureCommand<HttpRequest, HttpResponse, T> {
public HttpFutureCommand(String method, String uri, ResponseCallable<T> responseCallable) { public HttpFutureCommand(HttpMethod method, String uri, ResponseCallable<T> responseCallable) {
super(new HttpRequest(checkNotNull(method, "method"), checkNotNull(uri, "uri")), super(new HttpRequest(checkNotNull(method, "method"), checkNotNull(uri, "uri")),
responseCallable); responseCallable);
} }

View File

@ -0,0 +1,33 @@
/**
*
* 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.http;
/**
* {@code HttpMethod} is an enumeration of HTTP methods used in {@link HttpFutureCommand}
*
* @author Adrian Cole
*/
public enum HttpMethod {
DELETE, GET, HEAD, POST, PUT
}

View File

@ -33,60 +33,59 @@ import org.jclouds.logging.Logger;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
/** /**
* Represents a request that can be executed within * Represents a request that can be executed within {@link HttpFutureCommandClient}
* {@link HttpFutureCommandClient}
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class HttpRequest extends HttpMessage { public class HttpRequest extends HttpMessage {
private final String method; private final HttpMethod method;
private final String uri; private final String uri;
Object payload; Object payload;
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
public HttpRequest(String method, String uri) { public HttpRequest(HttpMethod method, String uri) {
this.method = checkNotNull(method, "method"); this.method = checkNotNull(method, "method");
this.uri = Utils.encodeUriPath(checkNotNull(uri, "uri")); this.uri = Utils.encodeUriPath(checkNotNull(uri, "uri"));
} }
@Override @Override
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("HttpRequest"); sb.append("HttpRequest");
sb.append("{method='").append(method).append('\''); sb.append("{method='").append(method).append('\'');
sb.append(", uri='").append(uri).append('\''); sb.append(", uri='").append(uri).append('\'');
sb.append(", headers=").append(headers); sb.append(", headers=").append(headers);
sb.append(", payload set=").append(payload != null); sb.append(", payload set=").append(payload != null);
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
public String getMethod() { public HttpMethod getMethod() {
return method; return method;
} }
public String getUri() { public String getUri() {
return uri; return uri;
} }
public boolean isReplayable() { public boolean isReplayable() {
Object content = getPayload(); Object content = getPayload();
if (content != null && content instanceof InputStream) { if (content != null && content instanceof InputStream) {
logger.warn("%1$s: InputStreams are not replayable", toString()); logger.warn("%1$s: InputStreams are not replayable", toString());
return false; return false;
} }
return true; return true;
} }
public Object getPayload() { public Object getPayload() {
return payload; return payload;
} }
public void setPayload(Object content) {
this.payload = content;
}
public void setPayload(Object content) {
this.payload = content;
}
} }

View File

@ -24,16 +24,17 @@
package org.jclouds.http.commands; package org.jclouds.http.commands;
import org.jclouds.http.HttpFutureCommand; import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
/** /**
* // TODO: Adrian: Document this! * // TODO: Adrian: Document this!
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class GetAndParseSax<T> extends HttpFutureCommand<T> { public class GetAndParseSax<T> extends HttpFutureCommand<T> {
public GetAndParseSax(String uri, ParseSax<T> callable) { public GetAndParseSax(String uri, ParseSax<T> callable) {
super("GET", uri, callable); super(HttpMethod.GET, uri, callable);
} }
} }

View File

@ -23,20 +23,22 @@
*/ */
package org.jclouds.http.commands; package org.jclouds.http.commands;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.ReturnStringIf200;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.commands.callables.ReturnStringIf200;
/** /**
* // TODO: Adrian: Document this! * // TODO: Adrian: Document this!
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class GetString extends HttpFutureCommand<String> { public class GetString extends HttpFutureCommand<String> {
@Inject @Inject
public GetString(ReturnStringIf200 callable, @Assisted String uri) { public GetString(ReturnStringIf200 callable, @Assisted String uri) {
super("GET", uri, callable); super(HttpMethod.GET, uri, callable);
} }
} }

View File

@ -23,20 +23,22 @@
*/ */
package org.jclouds.http.commands; package org.jclouds.http.commands;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
/** /**
* // TODO: Adrian: Document this! * // TODO: Adrian: Document this!
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class Head extends HttpFutureCommand<Boolean> { public class Head extends HttpFutureCommand<Boolean> {
@Inject @Inject
public Head(ReturnTrueIf2xx callable, @Assisted String uri) { public Head(ReturnTrueIf2xx callable, @Assisted String uri) {
super("HEAD", uri, callable); super(HttpMethod.HEAD, uri, callable);
} }
} }

View File

@ -23,10 +23,12 @@
*/ */
package org.jclouds.http.commands; package org.jclouds.http.commands;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
/** /**
* PUT a string and respond with true if successful. * PUT a string and respond with true if successful.
@ -38,7 +40,7 @@ public class Put extends HttpFutureCommand<Boolean> {
@Inject @Inject
public Put(ReturnTrueIf2xx callable, @Assisted("uri") String uri, public Put(ReturnTrueIf2xx callable, @Assisted("uri") String uri,
@Assisted("payload") String payload) { @Assisted("payload") String payload) {
super("PUT", uri, callable); super(HttpMethod.PUT, uri, callable);
this.getRequest().setPayload(payload); this.getRequest().setPayload(payload);
} }
} }

View File

@ -37,6 +37,7 @@ import org.apache.commons.io.IOUtils;
import org.jclouds.http.HttpConstants; import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpFutureCommand; import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpFutureCommandClient; import org.jclouds.http.HttpFutureCommandClient;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
@ -79,7 +80,7 @@ public class JavaUrlHttpFutureCommandClient extends BaseHttpFutureCommandClient
} finally { } finally {
// DO NOT disconnect, as it will also close the unconsumed // DO NOT disconnect, as it will also close the unconsumed
// outputStream from above. // outputStream from above.
if (request.getMethod().equals("HEAD")) if (request.getMethod().equals(HttpMethod.HEAD))
connection.disconnect(); connection.disconnect();
} }
} }
@ -110,7 +111,7 @@ public class JavaUrlHttpFutureCommandClient extends BaseHttpFutureCommandClient
connection.setDoOutput(true); connection.setDoOutput(true);
connection.setAllowUserInteraction(false); connection.setAllowUserInteraction(false);
connection.setInstanceFollowRedirects(true); connection.setInstanceFollowRedirects(true);
connection.setRequestMethod(request.getMethod()); connection.setRequestMethod(request.getMethod().toString());
for (String header : request.getHeaders().keySet()) { for (String header : request.getHeaders().keySet()) {
for (String value : request.getHeaders().get(header)) for (String value : request.getHeaders().get(header))
connection.setRequestProperty(header, value); connection.setRequestProperty(header, value);

View File

@ -23,6 +23,7 @@
*/ */
package org.jclouds.http.commands; package org.jclouds.http.commands;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.commands.callables.ReturnStringIf200; import org.jclouds.http.commands.callables.ReturnStringIf200;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
@ -56,6 +57,6 @@ public class GetStringTest {
public void testConstructor() { public void testConstructor() {
assert get.getResponseFuture() != null; assert get.getResponseFuture() != null;
assert get.getRequest().getUri().equals(GOOD_PATH); assert get.getRequest().getUri().equals(GOOD_PATH);
assert get.getRequest().getMethod().equals("GET"); assert get.getRequest().getMethod().equals(HttpMethod.GET);
} }
} }

View File

@ -30,6 +30,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import org.jclouds.http.HttpFutureCommand; import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.commands.callables.ReturnStringIf200; import org.jclouds.http.commands.callables.ReturnStringIf200;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -38,73 +39,88 @@ import org.testng.annotations.Test;
public class BackoffLimitedRetryHandlerTest { public class BackoffLimitedRetryHandlerTest {
BackoffLimitedRetryHandler handler = new BackoffLimitedRetryHandler(5); BackoffLimitedRetryHandler handler = new BackoffLimitedRetryHandler(5);
@Test @Test
void testExponentialBackoffDelay() throws InterruptedException { void testExponentialBackoffDelay() throws InterruptedException {
long acceptableDelay = 25; // Delay to forgive if tests run long. long acceptableDelay = 25; // Delay to forgive if tests run long.
long startTime = System.currentTimeMillis();
handler.imposeBackoffExponentialDelay(1, "TEST FAILURE: 1");
long elapsedTime = System.currentTimeMillis() - startTime;
assertTrue(elapsedTime >= 50);
assertTrue(elapsedTime < 50 + acceptableDelay);
startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
handler.imposeBackoffExponentialDelay(2, "TEST FAILURE: 2"); handler.imposeBackoffExponentialDelay(1, "TEST FAILURE: 1");
elapsedTime = System.currentTimeMillis() - startTime; long elapsedTime = System.currentTimeMillis() - startTime;
assertTrue(elapsedTime >= 200); assertTrue(elapsedTime >= 50);
assertTrue(elapsedTime < 200 + acceptableDelay); assertTrue(elapsedTime < 50 + acceptableDelay);
startTime = System.currentTimeMillis(); startTime = System.currentTimeMillis();
handler.imposeBackoffExponentialDelay(3, "TEST FAILURE: 3"); handler.imposeBackoffExponentialDelay(2, "TEST FAILURE: 2");
elapsedTime = System.currentTimeMillis() - startTime; elapsedTime = System.currentTimeMillis() - startTime;
assertTrue(elapsedTime >= 450); assertTrue(elapsedTime >= 200);
assertTrue(elapsedTime < 450 + acceptableDelay); assertTrue(elapsedTime < 200 + acceptableDelay);
startTime = System.currentTimeMillis(); startTime = System.currentTimeMillis();
handler.imposeBackoffExponentialDelay(4, "TEST FAILURE: 4"); handler.imposeBackoffExponentialDelay(3, "TEST FAILURE: 3");
elapsedTime = System.currentTimeMillis() - startTime; elapsedTime = System.currentTimeMillis() - startTime;
assertTrue(elapsedTime >= 800); assertTrue(elapsedTime >= 450);
assertTrue(elapsedTime < 800 + acceptableDelay); assertTrue(elapsedTime < 450 + acceptableDelay);
startTime = System.currentTimeMillis(); startTime = System.currentTimeMillis();
handler.imposeBackoffExponentialDelay(5, "TEST FAILURE: 5"); handler.imposeBackoffExponentialDelay(4, "TEST FAILURE: 4");
elapsedTime = System.currentTimeMillis() - startTime; elapsedTime = System.currentTimeMillis() - startTime;
assertTrue(elapsedTime >= 1250); assertTrue(elapsedTime >= 800);
assertTrue(elapsedTime < 1250 + acceptableDelay); assertTrue(elapsedTime < 800 + acceptableDelay);
startTime = System.currentTimeMillis();
handler.imposeBackoffExponentialDelay(5, "TEST FAILURE: 5");
elapsedTime = System.currentTimeMillis() - startTime;
assertTrue(elapsedTime >= 1250);
assertTrue(elapsedTime < 1250 + acceptableDelay);
} }
@Test @Test
void testClosesInputStream() throws InterruptedException, IOException { void testClosesInputStream() throws InterruptedException, IOException {
HttpFutureCommand<String> command = HttpFutureCommand<String> command = new HttpFutureCommand<String>(HttpMethod.HEAD, "uri",
new HttpFutureCommand<String>("method", "uri", new ReturnStringIf200()); new ReturnStringIf200());
HttpResponse response = new HttpResponse(); HttpResponse response = new HttpResponse();
InputStream inputStream = new InputStream() { InputStream inputStream = new InputStream() {
boolean isOpen = true; boolean isOpen = true;
@Override
public void close() { this.isOpen = false; } @Override
@Override public void close() {
public int read() throws IOException { if (this.isOpen) return 1; else return -1; } this.isOpen = false;
@Override }
public int available() throws IOException { if (this.isOpen) return 1; else return 0; }
@Override
public int read() throws IOException {
if (this.isOpen)
return 1;
else
return -1;
}
@Override
public int available() throws IOException {
if (this.isOpen)
return 1;
else
return 0;
}
}; };
response.setContent(inputStream); response.setContent(inputStream);
assertEquals(response.getContent().available(), 1); assertEquals(response.getContent().available(), 1);
assertEquals(response.getContent().read(), 1); assertEquals(response.getContent().read(), 1);
handler.retryRequest(command, response); handler.retryRequest(command, response);
assertEquals(response.getContent().available(), 0); assertEquals(response.getContent().available(), 0);
assertEquals(response.getContent().read(), -1); assertEquals(response.getContent().read(), -1);
} }
@Test @Test
void testIncrementsFailureCount() throws InterruptedException { void testIncrementsFailureCount() throws InterruptedException {
HttpFutureCommand<String> command = HttpFutureCommand<String> command = new HttpFutureCommand<String>(HttpMethod.HEAD, "uri",
new HttpFutureCommand<String>("method", "uri", new ReturnStringIf200()); new ReturnStringIf200());
HttpResponse response = new HttpResponse(); HttpResponse response = new HttpResponse();
handler.retryRequest(command, response); handler.retryRequest(command, response);
assertEquals(command.getFailureCount(), 1); assertEquals(command.getFailureCount(), 1);
@ -117,21 +133,21 @@ public class BackoffLimitedRetryHandlerTest {
@Test @Test
void testDisallowsExcessiveRetries() throws InterruptedException { void testDisallowsExcessiveRetries() throws InterruptedException {
HttpFutureCommand<String> command = HttpFutureCommand<String> command = new HttpFutureCommand<String>(HttpMethod.HEAD, "uri",
new HttpFutureCommand<String>("method", "uri", new ReturnStringIf200()); new ReturnStringIf200());
HttpResponse response = new HttpResponse(); HttpResponse response = new HttpResponse();
assertEquals(handler.retryRequest(command, response), true); // Failure 1 assertEquals(handler.retryRequest(command, response), true); // Failure 1
assertEquals(handler.retryRequest(command, response), true); // Failure 2 assertEquals(handler.retryRequest(command, response), true); // Failure 2
assertEquals(handler.retryRequest(command, response), true); // Failure 3 assertEquals(handler.retryRequest(command, response), true); // Failure 3
assertEquals(handler.retryRequest(command, response), true); // Failure 4
assertEquals(handler.retryRequest(command, response), true); // Failure 5
assertEquals(handler.retryRequest(command, response), false); // Failure 6 assertEquals(handler.retryRequest(command, response), true); // Failure 4
assertEquals(handler.retryRequest(command, response), true); // Failure 5
assertEquals(handler.retryRequest(command, response), false); // Failure 6
} }
} }

View File

@ -167,13 +167,13 @@ public class URLFetchServiceClient extends BaseHttpFutureCommandClient {
} else { } else {
url = new URL(target, request.getUri()); url = new URL(target, request.getUri());
} }
FetchOptions options = disallowTruncate(); FetchOptions options = disallowTruncate();
followRedirectsUnlessRequestContainsPayload(request, options); followRedirectsUnlessRequestContainsPayload(request, options);
HTTPRequest gaeRequest = new HTTPRequest(url, HTTPMethod.valueOf(request.getMethod()), HTTPRequest gaeRequest = new HTTPRequest(url, HTTPMethod.valueOf(request.getMethod()
options); .toString()), options);
for (String header : request.getHeaders().keySet()) { for (String header : request.getHeaders().keySet()) {
// GAE/J v1.2.1 re-writes the host header, so we'll skip it. // GAE/J v1.2.1 re-writes the host header, so we'll skip it.
if (!header.equals(HttpConstants.HOST)) { if (!header.equals(HttpConstants.HOST)) {
@ -182,7 +182,7 @@ public class URLFetchServiceClient extends BaseHttpFutureCommandClient {
} }
} }
} }
if (request.getPayload() != null) { if (request.getPayload() != null) {
changeRequestContentToBytes(request); changeRequestContentToBytes(request);
gaeRequest.setPayload((byte[]) request.getPayload()); gaeRequest.setPayload((byte[]) request.getPayload());

View File

@ -40,6 +40,7 @@ import java.util.List;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.http.HttpHeaders; import org.jclouds.http.HttpHeaders;
import org.jclouds.http.HttpMethod;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
@ -100,21 +101,21 @@ public class URLFetchServiceClientTest {
@Test @Test
void testConvertRequestGetsTargetAndUri() throws IOException { void testConvertRequestGetsTargetAndUri() throws IOException {
HttpRequest request = new HttpRequest("GET", "foo"); HttpRequest request = new HttpRequest(HttpMethod.GET, "foo");
HTTPRequest gaeRequest = client.convert(request); HTTPRequest gaeRequest = client.convert(request);
assertEquals(gaeRequest.getURL().getPath(), "/foo"); assertEquals(gaeRequest.getURL().getPath(), "/foo");
} }
@Test @Test
void testConvertRequestSetsFetchOptions() throws IOException { void testConvertRequestSetsFetchOptions() throws IOException {
HttpRequest request = new HttpRequest("GET", "foo"); HttpRequest request = new HttpRequest(HttpMethod.GET, "foo");
HTTPRequest gaeRequest = client.convert(request); HTTPRequest gaeRequest = client.convert(request);
assert gaeRequest.getFetchOptions() != null; assert gaeRequest.getFetchOptions() != null;
} }
@Test @Test
void testConvertRequestSetsHeaders() throws IOException { void testConvertRequestSetsHeaders() throws IOException {
HttpRequest request = new HttpRequest("GET", "foo"); HttpRequest request = new HttpRequest(HttpMethod.GET, "foo");
request.getHeaders().put("foo", "bar"); request.getHeaders().put("foo", "bar");
HTTPRequest gaeRequest = client.convert(request); HTTPRequest gaeRequest = client.convert(request);
assertEquals(gaeRequest.getHeaders().get(0).getName(), "foo"); assertEquals(gaeRequest.getHeaders().get(0).getName(), "foo");
@ -123,36 +124,36 @@ public class URLFetchServiceClientTest {
@Test @Test
void testConvertRequestNoContent() throws IOException { void testConvertRequestNoContent() throws IOException {
HttpRequest request = new HttpRequest("GET", "foo"); HttpRequest request = new HttpRequest(HttpMethod.GET, "foo");
HTTPRequest gaeRequest = client.convert(request); HTTPRequest gaeRequest = client.convert(request);
assert gaeRequest.getPayload() == null; assert gaeRequest.getPayload() == null;
assertEquals(gaeRequest.getHeaders().size(), 1);//content length assertEquals(gaeRequest.getHeaders().size(), 1);// content length
} }
@Test @Test
void testConvertRequestStringContent() throws IOException { void testConvertRequestStringContent() throws IOException {
HttpRequest request = new HttpRequest("GET", "foo"); HttpRequest request = new HttpRequest(HttpMethod.GET, "foo");
request.setPayload("hoot!"); request.setPayload("hoot!");
testHoot(request); testHoot(request);
} }
@Test @Test
void testConvertRequestInputStreamContent() throws IOException { void testConvertRequestInputStreamContent() throws IOException {
HttpRequest request = new HttpRequest("GET", "foo"); HttpRequest request = new HttpRequest(HttpMethod.GET, "foo");
request.setPayload(IOUtils.toInputStream("hoot!")); request.setPayload(IOUtils.toInputStream("hoot!"));
testHoot(request); testHoot(request);
} }
@Test @Test
void testConvertRequestBytesContent() throws IOException { void testConvertRequestBytesContent() throws IOException {
HttpRequest request = new HttpRequest("GET", "foo"); HttpRequest request = new HttpRequest(HttpMethod.GET, "foo");
request.setPayload("hoot!".getBytes()); request.setPayload("hoot!".getBytes());
testHoot(request); testHoot(request);
} }
@Test(expectedExceptions = UnsupportedOperationException.class) @Test(expectedExceptions = UnsupportedOperationException.class)
void testConvertRequestBadContent() throws IOException { void testConvertRequestBadContent() throws IOException {
HttpRequest request = new HttpRequest("GET", "foo"); HttpRequest request = new HttpRequest(HttpMethod.GET, "foo");
request.setPayload(new Date()); request.setPayload(new Date());
client.convert(request); client.convert(request);
@ -164,7 +165,7 @@ public class URLFetchServiceClientTest {
File file = new File(basedir, "target/testfiles/hoot"); File file = new File(basedir, "target/testfiles/hoot");
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
IOUtils.write("hoot!", new FileOutputStream(file)); IOUtils.write("hoot!", new FileOutputStream(file));
HttpRequest request = new HttpRequest("GET", "foo"); HttpRequest request = new HttpRequest(HttpMethod.GET, "foo");
request.setPayload(file); request.setPayload(file);
testHoot(request); testHoot(request);
} }

View File

@ -41,79 +41,71 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
public class HttpNioUtils { public class HttpNioUtils {
public static HttpEntityEnclosingRequest convertToApacheRequest( public static HttpEntityEnclosingRequest convertToApacheRequest(HttpRequest object) {
HttpRequest object) { BasicHttpEntityEnclosingRequest apacheRequest = new BasicHttpEntityEnclosingRequest(object
BasicHttpEntityEnclosingRequest apacheRequest = new BasicHttpEntityEnclosingRequest( .getMethod().toString(), object.getUri(), HttpVersion.HTTP_1_1);
object.getMethod(), object.getUri(), HttpVersion.HTTP_1_1);
Object content = object.getPayload(); Object content = object.getPayload();
// Since we may remove headers, ensure they are added to the apache // Since we may remove headers, ensure they are added to the apache
// request after this block // request after this block
if (content != null) { if (content != null) {
long contentLength = Long.parseLong(object long contentLength = Long.parseLong(object
.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH)); .getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH));
object.getHeaders().removeAll(HttpHeaders.CONTENT_LENGTH); object.getHeaders().removeAll(HttpHeaders.CONTENT_LENGTH);
String contentType = object String contentType = object.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE);
.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE); object.getHeaders().removeAll(HttpHeaders.CONTENT_TYPE);
object.getHeaders().removeAll(HttpHeaders.CONTENT_TYPE); addEntityForContent(apacheRequest, content, contentType, contentLength);
addEntityForContent(apacheRequest, content, contentType, }
contentLength);
}
for (String header : object.getHeaders().keySet()) { for (String header : object.getHeaders().keySet()) {
for (String value : object.getHeaders().get(header)) for (String value : object.getHeaders().get(header))
apacheRequest.addHeader(header, value); apacheRequest.addHeader(header, value);
} }
return apacheRequest; return apacheRequest;
} }
public static void addEntityForContent( public static void addEntityForContent(BasicHttpEntityEnclosingRequest apacheRequest,
BasicHttpEntityEnclosingRequest apacheRequest, Object content, Object content, String contentType, long length) {
String contentType, long length) { if (content instanceof InputStream) {
if (content instanceof InputStream) { InputStream inputStream = (InputStream) content;
InputStream inputStream = (InputStream) content; if (length == -1)
if (length == -1) throw new IllegalArgumentException(
throw new IllegalArgumentException( "you must specify size when content is an InputStream");
"you must specify size when content is an InputStream"); InputStreamEntity entity = new InputStreamEntity(inputStream, length);
InputStreamEntity entity = new InputStreamEntity(inputStream, entity.setContentType(contentType);
length); apacheRequest.setEntity(entity);
entity.setContentType(contentType); } else if (content instanceof String) {
apacheRequest.setEntity(entity); NStringEntity nStringEntity = null;
} else if (content instanceof String) { try {
NStringEntity nStringEntity = null; nStringEntity = new NStringEntity((String) content);
try { } catch (UnsupportedEncodingException e) {
nStringEntity = new NStringEntity((String) content); throw new UnsupportedOperationException("Encoding not supported", e);
} catch (UnsupportedEncodingException e) { }
throw new UnsupportedOperationException( nStringEntity.setContentType(contentType);
"Encoding not supported", e); apacheRequest.setEntity(nStringEntity);
} } else if (content instanceof File) {
nStringEntity.setContentType(contentType); apacheRequest.setEntity(new NFileEntity((File) content, contentType, true));
apacheRequest.setEntity(nStringEntity); } else if (content instanceof byte[]) {
} else if (content instanceof File) { NByteArrayEntity entity = new NByteArrayEntity((byte[]) content);
apacheRequest.setEntity(new NFileEntity((File) content, entity.setContentType(contentType);
contentType, true)); apacheRequest.setEntity(entity);
} else if (content instanceof byte[]) { } else {
NByteArrayEntity entity = new NByteArrayEntity((byte[]) content); throw new UnsupportedOperationException("Content class not supported: "
entity.setContentType(contentType); + content.getClass().getName());
apacheRequest.setEntity(entity); }
} else { }
throw new UnsupportedOperationException(
"Content class not supported: "
+ content.getClass().getName());
}
}
public static HttpResponse convertToJavaCloudsResponse( public static HttpResponse convertToJavaCloudsResponse(
org.apache.http.HttpResponse apacheResponse) throws IOException { org.apache.http.HttpResponse apacheResponse) throws IOException {
HttpResponse response = new HttpResponse(); HttpResponse response = new HttpResponse();
if (apacheResponse.getEntity() != null) { if (apacheResponse.getEntity() != null) {
response.setContent(apacheResponse.getEntity().getContent()); response.setContent(apacheResponse.getEntity().getContent());
} }
for (Header header : apacheResponse.getAllHeaders()) { for (Header header : apacheResponse.getAllHeaders()) {
response.getHeaders().put(header.getName(), header.getValue()); response.getHeaders().put(header.getName(), header.getValue());
} }
response.setStatusCode(apacheResponse.getStatusLine().getStatusCode()); response.setStatusCode(apacheResponse.getStatusLine().getStatusCode());
return response; return response;
} }
} }