From a17da70588db2f6964262efe249249baafa5ba9a Mon Sep 17 00:00:00 2001 From: "adrian.f.cole" Date: Fri, 22 Jan 2010 00:30:07 +0000 Subject: [PATCH] support null; add AuthorizationException git-svn-id: http://jclouds.googlecode.com/svn/trunk@2717 3d8758e0-26b5-11de-8745-db77d3ebf521 --- .../saas/blobstore/AtmosAsyncBlobStore.java | 21 +++--- .../saas/blobstore/AtmosBlobStore.java | 19 +++++- .../functions/BlobMetadataToObject.java | 10 +-- .../blobstore/functions/BlobToObject.java | 2 + .../blobstore/functions/ObjectToBlob.java | 2 + .../functions/ObjectToBlobMetadata.java | 2 + .../ReturnEndpointIfAlreadyExists.java | 6 +- .../saas/AtmosStorageClientTest.java | 6 +- .../internal/StubAtmosStorageAsyncClient.java | 13 +--- .../functions/ReturnVoidOnGroupNotFound.java | 18 +---- .../ReturnVoidOnVolumeAvailable.java | 18 +---- .../aws/s3/blobstore/S3AsyncBlobStore.java | 20 +++--- .../jclouds/aws/s3/blobstore/S3BlobStore.java | 13 +++- .../s3/blobstore/functions/BlobToObject.java | 2 + .../functions/BlobToObjectMetadata.java | 22 ++++--- .../s3/blobstore/functions/ObjectToBlob.java | 2 + .../functions/ObjectToBlobMetadata.java | 2 + .../ReturnTrueIfBucketAlreadyOwnedByYou.java | 5 +- .../ReturnTrueOn404FalseIfNotEmpty.java | 5 +- .../aws/ec2/services/AMIAsyncClientTest.java | 14 ++-- .../ElasticBlockStoreAsyncClientTest.java | 14 ++-- .../ElasticIPAddressAsyncClientTest.java | 8 +-- .../ec2/services/InstanceAsyncClientTest.java | 18 ++--- .../ec2/services/KeyPairAsyncClientTest.java | 4 +- .../SecurityGroupAsyncClientTest.java | 14 ++-- .../org/jclouds/aws/s3/S3AsyncClientTest.java | 12 ++-- ...turnTrueIfBucketAlreadyOwnedByYouTest.java | 19 ++---- .../aws/s3/internal/StubS3AsyncClient.java | 2 +- .../aws/s3/jets3t/JCloudsS3Service.java | 2 +- .../blob/blobstore/AzureAsyncBlobStore.java | 20 +++--- .../blob/blobstore/AzureBlobStore.java | 16 ++++- .../blobstore/functions/AzureBlobToBlob.java | 2 + .../BlobMetadataToBlobProperties.java | 22 ++++--- .../BlobPropertiesToBlobMetadata.java | 2 + .../blobstore/functions/BlobToAzureBlob.java | 2 + .../ReturnTrueIfContainerAlreadyExists.java | 4 +- .../blob/AzureBlobAsyncClientTest.java | 26 ++++---- .../queue/AzureQueueAsyncClientTest.java | 22 +++---- .../functions/ClearAndDeleteIfNotEmpty.java | 21 ++---- .../functions/ReturnVoidOnNotFoundOr404.java | 24 ++----- .../ThrowContainerNotFoundOn404.java | 4 +- .../functions/ThrowKeyNotFoundOn404.java | 4 +- .../blobstore/internal/BaseBlobMap.java | 4 -- .../blobstore/internal/BlobMapImpl.java | 13 ++-- .../internal/InputStreamMapImpl.java | 17 ++--- .../GetAllBlobsInListAndRetryOnFailure.java | 26 +++----- .../blobstore/util/BlobStoreUtils.java | 12 ++++ .../internal/BaseBlobIntegrationTest.java | 3 + .../internal/StubAsyncBlobStore.java | 15 +++-- ...etryOnNotFoundGetAllBlobsStrategyTest.java | 9 ++- .../compute/BaseComputeServiceLiveTest.java | 3 +- .../{internal => }/ConcurrentUtils.java | 12 +++- .../ConvertFutureExceptionToValue.java | 66 +++++++++++++++++++ .../concurrent/FutureExceptionParser.java | 13 ++-- ...dIf2xx.java => CloseContentAndReturn.java} | 23 +------ .../http/functions/ReturnFalseOn404.java | 4 +- .../http/functions/ReturnTrueOn404.java | 4 +- .../BaseHttpCommandExecutorService.java | 2 +- .../jclouds/rest/AuthorizationException.java | 47 +++++++++++++ .../org/jclouds/rest/RestContextFactory.java | 8 ++- ....java => MapHttp4xxCodesToExceptions.java} | 14 ++-- .../rest/internal/AsyncRestClientProxy.java | 4 +- .../internal/RestAnnotationProcessor.java | 8 +-- .../src/main/java/org/jclouds/util/Utils.java | 7 ++ .../concurrent/FutureExceptionParserTest.java | 14 ++-- .../concurrent/internal/SyncProxyTest.java | 2 +- .../java/org/jclouds/rest/RestClientTest.java | 4 +- .../internal/RestAnnotationProcessorTest.java | 4 +- ...ransformingHttpCommandExecutorService.java | 2 +- .../functions/AddMetadataItemIntoMap.java | 15 +---- .../ReturnFalseIfContainerNotFound.java | 4 +- .../ReturnTrueIfContainerAlreadyExists.java | 4 +- .../org/jclouds/mezeo/pcs2/PCSClientTest.java | 18 ++--- .../org/jclouds/mezeo/pcs2/PCSCloudTest.java | 4 +- .../jclouds/nirvanix/sdn/SDNClientTest.java | 6 +- .../blobstore/CloudFilesAsyncBlobStore.java | 9 ++- .../blobstore/CloudFilesBlobStore.java | 18 +++-- .../blobstore/functions/BlobToObject.java | 2 + .../blobstore/functions/ObjectToBlob.java | 2 + .../functions/ObjectToBlobMetadata.java | 2 + .../functions/ResourceToObjectInfo.java | 28 ++++---- .../functions/ReturnTrueOn404FalseOn409.java | 5 +- .../RackspaceAuthenticationLiveTest.java | 4 +- .../cloudservers/CloudServersClientTest.java | 44 ++++++------- .../functions/ParseRimuHostingException.java | 21 +++--- .../jclouds/vcloud/VCloudAsyncClientTest.java | 8 +-- .../ReturnVoidOnDeleteDefaultIp.java | 19 ++---- .../TerremarkVCloudAsyncClientTest.java | 6 +- 88 files changed, 580 insertions(+), 443 deletions(-) rename core/src/main/java/org/jclouds/concurrent/{internal => }/ConcurrentUtils.java (90%) create mode 100644 core/src/main/java/org/jclouds/concurrent/ConvertFutureExceptionToValue.java rename core/src/main/java/org/jclouds/http/functions/{ReturnVoidIf2xx.java => CloseContentAndReturn.java} (62%) create mode 100644 core/src/main/java/org/jclouds/rest/AuthorizationException.java rename core/src/main/java/org/jclouds/rest/functions/{ThrowResourceNotFoundOn404.java => MapHttp4xxCodesToExceptions.java} (72%) diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosAsyncBlobStore.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosAsyncBlobStore.java index 82c152168a..5384cf0ea1 100644 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosAsyncBlobStore.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosAsyncBlobStore.java @@ -20,7 +20,8 @@ package org.jclouds.atmosonline.saas.blobstore; import static com.google.common.util.concurrent.Futures.compose; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive; -import static org.jclouds.concurrent.internal.ConcurrentUtils.makeListenable; +import static org.jclouds.concurrent.ConcurrentUtils.convertExceptionToValue; +import static org.jclouds.concurrent.ConcurrentUtils.makeListenable; import java.net.URI; import java.util.concurrent.Callable; @@ -39,6 +40,7 @@ import org.jclouds.atmosonline.saas.blobstore.internal.BaseAtmosBlobStore; import org.jclouds.atmosonline.saas.domain.AtmosObject; import org.jclouds.atmosonline.saas.options.ListOptions; import org.jclouds.blobstore.AsyncBlobStore; +import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.ListContainerResponse; @@ -81,13 +83,13 @@ public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlob * This implementation uses the AtmosStorage HEAD Object command to return the result */ public ListenableFuture blobMetadata(String container, String key) { - return compose(async.headFile(container + "/" + key), - new Function() { - @Override - public BlobMetadata apply(AtmosObject from) { - return object2BlobMd.apply(from); - } - }, service); + return compose(convertExceptionToValue(async.headFile(container + "/" + key), + KeyNotFoundException.class, null), new Function() { + @Override + public BlobMetadata apply(AtmosObject from) { + return object2BlobMd.apply(from); + } + }, service); } public ListenableFuture clearContainer(final String container) { @@ -155,7 +157,8 @@ public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlob org.jclouds.blobstore.options.GetOptions... optionsList) { GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList); ListenableFuture returnVal = async.readFile(container + "/" + key, httpOptions); - return compose(returnVal, object2Blob, service); + return compose(convertExceptionToValue(returnVal, KeyNotFoundException.class, null), + object2Blob, service); } public ListenableFuture> list() { diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobStore.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobStore.java index 2acde8548c..65a2d62305 100644 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobStore.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobStore.java @@ -19,6 +19,7 @@ package org.jclouds.atmosonline.saas.blobstore; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive; +import static org.jclouds.blobstore.util.BlobStoreUtils.returnNullOnKeyNotFoundOrPropagate; import java.util.concurrent.ExecutorService; @@ -71,7 +72,11 @@ public class AtmosBlobStore extends BaseAtmosBlobStore implements BlobStore { * This implementation uses the AtmosStorage HEAD Object command to return the result */ public BlobMetadata blobMetadata(String container, String key) { - return object2BlobMd.apply(sync.headFile(container + "/" + key)); + try { + return object2BlobMd.apply(sync.headFile(container + "/" + key)); + } catch (Exception e) { + return returnNullOnKeyNotFoundOrPropagate(e); + } } public void clearContainer(final String container) { @@ -115,13 +120,21 @@ public class AtmosBlobStore extends BaseAtmosBlobStore implements BlobStore { } public boolean directoryExists(String container, String directory) { - return sync.pathExists(container + "/" + directory); + try { + return sync.pathExists(container + "/" + directory); + } catch (Exception e) { + return (Boolean)returnNullOnKeyNotFoundOrPropagate(e); + } } public Blob getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions... optionsList) { GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList); - return object2Blob.apply(sync.readFile(container + "/" + key, httpOptions)); + try { + return object2Blob.apply(sync.readFile(container + "/" + key, httpOptions)); + } catch (Exception e) { + return returnNullOnKeyNotFoundOrPropagate(e); + } } public ListResponse list() { diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/BlobMetadataToObject.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/BlobMetadataToObject.java index 6ef7bd74e6..d88611d932 100644 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/BlobMetadataToObject.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/BlobMetadataToObject.java @@ -44,11 +44,13 @@ public class BlobMetadataToObject implements Function this.blob2SysMd = blob2SysMd; } - public AtmosObject apply(BlobMetadata base) { + public AtmosObject apply(BlobMetadata from) { + if (from == null) + return null; UserMetadata userMd = new UserMetadata(); - if (base.getUserMetadata() != null) - userMd.getMetadata().putAll(base.getUserMetadata()); - return factory.create(blob2ContentMd.apply(base), blob2SysMd.apply(base), userMd); + if (from.getUserMetadata() != null) + userMd.getMetadata().putAll(from.getUserMetadata()); + return factory.create(blob2ContentMd.apply(from), blob2SysMd.apply(from), userMd); } } \ No newline at end of file diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/BlobToObject.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/BlobToObject.java index dba20ce1b6..1b88bc389e 100644 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/BlobToObject.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/BlobToObject.java @@ -39,6 +39,8 @@ public class BlobToObject implements Function { } public AtmosObject apply(Blob from) { + if (from == null) + return null; AtmosObject object = blobMd2Object.apply(from.getMetadata()); object.setPayload(from.getPayload()); object.setAllHeaders(from.getAllHeaders()); diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/ObjectToBlob.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/ObjectToBlob.java index a4f902a718..70b88efe78 100644 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/ObjectToBlob.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/ObjectToBlob.java @@ -42,6 +42,8 @@ public class ObjectToBlob implements Function { } public Blob apply(AtmosObject from) { + if (from == null) + return null; Blob blob = blobFactory.create(object2BlobMd.apply(from)); if (from.getContentMetadata().getContentLength() != null) blob.setContentLength(from.getContentMetadata().getContentLength()); diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/ObjectToBlobMetadata.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/ObjectToBlobMetadata.java index 3e1f157678..8a7229c5da 100644 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/ObjectToBlobMetadata.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/functions/ObjectToBlobMetadata.java @@ -55,6 +55,8 @@ public class ObjectToBlobMetadata implements Function, if (from instanceof KeyAlreadyExistsException) { return endpoint; } - return null; + return URI.class.cast(propagateOrNull(from)); } public void setContext(GeneratedHttpRequest request) { - this.endpoint = request == null?null:request.getEndpoint(); + this.endpoint = request == null ? null : request.getEndpoint(); } } \ No newline at end of file diff --git a/atmos/src/test/java/org/jclouds/atmosonline/saas/AtmosStorageClientTest.java b/atmos/src/test/java/org/jclouds/atmosonline/saas/AtmosStorageClientTest.java index d2f23069d0..fcfbce2a16 100644 --- a/atmos/src/test/java/org/jclouds/atmosonline/saas/AtmosStorageClientTest.java +++ b/atmos/src/test/java/org/jclouds/atmosonline/saas/AtmosStorageClientTest.java @@ -45,7 +45,7 @@ import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.date.TimeStamp; import org.jclouds.encryption.internal.Base64; import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x; -import org.jclouds.http.functions.ReturnVoidIf2xx; +import org.jclouds.http.functions.CloseContentAndReturn; import org.jclouds.http.options.GetOptions; import org.jclouds.logging.Logger; import org.jclouds.logging.Logger.LoggerFactory; @@ -199,7 +199,7 @@ public class AtmosStorageClientTest extends RestClientTest= 1) - return immediateFuture(false); return immediateFailedFuture(e); } } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/functions/ReturnVoidOnGroupNotFound.java b/aws/core/src/main/java/org/jclouds/aws/ec2/functions/ReturnVoidOnGroupNotFound.java index b5590e4dca..2b6277859a 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/functions/ReturnVoidOnGroupNotFound.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/functions/ReturnVoidOnGroupNotFound.java @@ -18,7 +18,7 @@ */ package org.jclouds.aws.ec2.functions; -import java.lang.reflect.Constructor; +import static org.jclouds.util.Utils.propagateOrNull; import javax.inject.Singleton; @@ -29,24 +29,12 @@ import com.google.common.base.Function; @Singleton public class ReturnVoidOnGroupNotFound implements Function { - static final Void v; - static { - Constructor cv; - try { - cv = Void.class.getDeclaredConstructor(); - cv.setAccessible(true); - v = cv.newInstance(); - } catch (Exception e) { - throw new Error("Error setting up class", e); - } - } - public Void apply(Exception from) { if (from instanceof AWSResponseException) { if (((AWSResponseException) from).getError().getCode().equals("InvalidGroup.NotFound")) - return v; + return null; } - return null; + return Void.class.cast(propagateOrNull(from)); } } \ No newline at end of file diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/functions/ReturnVoidOnVolumeAvailable.java b/aws/core/src/main/java/org/jclouds/aws/ec2/functions/ReturnVoidOnVolumeAvailable.java index 634742628d..1ca4489391 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/functions/ReturnVoidOnVolumeAvailable.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/functions/ReturnVoidOnVolumeAvailable.java @@ -18,7 +18,7 @@ */ package org.jclouds.aws.ec2.functions; -import java.lang.reflect.Constructor; +import static org.jclouds.util.Utils.propagateOrNull; import javax.inject.Singleton; @@ -29,26 +29,14 @@ import com.google.common.base.Function; @Singleton public class ReturnVoidOnVolumeAvailable implements Function { - static final Void v; - static { - Constructor cv; - try { - cv = Void.class.getDeclaredConstructor(); - cv.setAccessible(true); - v = cv.newInstance(); - } catch (Exception e) { - throw new Error("Error setting up class", e); - } - } - public Void apply(Exception from) { if (from instanceof AWSResponseException) { AWSResponseException e = (AWSResponseException) from; if (e.getError().getCode().equals("IncorrectState") && e.getError().getCode().contains("available")) - return v; + return null; } - return null; + return Void.class.cast(propagateOrNull(from)); } } \ No newline at end of file diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3AsyncBlobStore.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3AsyncBlobStore.java index 463572be4a..a5f37fd5fe 100644 --- a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3AsyncBlobStore.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3AsyncBlobStore.java @@ -20,7 +20,8 @@ package org.jclouds.aws.s3.blobstore; import static com.google.common.util.concurrent.Futures.compose; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive; -import static org.jclouds.concurrent.internal.ConcurrentUtils.makeListenable; +import static org.jclouds.concurrent.ConcurrentUtils.convertExceptionToValue; +import static org.jclouds.concurrent.ConcurrentUtils.makeListenable; import java.util.SortedSet; import java.util.concurrent.Callable; @@ -87,15 +88,15 @@ public class S3AsyncBlobStore extends BaseS3BlobStore implements AsyncBlobStore * This implementation uses the S3 HEAD Object command to return the result */ public ListenableFuture blobMetadata(String container, String key) { - return compose(makeListenable(async.headObject(container, key), service), - new Function() { + return compose(convertExceptionToValue(async.headObject(container, key), + KeyNotFoundException.class, null), new Function() { - @Override - public BlobMetadata apply(ObjectMetadata from) { - return object2BlobMd.apply(from); - } + @Override + public BlobMetadata apply(ObjectMetadata from) { + return object2BlobMd.apply(from); + } - }, service); + }, service); } public ListenableFuture clearContainer(final String container) { @@ -158,7 +159,8 @@ public class S3AsyncBlobStore extends BaseS3BlobStore implements AsyncBlobStore public ListenableFuture getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions... optionsList) { GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList); - return compose(async.getObject(container, key, httpOptions), object2Blob, service); + return compose(convertExceptionToValue(async.getObject(container, key, httpOptions), + KeyNotFoundException.class, null), object2Blob, service); } public ListenableFuture> list() { diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3BlobStore.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3BlobStore.java index c601587de6..f47f20d166 100644 --- a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3BlobStore.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3BlobStore.java @@ -19,6 +19,7 @@ package org.jclouds.aws.s3.blobstore; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive; +import static org.jclouds.blobstore.util.BlobStoreUtils.returnNullOnKeyNotFoundOrPropagate; import java.util.SortedSet; import java.util.concurrent.ExecutorService; @@ -80,7 +81,11 @@ public class S3BlobStore extends BaseS3BlobStore implements BlobStore { * This implementation uses the S3 HEAD Object command to return the result */ public BlobMetadata blobMetadata(String container, String key) { - return object2BlobMd.apply(sync.headObject(container, key)); + try { + return object2BlobMd.apply(sync.headObject(container, key)); + } catch (Exception e) { + return returnNullOnKeyNotFoundOrPropagate(e); + } } public void clearContainer(String container) { @@ -116,7 +121,11 @@ public class S3BlobStore extends BaseS3BlobStore implements BlobStore { public Blob getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions... optionsList) { GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList); - return object2Blob.apply(sync.getObject(container, key, httpOptions)); + try { + return object2Blob.apply(sync.getObject(container, key, httpOptions)); + } catch (Exception e) { + return returnNullOnKeyNotFoundOrPropagate(e); + } } public ListResponse list() { diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/BlobToObject.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/BlobToObject.java index c56edcbf64..35f2fb887a 100644 --- a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/BlobToObject.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/BlobToObject.java @@ -41,6 +41,8 @@ public class BlobToObject implements Function { } public S3Object apply(Blob from) { + if (from == null) + return null; S3Object object = objectProvider.create(blob2ObjectMd.apply(from.getMetadata())); if (from.getContentLength() != null) object.setContentLength(from.getContentLength()); diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/BlobToObjectMetadata.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/BlobToObjectMetadata.java index f91a702138..154fbe72d1 100644 --- a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/BlobToObjectMetadata.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/BlobToObjectMetadata.java @@ -31,17 +31,19 @@ import com.google.common.base.Function; */ @Singleton public class BlobToObjectMetadata implements Function { - public MutableObjectMetadata apply(BlobMetadata base) { + public MutableObjectMetadata apply(BlobMetadata from) { + if (from == null) + return null; MutableObjectMetadata to = new MutableObjectMetadataImpl(); - to.setContentType(base.getContentType()); - to.setETag(base.getETag()); - to.setContentMD5(base.getContentMD5()); - to.setKey(base.getName()); - to.setLastModified(base.getLastModified()); - if (base.getSize() != null) - to.setSize(base.getSize()); - if (base.getUserMetadata() != null) - to.setUserMetadata(base.getUserMetadata()); + to.setContentType(from.getContentType()); + to.setETag(from.getETag()); + to.setContentMD5(from.getContentMD5()); + to.setKey(from.getName()); + to.setLastModified(from.getLastModified()); + if (from.getSize() != null) + to.setSize(from.getSize()); + if (from.getUserMetadata() != null) + to.setUserMetadata(from.getUserMetadata()); return to; } diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/ObjectToBlob.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/ObjectToBlob.java index 91790d0a65..543c8a4680 100644 --- a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/ObjectToBlob.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/ObjectToBlob.java @@ -42,6 +42,8 @@ public class ObjectToBlob implements Function { } public Blob apply(S3Object from) { + if (from == null) + return null; Blob blob = blobFactory.create(object2BlobMd.apply(from.getMetadata())); if (from.getContentLength() != null) blob.setContentLength(from.getContentLength()); diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/ObjectToBlobMetadata.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/ObjectToBlobMetadata.java index 668ab1a0e8..3c002b9bff 100644 --- a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/ObjectToBlobMetadata.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/functions/ObjectToBlobMetadata.java @@ -42,6 +42,8 @@ public class ObjectToBlobMetadata implements Function { "Content-Length: 57\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); assertPayloadEquals(httpMethod, "Version=2009-11-30&Action=DeregisterImage&ImageId=imageId"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -339,7 +339,7 @@ public class AMIAsyncClientTest extends RestClientTest { httpMethod, "Action=ModifyImageAttribute&Attribute=launchPermission&ImageId=imageId&OperationType=add&Signature=pWWwIIdcLSw0vrWFpRsCnHk93X3qYWVfcl%2FaXRhoFd8%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&UserGroup.1=all&UserId.1=bob&UserId.2=sue&Version=2009-11-30&AWSAccessKeyId=user"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -359,7 +359,7 @@ public class AMIAsyncClientTest extends RestClientTest { assertPayloadEquals( httpMethod, "Version=2009-11-30&Action=ModifyImageAttribute&OperationType=remove&Attribute=launchPermission&ImageId=imageId&UserGroup.1=all&UserId.1=bob&UserId.2=sue"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -378,7 +378,7 @@ public class AMIAsyncClientTest extends RestClientTest { "Content-Length: 88\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); assertPayloadEquals(httpMethod, "Version=2009-11-30&Action=ResetImageAttribute&Attribute=launchPermission&ImageId=imageId"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -399,7 +399,7 @@ public class AMIAsyncClientTest extends RestClientTest { httpMethod, "Version=2009-11-30&Action=ModifyImageAttribute&OperationType=add&Attribute=productCodes&ImageId=imageId&ProductCode.1=code1&ProductCode.2=code2"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -420,7 +420,7 @@ public class AMIAsyncClientTest extends RestClientTest { httpMethod, "Version=2009-11-30&Action=ModifyImageAttribute&OperationType=remove&Attribute=productCodes&ImageId=imageId&ProductCode.1=code1&ProductCode.2=code2"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/services/ElasticBlockStoreAsyncClientTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/services/ElasticBlockStoreAsyncClientTest.java index 0350c61426..fba6110a76 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/services/ElasticBlockStoreAsyncClientTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/services/ElasticBlockStoreAsyncClientTest.java @@ -47,7 +47,7 @@ import org.jclouds.aws.filters.FormSigner; import org.jclouds.aws.reference.AWSConstants; import org.jclouds.date.TimeStamp; import org.jclouds.http.functions.ParseSax; -import org.jclouds.http.functions.ReturnVoidIf2xx; +import org.jclouds.http.functions.CloseContentAndReturn; import org.jclouds.logging.Logger; import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.rest.RestClientTest; @@ -121,7 +121,7 @@ public class ElasticBlockStoreAsyncClientTest extends RestClientTest assertPayloadEquals(httpMethod, "Version=2009-11-30&Action=RebootInstances&InstanceId.1=1&InstanceId.2=2"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -409,7 +409,7 @@ public class InstanceAsyncClientTest extends RestClientTest httpMethod, "Action=ModifyInstanceAttribute&Attribute=userData&InstanceId=1&Signature=LyanxPcmESLrkIIFu9RX2yGN1rSQmyF489LYcoszbFE%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Value=dGVzdA%3D%3D&Version=2009-11-30&AWSAccessKeyId=user"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -428,7 +428,7 @@ public class InstanceAsyncClientTest extends RestClientTest "Content-Length: 91\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); assertPayloadEquals(httpMethod, "Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=ramdisk&Value=test&InstanceId=1"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -447,7 +447,7 @@ public class InstanceAsyncClientTest extends RestClientTest "Content-Length: 90\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); assertPayloadEquals(httpMethod, "Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=kernel&Value=test&InstanceId=1"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -469,7 +469,7 @@ public class InstanceAsyncClientTest extends RestClientTest httpMethod, "Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=disableApiTermination&Value=true&InstanceId=1"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -490,7 +490,7 @@ public class InstanceAsyncClientTest extends RestClientTest httpMethod, "Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=instanceType&Value=c1.medium&InstanceId=1"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -512,7 +512,7 @@ public class InstanceAsyncClientTest extends RestClientTest httpMethod, "Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=instanceInitiatedShutdownBehavior&Value=terminate&InstanceId=1"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -538,7 +538,7 @@ public class InstanceAsyncClientTest extends RestClientTest httpMethod, "Action=ModifyInstanceAttribute&Attribute=blockDeviceMapping&InstanceId=1&Signature=KNCKfLATSmpXGuIBpXOx3lBmHv9tyu17Cxrfi%2FTzQHE%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Value=test&Version=2009-11-30&AWSAccessKeyId=user"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/services/KeyPairAsyncClientTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/services/KeyPairAsyncClientTest.java index dbe654647e..fa22d259e7 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/services/KeyPairAsyncClientTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/services/KeyPairAsyncClientTest.java @@ -35,7 +35,7 @@ import org.jclouds.aws.filters.FormSigner; import org.jclouds.aws.reference.AWSConstants; import org.jclouds.date.TimeStamp; import org.jclouds.http.functions.ParseSax; -import org.jclouds.http.functions.ReturnVoidIf2xx; +import org.jclouds.http.functions.CloseContentAndReturn; import org.jclouds.logging.Logger; import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.rest.RestClientTest; @@ -69,7 +69,7 @@ public class KeyPairAsyncClientTest extends RestClientTest { "Content-Length: 53\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); assertPayloadEquals(httpMethod, "Version=2009-11-30&Action=DeleteKeyPair&KeyName=mykey"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/services/SecurityGroupAsyncClientTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/services/SecurityGroupAsyncClientTest.java index 6631ddd91f..479904c5d9 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/services/SecurityGroupAsyncClientTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/services/SecurityGroupAsyncClientTest.java @@ -38,7 +38,7 @@ import org.jclouds.aws.filters.FormSigner; import org.jclouds.aws.reference.AWSConstants; import org.jclouds.date.TimeStamp; import org.jclouds.http.functions.ParseSax; -import org.jclouds.http.functions.ReturnVoidIf2xx; +import org.jclouds.http.functions.CloseContentAndReturn; import org.jclouds.logging.Logger; import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.rest.RestClientTest; @@ -74,7 +74,7 @@ public class SecurityGroupAsyncClientTest extends RestClientTest { httpMethod, "BucketOwner"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -153,7 +153,7 @@ public class S3AsyncClientTest extends RestClientTest { httpMethod, "Requester"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -237,7 +237,7 @@ public class S3AsyncClientTest extends RestClientTest { assertHeadersEqual(httpMethod, "Host: bucket.stub\n"); assertPayloadEquals(httpMethod, null); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); @@ -458,7 +458,7 @@ public class S3AsyncClientTest extends RestClientTest { assertPayloadEquals(httpMethod, ""); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -479,7 +479,7 @@ public class S3AsyncClientTest extends RestClientTest { assertPayloadEquals(httpMethod, Utils.toStringAndClose(getClass().getResourceAsStream( "/s3/bucket_logging.xml"))); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); diff --git a/aws/core/src/test/java/org/jclouds/aws/s3/functions/ReturnTrueIfBucketAlreadyOwnedByYouTest.java b/aws/core/src/test/java/org/jclouds/aws/s3/functions/ReturnTrueIfBucketAlreadyOwnedByYouTest.java index 035eb819ae..4bb9b2bd3d 100755 --- a/aws/core/src/test/java/org/jclouds/aws/s3/functions/ReturnTrueIfBucketAlreadyOwnedByYouTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/s3/functions/ReturnTrueIfBucketAlreadyOwnedByYouTest.java @@ -18,13 +18,8 @@ */ package org.jclouds.aws.s3.functions; -import static org.easymock.EasyMock.expect; -import static org.easymock.classextension.EasyMock.createMock; -import static org.easymock.classextension.EasyMock.replay; - import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.domain.AWSError; -import org.jclouds.aws.s3.functions.ReturnTrueIfBucketAlreadyOwnedByYou; import org.testng.annotations.Test; /** @@ -39,19 +34,15 @@ public class ReturnTrueIfBucketAlreadyOwnedByYouTest { assert new ReturnTrueIfBucketAlreadyOwnedByYou().apply(e); } - @Test + @Test(expectedExceptions = AWSResponseException.class) void testBlahIsNotOk() throws Exception { Exception e = getErrorWithCode("blah"); - assert new ReturnTrueIfBucketAlreadyOwnedByYou().apply(e) == null; + new ReturnTrueIfBucketAlreadyOwnedByYou().apply(e); } private Exception getErrorWithCode(String code) { - AWSResponseException inner = createMock(AWSResponseException.class); - AWSError error = createMock(AWSError.class); - expect(inner.getError()).andReturn(error); - expect(error.getCode()).andReturn(code); - replay(inner); - replay(error); - return inner; + AWSError error = new AWSError(); + error.setCode(code); + return new AWSResponseException(null, null, null, error); } } \ No newline at end of file diff --git a/aws/core/src/test/java/org/jclouds/aws/s3/internal/StubS3AsyncClient.java b/aws/core/src/test/java/org/jclouds/aws/s3/internal/StubS3AsyncClient.java index f0f5936bd3..49b5bb1bd1 100755 --- a/aws/core/src/test/java/org/jclouds/aws/s3/internal/StubS3AsyncClient.java +++ b/aws/core/src/test/java/org/jclouds/aws/s3/internal/StubS3AsyncClient.java @@ -64,7 +64,7 @@ import org.jclouds.blobstore.domain.MutableBlobMetadata; import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions; import org.jclouds.blobstore.integration.internal.StubAsyncBlobStore; import org.jclouds.blobstore.options.ListContainerOptions; -import org.jclouds.concurrent.internal.ConcurrentUtils; +import org.jclouds.concurrent.ConcurrentUtils; import org.jclouds.date.DateService; import org.jclouds.http.options.GetOptions; diff --git a/aws/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java b/aws/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java index c15f868624..6e120136db 100755 --- a/aws/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java +++ b/aws/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java @@ -122,7 +122,7 @@ public class JCloudsS3Service extends S3Service { throw new UnsupportedOperationException("Bucket ACL is not yet supported"); try { - if (connection.putBucketInRegion(Region.fromValue(location), bucketName)) { + if (connection.putBucketInRegion(Region.DEFAULT, bucketName)) { // Bucket created. } } catch (Exception e) { diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureAsyncBlobStore.java b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureAsyncBlobStore.java index 8bce26e1c7..ee57e36020 100644 --- a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureAsyncBlobStore.java +++ b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureAsyncBlobStore.java @@ -20,7 +20,8 @@ package org.jclouds.azure.storage.blob.blobstore; import static com.google.common.util.concurrent.Futures.compose; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive; -import static org.jclouds.concurrent.internal.ConcurrentUtils.makeListenable; +import static org.jclouds.concurrent.ConcurrentUtils.convertExceptionToValue; +import static org.jclouds.concurrent.ConcurrentUtils.makeListenable; import static org.jclouds.azure.storage.options.ListOptions.Builder.*; import java.util.Set; import java.util.concurrent.Callable; @@ -87,15 +88,15 @@ public class AzureAsyncBlobStore extends BaseAzureBlobStore implements AsyncBlob * This implementation uses the AzureBlob HEAD Object command to return the result */ public ListenableFuture blobMetadata(String container, String key) { - return compose(async.getBlobProperties(container, key), - new Function() { + return compose(convertExceptionToValue(async.getBlobProperties(container, key), + KeyNotFoundException.class, null), new Function() { - @Override - public BlobMetadata apply(BlobProperties from) { - return object2BlobMd.apply(from); - } + @Override + public BlobMetadata apply(BlobProperties from) { + return object2BlobMd.apply(from); + } - }, service); + }, service); } public ListenableFuture clearContainer(final String container) { @@ -129,7 +130,8 @@ public class AzureAsyncBlobStore extends BaseAzureBlobStore implements AsyncBlob org.jclouds.blobstore.options.GetOptions... optionsList) { GetOptions azureOptions = blob2ObjectGetOptions.apply(optionsList); ListenableFuture returnVal = async.getBlob(container, key, azureOptions); - return compose(returnVal, object2Blob, service); + return compose(convertExceptionToValue(returnVal, KeyNotFoundException.class, null), + object2Blob, service); } public ListenableFuture> list() { diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobStore.java b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobStore.java index 0140b347f6..c84e782728 100644 --- a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobStore.java +++ b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobStore.java @@ -20,6 +20,7 @@ package org.jclouds.azure.storage.blob.blobstore; import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive; +import static org.jclouds.blobstore.util.BlobStoreUtils.returnNullOnKeyNotFoundOrPropagate; import java.util.Set; import java.util.concurrent.ExecutorService; @@ -80,7 +81,11 @@ public class AzureBlobStore extends BaseAzureBlobStore implements BlobStore { * This implementation uses the AzureBlob HEAD Object command to return the result */ public BlobMetadata blobMetadata(String container, String key) { - return object2BlobMd.apply(sync.getBlobProperties(container, key)); + try { + return object2BlobMd.apply(sync.getBlobProperties(container, key)); + } catch (Exception e) { + return returnNullOnKeyNotFoundOrPropagate(e); + } } public void clearContainer(final String container) { @@ -118,7 +123,11 @@ public class AzureBlobStore extends BaseAzureBlobStore implements BlobStore { public Blob getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions... optionsList) { GetOptions azureOptions = blob2ObjectGetOptions.apply(optionsList); - return object2Blob.apply(sync.getBlob(container, key, azureOptions)); + try { + return object2Blob.apply(sync.getBlob(container, key, azureOptions)); + } catch (Exception e) { + return returnNullOnKeyNotFoundOrPropagate(e); + } } public ListResponse list() { @@ -134,7 +143,8 @@ public class AzureBlobStore extends BaseAzureBlobStore implements BlobStore { public ListContainerResponse list(String container, ListContainerOptions... optionsList) { ListBlobsOptions azureOptions = container2ContainerListOptions.apply(optionsList); - return container2ResourceList.apply(sync.listBlobs(container, azureOptions.includeMetadata())); + return container2ResourceList + .apply(sync.listBlobs(container, azureOptions.includeMetadata())); } public String putBlob(String container, Blob blob) { diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/functions/AzureBlobToBlob.java b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/functions/AzureBlobToBlob.java index 1d15eb1053..d99530d472 100644 --- a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/functions/AzureBlobToBlob.java +++ b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/functions/AzureBlobToBlob.java @@ -42,6 +42,8 @@ public class AzureBlobToBlob implements Function { } public Blob apply(AzureBlob from) { + if (from == null) + return null; Blob blob = blobFactory.create(blobPr2BlobMd.apply(from.getProperties())); if (from.getContentLength() != null) blob.setContentLength(from.getContentLength()); diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/functions/BlobMetadataToBlobProperties.java b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/functions/BlobMetadataToBlobProperties.java index 23bc844e97..41dff3116a 100644 --- a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/functions/BlobMetadataToBlobProperties.java +++ b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/functions/BlobMetadataToBlobProperties.java @@ -31,17 +31,19 @@ import com.google.common.base.Function; */ @Singleton public class BlobMetadataToBlobProperties implements Function { - public MutableBlobProperties apply(BlobMetadata base) { + public MutableBlobProperties apply(BlobMetadata from) { + if (from == null) + return null; MutableBlobProperties to = new MutableBlobPropertiesImpl(); - to.setContentType(base.getContentType()); - to.setETag(base.getETag()); - to.setContentMD5(base.getContentMD5()); - to.setName(base.getName()); - to.setLastModified(base.getLastModified()); - if (base.getSize() != null) - to.setContentLength(base.getSize()); - if (base.getUserMetadata() != null) - to.setMetadata(base.getUserMetadata()); + to.setContentType(from.getContentType()); + to.setETag(from.getETag()); + to.setContentMD5(from.getContentMD5()); + to.setName(from.getName()); + to.setLastModified(from.getLastModified()); + if (from.getSize() != null) + to.setContentLength(from.getSize()); + if (from.getUserMetadata() != null) + to.setMetadata(from.getUserMetadata()); return to; } diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/functions/BlobPropertiesToBlobMetadata.java b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/functions/BlobPropertiesToBlobMetadata.java index 66ba940921..d59a080fcd 100644 --- a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/functions/BlobPropertiesToBlobMetadata.java +++ b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/functions/BlobPropertiesToBlobMetadata.java @@ -42,6 +42,8 @@ public class BlobPropertiesToBlobMetadata implements Function { } public AzureBlob apply(Blob from) { + if (from == null) + return null; AzureBlob object = objectProvider.create(blob2ObjectMd.apply(from.getMetadata())); if (from.getContentLength() != null) object.setContentLength(from.getContentLength()); diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/functions/ReturnTrueIfContainerAlreadyExists.java b/azure/src/main/java/org/jclouds/azure/storage/blob/functions/ReturnTrueIfContainerAlreadyExists.java index cab4351585..d23baadebb 100644 --- a/azure/src/main/java/org/jclouds/azure/storage/blob/functions/ReturnTrueIfContainerAlreadyExists.java +++ b/azure/src/main/java/org/jclouds/azure/storage/blob/functions/ReturnTrueIfContainerAlreadyExists.java @@ -18,6 +18,8 @@ */ package org.jclouds.azure.storage.blob.functions; +import static org.jclouds.util.Utils.propagateOrNull; + import org.jclouds.azure.storage.AzureStorageResponseException; import com.google.common.base.Function; @@ -35,7 +37,7 @@ public class ReturnTrueIfContainerAlreadyExists implements Functionmessage"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -207,7 +207,7 @@ public class AzureQueueAsyncClientTest extends RestClientTestmessage"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -223,7 +223,7 @@ public class AzureQueueAsyncClientTest extends RestClientTest, InvocationContext { - static final Void v; - static { - Constructor cv; - try { - cv = Void.class.getDeclaredConstructor(); - cv.setAccessible(true); - v = cv.newInstance(); - } catch (Exception e) { - throw new Error("Error setting up class", e); - } - } + /** * maximum duration of an blob Request */ @@ -69,13 +60,13 @@ public class ClearAndDeleteIfNotEmpty implements Function, Invo if (from instanceof HttpResponseException) { HttpResponseException responseException = (HttpResponseException) from; if (responseException.getResponse().getStatusCode() == 404) { - return v; + return null; } else if (responseException.getResponse().getStatusCode() == 409) { clear.execute(request.getArgs()[0].toString()); try { connection.deleteContainer(request.getArgs()[0].toString()).get( requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); - return v; + return null; } catch (Exception e) { Throwables.propagateIfPossible(e, BlobRuntimeException.class); throw new BlobRuntimeException("Error deleting container: " @@ -83,7 +74,7 @@ public class ClearAndDeleteIfNotEmpty implements Function, Invo } } } - return null; + return Void.class.cast(propagateOrNull(from)); } public void setContext(GeneratedHttpRequest request) { diff --git a/blobstore/src/main/java/org/jclouds/blobstore/functions/ReturnVoidOnNotFoundOr404.java b/blobstore/src/main/java/org/jclouds/blobstore/functions/ReturnVoidOnNotFoundOr404.java index 43549a324f..b89109bac7 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/functions/ReturnVoidOnNotFoundOr404.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/functions/ReturnVoidOnNotFoundOr404.java @@ -19,8 +19,7 @@ package org.jclouds.blobstore.functions; import static com.google.common.base.Preconditions.checkNotNull; - -import java.lang.reflect.Constructor; +import static org.jclouds.util.Utils.propagateOrNull; import javax.inject.Inject; import javax.inject.Singleton; @@ -34,18 +33,6 @@ import com.google.common.base.Function; @Singleton public class ReturnVoidOnNotFoundOr404 implements Function { - static final Void v; - static { - Constructor cv; - try { - cv = Void.class.getDeclaredConstructor(); - cv.setAccessible(true); - v = cv.newInstance(); - } catch (Exception e) { - throw new Error("Error setting up class", e); - } - } - private final ReturnTrueOn404 rto404; @Inject @@ -55,11 +42,12 @@ public class ReturnVoidOnNotFoundOr404 implements Function { public Void apply(Exception from) { if (from instanceof KeyNotFoundException || from instanceof ContainerNotFoundException) { - return v; + return null; } else { - return rto404.apply(from) ? v : null; + Boolean value = rto404.apply(from); + if (value != null && value) + return null; } - + return Void.class.cast(propagateOrNull(from)); } - } \ No newline at end of file diff --git a/blobstore/src/main/java/org/jclouds/blobstore/functions/ThrowContainerNotFoundOn404.java b/blobstore/src/main/java/org/jclouds/blobstore/functions/ThrowContainerNotFoundOn404.java index 178b13d5b9..6ffe1472e9 100755 --- a/blobstore/src/main/java/org/jclouds/blobstore/functions/ThrowContainerNotFoundOn404.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/functions/ThrowContainerNotFoundOn404.java @@ -18,6 +18,8 @@ */ package org.jclouds.blobstore.functions; +import static org.jclouds.util.Utils.propagateOrNull; + import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.http.HttpResponseException; @@ -40,7 +42,7 @@ public class ThrowContainerNotFoundOn404 implements Function throw new ContainerNotFoundException(from); } } - return null; + return propagateOrNull(from); } } diff --git a/blobstore/src/main/java/org/jclouds/blobstore/functions/ThrowKeyNotFoundOn404.java b/blobstore/src/main/java/org/jclouds/blobstore/functions/ThrowKeyNotFoundOn404.java index d6aada6d38..383ecab5ab 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/functions/ThrowKeyNotFoundOn404.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/functions/ThrowKeyNotFoundOn404.java @@ -18,6 +18,8 @@ */ package org.jclouds.blobstore.functions; +import static org.jclouds.util.Utils.propagateOrNull; + import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.http.HttpResponseException; @@ -40,7 +42,7 @@ public class ThrowKeyNotFoundOn404 implements Function { throw new KeyNotFoundException(from); } } - return null; + return propagateOrNull(from); } } diff --git a/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseBlobMap.java b/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseBlobMap.java index b837bd0a26..6cfe6bcbed 100755 --- a/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseBlobMap.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseBlobMap.java @@ -42,7 +42,6 @@ import org.jclouds.blobstore.strategy.ContainsValueInListStrategy; import org.jclouds.blobstore.strategy.CountListStrategy; import org.jclouds.blobstore.strategy.GetBlobsInListStrategy; import org.jclouds.blobstore.strategy.ListBlobMetadataStrategy; -import org.jclouds.rest.ResourceNotFoundException; import com.google.common.base.Function; import com.google.common.base.Throwables; @@ -205,9 +204,6 @@ public abstract class BaseBlobMap { return connection.blobMetadata(containerName, realKey).get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS) != null; } catch (Exception e) { - if (Iterables.size(Iterables.filter(Throwables.getCausalChain(e), - ResourceNotFoundException.class)) >= 1) - return false; Throwables.propagateIfPossible(e, BlobRuntimeException.class); throw new BlobRuntimeException(String.format("Error searching for %1$s:%2$s", containerName, realKey), e); diff --git a/blobstore/src/main/java/org/jclouds/blobstore/internal/BlobMapImpl.java b/blobstore/src/main/java/org/jclouds/blobstore/internal/BlobMapImpl.java index 2a6d87daf2..58550f7dce 100755 --- a/blobstore/src/main/java/org/jclouds/blobstore/internal/BlobMapImpl.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/internal/BlobMapImpl.java @@ -40,7 +40,6 @@ import org.jclouds.blobstore.strategy.ListBlobMetadataStrategy; import com.google.common.base.Function; import com.google.common.base.Throwables; import com.google.common.collect.Collections2; -import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.common.util.concurrent.ListenableFuture; @@ -116,12 +115,10 @@ public class BlobMapImpl extends BaseBlobMap implements BlobMap { public Blob get(Object key) { String realKey = prefixer.apply(key.toString()); try { - return stripPrefix(connection.getBlob(containerName, realKey).get( - requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)); + Blob blob = connection.getBlob(containerName, realKey).get(requestTimeoutMilliseconds, + TimeUnit.MILLISECONDS); + return blob != null ? stripPrefix(blob) : null; } catch (Exception e) { - if (Iterables.size(Iterables.filter(Throwables.getCausalChain(e), - KeyNotFoundException.class)) >= 1) - return null; Throwables.propagateIfPossible(e, BlobRuntimeException.class); throw new BlobRuntimeException(String.format("Error geting blob %s:%s", containerName, realKey), e); @@ -180,8 +177,8 @@ public class BlobMapImpl extends BaseBlobMap implements BlobMap { TimeUnit.MILLISECONDS); } catch (Exception e) { Throwables.propagateIfPossible(e, BlobRuntimeException.class); - throw new BlobRuntimeException(String.format("Error removing blob %s:%s", - containerName, realKey), e); + throw new BlobRuntimeException(String.format("Error removing blob %s:%s", containerName, + realKey), e); } return old; } diff --git a/blobstore/src/main/java/org/jclouds/blobstore/internal/InputStreamMapImpl.java b/blobstore/src/main/java/org/jclouds/blobstore/internal/InputStreamMapImpl.java index 49a8052a15..dfcaedeace 100755 --- a/blobstore/src/main/java/org/jclouds/blobstore/internal/InputStreamMapImpl.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/internal/InputStreamMapImpl.java @@ -49,7 +49,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.Throwables; import com.google.common.collect.Collections2; -import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.common.util.concurrent.ListenableFuture; @@ -82,12 +81,10 @@ public class InputStreamMapImpl extends BaseBlobMap implements Inpu public InputStream get(Object o) { String realKey = prefixer.apply(o.toString()); try { - return connection.getBlob(containerName, realKey).get(requestTimeoutMilliseconds, - TimeUnit.MILLISECONDS).getContent(); + Blob blob = connection.getBlob(containerName, realKey).get(requestTimeoutMilliseconds, + TimeUnit.MILLISECONDS); + return blob != null ? blob.getContent() : null; } catch (Exception e) { - if (Iterables.size(Iterables.filter(Throwables.getCausalChain(e), - KeyNotFoundException.class)) >= 1) - return null; Throwables.propagateIfPossible(e, BlobRuntimeException.class); throw new BlobRuntimeException(String.format("Error geting blob %s:%s", containerName, realKey), e); @@ -107,8 +104,8 @@ public class InputStreamMapImpl extends BaseBlobMap implements Inpu TimeUnit.MILLISECONDS); } catch (Exception e) { Throwables.propagateIfPossible(e, BlobRuntimeException.class); - throw new BlobRuntimeException(String.format("Error removing blob %s:%s", - containerName, realKey), e); + throw new BlobRuntimeException(String.format("Error removing blob %s:%s", containerName, + realKey), e); } return old; } @@ -295,8 +292,8 @@ public class InputStreamMapImpl extends BaseBlobMap implements Inpu return returnVal; } catch (Exception e) { Throwables.propagateIfPossible(e, BlobRuntimeException.class); - throw new BlobRuntimeException(String.format("Error adding blob %s:%s", - containerName, object), e); + throw new BlobRuntimeException(String.format("Error adding blob %s:%s", containerName, + object), e); } } diff --git a/blobstore/src/main/java/org/jclouds/blobstore/strategy/internal/GetAllBlobsInListAndRetryOnFailure.java b/blobstore/src/main/java/org/jclouds/blobstore/strategy/internal/GetAllBlobsInListAndRetryOnFailure.java index e8599f5d31..db84f0b926 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/strategy/internal/GetAllBlobsInListAndRetryOnFailure.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/strategy/internal/GetAllBlobsInListAndRetryOnFailure.java @@ -30,7 +30,6 @@ import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.blobstore.AsyncBlobStore; -import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.internal.BlobRuntimeException; @@ -41,7 +40,6 @@ import org.jclouds.blobstore.strategy.ListBlobMetadataStrategy; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Throwables; -import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.util.concurrent.ListenableFuture; @@ -84,7 +82,8 @@ public class GetAllBlobsInListAndRetryOnFailure implements GetBlobsInListStrateg for (BlobMetadata md : getAllBlobMetadata.execute(container, options)) { futureObjects.put(md.getName(), connection.getBlob(container, md.getName())); } - for (Entry> futureObjectEntry : futureObjects.entrySet()) { + for (Entry> futureObjectEntry : futureObjects + .entrySet()) { try { ifNotFoundRetryOtherwiseAddToSet(container, futureObjectEntry.getKey(), futureObjectEntry.getValue(), objects); @@ -103,20 +102,15 @@ public class GetAllBlobsInListAndRetryOnFailure implements GetBlobsInListStrateg ListenableFuture value, Set objects) throws InterruptedException, ExecutionException, TimeoutException { for (int i = 0; i < 3; i++) { - try { - Blob object = value.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); - object.getMetadata().setName(key); - objects.add(object); - return; - } catch (Exception e) { - if (Iterables.size(Iterables.filter(Throwables.getCausalChain(e), - KeyNotFoundException.class)) >= 1) { - Thread.sleep(requestRetryMilliseconds); - value = connection.getBlob(container, key); - } else { - Throwables.propagate(e); - } + Blob object = value.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); + if (object == null) { + Thread.sleep(requestRetryMilliseconds); + value = connection.getBlob(container, key); + continue; } + object.getMetadata().setName(key); + objects.add(object); + return; } } } \ No newline at end of file diff --git a/blobstore/src/main/java/org/jclouds/blobstore/util/BlobStoreUtils.java b/blobstore/src/main/java/org/jclouds/blobstore/util/BlobStoreUtils.java index c65079dcb8..c9c02f4117 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/util/BlobStoreUtils.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/util/BlobStoreUtils.java @@ -19,22 +19,34 @@ package org.jclouds.blobstore.util; import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.util.Utils.propagateOrNull; import java.io.IOException; import java.io.InputStream; import org.jclouds.blobstore.BlobStore; +import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.util.Utils; +import com.google.common.base.Throwables; +import com.google.common.collect.Iterables; + /** * Encryption, Hashing, and IO Utilities needed to sign and verify S3 requests and responses. * * @author Adrian Cole */ public class BlobStoreUtils { + @SuppressWarnings("unchecked") + public static T returnNullOnKeyNotFoundOrPropagate(Exception e) { + if (Iterables + .size(Iterables.filter(Throwables.getCausalChain(e), KeyNotFoundException.class)) >= 1) + return null; + return (T) propagateOrNull(e); + } public static Blob newBlob(BlobStore blobStore, StorageMetadata blobMeta) { Blob blob = blobStore.newBlob(blobMeta.getName()); diff --git a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java index d57070a526..a6ed10fd0d 100755 --- a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java +++ b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java @@ -25,6 +25,7 @@ import static org.jclouds.blobstore.options.GetOptions.Builder.ifUnmodifiedSince import static org.jclouds.blobstore.options.GetOptions.Builder.range; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; import java.io.File; import java.io.FileInputStream; @@ -328,6 +329,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { object.getMetadata().setContentMD5(new JCEEncryptionService().md5(TEST_STRING.getBytes())); String containerName = getContainerName(); try { + assertNull(context.getBlobStore().blobMetadata(containerName, "powderpuff")); + addBlobToContainer(containerName, object); Blob newObject = validateContent(containerName, key); diff --git a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/StubAsyncBlobStore.java b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/StubAsyncBlobStore.java index ff5ba29a3c..d9021ce053 100755 --- a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/StubAsyncBlobStore.java +++ b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/StubAsyncBlobStore.java @@ -21,7 +21,7 @@ package org.jclouds.blobstore.integration.internal; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.util.concurrent.Futures.immediateFailedFuture; import static com.google.common.util.concurrent.Futures.immediateFuture; -import static org.jclouds.concurrent.internal.ConcurrentUtils.makeListenable; +import static org.jclouds.concurrent.ConcurrentUtils.makeListenable; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -150,7 +150,6 @@ public class StubAsyncBlobStore implements AsyncBlobStore { throw new UnsupportedOperationException("Content not supported " + data.getClass()); } return bytes; - } public ListenableFuture getBlob(final String bucketName, final String key) { @@ -158,7 +157,7 @@ public class StubAsyncBlobStore implements AsyncBlobStore { return immediateFailedFuture(new ContainerNotFoundException(bucketName)); Map realContents = getContainerToBlobs().get(bucketName); if (!realContents.containsKey(key)) - return immediateFailedFuture(new KeyNotFoundException(bucketName, key)); + return immediateFuture(null); Blob object = realContents.get(key); Blob returnVal = blobProvider.create(copy(object.getMetadata())); returnVal.setPayload(object.getContent()); @@ -490,7 +489,7 @@ public class StubAsyncBlobStore implements AsyncBlobStore { return immediateFailedFuture(new ContainerNotFoundException(bucketName)); Map realContents = getContainerToBlobs().get(bucketName); if (!realContents.containsKey(key)) - return immediateFailedFuture(new KeyNotFoundException(bucketName, key)); + return immediateFuture(null); Blob object = realContents.get(key); @@ -562,10 +561,12 @@ public class StubAsyncBlobStore implements AsyncBlobStore { public ListenableFuture blobMetadata(final String container, final String key) { try { - return immediateFuture((BlobMetadata) copy(getBlob(container, key).get().getMetadata())); + Blob blob = getBlob(container, key).get(); + return immediateFuture(blob != null ? (BlobMetadata) copy(blob.getMetadata()) : null); } catch (Exception e) { - Throwables.propagateIfPossible(e, ContainerNotFoundException.class); - Throwables.propagateIfPossible(e, KeyNotFoundException.class); + if (Iterables.size(Iterables.filter(Throwables.getCausalChain(e), + KeyNotFoundException.class)) >= 1) + return immediateFuture(null); return immediateFailedFuture(e); } } diff --git a/blobstore/src/test/java/org/jclouds/blobstore/strategy/internal/RetryOnNotFoundGetAllBlobsStrategyTest.java b/blobstore/src/test/java/org/jclouds/blobstore/strategy/internal/RetryOnNotFoundGetAllBlobsStrategyTest.java index 50886fbc84..e533f3ef9f 100644 --- a/blobstore/src/test/java/org/jclouds/blobstore/strategy/internal/RetryOnNotFoundGetAllBlobsStrategyTest.java +++ b/blobstore/src/test/java/org/jclouds/blobstore/strategy/internal/RetryOnNotFoundGetAllBlobsStrategyTest.java @@ -32,7 +32,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.jclouds.blobstore.AsyncBlobStore; -import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.config.BlobStoreObjectModule; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob.Factory; @@ -74,8 +73,8 @@ public class RetryOnNotFoundGetAllBlobsStrategyTest { Blob object = blobProvider.create(null); object.getMetadata().setName("key"); object.setPayload("goo"); - expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow( - new KeyNotFoundException()); + expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andReturn( + null); context.getInstance(AsyncBlobStore.class).putBlob("container", object).get(); replay(futureObject); Set objects = new HashSet(); @@ -99,8 +98,8 @@ public class RetryOnNotFoundGetAllBlobsStrategyTest { ListenableFuture futureObject = createMock(ListenableFuture.class); Blob object = createMock(Blob.class); - expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow( - new KeyNotFoundException()).atLeastOnce(); + expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andReturn( + null).atLeastOnce(); replay(futureObject); Set objects = new HashSet(); long time = System.currentTimeMillis(); diff --git a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java index 8188bdf42d..aa99804ee9 100644 --- a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java @@ -25,7 +25,6 @@ import static org.testng.Assert.assertNotNull; import java.io.IOException; import java.net.InetSocketAddress; import java.util.NoSuchElementException; -import java.util.Properties; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -102,7 +101,7 @@ public abstract class BaseComputeServiceLiveTest { user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user"); password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key"); context = new ComputeServiceContextFactory().createContext(service, user, password, - ImmutableSet.of(new Log4JLoggingModule(), getSshModule()), new Properties()); + ImmutableSet.of(new Log4JLoggingModule(), getSshModule())); Injector injector = Guice.createInjector(getSshModule()); sshFactory = injector.getInstance(SshClient.Factory.class); SocketOpen socketOpen = injector.getInstance(SocketOpen.class); diff --git a/core/src/main/java/org/jclouds/concurrent/internal/ConcurrentUtils.java b/core/src/main/java/org/jclouds/concurrent/ConcurrentUtils.java similarity index 90% rename from core/src/main/java/org/jclouds/concurrent/internal/ConcurrentUtils.java rename to core/src/main/java/org/jclouds/concurrent/ConcurrentUtils.java index d4c0ba2d50..b7aaf8ad3e 100644 --- a/core/src/main/java/org/jclouds/concurrent/internal/ConcurrentUtils.java +++ b/core/src/main/java/org/jclouds/concurrent/ConcurrentUtils.java @@ -16,7 +16,7 @@ * limitations under the License. * ==================================================================== */ -package org.jclouds.concurrent.internal; +package org.jclouds.concurrent; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; @@ -38,13 +38,21 @@ import com.google.common.util.concurrent.ListenableFuture; */ @Singleton public class ConcurrentUtils { + /** + * Converts an exception into an object, which is useful for transforming to null or false. + */ + public static ListenableFuture convertExceptionToValue(ListenableFuture future, + Class clazz, T toValue) { + return new ConvertFutureExceptionToValue(future, clazz, toValue); + } /** * Just like {@code Futures#makeListenable} except that we pass in an executorService. *

