changes that facilitate synchronous fallbacks and http invocation

This commit is contained in:
adriancole 2013-01-29 04:09:45 -08:00
parent 878313582a
commit 40d9f8bfe7
27 changed files with 323 additions and 221 deletions

View File

@ -35,8 +35,9 @@ import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
import org.jclouds.reflect.Invocation; import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.reflect.Invokable; import com.google.common.reflect.Invokable;
@ -46,7 +47,7 @@ import com.google.common.reflect.Invokable;
*/ */
@Singleton @Singleton
public class AtmosBlobRequestSigner implements BlobRequestSigner { public class AtmosBlobRequestSigner implements BlobRequestSigner {
private final RestAnnotationProcessor processor; private final Function<Invocation, HttpRequest> processor;
private final BlobToObject blobToObject; private final BlobToObject blobToObject;
private final BlobToHttpGetOptions blob2ObjectGetOptions; private final BlobToHttpGetOptions blob2ObjectGetOptions;
@ -55,7 +56,7 @@ public class AtmosBlobRequestSigner implements BlobRequestSigner {
private final Invokable<?, ?> createMethod; private final Invokable<?, ?> createMethod;
@Inject @Inject
public AtmosBlobRequestSigner(RestAnnotationProcessor processor, BlobToObject blobToObject, public AtmosBlobRequestSigner(Function<Invocation, HttpRequest> processor, BlobToObject blobToObject,
BlobToHttpGetOptions blob2ObjectGetOptions) throws SecurityException, NoSuchMethodException { BlobToHttpGetOptions blob2ObjectGetOptions) throws SecurityException, NoSuchMethodException {
this.processor = checkNotNull(processor, "processor"); this.processor = checkNotNull(processor, "processor");
this.blobToObject = checkNotNull(blobToObject, "blobToObject"); this.blobToObject = checkNotNull(blobToObject, "blobToObject");

View File

@ -24,27 +24,32 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
import java.net.URI; import java.net.URI;
import org.jclouds.Fallback;
import org.jclouds.blobstore.KeyAlreadyExistsException; import org.jclouds.blobstore.KeyAlreadyExistsException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.rest.InvocationContext; import org.jclouds.rest.InvocationContext;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class EndpointIfAlreadyExists implements FutureFallback<URI>, InvocationContext<EndpointIfAlreadyExists> { public class EndpointIfAlreadyExists implements Fallback<URI>, InvocationContext<EndpointIfAlreadyExists> {
private URI endpoint; private URI endpoint;
@Override @Override
public ListenableFuture<URI> create(Throwable t) { public ListenableFuture<URI> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public URI createOrPropagate(Throwable t) throws Exception {
if (checkNotNull(t, "throwable") instanceof KeyAlreadyExistsException) { if (checkNotNull(t, "throwable") instanceof KeyAlreadyExistsException) {
return immediateFuture(endpoint); return endpoint;
} }
throw propagate(t); throw propagate(t);
} }

View File

@ -35,24 +35,24 @@ import org.testng.annotations.Test;
public class EndpointIfAlreadyExistsTest { public class EndpointIfAlreadyExistsTest {
@Test @Test
public void testFoundIsNullWhenEndpointNotSet() { public void testFoundIsNullWhenEndpointNotSet() throws Exception {
assertNull(getUnchecked(new EndpointIfAlreadyExists().create(new KeyAlreadyExistsException()))); assertNull(getUnchecked(new EndpointIfAlreadyExists().create(new KeyAlreadyExistsException())));
} }
@Test @Test
public void testFoundIsEndpointWhenSet() { public void testFoundIsEndpointWhenSet() throws Exception {
assertEquals( assertEquals(
getUnchecked(new EndpointIfAlreadyExists().setEndpoint(URI.create("foo")).create( getUnchecked(new EndpointIfAlreadyExists().setEndpoint(URI.create("foo")).create(
new KeyAlreadyExistsException())), URI.create("foo")); new KeyAlreadyExistsException())), URI.create("foo"));
} }
@Test(expectedExceptions = RuntimeException.class) @Test(expectedExceptions = RuntimeException.class)
public void testNotFoundPropagates() { public void testNotFoundPropagates() throws Exception {
new EndpointIfAlreadyExists().create(new RuntimeException()); new EndpointIfAlreadyExists().create(new RuntimeException());
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testNullIsBad() { public void testNullIsBad() throws Exception {
new EndpointIfAlreadyExists().create(null); new EndpointIfAlreadyExists().create(null);
} }
} }

View File

@ -20,11 +20,11 @@ package org.jclouds.cloudstack.functions;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.immediateFuture; import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.Fallbacks.valOnNotFoundOr404;
import static org.jclouds.util.Throwables2.getFirstThrowableOfType; import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
import org.jclouds.Fallbacks; import org.jclouds.Fallback;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
public final class CloudStackFallbacks { public final class CloudStackFallbacks {
@ -35,14 +35,19 @@ public final class CloudStackFallbacks {
* CloudStack is currently sending 431 errors with the text "Unable to find account owner for ip ". In this case, we * CloudStack is currently sending 431 errors with the text "Unable to find account owner for ip ". In this case, we
* have to ignore as there's no means for us to avoid the problem, or action to take. * have to ignore as there's no means for us to avoid the problem, or action to take.
*/ */
public static final class VoidOnNotFoundOr404OrUnableToFindAccountOwner implements FutureFallback<Void> { public static final class VoidOnNotFoundOr404OrUnableToFindAccountOwner implements Fallback<Void> {
@Override @Override
public ListenableFuture<Void> create(final Throwable t) { public ListenableFuture<Void> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public Void createOrPropagate(Throwable t) throws Exception {
IllegalStateException e = getFirstThrowableOfType(checkNotNull(t, "throwable"), IllegalStateException.class); IllegalStateException e = getFirstThrowableOfType(checkNotNull(t, "throwable"), IllegalStateException.class);
if (e != null && e.getMessage().indexOf("Unable to find account owner for") != -1) { if (e != null && e.getMessage().indexOf("Unable to find account owner for") != -1) {
return immediateFuture(null); return null;
} else { } else {
return Fallbacks.valOnNotFoundOr404(null, t); return valOnNotFoundOr404(null, t);
} }
} }
} }

View File

@ -23,24 +23,29 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate; import static com.google.common.base.Throwables.propagate;
import static com.google.common.util.concurrent.Futures.immediateFuture; import static com.google.common.util.concurrent.Futures.immediateFuture;
import org.jclouds.Fallback;
import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.AWSResponseException;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
public final class EC2Fallbacks { public final class EC2Fallbacks {
private EC2Fallbacks() { private EC2Fallbacks() {
} }
public static final class VoidOnVolumeAvailable implements FutureFallback<Object> { public static final class VoidOnVolumeAvailable implements Fallback<Void> {
@Override @Override
public ListenableFuture<Object> create(final Throwable t) { public ListenableFuture<Void> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public Void createOrPropagate(Throwable t) throws Exception {
if (checkNotNull(t, "throwable") instanceof AWSResponseException) { if (checkNotNull(t, "throwable") instanceof AWSResponseException) {
AWSResponseException e = AWSResponseException.class.cast(t); AWSResponseException e = AWSResponseException.class.cast(t);
if (Predicates.in(ImmutableSet.of("IncorrectState", "available")).apply(e.getError().getCode())) if (Predicates.in(ImmutableSet.of("IncorrectState", "available")).apply(e.getError().getCode()))
return immediateFuture(null); return null;
} }
throw propagate(t); throw propagate(t);
} }

View File

@ -18,27 +18,33 @@
*/ */
package org.jclouds.openstack.keystone.v2_0; package org.jclouds.openstack.keystone.v2_0;
import org.jclouds.Fallbacks; import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.Fallbacks.valOnNotFoundOr404;
import org.jclouds.Fallback;
import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection; import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
import org.jclouds.openstack.v2_0.domain.Link; import org.jclouds.openstack.v2_0.domain.Link;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
public final class KeystoneFallbacks { public final class KeystoneFallbacks {
private KeystoneFallbacks() { private KeystoneFallbacks() {
} }
public static final class EmptyPaginatedCollectionOnNotFoundOr404 implements public static final class EmptyPaginatedCollectionOnNotFoundOr404 implements Fallback<PaginatedCollection<Object>> {
FutureFallback<PaginatedCollection<Object>> {
private static final PaginatedCollection<Object> EMPTY = new PaginatedCollection<Object>( private static final PaginatedCollection<Object> EMPTY = new PaginatedCollection<Object>(
ImmutableSet.<Object> of(), ImmutableSet.<Link> of()) { ImmutableSet.<Object> of(), ImmutableSet.<Link> of()) {
}; };
@Override @Override
public ListenableFuture<PaginatedCollection<Object>> create(Throwable t) { public ListenableFuture<PaginatedCollection<Object>> create(Throwable t) throws Exception {
return Fallbacks.valOnNotFoundOr404(EMPTY, t); return immediateFuture(createOrPropagate(t));
}
@Override
public PaginatedCollection<Object> createOrPropagate(Throwable t) throws Exception {
return valOnNotFoundOr404(EMPTY, t);
} }
} }

View File

@ -25,24 +25,29 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull; import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import static org.jclouds.util.Throwables2.getFirstThrowableOfType; import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
import org.jclouds.Fallback;
import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.ContainerNotFoundException;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
public final class S3Fallbacks { public final class S3Fallbacks {
private S3Fallbacks() { private S3Fallbacks() {
} }
public static final class TrueOn404OrNotFoundFalseOnIllegalState implements FutureFallback<Boolean> { public static final class TrueOn404OrNotFoundFalseOnIllegalState implements Fallback<Boolean> {
@Override @Override
public ListenableFuture<Boolean> create(final Throwable t) { public ListenableFuture<Boolean> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public Boolean createOrPropagate(Throwable t) throws Exception {
if (getFirstThrowableOfType(checkNotNull(t, "throwable"), IllegalStateException.class) != null) if (getFirstThrowableOfType(checkNotNull(t, "throwable"), IllegalStateException.class) != null)
return immediateFuture(false); return false;
if (getFirstThrowableOfType(t, ContainerNotFoundException.class) != null) if (getFirstThrowableOfType(t, ContainerNotFoundException.class) != null)
return immediateFuture(true); return true;
if (returnValueOnCodeOrNull(t, true, equalTo(404)) != null) if (returnValueOnCodeOrNull(t, true, equalTo(404)) != null)
return immediateFuture(true); return true;
throw propagate(t); throw propagate(t);
} }
} }

View File

@ -26,20 +26,20 @@ import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.Fallback;
import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.AWSResponseException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.rest.InvocationContext; import org.jclouds.rest.InvocationContext;
import org.jclouds.s3.S3Client; import org.jclouds.s3.S3Client;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists implements FutureFallback<Boolean>, public class FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists implements Fallback<Boolean>,
InvocationContext<FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists> { InvocationContext<FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists> {
private final S3Client client; private final S3Client client;
@ -51,14 +51,19 @@ public class FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists im
} }
@Override @Override
public ListenableFuture<Boolean> create(final Throwable t) { public ListenableFuture<Boolean> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public Boolean createOrPropagate(Throwable t) throws Exception {
AWSResponseException exception = getFirstThrowableOfType(checkNotNull(t, "throwable"), AWSResponseException.class); AWSResponseException exception = getFirstThrowableOfType(checkNotNull(t, "throwable"), AWSResponseException.class);
if (exception != null && exception.getError() != null && exception.getError().getCode() != null) { if (exception != null && exception.getError() != null && exception.getError().getCode() != null) {
String code = exception.getError().getCode(); String code = exception.getError().getCode();
if (code.equals("BucketAlreadyOwnedByYou")) if (code.equals("BucketAlreadyOwnedByYou"))
return immediateFuture(false); return false;
else if (code.equals("OperationAborted") && bucket != null && client.bucketExists(bucket)) else if (code.equals("OperationAborted") && bucket != null && client.bucketExists(bucket))
return immediateFuture(false); return false;
} }
throw propagate(t); throw propagate(t);
} }

View File

@ -25,20 +25,26 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.http.HttpUtils.contains404; import static org.jclouds.http.HttpUtils.contains404;
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull; import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import com.google.common.util.concurrent.FutureFallback; import org.jclouds.Fallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
public final class SwiftFallbacks { public final class SwiftFallbacks {
private SwiftFallbacks() { private SwiftFallbacks() {
} }
public static final class TrueOn404FalseOn409 implements FutureFallback<Boolean> { public static final class TrueOn404FalseOn409 implements Fallback<Boolean> {
@Override @Override
public ListenableFuture<Boolean> create(final Throwable t) { public ListenableFuture<Boolean> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public Boolean createOrPropagate(Throwable t) throws Exception {
if (contains404(checkNotNull(t, "throwable"))) if (contains404(checkNotNull(t, "throwable")))
return immediateFuture(true); return true;
if (returnValueOnCodeOrNull(t, false, equalTo(409)) != null) if (returnValueOnCodeOrNull(t, false, equalTo(409)) != null)
return immediateFuture(false); return false;
throw propagate(t); throw propagate(t);
} }
} }

View File

@ -47,9 +47,8 @@ import org.jclouds.openstack.swift.TemporaryUrlKey;
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject; import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
import org.jclouds.openstack.swift.domain.SwiftObject; import org.jclouds.openstack.swift.domain.SwiftObject;
import org.jclouds.reflect.Invocation; import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -64,7 +63,7 @@ import com.google.inject.Provider;
@Singleton @Singleton
public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRequestSigner { public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRequestSigner {
private final RestAnnotationProcessor processor; private final Function<Invocation, HttpRequest> processor;
private final Crypto crypto; private final Crypto crypto;
private final Provider<Long> unixEpochTimestampProvider; private final Provider<Long> unixEpochTimestampProvider;
@ -86,8 +85,9 @@ public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRe
@Inject @Inject
protected SwiftBlobSigner(BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto, protected SwiftBlobSigner(BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto,
@TimeStamp Provider<Long> unixEpochTimestampProvider, @TimeStamp Provider<Long> unixEpochTimestampProvider,
@TemporaryUrlKey Supplier<String> temporaryUrlKeySupplier, RestAnnotationProcessor processor, @TemporaryUrlKey Supplier<String> temporaryUrlKeySupplier,
Class<T> ownerType) throws SecurityException, NoSuchMethodException { Function<Invocation, HttpRequest> processor, Class<T> ownerType) throws SecurityException,
NoSuchMethodException {
this.processor = checkNotNull(processor, "processor"); this.processor = checkNotNull(processor, "processor");
this.crypto = checkNotNull(crypto, "crypto"); this.crypto = checkNotNull(crypto, "crypto");
@ -112,8 +112,7 @@ public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRe
public HttpRequest signGetBlob(String container, String name, long timeInSeconds) { public HttpRequest signGetBlob(String container, String name, long timeInSeconds) {
checkNotNull(container, "container"); checkNotNull(container, "container");
checkNotNull(name, "name"); checkNotNull(name, "name");
GeneratedHttpRequest request = processor.apply(Invocation.create(getMethod, HttpRequest request = processor.apply(Invocation.create(getMethod, ImmutableList.<Object> of(container, name)));
ImmutableList.<Object> of(container, name)));
return cleanRequest(signForTemporaryAccess(request, timeInSeconds)); return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
} }
@ -137,7 +136,7 @@ public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRe
public HttpRequest signPutBlob(String container, Blob blob, long timeInSeconds) { public HttpRequest signPutBlob(String container, Blob blob, long timeInSeconds) {
checkNotNull(container, "container"); checkNotNull(container, "container");
checkNotNull(blob, "blob"); checkNotNull(blob, "blob");
GeneratedHttpRequest request = processor.apply(Invocation.create(createMethod, HttpRequest request = processor.apply(Invocation.create(createMethod,
ImmutableList.<Object> of(container, blobToObject.apply(blob)))); ImmutableList.<Object> of(container, blobToObject.apply(blob))));
return cleanRequest(signForTemporaryAccess(request, timeInSeconds)); return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
} }

View File

@ -23,20 +23,20 @@ import static com.google.common.base.Throwables.propagate;
import static com.google.common.util.concurrent.Futures.immediateFuture; import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.http.HttpUtils.contains404; import static org.jclouds.http.HttpUtils.contains404;
import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.Fallback;
import org.jclouds.blobstore.KeyNotFoundException;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
public final class BlobStoreFallbacks { public final class BlobStoreFallbacks {
private BlobStoreFallbacks() { private BlobStoreFallbacks() {
} }
public static final class ThrowContainerNotFoundOn404 implements FutureFallback<Object> { public static final class ThrowContainerNotFoundOn404 implements Fallback<Object> {
public ListenableFuture<Object> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override public Object createOrPropagate(Throwable t) throws Exception {
public ListenableFuture<Object> create(Throwable t) {
if (contains404(checkNotNull(t, "throwable"))) if (contains404(checkNotNull(t, "throwable")))
throw new ContainerNotFoundException(t); throw new ContainerNotFoundException(t);
throw propagate(t); throw propagate(t);
@ -44,10 +44,12 @@ public final class BlobStoreFallbacks {
} }
public static final class ThrowKeyNotFoundOn404 implements FutureFallback<Object> { public static final class ThrowKeyNotFoundOn404 implements Fallback<Object> {
public ListenableFuture<Object> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override public Object createOrPropagate(Throwable t) throws Exception {
public ListenableFuture<Object> create(Throwable t) {
if (contains404(checkNotNull(t, "throwable"))) if (contains404(checkNotNull(t, "throwable")))
throw new KeyNotFoundException(t); throw new KeyNotFoundException(t);
throw propagate(t); throw propagate(t);
@ -55,45 +57,53 @@ public final class BlobStoreFallbacks {
} }
public static final class FalseOnContainerNotFound implements FutureFallback<Boolean> { public static final class FalseOnContainerNotFound implements Fallback<Boolean> {
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override public Boolean createOrPropagate(Throwable t) throws Exception {
public ListenableFuture<Boolean> create(Throwable t) {
if (checkNotNull(t, "throwable") instanceof ContainerNotFoundException) { if (checkNotNull(t, "throwable") instanceof ContainerNotFoundException) {
return immediateFuture(false); return false;
} }
throw propagate(t); throw propagate(t);
} }
} }
public static final class FalseOnKeyNotFound implements FutureFallback<Boolean> { public static final class FalseOnKeyNotFound implements Fallback<Boolean> {
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override public Boolean createOrPropagate(Throwable t) throws Exception {
public ListenableFuture<Boolean> create(Throwable t) {
if (checkNotNull(t, "throwable") instanceof KeyNotFoundException) { if (checkNotNull(t, "throwable") instanceof KeyNotFoundException) {
return immediateFuture(false); return false;
} }
throw propagate(t); throw propagate(t);
} }
} }
public static final class NullOnContainerNotFound implements FutureFallback<Object> { public static final class NullOnContainerNotFound implements Fallback<Object> {
public ListenableFuture<Object> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override public Object createOrPropagate(Throwable t) throws Exception {
public ListenableFuture<Object> create(Throwable t) {
if (checkNotNull(t, "throwable") instanceof ContainerNotFoundException) { if (checkNotNull(t, "throwable") instanceof ContainerNotFoundException) {
return immediateFuture(null); return null;
} }
throw propagate(t); throw propagate(t);
} }
} }
public static final class NullOnKeyNotFound implements FutureFallback<Object> { public static final class NullOnKeyNotFound implements Fallback<Object> {
public ListenableFuture<Object> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override public Object createOrPropagate(Throwable t) throws Exception {
public ListenableFuture<Object> create(Throwable t) {
if (checkNotNull(t, "throwable") instanceof KeyNotFoundException) { if (checkNotNull(t, "throwable") instanceof KeyNotFoundException) {
return immediateFuture(null); return null;
} }
throw propagate(t); throw propagate(t);
} }

View File

@ -24,10 +24,10 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.jclouds.Fallback;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
public final class TerremarkVCloudFallbacks { public final class TerremarkVCloudFallbacks {
@ -40,19 +40,24 @@ public final class TerremarkVCloudFallbacks {
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public static final class VoidOnDeleteDefaultIp implements FutureFallback<Void> { public static final class VoidOnDeleteDefaultIp implements Fallback<Void> {
public static final Pattern MESSAGE_PATTERN = Pattern public static final Pattern MESSAGE_PATTERN = Pattern
.compile(".*Cannot release this Public IP as it is default oubound IP.*"); .compile(".*Cannot release this Public IP as it is default oubound IP.*");
@Override @Override
public ListenableFuture<Void> create(final Throwable t) { public ListenableFuture<Void> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public Void createOrPropagate(Throwable t) throws Exception {
if (checkNotNull(t, "throwable") instanceof HttpResponseException) { if (checkNotNull(t, "throwable") instanceof HttpResponseException) {
HttpResponseException hre = HttpResponseException.class.cast(t); HttpResponseException hre = HttpResponseException.class.cast(t);
if (hre.getResponse().getStatusCode() == 503 || hre.getResponse().getStatusCode() == 401 if (hre.getResponse().getStatusCode() == 503 || hre.getResponse().getStatusCode() == 401
|| MESSAGE_PATTERN.matcher(hre.getMessage()).matches()) || MESSAGE_PATTERN.matcher(hre.getMessage()).matches())
return immediateFuture(null); return null;
} else if (t instanceof AuthorizationException) { } else if (t instanceof AuthorizationException) {
return immediateFuture(null); return null;
} }
throw propagate(t); throw propagate(t);
} }

View File

@ -26,12 +26,12 @@ import static org.jclouds.http.HttpUtils.wirePayloadIfEnabled;
import java.io.IOException; import java.io.IOException;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.JcloudsVersion;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpCommandExecutorService; import org.jclouds.http.HttpCommandExecutorService;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
@ -42,58 +42,72 @@ import org.jclouds.http.HttpUtils;
import org.jclouds.http.IOExceptionRetryHandler; import org.jclouds.http.IOExceptionRetryHandler;
import org.jclouds.http.handlers.DelegatingErrorHandler; import org.jclouds.http.handlers.DelegatingErrorHandler;
import org.jclouds.http.handlers.DelegatingRetryHandler; import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.http.internal.BaseHttpCommandExecutorService;
import org.jclouds.http.internal.HttpWire; import org.jclouds.http.internal.HttpWire;
import org.jclouds.logging.Logger; import org.jclouds.io.ContentMetadataCodec;
import org.jclouds.util.Throwables2; import org.jclouds.util.Throwables2;
import com.google.appengine.api.urlfetch.HTTPRequest; import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService; import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.ListeningExecutorService;
/** /**
* Google App Engine version of {@link HttpCommandExecutorService} using their fetchAsync call * Google App Engine version of {@link HttpCommandExecutorService} using their
* fetchAsync call
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class AsyncGaeHttpCommandExecutorService implements HttpCommandExecutorService { public class AsyncGaeHttpCommandExecutorService extends BaseHttpCommandExecutorService<HTTPRequest> {
private final ListeningExecutorService ioExecutor; // TODO: look up gae version
public static final String USER_AGENT = String.format("jclouds/%s urlfetch/%s", JcloudsVersion.get(), "1.6.5");
private final URLFetchService urlFetchService; private final URLFetchService urlFetchService;
private final ConvertToGaeRequest convertToGaeRequest; private final ConvertToGaeRequest convertToGaeRequest;
private final ConvertToJcloudsResponse convertToJcloudsResponse; private final ConvertToJcloudsResponse convertToJcloudsResponse;
private final DelegatingRetryHandler retryHandler; private final ListeningExecutorService ioExecutor;
private final IOExceptionRetryHandler ioRetryHandler;
private final DelegatingErrorHandler errorHandler;
@Resource
protected Logger logger = Logger.NULL;
@Resource
@Named(Constants.LOGGER_HTTP_HEADERS)
protected Logger headerLog = Logger.NULL;
protected final HttpWire wire;
protected final HttpUtils utils;
@Inject @Inject
public AsyncGaeHttpCommandExecutorService( public AsyncGaeHttpCommandExecutorService(URLFetchService urlFetchService, HttpUtils utils,
ContentMetadataCodec contentMetadataCodec,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor, @Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
URLFetchService urlFetchService, ConvertToGaeRequest convertToGaeRequest, IOExceptionRetryHandler ioRetryHandler, DelegatingRetryHandler retryHandler,
ConvertToJcloudsResponse convertToJcloudsResponse, DelegatingRetryHandler retryHandler, DelegatingErrorHandler errorHandler, HttpWire wire, ConvertToGaeRequest convertToGaeRequest,
IOExceptionRetryHandler ioRetryHandler, DelegatingErrorHandler errorHandler, HttpUtils utils, HttpWire wire) { ConvertToJcloudsResponse convertToJcloudsResponse) {
super(utils, contentMetadataCodec, ioExecutor, retryHandler, ioRetryHandler, errorHandler, wire);
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.urlFetchService = urlFetchService; this.urlFetchService = urlFetchService;
this.convertToGaeRequest = convertToGaeRequest; this.convertToGaeRequest = convertToGaeRequest;
this.convertToJcloudsResponse = convertToJcloudsResponse; this.convertToJcloudsResponse = convertToJcloudsResponse;
this.retryHandler = retryHandler; }
this.ioRetryHandler = ioRetryHandler;
this.errorHandler = errorHandler; @VisibleForTesting
this.utils = utils; protected HttpResponse convert(HTTPResponse gaeResponse) {
this.wire = wire; return convertToJcloudsResponse.apply(gaeResponse);
}
@VisibleForTesting
protected HTTPRequest convert(HttpRequest request) throws IOException {
return convertToGaeRequest.apply(request);
}
/**
* nothing to clean up.
*/
@Override
protected void cleanup(HTTPRequest nativeRequest) {
}
@Override
protected HttpResponse invoke(HTTPRequest request) throws IOException {
return convert(urlFetchService.fetch(request));
} }
public HTTPRequest filterLogAndConvertRe(HttpRequest request) { public HTTPRequest filterLogAndConvertRe(HttpRequest request) {
for (HttpRequestFilter filter : request.getFilters()) { for (HttpRequestFilter filter : request.getFilters()) {
request = filter.filter(request); request = filter.filter(request);
} }
@ -108,61 +122,59 @@ public class AsyncGaeHttpCommandExecutorService implements HttpCommandExecutorSe
@Override @Override
public ListenableFuture<HttpResponse> submit(final HttpCommand command) { public ListenableFuture<HttpResponse> submit(final HttpCommand command) {
HTTPRequest nativeRequest = filterLogAndConvertRe(command.getCurrentRequest()); HTTPRequest nativeRequest = filterLogAndConvertRe(command.getCurrentRequest());
ListenableFuture<HttpResponse> response = transform( ListenableFuture<HttpResponse> response = transform(
listenInPoolThread(urlFetchService.fetchAsync(nativeRequest)), convertToJcloudsResponse); listenInPoolThread(urlFetchService.fetchAsync(nativeRequest)), convertToJcloudsResponse);
return transform(response, new Function<HttpResponse, HttpResponse>() { return transform(response, new Function<HttpResponse, HttpResponse>() {
@Override
public HttpResponse apply(HttpResponse response) { public HttpResponse apply(HttpResponse response) {
try { return receiveResponse(command, response);
logger.debug("Receiving response %s: %s", command.getCurrentRequest().hashCode(),
response.getStatusLine());
utils.logResponse(headerLog, response, "<<");
if (response.getPayload() != null && wire.enabled())
wire.input(response);
int statusCode = response.getStatusCode();
if (statusCode >= 300) {
if (shouldContinue(response))
return submit(command).get();
else
return response;
}
return response;
} catch (Exception e) {
IOException ioe = Throwables2.getFirstThrowableOfType(e, IOException.class);
if (ioe != null && ioRetryHandler.shouldRetryRequest(command, ioe)) {
try {
return submit(command).get();
} catch (Exception e1) {
command.setException(e1);
return response;
}
} else {
command.setException(new HttpResponseException(e.getMessage() + " connecting to "
+ command.getCurrentRequest().getRequestLine(), command, null, e));
return response;
}
} finally {
if (command.getException() != null)
propagate(command.getException());
}
} }
private boolean shouldContinue(HttpResponse response) {
boolean shouldContinue = false;
if (retryHandler.shouldRetryRequest(command, response)) {
shouldContinue = true;
} else {
errorHandler.handleError(command, response);
}
return shouldContinue;
}
}, ioExecutor); }, ioExecutor);
} }
private HttpResponse receiveResponse(HttpCommand command, HttpResponse response) {
try {
logger.debug("Receiving response %s: %s", command.getCurrentRequest().hashCode(), response.getStatusLine());
utils.logResponse(headerLog, response, "<<");
if (response.getPayload() != null && wire.enabled())
wire.input(response);
int statusCode = response.getStatusCode();
if (statusCode >= 300) {
if (shouldContinue(command, response))
return submit(command).get();
else
return response;
}
return response;
} catch (Exception e) {
IOException ioe = Throwables2.getFirstThrowableOfType(e, IOException.class);
if (ioe != null && ioRetryHandler.shouldRetryRequest(command, ioe)) {
try {
return submit(command).get();
} catch (Exception e1) {
command.setException(e1);
return response;
}
} else {
command.setException(new HttpResponseException(e.getMessage() + " connecting to "
+ command.getCurrentRequest().getRequestLine(), command, null, e));
return response;
}
} finally {
if (command.getException() != null)
propagate(command.getException());
}
}
private boolean shouldContinue(HttpCommand command, HttpResponse response) {
boolean shouldContinue = false;
if (retryHandler.shouldRetryRequest(command, response)) {
shouldContinue = true;
} else {
errorHandler.handleError(command, response);
}
return shouldContinue;
}
} }

View File

@ -25,7 +25,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;

View File

@ -53,7 +53,7 @@ import com.google.common.util.concurrent.ListeningExecutorService;
@Singleton @Singleton
public class GaeHttpCommandExecutorService extends BaseHttpCommandExecutorService<HTTPRequest> { public class GaeHttpCommandExecutorService extends BaseHttpCommandExecutorService<HTTPRequest> {
//TODO: look up gae version //TODO: look up gae version
public static final String USER_AGENT = String.format("jclouds/%s urlfetch/%s", JcloudsVersion.get(), "1.4.3"); public static final String USER_AGENT = String.format("jclouds/%s urlfetch/%s", JcloudsVersion.get(), "1.6.5");
private final URLFetchService urlFetchService; private final URLFetchService urlFetchService;
private final ConvertToGaeRequest convertToGaeRequest; private final ConvertToGaeRequest convertToGaeRequest;

View File

@ -26,13 +26,13 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import org.jclouds.Fallback;
import org.jclouds.abiquo.domain.exception.AbiquoException; import org.jclouds.abiquo.domain.exception.AbiquoException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
/** /**
@ -47,22 +47,30 @@ public final class AbiquoFallbacks {
/** /**
* Return an Abiquo Exception on not found errors. * Return an Abiquo Exception on not found errors.
*/ */
public static final class PropagateAbiquoExceptionOnNotFoundOr4xx implements FutureFallback<Object> { public static final class PropagateAbiquoExceptionOnNotFoundOr4xx implements Fallback<Object> {
@Override @Override
public ListenableFuture<Object> create(final Throwable from) { public ListenableFuture<Object> create(Throwable from) throws Exception {
Throwable exception = find(getCausalChain(from), isNotFoundAndHasAbiquoException(from), null); return immediateFuture(createOrPropagate(from));
throw propagate(exception == null ? from : exception.getCause());
} }
@Override
public Object createOrPropagate(Throwable from) throws Exception {
Throwable exception = find(getCausalChain(from), isNotFoundAndHasAbiquoException(from), null);
throw propagate(exception == null ? from : exception.getCause());
}
} }
/** /**
* Return <code>null</code> on 303 response codes when requesting a task. * Return <code>null</code> on 303 response codes when requesting a task.
*/ */
public static final class NullOn303 implements FutureFallback<Object> { public static final class NullOn303 implements Fallback<Object> {
@Override @Override
public ListenableFuture<Object> create(final Throwable from) { public ListenableFuture<Object> create(Throwable from) throws Exception {
return immediateFuture(createOrPropagate(from));
}
@Override
public Object createOrPropagate(Throwable from) throws Exception {
Throwable exception = find(getCausalChain(from), hasResponse(from), null); Throwable exception = find(getCausalChain(from), hasResponse(from), null);
if (exception != null) { if (exception != null) {
@ -70,7 +78,7 @@ public final class AbiquoFallbacks {
HttpResponse response = responseException.getResponse(); HttpResponse response = responseException.getResponse();
if (response != null && response.getStatusCode() == Status.SEE_OTHER.getStatusCode()) { if (response != null && response.getStatusCode() == Status.SEE_OTHER.getStatusCode()) {
return immediateFuture(null); return null;
} }
} }
@ -82,9 +90,14 @@ public final class AbiquoFallbacks {
/** /**
* Return false on service error exceptions. * Return false on service error exceptions.
*/ */
public static final class FalseOn5xx implements FutureFallback<Boolean> { public static final class FalseOn5xx implements Fallback<Boolean> {
@Override @Override
public ListenableFuture<Boolean> create(final Throwable from) { public ListenableFuture<Boolean> create(Throwable from) throws Exception {
return immediateFuture(createOrPropagate(from));
}
@Override
public Boolean createOrPropagate(Throwable from) throws Exception {
Throwable exception = find(getCausalChain(from), hasResponse(from), null); Throwable exception = find(getCausalChain(from), hasResponse(from), null);
if (exception != null) { if (exception != null) {
@ -92,7 +105,7 @@ public final class AbiquoFallbacks {
HttpResponse response = responseException.getResponse(); HttpResponse response = responseException.getResponse();
if (response != null && response.getStatusCode() >= 500 && response.getStatusCode() < 600) { if (response != null && response.getStatusCode() >= 500 && response.getStatusCode() < 600) {
return immediateFuture(false); return false;
} }
} }
@ -104,9 +117,14 @@ public final class AbiquoFallbacks {
/** /**
* Return false on service error exceptions. * Return false on service error exceptions.
*/ */
public static final class FalseIfNotAvailable implements FutureFallback<Boolean> { public static final class FalseIfNotAvailable implements Fallback<Boolean> {
@Override @Override
public ListenableFuture<Boolean> create(final Throwable from) { public ListenableFuture<Boolean> create(Throwable from) throws Exception {
return immediateFuture(createOrPropagate(from));
}
@Override
public Boolean createOrPropagate(Throwable from) throws Exception {
Throwable exception = find(getCausalChain(from), isNotAvailableException(from), null); Throwable exception = find(getCausalChain(from), isNotAvailableException(from), null);
if (exception != null) { if (exception != null) {
@ -115,11 +133,11 @@ public final class AbiquoFallbacks {
HttpResponse response = responseException.getResponse(); HttpResponse response = responseException.getResponse();
if (response != null && response.getStatusCode() >= 500 && response.getStatusCode() < 600) { if (response != null && response.getStatusCode() >= 500 && response.getStatusCode() < 600) {
return immediateFuture(false); return false;
} }
} else { } else {
// Will enter here when exception is a ResourceNotFoundException // Will enter here when exception is a ResourceNotFoundException
return immediateFuture(false); return false;
} }
} }

View File

@ -28,6 +28,7 @@ import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import org.jclouds.Fallback;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.http.functions.ParseXMLWithJAXB; import org.jclouds.http.functions.ParseXMLWithJAXB;
@ -37,7 +38,6 @@ import com.abiquo.server.core.infrastructure.storage.MovedVolumeDto;
import com.abiquo.server.core.infrastructure.storage.VolumeManagementDto; import com.abiquo.server.core.infrastructure.storage.VolumeManagementDto;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -47,7 +47,7 @@ import com.google.inject.TypeLiteral;
* @author Ignasi Barrera * @author Ignasi Barrera
*/ */
@Singleton @Singleton
public class MovedVolume implements FutureFallback<VolumeManagementDto> { public class MovedVolume implements Fallback<VolumeManagementDto> {
@Singleton @Singleton
@VisibleForTesting @VisibleForTesting
@ -67,14 +67,19 @@ public class MovedVolume implements FutureFallback<VolumeManagementDto> {
} }
@Override @Override
public ListenableFuture<VolumeManagementDto> create(final Throwable from) { public ListenableFuture<VolumeManagementDto> create(Throwable from) throws Exception {
return immediateFuture(createOrPropagate(from));
}
@Override
public VolumeManagementDto createOrPropagate(Throwable from) throws Exception {
Throwable exception = find(getCausalChain(from), isMovedException(from), null); Throwable exception = find(getCausalChain(from), isMovedException(from), null);
if (exception != null) { if (exception != null) {
HttpResponseException responseException = (HttpResponseException) exception; HttpResponseException responseException = (HttpResponseException) exception;
HttpResponse response = responseException.getResponse(); HttpResponse response = responseException.getResponse();
return immediateFuture(parser.apply(response).getVolume()); return parser.apply(response).getVolume();
} }
throw propagate(from); throw propagate(from);

View File

@ -19,7 +19,6 @@
package org.jclouds.abiquo.fallbacks; package org.jclouds.abiquo.fallbacks;
import static com.google.common.util.concurrent.Futures.getUnchecked;
import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify; import static org.easymock.EasyMock.verify;
@ -45,13 +44,13 @@ public class FalseIfNotAvailableTest {
RuntimeException exception = new RuntimeException(); RuntimeException exception = new RuntimeException();
try { try {
function.create(exception); function.createOrPropagate(exception);
} catch (Exception ex) { } catch (Exception ex) {
assertEquals(ex, exception); assertEquals(ex, exception);
} }
} }
public void testFalseIf5xx() { public void testFalseIf5xx() throws Exception {
FalseIfNotAvailable function = new FalseIfNotAvailable(); FalseIfNotAvailable function = new FalseIfNotAvailable();
HttpResponse response = EasyMock.createMock(HttpResponse.class); HttpResponse response = EasyMock.createMock(HttpResponse.class);
HttpResponseException exception = EasyMock.createMock(HttpResponseException.class); HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);
@ -68,7 +67,7 @@ public class FalseIfNotAvailableTest {
replay(response); replay(response);
replay(exception); replay(exception);
assertFalse(getUnchecked(function.create(exception))); assertFalse(function.createOrPropagate(exception));
verify(response); verify(response);
verify(exception); verify(exception);
@ -92,7 +91,7 @@ public class FalseIfNotAvailableTest {
replay(exception); replay(exception);
try { try {
function.create(exception); function.createOrPropagate(exception);
} catch (Exception ex) { } catch (Exception ex) {
assertEquals(ex, exception); assertEquals(ex, exception);
} }
@ -101,11 +100,11 @@ public class FalseIfNotAvailableTest {
verify(exception); verify(exception);
} }
public void testFalseIfResourceNotFound() { public void testFalseIfResourceNotFound() throws Exception {
FalseIfNotAvailable function = new FalseIfNotAvailable(); FalseIfNotAvailable function = new FalseIfNotAvailable();
ResourceNotFoundException exception = new ResourceNotFoundException(); ResourceNotFoundException exception = new ResourceNotFoundException();
assertFalse(getUnchecked(function.create(exception))); assertFalse(function.createOrPropagate(exception));
} }
} }

View File

@ -19,7 +19,6 @@
package org.jclouds.abiquo.fallbacks; package org.jclouds.abiquo.fallbacks;
import static com.google.common.util.concurrent.Futures.getUnchecked;
import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify; import static org.easymock.EasyMock.verify;
@ -44,13 +43,13 @@ public class FalseOn5xxTest {
RuntimeException exception = new RuntimeException(); RuntimeException exception = new RuntimeException();
try { try {
function.create(exception); function.createOrPropagate(exception);
} catch (Exception ex) { } catch (Exception ex) {
assertEquals(ex, exception); assertEquals(ex, exception);
} }
} }
public void testFalseIf5xx() { public void testFalseIf5xx() throws Exception {
FalseOn5xx function = new FalseOn5xx(); FalseOn5xx function = new FalseOn5xx();
HttpResponse response = EasyMock.createMock(HttpResponse.class); HttpResponse response = EasyMock.createMock(HttpResponse.class);
HttpResponseException exception = EasyMock.createMock(HttpResponseException.class); HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);
@ -67,7 +66,7 @@ public class FalseOn5xxTest {
replay(response); replay(response);
replay(exception); replay(exception);
assertFalse(getUnchecked(function.create(exception))); assertFalse(function.createOrPropagate(exception));
verify(response); verify(response);
verify(exception); verify(exception);
@ -91,7 +90,7 @@ public class FalseOn5xxTest {
replay(exception); replay(exception);
try { try {
function.create(exception); function.createOrPropagate(exception);
} catch (Exception ex) { } catch (Exception ex) {
assertEquals(ex, exception); assertEquals(ex, exception);
} }

View File

@ -24,8 +24,6 @@ import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify; import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.io.IOException;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import org.easymock.EasyMock; import org.easymock.EasyMock;
@ -61,7 +59,7 @@ public class MovedVolumeTest {
} }
} }
public void testReturnVolume() throws IOException { public void testReturnVolume() throws Exception {
JAXBParser xmlParser = new JAXBParser("false"); JAXBParser xmlParser = new JAXBParser("false");
MovedVolume function = new MovedVolume(new ReturnMoveVolumeReference( MovedVolume function = new MovedVolume(new ReturnMoveVolumeReference(
new JAXBParser("false"), TypeLiteral.get(MovedVolumeDto.class))); new JAXBParser("false"), TypeLiteral.get(MovedVolumeDto.class)));

View File

@ -19,7 +19,6 @@
package org.jclouds.abiquo.fallbacks; package org.jclouds.abiquo.fallbacks;
import static com.google.common.util.concurrent.Futures.getUnchecked;
import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify; import static org.easymock.EasyMock.verify;
@ -44,13 +43,13 @@ public class NullOn303Test {
RuntimeException exception = new RuntimeException(); RuntimeException exception = new RuntimeException();
try { try {
function.create(exception); function.createOrPropagate(exception);
} catch (Exception ex) { } catch (Exception ex) {
assertEquals(ex, exception); assertEquals(ex, exception);
} }
} }
public void testNullIf303() { public void testNullIf303() throws Exception {
NullOn303 function = new NullOn303(); NullOn303 function = new NullOn303();
HttpResponse response = EasyMock.createMock(HttpResponse.class); HttpResponse response = EasyMock.createMock(HttpResponse.class);
HttpResponseException exception = EasyMock.createMock(HttpResponseException.class); HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);
@ -66,7 +65,7 @@ public class NullOn303Test {
replay(response); replay(response);
replay(exception); replay(exception);
assertNull(getUnchecked(function.create(exception))); assertNull(function.createOrPropagate(exception));
verify(response); verify(response);
verify(exception); verify(exception);
@ -89,7 +88,7 @@ public class NullOn303Test {
replay(exception); replay(exception);
try { try {
function.create(exception); function.createOrPropagate(exception);
} catch (Exception ex) { } catch (Exception ex) {
assertEquals(ex, exception); assertEquals(ex, exception);
} }

View File

@ -23,7 +23,8 @@ import static com.google.common.base.Throwables.propagate;
import static com.google.common.util.concurrent.Futures.immediateFuture; import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull; import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import com.google.common.util.concurrent.FutureFallback; import org.jclouds.Fallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
/** /**
@ -34,10 +35,16 @@ public final class DynECTFallbacks {
private DynECTFallbacks() { private DynECTFallbacks() {
} }
public static class FalseOn400 implements FutureFallback<Boolean> { public static class FalseOn400 implements Fallback<Boolean> {
public ListenableFuture<Boolean> create(Throwable t) { @Override
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public Boolean createOrPropagate(Throwable t) throws Exception {
if (returnValueOnCodeOrNull(t, false, equalTo(400)) != null) if (returnValueOnCodeOrNull(t, false, equalTo(400)) != null)
return immediateFuture(false); return false;
throw propagate(t); throw propagate(t);
} }
} }

View File

@ -24,8 +24,9 @@ import static com.google.common.base.Throwables.propagate;
import static com.google.common.util.concurrent.Futures.immediateFuture; import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull; import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import org.jclouds.Fallback;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
/** /**
@ -36,13 +37,18 @@ public final class JenkinsFallbacks {
private JenkinsFallbacks() { private JenkinsFallbacks() {
} }
public static final class VoidOn302Or404 implements FutureFallback<Void> { public static final class VoidOn302Or404 implements Fallback<Void> {
@Override @Override
public ListenableFuture<Void> create(final Throwable t) { public ListenableFuture<Void> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public Void createOrPropagate(Throwable t) throws Exception {
Boolean returnVal = returnValueOnCodeOrNull(checkNotNull(t, "throwable"), true, Boolean returnVal = returnValueOnCodeOrNull(checkNotNull(t, "throwable"), true,
Predicates.<Integer> or(equalTo(302), equalTo(404))); Predicates.<Integer> or(equalTo(302), equalTo(404)));
if (returnVal != null && returnVal) if (returnVal != null && returnVal)
return immediateFuture(null); return null;
throw propagate(t); throw propagate(t);
} }

View File

@ -22,23 +22,28 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.immediateFuture; import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.Fallbacks.valOnNotFoundOr404; import static org.jclouds.Fallbacks.valOnNotFoundOr404;
import org.jclouds.Fallback;
import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.AWSResponseException;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
public final class RDSFallbacks { public final class RDSFallbacks {
private RDSFallbacks() { private RDSFallbacks() {
} }
public static final class NullOnStateDeletingNotFoundOr404 implements FutureFallback<Object> { public static final class NullOnStateDeletingNotFoundOr404 implements Fallback<Object> {
@Override @Override
public ListenableFuture<Object> create(final Throwable t) { public ListenableFuture<Object> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public Object createOrPropagate(Throwable t) throws Exception {
if (checkNotNull(t, "throwable") instanceof AWSResponseException) { if (checkNotNull(t, "throwable") instanceof AWSResponseException) {
AWSResponseException e = AWSResponseException.class.cast(t); AWSResponseException e = AWSResponseException.class.cast(t);
if ("InvalidDBInstanceState".equals(e.getError().getCode()) if ("InvalidDBInstanceState".equals(e.getError().getCode())
&& e.getError().getMessage().contains("has state: deleting")) && e.getError().getMessage().contains("has state: deleting"))
return immediateFuture(null); return null;
} }
return valOnNotFoundOr404(null, t); return valOnNotFoundOr404(null, t);
} }

View File

@ -22,9 +22,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate; import static com.google.common.base.Throwables.propagate;
import static com.google.common.util.concurrent.Futures.immediateFuture; import static com.google.common.util.concurrent.Futures.immediateFuture;
import org.jclouds.Fallback;
import org.jclouds.azure.storage.AzureStorageResponseException; import org.jclouds.azure.storage.AzureStorageResponseException;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
/** /**
@ -35,14 +35,18 @@ public final class AzureBlobFallbacks {
private AzureBlobFallbacks() { private AzureBlobFallbacks() {
} }
public static final class FalseIfContainerAlreadyExists implements FutureFallback<Boolean> { public static final class FalseIfContainerAlreadyExists implements Fallback<Boolean> {
@Override
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override @Override
public ListenableFuture<Boolean> create(Throwable t) { public Boolean createOrPropagate(Throwable t) throws Exception {
if (checkNotNull(t, "throwable") instanceof AzureStorageResponseException) { if (checkNotNull(t, "throwable") instanceof AzureStorageResponseException) {
AzureStorageResponseException responseException = AzureStorageResponseException.class.cast(t); AzureStorageResponseException responseException = AzureStorageResponseException.class.cast(t);
if ("ContainerAlreadyExists".equals(responseException.getError().getCode())) { if ("ContainerAlreadyExists".equals(responseException.getError().getCode())) {
return immediateFuture(false); return false;
} }
} }
throw propagate(t); throw propagate(t);

View File

@ -34,8 +34,9 @@ import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
import org.jclouds.reflect.Invocation; import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.reflect.Invokable; import com.google.common.reflect.Invokable;
@ -45,7 +46,7 @@ import com.google.common.reflect.Invokable;
*/ */
@Singleton @Singleton
public class AzureBlobRequestSigner implements BlobRequestSigner { public class AzureBlobRequestSigner implements BlobRequestSigner {
private final RestAnnotationProcessor processor; private final Function<Invocation, HttpRequest> processor;
private final BlobToAzureBlob blobToBlob; private final BlobToAzureBlob blobToBlob;
private final BlobToHttpGetOptions blob2HttpGetOptions; private final BlobToHttpGetOptions blob2HttpGetOptions;
@ -54,7 +55,7 @@ public class AzureBlobRequestSigner implements BlobRequestSigner {
private final Invokable<?, ?> createMethod; private final Invokable<?, ?> createMethod;
@Inject @Inject
public AzureBlobRequestSigner(RestAnnotationProcessor processor, BlobToAzureBlob blobToBlob, public AzureBlobRequestSigner(Function<Invocation, HttpRequest> processor, BlobToAzureBlob blobToBlob,
BlobToHttpGetOptions blob2HttpGetOptions) throws SecurityException, NoSuchMethodException { BlobToHttpGetOptions blob2HttpGetOptions) throws SecurityException, NoSuchMethodException {
this.processor = checkNotNull(processor, "processor"); this.processor = checkNotNull(processor, "processor");
this.blobToBlob = checkNotNull(blobToBlob, "blobToBlob"); this.blobToBlob = checkNotNull(blobToBlob, "blobToBlob");

View File

@ -51,9 +51,8 @@ import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject; import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
import org.jclouds.openstack.swift.domain.SwiftObject; import org.jclouds.openstack.swift.domain.SwiftObject;
import org.jclouds.reflect.Invocation; import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -69,7 +68,7 @@ import com.google.inject.Provider;
@Singleton @Singleton
public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner { public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner {
private final RestAnnotationProcessor processor; private final Function<Invocation, HttpRequest> processor;
private final Crypto crypto; private final Crypto crypto;
private final Provider<Long> unixEpochTimestampProvider; private final Provider<Long> unixEpochTimestampProvider;
@ -84,7 +83,7 @@ public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner
private final Invokable<?, ?> createMethod; private final Invokable<?, ?> createMethod;
@Inject @Inject
public HPCloudObjectStorageBlobRequestSigner(RestAnnotationProcessor processor, public HPCloudObjectStorageBlobRequestSigner(Function<Invocation, HttpRequest> processor,
BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto, BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto,
@TimeStamp Provider<Long> unixEpochTimestampProvider, Supplier<Access> access, @TimeStamp Provider<Long> unixEpochTimestampProvider, Supplier<Access> access,
@org.jclouds.location.Provider final Supplier<Credentials> creds) throws SecurityException, @org.jclouds.location.Provider final Supplier<Credentials> creds) throws SecurityException,
@ -115,8 +114,7 @@ public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner
public HttpRequest signGetBlob(String container, String name, long timeInSeconds) { public HttpRequest signGetBlob(String container, String name, long timeInSeconds) {
checkNotNull(container, "container"); checkNotNull(container, "container");
checkNotNull(name, "name"); checkNotNull(name, "name");
GeneratedHttpRequest request = processor.apply(Invocation.create(getMethod, HttpRequest request = processor.apply(Invocation.create(getMethod, ImmutableList.<Object> of(container, name)));
ImmutableList.<Object> of(container, name)));
return cleanRequest(signForTemporaryAccess(request, timeInSeconds)); return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
} }
@ -140,7 +138,7 @@ public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner
public HttpRequest signPutBlob(String container, Blob blob, long timeInSeconds) { public HttpRequest signPutBlob(String container, Blob blob, long timeInSeconds) {
checkNotNull(container, "container"); checkNotNull(container, "container");
checkNotNull(blob, "blob"); checkNotNull(blob, "blob");
GeneratedHttpRequest request = processor.apply(Invocation.create(createMethod, HttpRequest request = processor.apply(Invocation.create(createMethod,
ImmutableList.<Object> of(container, blobToObject.apply(blob)))); ImmutableList.<Object> of(container, blobToObject.apply(blob))));
return cleanRequest(signForTemporaryAccess(request, timeInSeconds)); return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
} }