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.options.GetOptions;
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.reflect.Invokable;
@ -46,7 +47,7 @@ import com.google.common.reflect.Invokable;
*/
@Singleton
public class AtmosBlobRequestSigner implements BlobRequestSigner {
private final RestAnnotationProcessor processor;
private final Function<Invocation, HttpRequest> processor;
private final BlobToObject blobToObject;
private final BlobToHttpGetOptions blob2ObjectGetOptions;
@ -55,7 +56,7 @@ public class AtmosBlobRequestSigner implements BlobRequestSigner {
private final Invokable<?, ?> createMethod;
@Inject
public AtmosBlobRequestSigner(RestAnnotationProcessor processor, BlobToObject blobToObject,
public AtmosBlobRequestSigner(Function<Invocation, HttpRequest> processor, BlobToObject blobToObject,
BlobToHttpGetOptions blob2ObjectGetOptions) throws SecurityException, NoSuchMethodException {
this.processor = checkNotNull(processor, "processor");
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 org.jclouds.Fallback;
import org.jclouds.blobstore.KeyAlreadyExistsException;
import org.jclouds.http.HttpRequest;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.rest.InvocationContext;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
/**
*
* @author Adrian Cole
*/
public class EndpointIfAlreadyExists implements FutureFallback<URI>, InvocationContext<EndpointIfAlreadyExists> {
public class EndpointIfAlreadyExists implements Fallback<URI>, InvocationContext<EndpointIfAlreadyExists> {
private URI endpoint;
@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) {
return immediateFuture(endpoint);
return endpoint;
}
throw propagate(t);
}

View File

@ -35,24 +35,24 @@ import org.testng.annotations.Test;
public class EndpointIfAlreadyExistsTest {
@Test
public void testFoundIsNullWhenEndpointNotSet() {
public void testFoundIsNullWhenEndpointNotSet() throws Exception {
assertNull(getUnchecked(new EndpointIfAlreadyExists().create(new KeyAlreadyExistsException())));
}
@Test
public void testFoundIsEndpointWhenSet() {
public void testFoundIsEndpointWhenSet() throws Exception {
assertEquals(
getUnchecked(new EndpointIfAlreadyExists().setEndpoint(URI.create("foo")).create(
new KeyAlreadyExistsException())), URI.create("foo"));
}
@Test(expectedExceptions = RuntimeException.class)
public void testNotFoundPropagates() {
public void testNotFoundPropagates() throws Exception {
new EndpointIfAlreadyExists().create(new RuntimeException());
}
@Test(expectedExceptions = NullPointerException.class)
public void testNullIsBad() {
public void testNullIsBad() throws Exception {
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.util.concurrent.Futures.immediateFuture;
import static org.jclouds.Fallbacks.valOnNotFoundOr404;
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;
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
* 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
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);
if (e != null && e.getMessage().indexOf("Unable to find account owner for") != -1) {
return immediateFuture(null);
return null;
} 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.util.concurrent.Futures.immediateFuture;
import org.jclouds.Fallback;
import org.jclouds.aws.AWSResponseException;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
public final class EC2Fallbacks {
private EC2Fallbacks() {
}
public static final class VoidOnVolumeAvailable implements FutureFallback<Object> {
public static final class VoidOnVolumeAvailable implements Fallback<Void> {
@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) {
AWSResponseException e = AWSResponseException.class.cast(t);
if (Predicates.in(ImmutableSet.of("IncorrectState", "available")).apply(e.getError().getCode()))
return immediateFuture(null);
return null;
}
throw propagate(t);
}

View File

@ -18,27 +18,33 @@
*/
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.v2_0.domain.Link;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
public final class KeystoneFallbacks {
private KeystoneFallbacks() {
}
public static final class EmptyPaginatedCollectionOnNotFoundOr404 implements
FutureFallback<PaginatedCollection<Object>> {
public static final class EmptyPaginatedCollectionOnNotFoundOr404 implements Fallback<PaginatedCollection<Object>> {
private static final PaginatedCollection<Object> EMPTY = new PaginatedCollection<Object>(
ImmutableSet.<Object> of(), ImmutableSet.<Link> of()) {
};
@Override
public ListenableFuture<PaginatedCollection<Object>> create(Throwable t) {
return Fallbacks.valOnNotFoundOr404(EMPTY, t);
public ListenableFuture<PaginatedCollection<Object>> create(Throwable t) throws Exception {
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.util.Throwables2.getFirstThrowableOfType;
import org.jclouds.Fallback;
import org.jclouds.blobstore.ContainerNotFoundException;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
public final class S3Fallbacks {
private S3Fallbacks() {
}
public static final class TrueOn404OrNotFoundFalseOnIllegalState implements FutureFallback<Boolean> {
public static final class TrueOn404OrNotFoundFalseOnIllegalState implements Fallback<Boolean> {
@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)
return immediateFuture(false);
return false;
if (getFirstThrowableOfType(t, ContainerNotFoundException.class) != null)
return immediateFuture(true);
return true;
if (returnValueOnCodeOrNull(t, true, equalTo(404)) != null)
return immediateFuture(true);
return true;
throw propagate(t);
}
}

View File

@ -26,20 +26,20 @@ import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
import javax.inject.Inject;
import org.jclouds.Fallback;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.http.HttpRequest;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.rest.InvocationContext;
import org.jclouds.s3.S3Client;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
/**
*
* @author Adrian Cole
*/
public class FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists implements FutureFallback<Boolean>,
public class FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists implements Fallback<Boolean>,
InvocationContext<FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists> {
private final S3Client client;
@ -51,14 +51,19 @@ public class FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists im
}
@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);
if (exception != null && exception.getError() != null && exception.getError().getCode() != null) {
String code = exception.getError().getCode();
if (code.equals("BucketAlreadyOwnedByYou"))
return immediateFuture(false);
return false;
else if (code.equals("OperationAborted") && bucket != null && client.bucketExists(bucket))
return immediateFuture(false);
return false;
}
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.returnValueOnCodeOrNull;
import com.google.common.util.concurrent.FutureFallback;
import org.jclouds.Fallback;
import com.google.common.util.concurrent.ListenableFuture;
public final class SwiftFallbacks {
private SwiftFallbacks() {
}
public static final class TrueOn404FalseOn409 implements FutureFallback<Boolean> {
public static final class TrueOn404FalseOn409 implements Fallback<Boolean> {
@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")))
return immediateFuture(true);
return true;
if (returnValueOnCodeOrNull(t, false, equalTo(409)) != null)
return immediateFuture(false);
return false;
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.domain.SwiftObject;
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.Throwables;
import com.google.common.collect.ImmutableList;
@ -64,7 +63,7 @@ import com.google.inject.Provider;
@Singleton
public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRequestSigner {
private final RestAnnotationProcessor processor;
private final Function<Invocation, HttpRequest> processor;
private final Crypto crypto;
private final Provider<Long> unixEpochTimestampProvider;
@ -86,8 +85,9 @@ public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRe
@Inject
protected SwiftBlobSigner(BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto,
@TimeStamp Provider<Long> unixEpochTimestampProvider,
@TemporaryUrlKey Supplier<String> temporaryUrlKeySupplier, RestAnnotationProcessor processor,
Class<T> ownerType) throws SecurityException, NoSuchMethodException {
@TemporaryUrlKey Supplier<String> temporaryUrlKeySupplier,
Function<Invocation, HttpRequest> processor, Class<T> ownerType) throws SecurityException,
NoSuchMethodException {
this.processor = checkNotNull(processor, "processor");
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) {
checkNotNull(container, "container");
checkNotNull(name, "name");
GeneratedHttpRequest request = processor.apply(Invocation.create(getMethod,
ImmutableList.<Object> of(container, name)));
HttpRequest request = processor.apply(Invocation.create(getMethod, ImmutableList.<Object> of(container, name)));
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) {
checkNotNull(container, "container");
checkNotNull(blob, "blob");
GeneratedHttpRequest request = processor.apply(Invocation.create(createMethod,
HttpRequest request = processor.apply(Invocation.create(createMethod,
ImmutableList.<Object> of(container, blobToObject.apply(blob))));
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 org.jclouds.http.HttpUtils.contains404;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.Fallback;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
public final class 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 ListenableFuture<Object> create(Throwable t) {
public Object createOrPropagate(Throwable t) throws Exception {
if (contains404(checkNotNull(t, "throwable")))
throw new ContainerNotFoundException(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 ListenableFuture<Object> create(Throwable t) {
public Object createOrPropagate(Throwable t) throws Exception {
if (contains404(checkNotNull(t, "throwable")))
throw new KeyNotFoundException(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 ListenableFuture<Boolean> create(Throwable t) {
public Boolean createOrPropagate(Throwable t) throws Exception {
if (checkNotNull(t, "throwable") instanceof ContainerNotFoundException) {
return immediateFuture(false);
return false;
}
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 ListenableFuture<Boolean> create(Throwable t) {
public Boolean createOrPropagate(Throwable t) throws Exception {
if (checkNotNull(t, "throwable") instanceof KeyNotFoundException) {
return immediateFuture(false);
return false;
}
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 ListenableFuture<Object> create(Throwable t) {
public Object createOrPropagate(Throwable t) throws Exception {
if (checkNotNull(t, "throwable") instanceof ContainerNotFoundException) {
return immediateFuture(null);
return null;
}
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 ListenableFuture<Object> create(Throwable t) {
public Object createOrPropagate(Throwable t) throws Exception {
if (checkNotNull(t, "throwable") instanceof KeyNotFoundException) {
return immediateFuture(null);
return null;
}
throw propagate(t);
}

View File

@ -24,10 +24,10 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
import java.util.regex.Pattern;
import org.jclouds.Fallback;
import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
public final class TerremarkVCloudFallbacks {
@ -40,19 +40,24 @@ public final class TerremarkVCloudFallbacks {
*
* @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
.compile(".*Cannot release this Public IP as it is default oubound IP.*");
@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) {
HttpResponseException hre = HttpResponseException.class.cast(t);
if (hre.getResponse().getStatusCode() == 503 || hre.getResponse().getStatusCode() == 401
|| MESSAGE_PATTERN.matcher(hre.getMessage()).matches())
return immediateFuture(null);
return null;
} else if (t instanceof AuthorizationException) {
return immediateFuture(null);
return null;
}
throw propagate(t);
}

View File

@ -26,12 +26,12 @@ import static org.jclouds.http.HttpUtils.wirePayloadIfEnabled;
import java.io.IOException;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.JcloudsVersion;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpCommandExecutorService;
import org.jclouds.http.HttpRequest;
@ -42,58 +42,72 @@ import org.jclouds.http.HttpUtils;
import org.jclouds.http.IOExceptionRetryHandler;
import org.jclouds.http.handlers.DelegatingErrorHandler;
import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.http.internal.BaseHttpCommandExecutorService;
import org.jclouds.http.internal.HttpWire;
import org.jclouds.logging.Logger;
import org.jclouds.io.ContentMetadataCodec;
import org.jclouds.util.Throwables2;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
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
*/
@Singleton
public class AsyncGaeHttpCommandExecutorService implements HttpCommandExecutorService {
private final ListeningExecutorService ioExecutor;
public class AsyncGaeHttpCommandExecutorService extends BaseHttpCommandExecutorService<HTTPRequest> {
// 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 ConvertToGaeRequest convertToGaeRequest;
private final ConvertToJcloudsResponse convertToJcloudsResponse;
private final DelegatingRetryHandler retryHandler;
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;
private final ListeningExecutorService ioExecutor;
@Inject
public AsyncGaeHttpCommandExecutorService(
public AsyncGaeHttpCommandExecutorService(URLFetchService urlFetchService, HttpUtils utils,
ContentMetadataCodec contentMetadataCodec,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
URLFetchService urlFetchService, ConvertToGaeRequest convertToGaeRequest,
ConvertToJcloudsResponse convertToJcloudsResponse, DelegatingRetryHandler retryHandler,
IOExceptionRetryHandler ioRetryHandler, DelegatingErrorHandler errorHandler, HttpUtils utils, HttpWire wire) {
IOExceptionRetryHandler ioRetryHandler, DelegatingRetryHandler retryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire, ConvertToGaeRequest convertToGaeRequest,
ConvertToJcloudsResponse convertToJcloudsResponse) {
super(utils, contentMetadataCodec, ioExecutor, retryHandler, ioRetryHandler, errorHandler, wire);
this.ioExecutor = ioExecutor;
this.urlFetchService = urlFetchService;
this.convertToGaeRequest = convertToGaeRequest;
this.convertToJcloudsResponse = convertToJcloudsResponse;
this.retryHandler = retryHandler;
this.ioRetryHandler = ioRetryHandler;
this.errorHandler = errorHandler;
this.utils = utils;
this.wire = wire;
}
@VisibleForTesting
protected HttpResponse convert(HTTPResponse gaeResponse) {
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) {
for (HttpRequestFilter filter : request.getFilters()) {
request = filter.filter(request);
}
@ -108,61 +122,59 @@ public class AsyncGaeHttpCommandExecutorService implements HttpCommandExecutorSe
@Override
public ListenableFuture<HttpResponse> submit(final HttpCommand command) {
HTTPRequest nativeRequest = filterLogAndConvertRe(command.getCurrentRequest());
ListenableFuture<HttpResponse> response = transform(
listenInPoolThread(urlFetchService.fetchAsync(nativeRequest)), convertToJcloudsResponse);
return transform(response, new Function<HttpResponse, HttpResponse>() {
@Override
public HttpResponse apply(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(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());
}
return receiveResponse(command, response);
}
private boolean shouldContinue(HttpResponse response) {
boolean shouldContinue = false;
if (retryHandler.shouldRetryRequest(command, response)) {
shouldContinue = true;
} else {
errorHandler.handleError(command, response);
}
return shouldContinue;
}
}, 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.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

View File

@ -53,7 +53,7 @@ import com.google.common.util.concurrent.ListeningExecutorService;
@Singleton
public class GaeHttpCommandExecutorService extends BaseHttpCommandExecutorService<HTTPRequest> {
//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 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 org.jclouds.Fallback;
import org.jclouds.abiquo.domain.exception.AbiquoException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
/**
@ -47,22 +47,30 @@ public final class AbiquoFallbacks {
/**
* 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
public ListenableFuture<Object> create(final Throwable from) {
Throwable exception = find(getCausalChain(from), isNotFoundAndHasAbiquoException(from), null);
throw propagate(exception == null ? from : exception.getCause());
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), isNotFoundAndHasAbiquoException(from), null);
throw propagate(exception == null ? from : exception.getCause());
}
}
/**
* 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
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);
if (exception != null) {
@ -70,7 +78,7 @@ public final class AbiquoFallbacks {
HttpResponse response = responseException.getResponse();
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.
*/
public static final class FalseOn5xx implements FutureFallback<Boolean> {
public static final class FalseOn5xx implements Fallback<Boolean> {
@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);
if (exception != null) {
@ -92,7 +105,7 @@ public final class AbiquoFallbacks {
HttpResponse response = responseException.getResponse();
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.
*/
public static final class FalseIfNotAvailable implements FutureFallback<Boolean> {
public static final class FalseIfNotAvailable implements Fallback<Boolean> {
@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);
if (exception != null) {
@ -115,11 +133,11 @@ public final class AbiquoFallbacks {
HttpResponse response = responseException.getResponse();
if (response != null && response.getStatusCode() >= 500 && response.getStatusCode() < 600) {
return immediateFuture(false);
return false;
}
} else {
// 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.ws.rs.core.Response.Status;
import org.jclouds.Fallback;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
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.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.TypeLiteral;
@ -47,7 +47,7 @@ import com.google.inject.TypeLiteral;
* @author Ignasi Barrera
*/
@Singleton
public class MovedVolume implements FutureFallback<VolumeManagementDto> {
public class MovedVolume implements Fallback<VolumeManagementDto> {
@Singleton
@VisibleForTesting
@ -67,14 +67,19 @@ public class MovedVolume implements FutureFallback<VolumeManagementDto> {
}
@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);
if (exception != null) {
HttpResponseException responseException = (HttpResponseException) exception;
HttpResponse response = responseException.getResponse();
return immediateFuture(parser.apply(response).getVolume());
return parser.apply(response).getVolume();
}
throw propagate(from);

View File

@ -19,7 +19,6 @@
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.replay;
import static org.easymock.EasyMock.verify;
@ -45,13 +44,13 @@ public class FalseIfNotAvailableTest {
RuntimeException exception = new RuntimeException();
try {
function.create(exception);
function.createOrPropagate(exception);
} catch (Exception ex) {
assertEquals(ex, exception);
}
}
public void testFalseIf5xx() {
public void testFalseIf5xx() throws Exception {
FalseIfNotAvailable function = new FalseIfNotAvailable();
HttpResponse response = EasyMock.createMock(HttpResponse.class);
HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);
@ -68,7 +67,7 @@ public class FalseIfNotAvailableTest {
replay(response);
replay(exception);
assertFalse(getUnchecked(function.create(exception)));
assertFalse(function.createOrPropagate(exception));
verify(response);
verify(exception);
@ -92,7 +91,7 @@ public class FalseIfNotAvailableTest {
replay(exception);
try {
function.create(exception);
function.createOrPropagate(exception);
} catch (Exception ex) {
assertEquals(ex, exception);
}
@ -101,11 +100,11 @@ public class FalseIfNotAvailableTest {
verify(exception);
}
public void testFalseIfResourceNotFound() {
public void testFalseIfResourceNotFound() throws Exception {
FalseIfNotAvailable function = new FalseIfNotAvailable();
ResourceNotFoundException exception = new ResourceNotFoundException();
assertFalse(getUnchecked(function.create(exception)));
assertFalse(function.createOrPropagate(exception));
}
}

View File

@ -19,7 +19,6 @@
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.replay;
import static org.easymock.EasyMock.verify;
@ -44,13 +43,13 @@ public class FalseOn5xxTest {
RuntimeException exception = new RuntimeException();
try {
function.create(exception);
function.createOrPropagate(exception);
} catch (Exception ex) {
assertEquals(ex, exception);
}
}
public void testFalseIf5xx() {
public void testFalseIf5xx() throws Exception {
FalseOn5xx function = new FalseOn5xx();
HttpResponse response = EasyMock.createMock(HttpResponse.class);
HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);
@ -67,7 +66,7 @@ public class FalseOn5xxTest {
replay(response);
replay(exception);
assertFalse(getUnchecked(function.create(exception)));
assertFalse(function.createOrPropagate(exception));
verify(response);
verify(exception);
@ -91,7 +90,7 @@ public class FalseOn5xxTest {
replay(exception);
try {
function.create(exception);
function.createOrPropagate(exception);
} catch (Exception ex) {
assertEquals(ex, exception);
}

View File

@ -24,8 +24,6 @@ import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import javax.ws.rs.core.Response.Status;
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");
MovedVolume function = new MovedVolume(new ReturnMoveVolumeReference(
new JAXBParser("false"), TypeLiteral.get(MovedVolumeDto.class)));

View File

@ -19,7 +19,6 @@
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.replay;
import static org.easymock.EasyMock.verify;
@ -44,13 +43,13 @@ public class NullOn303Test {
RuntimeException exception = new RuntimeException();
try {
function.create(exception);
function.createOrPropagate(exception);
} catch (Exception ex) {
assertEquals(ex, exception);
}
}
public void testNullIf303() {
public void testNullIf303() throws Exception {
NullOn303 function = new NullOn303();
HttpResponse response = EasyMock.createMock(HttpResponse.class);
HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);
@ -66,7 +65,7 @@ public class NullOn303Test {
replay(response);
replay(exception);
assertNull(getUnchecked(function.create(exception)));
assertNull(function.createOrPropagate(exception));
verify(response);
verify(exception);
@ -89,7 +88,7 @@ public class NullOn303Test {
replay(exception);
try {
function.create(exception);
function.createOrPropagate(exception);
} catch (Exception ex) {
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 org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import com.google.common.util.concurrent.FutureFallback;
import org.jclouds.Fallback;
import com.google.common.util.concurrent.ListenableFuture;
/**
@ -34,10 +35,16 @@ public final class DynECTFallbacks {
private DynECTFallbacks() {
}
public static class FalseOn400 implements FutureFallback<Boolean> {
public ListenableFuture<Boolean> create(Throwable t) {
public static class FalseOn400 implements Fallback<Boolean> {
@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)
return immediateFuture(false);
return false;
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 org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import org.jclouds.Fallback;
import com.google.common.base.Predicates;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
/**
@ -36,13 +37,18 @@ public final class JenkinsFallbacks {
private JenkinsFallbacks() {
}
public static final class VoidOn302Or404 implements FutureFallback<Void> {
public static final class VoidOn302Or404 implements Fallback<Void> {
@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,
Predicates.<Integer> or(equalTo(302), equalTo(404)));
if (returnVal != null && returnVal)
return immediateFuture(null);
return null;
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 org.jclouds.Fallbacks.valOnNotFoundOr404;
import org.jclouds.Fallback;
import org.jclouds.aws.AWSResponseException;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
public final class RDSFallbacks {
private RDSFallbacks() {
}
public static final class NullOnStateDeletingNotFoundOr404 implements FutureFallback<Object> {
public static final class NullOnStateDeletingNotFoundOr404 implements Fallback<Object> {
@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) {
AWSResponseException e = AWSResponseException.class.cast(t);
if ("InvalidDBInstanceState".equals(e.getError().getCode())
&& e.getError().getMessage().contains("has state: deleting"))
return immediateFuture(null);
return null;
}
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.util.concurrent.Futures.immediateFuture;
import org.jclouds.Fallback;
import org.jclouds.azure.storage.AzureStorageResponseException;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
/**
@ -35,14 +35,18 @@ public final class 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
public ListenableFuture<Boolean> create(Throwable t) {
public Boolean createOrPropagate(Throwable t) throws Exception {
if (checkNotNull(t, "throwable") instanceof AzureStorageResponseException) {
AzureStorageResponseException responseException = AzureStorageResponseException.class.cast(t);
if ("ContainerAlreadyExists".equals(responseException.getError().getCode())) {
return immediateFuture(false);
return false;
}
}
throw propagate(t);

View File

@ -34,8 +34,9 @@ import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.options.GetOptions;
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.reflect.Invokable;
@ -45,7 +46,7 @@ import com.google.common.reflect.Invokable;
*/
@Singleton
public class AzureBlobRequestSigner implements BlobRequestSigner {
private final RestAnnotationProcessor processor;
private final Function<Invocation, HttpRequest> processor;
private final BlobToAzureBlob blobToBlob;
private final BlobToHttpGetOptions blob2HttpGetOptions;
@ -54,7 +55,7 @@ public class AzureBlobRequestSigner implements BlobRequestSigner {
private final Invokable<?, ?> createMethod;
@Inject
public AzureBlobRequestSigner(RestAnnotationProcessor processor, BlobToAzureBlob blobToBlob,
public AzureBlobRequestSigner(Function<Invocation, HttpRequest> processor, BlobToAzureBlob blobToBlob,
BlobToHttpGetOptions blob2HttpGetOptions) throws SecurityException, NoSuchMethodException {
this.processor = checkNotNull(processor, "processor");
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.domain.SwiftObject;
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.Throwables;
import com.google.common.collect.ImmutableList;
@ -69,7 +68,7 @@ import com.google.inject.Provider;
@Singleton
public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner {
private final RestAnnotationProcessor processor;
private final Function<Invocation, HttpRequest> processor;
private final Crypto crypto;
private final Provider<Long> unixEpochTimestampProvider;
@ -84,7 +83,7 @@ public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner
private final Invokable<?, ?> createMethod;
@Inject
public HPCloudObjectStorageBlobRequestSigner(RestAnnotationProcessor processor,
public HPCloudObjectStorageBlobRequestSigner(Function<Invocation, HttpRequest> processor,
BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto,
@TimeStamp Provider<Long> unixEpochTimestampProvider, Supplier<Access> access,
@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) {
checkNotNull(container, "container");
checkNotNull(name, "name");
GeneratedHttpRequest request = processor.apply(Invocation.create(getMethod,
ImmutableList.<Object> of(container, name)));
HttpRequest request = processor.apply(Invocation.create(getMethod, ImmutableList.<Object> of(container, name)));
return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
}
@ -140,7 +138,7 @@ public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner
public HttpRequest signPutBlob(String container, Blob blob, long timeInSeconds) {
checkNotNull(container, "container");
checkNotNull(blob, "blob");
GeneratedHttpRequest request = processor.apply(Invocation.create(createMethod,
HttpRequest request = processor.apply(Invocation.create(createMethod,
ImmutableList.<Object> of(container, blobToObject.apply(blob))));
return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
}