* Temporary hack until http://code.google.com/p/guava-libraries/issues/detail?id=317 is fixed. */ - public static ListenableFuture makeListenable(Future future, ExecutorService executorService) { + public static ListenableFuture makeListenable(Future future, + ExecutorService executorService) { if (future instanceof ListenableFuture) { return (ListenableFuture) future; } diff --git a/core/src/main/java/org/jclouds/concurrent/ConvertFutureExceptionToValue.java b/core/src/main/java/org/jclouds/concurrent/ConvertFutureExceptionToValue.java new file mode 100644 index 0000000000..1047099b51 --- /dev/null +++ b/core/src/main/java/org/jclouds/concurrent/ConvertFutureExceptionToValue.java @@ -0,0 +1,66 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.jclouds.concurrent; + +import static org.jclouds.util.Utils.propagateOrNull; + +import java.util.List; + +import javax.annotation.Nullable; + +import com.google.common.base.Function; +import com.google.common.base.Throwables; +import com.google.common.collect.Iterables; +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Matches on a particular exception and converts the response to null. + * + * @author Adrian Cole + */ +public class ConvertFutureExceptionToValue extends FutureExceptionParser { + public static class ExceptionToValueOrPropagate implements + Function { + + private final Class matchingClass; + private final T value; + + public ExceptionToValueOrPropagate(Class matchingClass, @Nullable T value) { + this.matchingClass = matchingClass; + this.value = value; + } + + @SuppressWarnings("unchecked") + @Override + public T apply(Exception from) { + List throwables = Throwables.getCausalChain(from); + Iterable matchingThrowables = Iterables.filter(throwables, matchingClass); + if (Iterables.size(matchingThrowables) >= 1) + return value; + return (T)propagateOrNull(from); + } + + } + + public ConvertFutureExceptionToValue(ListenableFuture delegate, + Class exceptionClass, @Nullable T value) { + super(delegate, new ExceptionToValueOrPropagate(exceptionClass, value)); + } + +} diff --git a/core/src/main/java/org/jclouds/concurrent/FutureExceptionParser.java b/core/src/main/java/org/jclouds/concurrent/FutureExceptionParser.java index 94d0a75a19..ffeb9876d4 100755 --- a/core/src/main/java/org/jclouds/concurrent/FutureExceptionParser.java +++ b/core/src/main/java/org/jclouds/concurrent/FutureExceptionParser.java @@ -51,25 +51,20 @@ public class FutureExceptionParser implements ListenableFuture { public T get() throws InterruptedException, ExecutionException { try { return delegate.get(); - } catch (ExecutionException e) { + } catch (Exception e) { return attemptConvert(e); } } - private T attemptConvert(ExecutionException e) throws ExecutionException { - if (e.getCause() instanceof Exception) { - T returnVal = function.apply((Exception) e.getCause()); - if (returnVal != null) - return returnVal; - } - throw e; + private T attemptConvert(Exception e) { + return function.apply(e instanceof ExecutionException ? (Exception) e.getCause() : e); } public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { try { return delegate.get(timeout, unit); - } catch (ExecutionException e) { + } catch (Exception e) { return attemptConvert(e); } } diff --git a/core/src/main/java/org/jclouds/http/functions/ReturnVoidIf2xx.java b/core/src/main/java/org/jclouds/http/functions/CloseContentAndReturn.java similarity index 62% rename from core/src/main/java/org/jclouds/http/functions/ReturnVoidIf2xx.java rename to core/src/main/java/org/jclouds/http/functions/CloseContentAndReturn.java index 28e0a00d5f..99fdf4e2d3 100644 --- a/core/src/main/java/org/jclouds/http/functions/ReturnVoidIf2xx.java +++ b/core/src/main/java/org/jclouds/http/functions/CloseContentAndReturn.java @@ -18,8 +18,6 @@ */ package org.jclouds.http.functions; -import java.lang.reflect.Constructor; - import javax.inject.Singleton; import org.jclouds.http.HttpResponse; @@ -28,30 +26,13 @@ import com.google.common.base.Function; import com.google.common.io.Closeables; /** - * Simply returns true when the http response code is in the range 200-299. * * @author Adrian Cole */ @Singleton -public class ReturnVoidIf2xx implements Function { - static final Void v; - static { - Constructor cv; - try { - cv = Void.class.getDeclaredConstructor(); - cv.setAccessible(true); - v = cv.newInstance(); - } catch (Exception e) { - throw new Error("Error setting up class", e); - } - } - +public class CloseContentAndReturn implements Function { public Void apply(HttpResponse from) { Closeables.closeQuietly(from.getContent()); - int code = from.getStatusCode(); - if (code >= 300 || code < 200) { - throw new IllegalStateException("incorrect code for this operation: " + from); - } - return v; + return null; } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/functions/ReturnFalseOn404.java b/core/src/main/java/org/jclouds/http/functions/ReturnFalseOn404.java index e061d8991b..0b67daab43 100644 --- a/core/src/main/java/org/jclouds/http/functions/ReturnFalseOn404.java +++ b/core/src/main/java/org/jclouds/http/functions/ReturnFalseOn404.java @@ -18,6 +18,8 @@ */ package org.jclouds.http.functions; +import static org.jclouds.util.Utils.propagateOrNull; + import javax.inject.Singleton; import org.jclouds.http.HttpResponseException; @@ -38,7 +40,7 @@ public class ReturnFalseOn404 implements Function { return false; } } - return null; + return Boolean.class.cast(propagateOrNull(from)); } } diff --git a/core/src/main/java/org/jclouds/http/functions/ReturnTrueOn404.java b/core/src/main/java/org/jclouds/http/functions/ReturnTrueOn404.java index 21ea5fbeeb..6fcd0bf334 100644 --- a/core/src/main/java/org/jclouds/http/functions/ReturnTrueOn404.java +++ b/core/src/main/java/org/jclouds/http/functions/ReturnTrueOn404.java @@ -18,6 +18,8 @@ */ package org.jclouds.http.functions; +import static org.jclouds.util.Utils.propagateOrNull; + import javax.inject.Singleton; import org.jclouds.http.HttpResponseException; @@ -34,7 +36,7 @@ public class ReturnTrueOn404 implements Function { return true; } } - return null; + return Boolean.class.cast(propagateOrNull(from)); } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/internal/BaseHttpCommandExecutorService.java b/core/src/main/java/org/jclouds/http/internal/BaseHttpCommandExecutorService.java index ea8b41af5b..b63658a01b 100644 --- a/core/src/main/java/org/jclouds/http/internal/BaseHttpCommandExecutorService.java +++ b/core/src/main/java/org/jclouds/http/internal/BaseHttpCommandExecutorService.java @@ -18,7 +18,7 @@ */ package org.jclouds.http.internal; -import static org.jclouds.concurrent.internal.ConcurrentUtils.makeListenable; +import static org.jclouds.concurrent.ConcurrentUtils.makeListenable; import java.io.IOException; import java.util.concurrent.Callable; diff --git a/core/src/main/java/org/jclouds/rest/AuthorizationException.java b/core/src/main/java/org/jclouds/rest/AuthorizationException.java new file mode 100644 index 0000000000..747fce3e4c --- /dev/null +++ b/core/src/main/java/org/jclouds/rest/AuthorizationException.java @@ -0,0 +1,47 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.jclouds.rest; + +/** + * Thrown when there is an authorization error. + * + * @author Adrian Cole + */ +public class AuthorizationException extends RuntimeException { + + /** The serialVersionUID */ + private static final long serialVersionUID = -2272965726680821281L; + + public AuthorizationException() { + super(); + } + + public AuthorizationException(String arg0, Throwable arg1) { + super(arg0, arg1); + } + + public AuthorizationException(String arg0) { + super(arg0); + } + + public AuthorizationException(Throwable arg0) { + super(arg0); + } + +} diff --git a/core/src/main/java/org/jclouds/rest/RestContextFactory.java b/core/src/main/java/org/jclouds/rest/RestContextFactory.java index 1077d8ca1c..34c5bb7d5a 100644 --- a/core/src/main/java/org/jclouds/rest/RestContextFactory.java +++ b/core/src/main/java/org/jclouds/rest/RestContextFactory.java @@ -48,7 +48,8 @@ public abstract class RestContextFactory> * Initializes with the default properties built-in to jclouds. This is typically stored in the * classpath resource {@code filename} * - * @param filename name of the properties file to initialize from + * @param filename + * name of the properties file to initialize from * @throws IOException * if the default properties file cannot be loaded * @see #getPropertiesFromResource @@ -125,6 +126,11 @@ public abstract class RestContextFactory> return createContext(hint, null, null, modules, overrides); } + public T createContext(String hint, @Nullable String account, @Nullable String key, + Iterable modules) { + return createContext(hint, account, key, modules, new Properties()); + } + /** * Creates a new remote context. * diff --git a/core/src/main/java/org/jclouds/rest/functions/ThrowResourceNotFoundOn404.java b/core/src/main/java/org/jclouds/rest/functions/MapHttp4xxCodesToExceptions.java similarity index 72% rename from core/src/main/java/org/jclouds/rest/functions/ThrowResourceNotFoundOn404.java rename to core/src/main/java/org/jclouds/rest/functions/MapHttp4xxCodesToExceptions.java index f3b960a51f..3f26730c59 100644 --- a/core/src/main/java/org/jclouds/rest/functions/ThrowResourceNotFoundOn404.java +++ b/core/src/main/java/org/jclouds/rest/functions/MapHttp4xxCodesToExceptions.java @@ -18,7 +18,10 @@ */ package org.jclouds.rest.functions; +import static org.jclouds.util.Utils.propagateOrNull; + import org.jclouds.http.HttpResponseException; +import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.ResourceNotFoundException; import com.google.common.base.Function; @@ -27,16 +30,19 @@ import com.google.common.base.Function; * * @author Adrian Cole */ -public class ThrowResourceNotFoundOn404 implements Function { +public class MapHttp4xxCodesToExceptions implements Function { public Object apply(Exception from) { if (from instanceof HttpResponseException) { HttpResponseException responseException = (HttpResponseException) from; - if (responseException.getResponse().getStatusCode() == 404) { - throw new ResourceNotFoundException(from); + switch (responseException.getResponse().getStatusCode()) { + case 401: + throw new AuthorizationException(from); + case 404: + throw new ResourceNotFoundException(from); } } - return null; + return propagateOrNull(from); } } diff --git a/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java b/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java index b544815d28..0774c561e7 100755 --- a/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java +++ b/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java @@ -98,9 +98,7 @@ public class AsyncRestClientProxy implements InvocationHandler { } } catch (RuntimeException e) { if (exceptionParser != null) { - final Object toReturn = exceptionParser.apply(e); - if (toReturn == null) - throw e; + Object toReturn = exceptionParser.apply(e); if (method.getReturnType().isAssignableFrom(ListenableFuture.class)) { ValueFuture returnVal = ValueFuture.create(); returnVal.set(toReturn); diff --git a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java index a888d1d565..a7287c6516 100755 --- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java +++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java @@ -66,7 +66,7 @@ import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x; import org.jclouds.http.functions.ReturnInputStream; import org.jclouds.http.functions.ReturnStringIf200; import org.jclouds.http.functions.ReturnTrueIf2xx; -import org.jclouds.http.functions.ReturnVoidIf2xx; +import org.jclouds.http.functions.CloseContentAndReturn; import org.jclouds.http.functions.ParseSax.HandlerWithResult; import org.jclouds.http.options.HttpRequestOptions; import org.jclouds.logging.Logger; @@ -90,7 +90,7 @@ import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; -import org.jclouds.rest.functions.ThrowResourceNotFoundOn404; +import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; @@ -216,7 +216,7 @@ public class RestAnnotationProcessor { if (annotation != null) { return injector.getInstance(annotation.value()); } - return injector.getInstance(ThrowResourceNotFoundOn404.class); + return injector.getInstance(MapHttp4xxCodesToExceptions.class); } @SuppressWarnings("unchecked") @@ -646,7 +646,7 @@ public class RestAnnotationProcessor { return ReturnStringIf200.class; } else if (method.getReturnType().equals(void.class) || TypeLiteral.get(method.getGenericReturnType()).equals(futureVoidLiteral)) { - return ReturnVoidIf2xx.class; + return CloseContentAndReturn.class; } else if (method.getReturnType().equals(URI.class) || TypeLiteral.get(method.getGenericReturnType()).equals(futureURILiteral)) { return ParseURIFromListOrLocationHeaderIf20x.class; diff --git a/core/src/main/java/org/jclouds/util/Utils.java b/core/src/main/java/org/jclouds/util/Utils.java index 720db26209..7ec8a3d7ed 100644 --- a/core/src/main/java/org/jclouds/util/Utils.java +++ b/core/src/main/java/org/jclouds/util/Utils.java @@ -38,6 +38,7 @@ import org.jclouds.logging.Logger; import com.google.common.base.Charsets; import com.google.common.base.Supplier; +import com.google.common.base.Throwables; import com.google.common.io.ByteStreams; import com.google.common.io.Closeables; import com.google.common.io.OutputSupplier; @@ -50,6 +51,12 @@ import com.google.common.io.OutputSupplier; public class Utils { public static final String UTF8_ENCODING = "UTF-8"; + public static Object propagateOrNull(Exception from) { + Throwables.propagate(from); + assert false : "exception should have propogated"; + return null; + } + public static String replaceTokens(String value, Collection> tokenValues) { for (Entry tokenValue : tokenValues) { value = replaceAll(value, TOKEN_TO_PATTERN.get(tokenValue.getKey()), tokenValue.getValue()); diff --git a/core/src/test/java/org/jclouds/concurrent/FutureExceptionParserTest.java b/core/src/test/java/org/jclouds/concurrent/FutureExceptionParserTest.java index f384d4a29f..a81ad69e14 100755 --- a/core/src/test/java/org/jclouds/concurrent/FutureExceptionParserTest.java +++ b/core/src/test/java/org/jclouds/concurrent/FutureExceptionParserTest.java @@ -18,7 +18,8 @@ */ package org.jclouds.concurrent; -import static org.jclouds.concurrent.internal.ConcurrentUtils.makeListenable; +import static org.jclouds.concurrent.ConcurrentUtils.makeListenable; +import static org.jclouds.util.Utils.propagateOrNull; import static org.testng.Assert.assertEquals; import java.util.concurrent.Callable; @@ -30,6 +31,8 @@ import java.util.concurrent.TimeoutException; import org.testng.annotations.Test; import com.google.common.base.Function; +import com.google.common.base.Throwables; +import com.google.common.collect.Iterables; import com.google.common.util.concurrent.Executors; import com.google.common.util.concurrent.ListenableFuture; @@ -48,7 +51,7 @@ public class FutureExceptionParserTest { assertEquals(future.get(), "foo"); } - @Test(expectedExceptions = ExecutionException.class) + @Test(expectedExceptions = Exception.class) public void testGetUnmatched() throws InterruptedException, ExecutionException { ListenableFuture future = createListenableFuture(new Exception("foo")); assertEquals(future.get(), "foo"); @@ -61,7 +64,7 @@ public class FutureExceptionParserTest { assertEquals(future.get(1, TimeUnit.SECONDS), "foo"); } - @Test(expectedExceptions = ExecutionException.class) + @Test(expectedExceptions = Exception.class) public void testGetLongTimeUnitUnmatched() throws InterruptedException, ExecutionException, TimeoutException { ListenableFuture future = createListenableFuture(new Exception("foo")); @@ -81,7 +84,10 @@ public class FutureExceptionParserTest { future = new FutureExceptionParser(future, new Function() { public String apply(Exception from) { - return (from instanceof RuntimeException) ? from.getMessage() : null; + if (Iterables.size(Iterables.filter(Throwables.getCausalChain(from), + RuntimeException.class)) >= 1) + return from.getMessage(); + return String.class.cast(propagateOrNull(from)); } }); diff --git a/core/src/test/java/org/jclouds/concurrent/internal/SyncProxyTest.java b/core/src/test/java/org/jclouds/concurrent/internal/SyncProxyTest.java index 437416fe99..ced5822f36 100644 --- a/core/src/test/java/org/jclouds/concurrent/internal/SyncProxyTest.java +++ b/core/src/test/java/org/jclouds/concurrent/internal/SyncProxyTest.java @@ -18,7 +18,7 @@ */ package org.jclouds.concurrent.internal; -import static org.jclouds.concurrent.internal.ConcurrentUtils.makeListenable; +import static org.jclouds.concurrent.ConcurrentUtils.makeListenable; import static org.testng.Assert.assertEquals; import java.io.FileNotFoundException; diff --git a/core/src/test/java/org/jclouds/rest/RestClientTest.java b/core/src/test/java/org/jclouds/rest/RestClientTest.java index 1bbed2b51a..da327d76ac 100644 --- a/core/src/test/java/org/jclouds/rest/RestClientTest.java +++ b/core/src/test/java/org/jclouds/rest/RestClientTest.java @@ -29,7 +29,7 @@ import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.http.HttpUtils; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.rest.config.RestModule; -import org.jclouds.rest.functions.ThrowResourceNotFoundOn404; +import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.util.Utils; @@ -83,7 +83,7 @@ public abstract class RestClientTest { protected void assertExceptionParserClassEquals(Method method, @Nullable Class parserClass) { if (parserClass == null) assertEquals(processor.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation( - method).getClass(), ThrowResourceNotFoundOn404.class); + method).getClass(), MapHttp4xxCodesToExceptions.class); else assertEquals(processor.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation( method).getClass(), parserClass); diff --git a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java index fa634a3dc7..ff0ec3c4ca 100755 --- a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java +++ b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java @@ -69,7 +69,7 @@ import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x; import org.jclouds.http.functions.ReturnInputStream; import org.jclouds.http.functions.ReturnStringIf200; import org.jclouds.http.functions.ReturnTrueIf2xx; -import org.jclouds.http.functions.ReturnVoidIf2xx; +import org.jclouds.http.functions.CloseContentAndReturn; import org.jclouds.http.options.BaseHttpRequestOptions; import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.HttpRequestOptions; @@ -1530,7 +1530,7 @@ public class RestAnnotationProcessorTest { assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections .singletonList("test".getBytes().length + "")); assertEquals(processor.createResponseParser(method, request).getClass(), - ReturnVoidIf2xx.class); + CloseContentAndReturn.class); } @Test diff --git a/extensions/httpnio/src/main/java/org/jclouds/http/pool/ConnectionPoolTransformingHttpCommandExecutorService.java b/extensions/httpnio/src/main/java/org/jclouds/http/pool/ConnectionPoolTransformingHttpCommandExecutorService.java index 990be28f36..bf4d7ccdd6 100755 --- a/extensions/httpnio/src/main/java/org/jclouds/http/pool/ConnectionPoolTransformingHttpCommandExecutorService.java +++ b/extensions/httpnio/src/main/java/org/jclouds/http/pool/ConnectionPoolTransformingHttpCommandExecutorService.java @@ -19,7 +19,7 @@ package org.jclouds.http.pool; import static com.google.common.base.Preconditions.checkArgument; -import static org.jclouds.concurrent.internal.ConcurrentUtils.makeListenable; +import static org.jclouds.concurrent.ConcurrentUtils.makeListenable; import java.net.URI; import java.util.concurrent.BlockingQueue; diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/AddMetadataItemIntoMap.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/AddMetadataItemIntoMap.java index 7469e333d2..0936d36912 100644 --- a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/AddMetadataItemIntoMap.java +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/AddMetadataItemIntoMap.java @@ -20,7 +20,6 @@ package org.jclouds.mezeo.pcs2.functions; import static com.google.common.base.Preconditions.checkState; -import java.lang.reflect.Constructor; import java.util.Map; import javax.inject.Inject; @@ -45,18 +44,6 @@ public class AddMetadataItemIntoMap implements Function, Inv this.returnIf200 = returnIf200; } - static final Void v; - static { - Constructor cv; - try { - cv = Void.class.getDeclaredConstructor(); - cv.setAccessible(true); - v = cv.newInstance(); - } catch (Exception e) { - throw new Error("Error setting up class", e); - } - } - @SuppressWarnings("unchecked") public Void apply(HttpResponse from) @@ -74,7 +61,7 @@ public class AddMetadataItemIntoMap implements Function, Inv checkState(key != null, "No String found in args, improper method declarations"); map.put(key, returnIf200.apply(from).trim()); - return v; + return null; } public void setContext(GeneratedHttpRequest request) { diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnFalseIfContainerNotFound.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnFalseIfContainerNotFound.java index 9e7641c353..c6781fa701 100644 --- a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnFalseIfContainerNotFound.java +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/functions/ReturnFalseIfContainerNotFound.java @@ -18,6 +18,8 @@ */ package org.jclouds.mezeo.pcs2.functions; +import static org.jclouds.util.Utils.propagateOrNull; + import javax.inject.Singleton; import org.jclouds.blobstore.ContainerNotFoundException; @@ -35,7 +37,7 @@ public class ReturnFalseIfContainerNotFound implements Function { assertEquals(httpMethod.getRequestLine(), "DELETE http://localhost/container/1234 HTTP/1.1"); assertEquals(httpMethod.getHeaders().size(), 0); assertEquals(processor.createResponseParser(method, httpMethod).getClass(), - ReturnVoidIf2xx.class); + CloseContentAndReturn.class); assertEquals(RestAnnotationProcessor.getSaxResponseParserClassOrNull(method), null); assertEquals(httpMethod.getFilters().size(), 1); assertEquals(httpMethod.getFilters().get(0).getClass(), BasicAuthentication.class); @@ -135,7 +135,7 @@ public class PCSClientTest extends RestClientTest { ContainerHandler.class); assertEquals(httpMethod.getFilters().size(), 1); assertEquals(httpMethod.getFilters().get(0).getClass(), BasicAuthentication.class); - assertEquals(processor.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), ThrowResourceNotFoundOn404.class); + assertEquals(processor.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), MapHttp4xxCodesToExceptions.class); } public void testGetFileInfo() throws SecurityException, NoSuchMethodException { @@ -185,7 +185,7 @@ public class PCSClientTest extends RestClientTest { assertHeadersEqual(httpMethod, "Content-Length: 5\n"); assertPayloadEquals(httpMethod, "hello"); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -216,7 +216,7 @@ public class PCSClientTest extends RestClientTest { assertEquals(httpMethod.getRequestLine(), "DELETE http://localhost/contents/file HTTP/1.1"); assertEquals(httpMethod.getHeaders().size(), 0); assertEquals(processor.createResponseParser(method, httpMethod).getClass(), - ReturnVoidIf2xx.class); + CloseContentAndReturn.class); assertEquals(RestAnnotationProcessor.getSaxResponseParserClassOrNull(method), null); assertEquals(httpMethod.getFilters().size(), 1); assertEquals(httpMethod.getFilters().get(0).getClass(), BasicAuthentication.class); @@ -238,9 +238,9 @@ public class PCSClientTest extends RestClientTest { assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections .singletonList("application/unknown")); assertEquals("bar", httpMethod.getPayload().getRawContent()); - assertEquals(processor.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), ThrowResourceNotFoundOn404.class); + assertEquals(processor.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), MapHttp4xxCodesToExceptions.class); assertEquals(processor.createResponseParser(method, httpMethod).getClass(), - ReturnVoidIf2xx.class); + CloseContentAndReturn.class); } public void testAddEntryToMap() throws SecurityException, NoSuchMethodException { @@ -253,7 +253,7 @@ public class PCSClientTest extends RestClientTest { assertEquals(httpMethod.getRequestLine(), "GET http://localhost/pow/metadata/newkey HTTP/1.1"); assertEquals(httpMethod.getHeaders().size(), 0); - assertEquals(processor.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), ThrowResourceNotFoundOn404.class); + assertEquals(processor.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), MapHttp4xxCodesToExceptions.class); assertEquals(processor.createResponseParser(method, httpMethod).getClass(), AddMetadataItemIntoMap.class); } diff --git a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSCloudTest.java b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSCloudTest.java index 30b77c8850..73b62828b7 100644 --- a/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSCloudTest.java +++ b/mezeo/pcs2/core/src/test/java/org/jclouds/mezeo/pcs2/PCSCloudTest.java @@ -36,7 +36,7 @@ import org.jclouds.logging.Logger; import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.mezeo.pcs2.xml.CloudXlinkHandler; import org.jclouds.rest.config.RestModule; -import org.jclouds.rest.functions.ThrowResourceNotFoundOn404; +import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.RestAnnotationProcessor; import org.testng.annotations.BeforeClass; @@ -69,7 +69,7 @@ public class PCSCloudTest { assertEquals(httpMethod.getFilters().get(0).getClass(), BasicAuthentication.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } private RestAnnotationProcessor processor; diff --git a/nirvanix/sdn/core/src/test/java/org/jclouds/nirvanix/sdn/SDNClientTest.java b/nirvanix/sdn/core/src/test/java/org/jclouds/nirvanix/sdn/SDNClientTest.java index 542d9ed117..18e839a170 100644 --- a/nirvanix/sdn/core/src/test/java/org/jclouds/nirvanix/sdn/SDNClientTest.java +++ b/nirvanix/sdn/core/src/test/java/org/jclouds/nirvanix/sdn/SDNClientTest.java @@ -29,7 +29,7 @@ import org.jclouds.blobstore.binders.BindBlobToMultipartFormTest; import org.jclouds.blobstore.config.BlobStoreObjectModule; import org.jclouds.blobstore.domain.Blob; import org.jclouds.http.functions.ReturnStringIf200; -import org.jclouds.http.functions.ReturnVoidIf2xx; +import org.jclouds.http.functions.CloseContentAndReturn; import org.jclouds.logging.Logger; import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.nirvanix.sdn.filters.AddSessionTokenToRequest; @@ -97,7 +97,7 @@ public class SDNClientTest extends RestClientTest { assertPayloadEquals(httpMethod, expects.toString()); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -115,7 +115,7 @@ public class SDNClientTest extends RestClientTest { assertHeadersEqual(httpMethod, ""); assertPayloadEquals(httpMethod, null); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesAsyncBlobStore.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesAsyncBlobStore.java index 1063d61000..f3f4462dd9 100644 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesAsyncBlobStore.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesAsyncBlobStore.java @@ -19,8 +19,9 @@ package org.jclouds.rackspace.cloudfiles.blobstore; import static com.google.common.util.concurrent.Futures.compose; -import static org.jclouds.concurrent.internal.ConcurrentUtils.makeListenable; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive; +import static org.jclouds.concurrent.ConcurrentUtils.convertExceptionToValue; +import static org.jclouds.concurrent.ConcurrentUtils.makeListenable; import java.util.SortedSet; import java.util.concurrent.Callable; @@ -89,7 +90,8 @@ public class CloudFilesAsyncBlobStore extends BaseCloudFilesBlobStore implements */ public ListenableFuture blobMetadata(String container, String key) { - return compose(async.getObjectInfo(container, key), + return compose(convertExceptionToValue(async.getObjectInfo(container, key), + KeyNotFoundException.class, null), new Function() { @Override @@ -139,7 +141,8 @@ public class CloudFilesAsyncBlobStore extends BaseCloudFilesBlobStore implements org.jclouds.blobstore.options.GetOptions... optionsList) { GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList); ListenableFuture returnVal = async.getObject(container, key, httpOptions); - return compose(returnVal, object2Blob, service); + return compose(convertExceptionToValue(returnVal, KeyNotFoundException.class, null), + object2Blob, service); } public ListenableFuture> list() { diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStore.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStore.java index fd630d20da..e249d68ddd 100644 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStore.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStore.java @@ -19,6 +19,7 @@ package org.jclouds.rackspace.cloudfiles.blobstore; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive; +import static org.jclouds.blobstore.util.BlobStoreUtils.returnNullOnKeyNotFoundOrPropagate; import java.util.SortedSet; import java.util.concurrent.ExecutorService; @@ -26,7 +27,6 @@ import java.util.concurrent.ExecutorService; import javax.inject.Inject; import org.jclouds.blobstore.BlobStore; -import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.ListContainerResponse; @@ -80,7 +80,11 @@ public class CloudFilesBlobStore extends BaseCloudFilesBlobStore implements Blob * This implementation uses the CloudFiles HEAD Object command to return the result */ public BlobMetadata blobMetadata(String container, String key) { - return object2BlobMd.apply(sync.getObjectInfo(container, key)); + try { + return object2BlobMd.apply(sync.getObjectInfo(container, key)); + } catch (Exception e) { + return returnNullOnKeyNotFoundOrPropagate(e); + } } public void clearContainer(final String container) { @@ -107,7 +111,11 @@ public class CloudFilesBlobStore extends BaseCloudFilesBlobStore implements Blob public Blob getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions... optionsList) { GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList); - return object2Blob.apply(sync.getObject(container, key, httpOptions)); + try { + return object2Blob.apply(sync.getObject(container, key, httpOptions)); + } catch (Exception e) { + return returnNullOnKeyNotFoundOrPropagate(e); + } } public ListResponse list() { @@ -139,8 +147,8 @@ public class CloudFilesBlobStore extends BaseCloudFilesBlobStore implements Blob try { getDirectoryStrategy.execute(aBlobStore, containerName, directory); return true; - } catch (KeyNotFoundException e) { - return false; + } catch (Exception e) { + return (Boolean)returnNullOnKeyNotFoundOrPropagate(e); } } diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObject.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObject.java index 1050e0fa6c..7954dac241 100644 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObject.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObject.java @@ -41,6 +41,8 @@ public class BlobToObject implements Function { } public CFObject apply(Blob from) { + if (from == null) + return null; CFObject object = objectProvider.create(blob2ObjectMd.apply(from.getMetadata())); if (from.getContentLength() != null) object.setContentLength(from.getContentLength()); diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ObjectToBlob.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ObjectToBlob.java index ff13e9fd05..6de6528594 100644 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ObjectToBlob.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ObjectToBlob.java @@ -42,6 +42,8 @@ public class ObjectToBlob implements Function { } public Blob apply(CFObject from) { + if (from == null) + return null; Blob blob = blobFactory.create(object2BlobMd.apply(from.getInfo())); if (from.getContentLength() != null) blob.setContentLength(from.getContentLength()); diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ObjectToBlobMetadata.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ObjectToBlobMetadata.java index 29502c3e19..d50f5cbb90 100644 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ObjectToBlobMetadata.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ObjectToBlobMetadata.java @@ -47,6 +47,8 @@ public class ObjectToBlobMetadata implements Function { return false; } } - return null; + return Boolean.class.cast(propagateOrNull(from)); } - } \ No newline at end of file diff --git a/rackspace/src/test/java/org/jclouds/rackspace/RackspaceAuthenticationLiveTest.java b/rackspace/src/test/java/org/jclouds/rackspace/RackspaceAuthenticationLiveTest.java index f76ff39218..af2e39e7dd 100755 --- a/rackspace/src/test/java/org/jclouds/rackspace/RackspaceAuthenticationLiveTest.java +++ b/rackspace/src/test/java/org/jclouds/rackspace/RackspaceAuthenticationLiveTest.java @@ -24,7 +24,6 @@ import static org.testng.Assert.assertNotNull; import java.net.URI; import java.util.List; -import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import javax.inject.Named; @@ -37,6 +36,7 @@ import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.rackspace.RackspaceAuthentication.AuthenticationResponse; import org.jclouds.rackspace.config.RackspaceAuthenticationRestModule; import org.jclouds.rackspace.reference.RackspaceConstants; +import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.RestClientFactory; import org.jclouds.rest.RestContext; @@ -110,7 +110,7 @@ public class RackspaceAuthenticationLiveTest { assertNotNull(response.getAuthToken()); } - @Test(expectedExceptions = ExecutionException.class) + @Test(expectedExceptions = AuthorizationException.class) public void testBadAuthentication() throws Exception { RackspaceAuthentication authentication = context.getAsyncApi(); authentication.authenticate("foo", "bar").get(10, TimeUnit.SECONDS); diff --git a/rackspace/src/test/java/org/jclouds/rackspace/cloudservers/CloudServersClientTest.java b/rackspace/src/test/java/org/jclouds/rackspace/cloudservers/CloudServersClientTest.java index 132ae0afec..08dcc048f6 100755 --- a/rackspace/src/test/java/org/jclouds/rackspace/cloudservers/CloudServersClientTest.java +++ b/rackspace/src/test/java/org/jclouds/rackspace/cloudservers/CloudServersClientTest.java @@ -68,7 +68,7 @@ import org.jclouds.rackspace.cloudservers.options.CreateSharedIpGroupOptions; import org.jclouds.rackspace.cloudservers.options.ListOptions; import org.jclouds.rackspace.cloudservers.options.RebuildServerOptions; import org.jclouds.rest.config.RestModule; -import org.jclouds.rest.functions.ThrowResourceNotFoundOn404; +import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.RestAnnotationProcessor; import org.testng.annotations.BeforeClass; @@ -176,7 +176,7 @@ public class CloudServersClientTest { ParseServerFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); assertNotNull(processor.getMapPayloadBinderOrNull(method, new Object[] { "", 1, 2, new CreateServerOptions[] { CreateServerOptions.Builder.withSharedIpGroup(1) } })); } @@ -212,7 +212,7 @@ public class CloudServersClientTest { ParseServerListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } Date now = new Date(); @@ -233,7 +233,7 @@ public class CloudServersClientTest { ParseServerListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testListServersDetail() throws SecurityException, NoSuchMethodException { @@ -251,7 +251,7 @@ public class CloudServersClientTest { ParseServerListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testGetServer() throws SecurityException, NoSuchMethodException { @@ -268,7 +268,7 @@ public class CloudServersClientTest { ParseServerFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testListFlavors() throws SecurityException, NoSuchMethodException { @@ -286,7 +286,7 @@ public class CloudServersClientTest { ParseFlavorListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testListFlavorsOptions() throws SecurityException, NoSuchMethodException { @@ -305,7 +305,7 @@ public class CloudServersClientTest { ParseFlavorListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testListFlavorsDetail() throws SecurityException, NoSuchMethodException { @@ -323,7 +323,7 @@ public class CloudServersClientTest { ParseFlavorListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testListFlavorsDetailOptions() throws SecurityException, NoSuchMethodException { @@ -342,7 +342,7 @@ public class CloudServersClientTest { ParseFlavorListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testGetFlavor() throws SecurityException, NoSuchMethodException { @@ -359,7 +359,7 @@ public class CloudServersClientTest { ParseFlavorFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testListImages() throws SecurityException, NoSuchMethodException { @@ -377,7 +377,7 @@ public class CloudServersClientTest { ParseImageListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testListImagesDetail() throws SecurityException, NoSuchMethodException { @@ -395,7 +395,7 @@ public class CloudServersClientTest { ParseImageListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testListImagesOptions() throws SecurityException, NoSuchMethodException { @@ -414,7 +414,7 @@ public class CloudServersClientTest { ParseImageListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testListImagesDetailOptions() throws SecurityException, NoSuchMethodException { @@ -433,7 +433,7 @@ public class CloudServersClientTest { ParseImageListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testGetImage() throws SecurityException, NoSuchMethodException { @@ -450,7 +450,7 @@ public class CloudServersClientTest { ParseImageFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testDeleteServer() throws SecurityException, NoSuchMethodException { @@ -638,7 +638,7 @@ public class CloudServersClientTest { ParseSharedIpGroupListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testListSharedIpGroupsOptions() throws SecurityException, NoSuchMethodException { @@ -657,7 +657,7 @@ public class CloudServersClientTest { ParseSharedIpGroupListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testListSharedIpGroupsDetail() throws SecurityException, NoSuchMethodException { @@ -675,7 +675,7 @@ public class CloudServersClientTest { ParseSharedIpGroupListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testListSharedIpGroupsDetailOptions() throws SecurityException, @@ -695,7 +695,7 @@ public class CloudServersClientTest { ParseSharedIpGroupListFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } public void testGetSharedIpGroup() throws SecurityException, NoSuchMethodException { @@ -712,7 +712,7 @@ public class CloudServersClientTest { ParseSharedIpGroupFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); } private static final Class createSharedIpGroupOptionsVarargsClass = new CreateSharedIpGroupOptions[] {} @@ -756,7 +756,7 @@ public class CloudServersClientTest { ParseSharedIpGroupFromJsonResponse.class); assertEquals(processor .createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(), - ThrowResourceNotFoundOn404.class); + MapHttp4xxCodesToExceptions.class); assertNotNull(processor.getMapPayloadBinderOrNull(method, new Object[] { "", new CreateSharedIpGroupOptions[] { withServer(2) } })); } diff --git a/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/functions/ParseRimuHostingException.java b/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/functions/ParseRimuHostingException.java index 927df53a07..0465317900 100644 --- a/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/functions/ParseRimuHostingException.java +++ b/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/functions/ParseRimuHostingException.java @@ -18,6 +18,8 @@ */ package org.jclouds.rimuhosting.miro.functions; +import static org.jclouds.util.Utils.propagateOrNull; + import com.google.common.base.Function; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; @@ -31,14 +33,15 @@ import java.util.Map; /** * On non 2xx we have an error. RimuHosting using the same json base object. - * + * * TODO: map exceptions out into something that suits jclouds. - * + * * @author Ivan Meredith */ @Singleton public class ParseRimuHostingException implements Function { private Gson gson; + @Inject public ParseRimuHostingException(Gson gson) { this.gson = gson; @@ -46,14 +49,16 @@ public class ParseRimuHostingException implements Function { @Override public Object apply(Exception e) { - if(e instanceof HttpResponseException){ - HttpResponseException responseException = (HttpResponseException)e; + if (e instanceof HttpResponseException) { + HttpResponseException responseException = (HttpResponseException) e; Type setType = new TypeToken>() { }.getType(); - Map responseMap = gson.fromJson(responseException.getContent(), setType); - throw new RuntimeException(responseMap.values().iterator().next().getErrorInfo().getErrorClass()); - } - return null; + Map responseMap = gson.fromJson(responseException + .getContent(), setType); + throw new RuntimeException(responseMap.values().iterator().next().getErrorInfo() + .getErrorClass()); + } + return propagateOrNull(e); } } diff --git a/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudAsyncClientTest.java b/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudAsyncClientTest.java index 246020bf76..b8181a0393 100644 --- a/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudAsyncClientTest.java +++ b/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudAsyncClientTest.java @@ -31,7 +31,7 @@ import java.util.Properties; import javax.inject.Provider; import org.jclouds.http.functions.ParseSax; -import org.jclouds.http.functions.ReturnVoidIf2xx; +import org.jclouds.http.functions.CloseContentAndReturn; import org.jclouds.logging.Logger; import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.rest.RestClientTest; @@ -381,7 +381,7 @@ public class VCloudAsyncClientTest extends RestClientTest { assertHeadersEqual(httpMethod, ""); assertPayloadEquals(httpMethod, null); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -458,7 +458,7 @@ public class VCloudAsyncClientTest extends RestClientTest { assertHeadersEqual(httpMethod, ""); assertPayloadEquals(httpMethod, null); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); @@ -488,7 +488,7 @@ public class VCloudAsyncClientTest extends RestClientTest { assertHeadersEqual(httpMethod, ""); assertPayloadEquals(httpMethod, null); - assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); + assertResponseParserClassEquals(method, httpMethod, CloseContentAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method, null); diff --git a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/functions/ReturnVoidOnDeleteDefaultIp.java b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/functions/ReturnVoidOnDeleteDefaultIp.java index 18d2d560fb..6fd7338812 100644 --- a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/functions/ReturnVoidOnDeleteDefaultIp.java +++ b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/functions/ReturnVoidOnDeleteDefaultIp.java @@ -18,7 +18,8 @@ */ package org.jclouds.vcloud.terremark.functions; -import java.lang.reflect.Constructor; +import static org.jclouds.util.Utils.propagateOrNull; + import java.util.regex.Pattern; import javax.inject.Singleton; @@ -38,25 +39,13 @@ public class ReturnVoidOnDeleteDefaultIp implements Function { public static final Pattern MESSAGE_PATTERN = Pattern .compile(".*Cannot release this Public IP as it is default oubound IP.*"); - static final Void v; - static { - Constructor cv; - try { - cv = Void.class.getDeclaredConstructor(); - cv.setAccessible(true); - v = cv.newInstance(); - } catch (Exception e) { - throw new Error("Error setting up class", e); - } - } - public Void apply(Exception from) { if (from instanceof HttpResponseException) { HttpResponseException hre = (HttpResponseException) from; if (hre.getResponse().getStatusCode() == 503 || hre.getResponse().getStatusCode() == 401 || MESSAGE_PATTERN.matcher(hre.getMessage()).matches()) - return v; + return null; } - return null; + return Void.class.cast(propagateOrNull(from)); } } \ No newline at end of file diff --git a/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/TerremarkVCloudAsyncClientTest.java b/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/TerremarkVCloudAsyncClientTest.java index 69eedbd547..04997cc9e8 100644 --- a/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/TerremarkVCloudAsyncClientTest.java +++ b/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/TerremarkVCloudAsyncClientTest.java @@ -34,7 +34,7 @@ import javax.inject.Provider; import javax.inject.Singleton; import org.jclouds.http.functions.ParseSax; -import org.jclouds.http.functions.ReturnVoidIf2xx; +import org.jclouds.http.functions.CloseContentAndReturn; import org.jclouds.logging.Logger; import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.rest.RestClientTest; @@ -283,7 +283,7 @@ public class TerremarkVCloudAsyncClientTest extends RestClientTest