Merge pull request #1260 from jclouds/sync-http

Synchronous commands now use calling thread
This commit is contained in:
Adrian Cole 2013-01-29 05:42:58 -08:00
commit 9f7507b1e8
97 changed files with 1394 additions and 948 deletions

View File

@ -17,8 +17,6 @@
* under the License.
*/
package org.jclouds.atmos;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import static org.jclouds.reflect.Reflection2.typeToken;
@ -69,10 +67,6 @@ public class AtmosApiMetadata extends BaseRestApiMetadata {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_REGIONS, "DEFAULT");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "X-Object-Meta-");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(5) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "AtmosClient.createFile", MINUTES.toMillis(10) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "AtmosClient.updateFile", MINUTES.toMillis(10) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "AtmosClient.readFile", MINUTES.toMillis(10) + "");
return properties;
}

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

@ -18,9 +18,6 @@
*/
package org.jclouds.cloudfiles;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import java.net.URI;
import java.util.Properties;
@ -65,7 +62,6 @@ public class CloudFilesApiMetadata extends SwiftApiMetadata {
public static Properties defaultProperties() {
Properties properties = SwiftApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "OpenStackAuthClient.authenticate", SECONDS.toMillis(30) + "");
return properties;
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.cloudservers;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI;
@ -63,8 +60,6 @@ public class CloudServersApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(1) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "OpenStackAuthClient.authenticate", SECONDS.toMillis(30) + "");
return properties;
}

View File

@ -17,8 +17,6 @@
* under the License.
*/
package org.jclouds.cloudsigma;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.cloudsigma.reference.CloudSigmaConstants.PROPERTY_VNC_PASSWORD;
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
import static org.jclouds.reflect.Reflection2.typeToken;
@ -63,8 +61,6 @@ public class CloudSigmaApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(1) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "CloudSigmaClient.cloneDrive", MINUTES.toMillis(5) + "");
properties.setProperty(PROPERTY_VNC_PASSWORD, "IL9vs34d");
// passwords are set post-boot, so auth failures are possible
// from a race condition applying the password set script

View File

@ -17,8 +17,6 @@
* under the License.
*/
package org.jclouds.cloudstack;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI;
@ -60,9 +58,6 @@ public class CloudStackApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(1) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "AddressClient.disassociateIPAddress", MINUTES.toMillis(2) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "NATClient.enableStaticNATForVirtualMachine", MINUTES.toMillis(2) + "");
properties.setProperty("jclouds.ssh.max-retries", "7");
properties.setProperty("jclouds.ssh.retry-auth", "true");
return properties;

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

@ -18,8 +18,6 @@
*/
package org.jclouds.cloudwatch;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
@ -59,7 +57,6 @@ public class CloudWatchApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
return properties;

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.ec2;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
@ -81,8 +79,6 @@ public class EC2ApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ec2:DescribeImages", MINUTES.toMillis(5) + "");
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "*");

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,8 +18,6 @@
*/
package org.jclouds.elasticstack;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.elasticstack.reference.ElasticStackConstants.PROPERTY_VNC_PASSWORD;
import static org.jclouds.reflect.Reflection2.typeToken;
@ -63,10 +61,6 @@ public class ElasticStackApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(1) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ElasticStackClient.startServer", MINUTES.toMillis(2) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ElasticStackClient.createDrive", MINUTES.toMillis(2) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ElasticStackClient.createAndStartServer", MINUTES.toMillis(2) + "");
properties.setProperty(PROPERTY_VNC_PASSWORD, "IL9vs34d");
// passwords are set post-boot, so auth failures are possible
// from a race condition applying the password set script

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.openstack.cinder.v1;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
@ -66,7 +64,6 @@ public class CinderApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
properties.setProperty(SERVICE_TYPE, ServiceType.BLOCK_STORAGE);
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
return properties;

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.openstack.keystone.v2_0;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
@ -66,8 +63,6 @@ public class KeystoneApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ExtensionApi", MINUTES.toMillis(3) + "");
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
properties.setProperty(SERVICE_TYPE, ServiceType.IDENTITY);
return properties;

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

@ -18,8 +18,6 @@
*/
package org.jclouds.openstack.nova.v2_0;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
import static org.jclouds.openstack.nova.v2_0.config.NovaProperties.AUTO_ALLOCATE_FLOATING_IPS;
@ -72,8 +70,6 @@ public class NovaApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ServerApi.create", MINUTES.toMillis(10) + "");
// auth fail can happen while cloud-init applies keypair updates
properties.setProperty("jclouds.ssh.max-retries", "7");
properties.setProperty("jclouds.ssh.retry-auth", "true");

View File

@ -17,8 +17,6 @@
* under the License.
*/
package org.jclouds.rackspace.cloudloadbalancers;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
import static org.jclouds.reflect.Reflection2.typeToken;
@ -67,7 +65,6 @@ public class CloudLoadBalancersApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(1) + "");
properties.setProperty(SERVICE_TYPE, ServiceType.LOAD_BALANCERS);
properties.setProperty(CREDENTIAL_TYPE, CloudIdentityCredentialTypes.API_KEY_CREDENTIALS);
return properties;

View File

@ -18,10 +18,8 @@
*/
package org.jclouds.s3;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_RELAX_HOSTNAME;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.blobstore.reference.BlobStoreConstants.DIRECTORY_SUFFIX_FOLDER;
@ -84,11 +82,6 @@ public class S3ApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(90) + "");
// 512KB/s for max size of 5GB
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "s3:GetObject", SECONDS.toMillis(5242880 / 512) + "");
// 128KB/s for max size of 5GB; applies also to copy object, upload part
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "s3:PutObject", SECONDS.toMillis(5242880 / 128) + "");
properties.setProperty(PROPERTY_API_VERSION, S3AsyncClient.VERSION);
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, S3Headers.DEFAULT_AMAZON_HEADERTAG);

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

@ -18,8 +18,6 @@
*/
package org.jclouds.sqs;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.sqs.config.SQSProperties.CREATE_QUEUE_MAX_RETRIES;
@ -63,9 +61,6 @@ public class SQSApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
// this will gracefully attempt to resolve name issues
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "sqs:CreateQueue", SECONDS.toMillis(61) + "");
properties.setProperty(CREATE_QUEUE_MAX_RETRIES, "60");
properties.setProperty(CREATE_QUEUE_RETRY_INTERVAL, "1000");
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.sts;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
@ -27,9 +25,9 @@ import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.sts.config.STSRestClientModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
import org.jclouds.sts.config.STSRestClientModule;
import com.google.common.reflect.TypeToken;
@ -59,7 +57,6 @@ public class STSApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
return properties;

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.openstack.swift;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import static org.jclouds.reflect.Reflection2.typeToken;
@ -67,12 +64,6 @@ public class SwiftApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(2) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "OpenStackAuthClient.authenticate", SECONDS.toMillis(10) + "");
// TODO: value was randomly copied from S3: 512KB/s for max size of 5GB
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "CommonSwiftClient.getObject", SECONDS.toMillis(5242880 / 512) + "");
// TODO: value was randomly copied from S3: 128KB/s for max size of 5GB
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "CommonSwiftClient.putObject", SECONDS.toMillis(5242880 / 128) + "");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "X-Object-Meta-");
properties.setProperty(PROPERTY_REGIONS, "DEFAULT");
return properties;

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

@ -17,9 +17,7 @@
* under the License.
*/
package org.jclouds.vcloud;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
import static org.jclouds.reflect.Reflection2.typeToken;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_FENCEMODE;
@ -69,9 +67,6 @@ public class VCloudApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(5) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "VCloudLoginClient.login", MINUTES.toMillis(3) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "VCloudVersionsClient.getSupportedVersions", MINUTES.toMillis(3) + "");
properties.setProperty(PROPERTY_VCLOUD_VERSION_SCHEMA, "1");
properties.setProperty(PROPERTY_VCLOUD_XML_NAMESPACE,
String.format("http://www.vmware.com/vcloud/v${%s}", PROPERTY_VCLOUD_VERSION_SCHEMA));

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

@ -1,9 +1,7 @@
package org.jclouds.trmk.vcloud_0_8.internal;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.trmk.vcloud_0_8.reference.TerremarkConstants.PROPERTY_TERREMARK_EXTENSION_NAME;
import static org.jclouds.trmk.vcloud_0_8.reference.TerremarkConstants.PROPERTY_TERREMARK_EXTENSION_NS;
import static org.jclouds.trmk.vcloud_0_8.reference.TerremarkConstants.PROPERTY_TERREMARK_EXTENSION_VERSION;
@ -32,9 +30,6 @@ public abstract class TerremarkVCloudApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(5) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "TerremarkVCloudLoginClient.login", SECONDS.toMillis(10) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "TerremarkVCloudVersionsClient.getSupportedVersions", SECONDS.toMillis(10) + "");
properties.setProperty(PROPERTY_VCLOUD_VERSION_SCHEMA, "0.8");
properties.setProperty(PROPERTY_SESSION_INTERVAL, 8 * 60 + "");
properties.setProperty(PROPERTY_VCLOUD_XML_SCHEMA, "http://vcloud.safesecureweb.com/ns/vcloud.xsd");

View File

@ -0,0 +1,45 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds;
import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.FutureFallback;
/**
* Provides a backup value to replace an earlier exception.
*
* @param <V>
* the result type of the backup value
*
* @author Adrian Cole
* @see FutureFallback
* @since 1.6
*/
@Beta
public interface Fallback<V> extends FutureFallback<V> {
/**
* The exception is provided so that the {@code Fallback} implementation can
* conditionally determine whether to propagate the exception or to attempt
* to recover.
*
* @param t
* the exception that made the call fail.
*/
V createOrPropagate(Throwable t) throws Exception;
}

View File

@ -40,7 +40,6 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
/**
@ -51,123 +50,153 @@ public final class Fallbacks {
private Fallbacks() {
}
public static final class NullOnNotFoundOr404 implements FutureFallback<Object> {
@Override
public ListenableFuture<Object> create(Throwable t) {
return valOnNotFoundOr404(null, checkNotNull(t, "throwable"));
public static final class NullOnNotFoundOr404 implements Fallback<Object> {
public ListenableFuture<Object> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
}
public static final class VoidOnNotFoundOr404 implements FutureFallback<Void> {
@Override
public ListenableFuture<Void> create(Throwable t) {
public Object createOrPropagate(Throwable t) throws Exception {
return valOnNotFoundOr404(null, checkNotNull(t, "throwable"));
}
}
public static final class TrueOnNotFoundOr404 implements FutureFallback<Boolean> {
public static final class VoidOnNotFoundOr404 implements Fallback<Void> {
public ListenableFuture<Void> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
@Override
public ListenableFuture<Boolean> create(Throwable t) {
public Void createOrPropagate(Throwable t) throws Exception {
return valOnNotFoundOr404(null, checkNotNull(t, "throwable"));
}
}
public static final class TrueOnNotFoundOr404 implements Fallback<Boolean> {
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
public Boolean createOrPropagate(Throwable t) throws Exception {
return valOnNotFoundOr404(true, checkNotNull(t, "throwable"));
}
}
public static final class FalseOnNotFoundOr404 implements FutureFallback<Boolean> {
public static final class FalseOnNotFoundOr404 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 {
return valOnNotFoundOr404(false, checkNotNull(t, "throwable"));
}
}
public static final class FalseOnNotFoundOr422 implements FutureFallback<Boolean> {
@Override
public ListenableFuture<Boolean> create(Throwable t) {
if (containsResourceNotFoundException(checkNotNull(t, "throwable"))
|| returnValueOnCodeOrNull(t, true, equalTo(422)) != null)
return immediateFuture(false);
throw propagate(t);
public static final class FalseOnNotFoundOr422 implements Fallback<Boolean> {
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
public Boolean createOrPropagate(Throwable t) throws Exception {
if (containsResourceNotFoundException(checkNotNull(t, "throwable"))
|| returnValueOnCodeOrNull(t, true, equalTo(422)) != null)
return false;
throw propagate(t);
}
}
/**
* @author Leander Beernaert
*/
public static final class AbsentOn403Or404Or500 implements FutureFallback<Optional<Object>> {
@Override
public ListenableFuture<Optional<Object>> create(Throwable t) {
Boolean returnVal = returnValueOnCodeOrNull(checkNotNull(t, "throwable"), true, in(asList(403, 404, 500)));
if (returnVal != null)
return immediateFuture(Optional.absent());
throw propagate(t);
public static final class AbsentOn403Or404Or500 implements Fallback<Optional<Object>> {
public ListenableFuture<Optional<Object>> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
public Optional<Object> createOrPropagate(Throwable t) throws Exception {
Boolean returnVal = returnValueOnCodeOrNull(checkNotNull(t, "throwable"), true, in(asList(403, 404, 500)));
if (returnVal != null)
return Optional.absent();
throw propagate(t);
}
}
public static final class EmptyFluentIterableOnNotFoundOr404 implements FutureFallback<FluentIterable<Object>> {
@Override
public ListenableFuture<FluentIterable<Object>> create(Throwable t) {
public static final class EmptyFluentIterableOnNotFoundOr404 implements Fallback<FluentIterable<Object>> {
public ListenableFuture<FluentIterable<Object>> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
public FluentIterable<Object> createOrPropagate(Throwable t) throws Exception {
return valOnNotFoundOr404(FluentIterable.from(ImmutableSet.of()), checkNotNull(t, "throwable"));
}
}
public static final class EmptyIterableWithMarkerOnNotFoundOr404 implements
FutureFallback<IterableWithMarker<Object>> {
@Override
public ListenableFuture<IterableWithMarker<Object>> create(Throwable t) {
public static final class EmptyIterableWithMarkerOnNotFoundOr404 implements Fallback<IterableWithMarker<Object>> {
public ListenableFuture<IterableWithMarker<Object>> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
public IterableWithMarker<Object> createOrPropagate(Throwable t) throws Exception {
return valOnNotFoundOr404(IterableWithMarkers.from(ImmutableSet.of()), checkNotNull(t, "throwable"));
}
}
public static final class EmptyPagedIterableOnNotFoundOr404 implements FutureFallback<PagedIterable<Object>> {
@Override
public ListenableFuture<PagedIterable<Object>> create(Throwable t) {
public static final class EmptyPagedIterableOnNotFoundOr404 implements Fallback<PagedIterable<Object>> {
public ListenableFuture<PagedIterable<Object>> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
public PagedIterable<Object> createOrPropagate(Throwable t) throws Exception {
return valOnNotFoundOr404(PagedIterables.of(IterableWithMarkers.from(ImmutableSet.of())),
checkNotNull(t, "throwable"));
}
}
public static final class EmptyListOnNotFoundOr404 implements FutureFallback<ImmutableList<Object>> { // NO_UCD (unused code)
@Override
public ListenableFuture<ImmutableList<Object>> create(Throwable t) {
public static final class EmptyListOnNotFoundOr404 implements Fallback<ImmutableList<Object>> { // NO_UCD
// (unused
// code)
public ListenableFuture<ImmutableList<Object>> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
public ImmutableList<Object> createOrPropagate(Throwable t) throws Exception {
return valOnNotFoundOr404(ImmutableList.of(), checkNotNull(t, "throwable"));
}
}
public static final class EmptySetOnNotFoundOr404 implements FutureFallback<ImmutableSet<Object>> {
@Override
public ListenableFuture<ImmutableSet<Object>> create(Throwable t) {
public static final class EmptySetOnNotFoundOr404 implements Fallback<ImmutableSet<Object>> {
public ListenableFuture<ImmutableSet<Object>> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
public ImmutableSet<Object> createOrPropagate(Throwable t) throws Exception {
return valOnNotFoundOr404(ImmutableSet.of(), checkNotNull(t, "throwable"));
}
}
public static final class EmptyMapOnNotFoundOr404 implements FutureFallback<ImmutableMap<Object, Object>> {
@Override
public ListenableFuture<ImmutableMap<Object, Object>> create(Throwable t) {
public static final class EmptyMapOnNotFoundOr404 implements Fallback<ImmutableMap<Object, Object>> {
public ListenableFuture<ImmutableMap<Object, Object>> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
public ImmutableMap<Object, Object> createOrPropagate(Throwable t) throws Exception {
return valOnNotFoundOr404(ImmutableMap.of(), checkNotNull(t, "throwable"));
}
}
public static final class EmptyMultimapOnNotFoundOr404 implements FutureFallback<ImmutableMultimap<Object, Object>> { // NO_UCD (unused code)
@Override
public ListenableFuture<ImmutableMultimap<Object, Object>> create(Throwable t) {
public static final class EmptyMultimapOnNotFoundOr404 implements Fallback<ImmutableMultimap<Object, Object>> { // NO_UCD
// (unused
// code)
public ListenableFuture<ImmutableMultimap<Object, Object>> create(Throwable t) throws Exception {
return immediateFuture(createOrPropagate(t));
}
public ImmutableMultimap<Object, Object> createOrPropagate(Throwable t) throws Exception {
return valOnNotFoundOr404(ImmutableMultimap.of(), checkNotNull(t, "throwable"));
}
}
public static <T> ListenableFuture<T> valOnNotFoundOr404(T val, Throwable t) {
public static <T> T valOnNotFoundOr404(T val, Throwable t) {
if (containsResourceNotFoundException(checkNotNull(t, "throwable")) || contains404(t))
return immediateFuture(val);
return val;
throw propagate(t);
}

View File

@ -38,7 +38,9 @@ import org.jclouds.lifecycle.Closer;
import org.jclouds.logging.Logger;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.SimpleTimeLimiter;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.common.util.concurrent.TimeLimiter;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
@ -98,6 +100,12 @@ public class ExecutorServiceModule extends AbstractModule {
protected void configure() { // NO_UCD
}
@Provides
@Singleton
TimeLimiter timeLimiter(@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor){
return new SimpleTimeLimiter(userExecutor);
}
@Provides
@Singleton
@Named(PROPERTY_USER_THREADS)

View File

@ -20,15 +20,16 @@ package org.jclouds.fallbacks;
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 javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.Fallback;
import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
/**
@ -36,7 +37,7 @@ import com.google.common.util.concurrent.ListenableFuture;
* @author Adrian Cole
*/
@Singleton
public final class MapHttp4xxCodesToExceptions implements FutureFallback<Object> {
public final class MapHttp4xxCodesToExceptions implements Fallback<Object> {
private final PropagateIfRetryAfter propagateIfRetryAfter;
@ -46,7 +47,12 @@ public final class MapHttp4xxCodesToExceptions implements FutureFallback<Object>
}
@Override
public ListenableFuture<Object> create(Throwable t) { // NO_UCD
public ListenableFuture<Object> create(Throwable t) throws Exception { // NO_UCD
return immediateFuture(createOrPropagate(t));
}
@Override
public Object createOrPropagate(Throwable t) throws Exception {
propagateIfRetryAfter.create(t); // if we pass here, we aren't a retry-after exception
if (t instanceof HttpResponseException) {
HttpResponseException responseException = HttpResponseException.class.cast(t);

View File

@ -27,15 +27,21 @@ import com.google.common.util.concurrent.ListenableFuture;
*
* @author Adrian Cole
*/
public interface HttpCommandExecutorService {
public interface HttpCommandExecutorService {
/**
* Asks the command to build a request relevant for an endpoint that produces responses of
* generic type {@code HttpResponse}. and invokes it on the endpoint, returning a future
* Returns a potentially deferred {@code HttpResponse} from a server responding to the
* {@code command}. The output {@code ListenableFuture} need not be
* {@linkplain Future#isDone done}, making {@code HttpCommandExecutorService}
* suitable for asynchronous derivations.
*
* @param command
* that generates requests
* @return {@link Future} containing the response from the {@code endpoint}
*/
ListenableFuture<HttpResponse> submit(HttpCommand command);
/**
* Returns a {@code HttpResponse} from the server which responded to the
* {@code command}.
*/
HttpResponse invoke(HttpCommand command);
}

View File

@ -19,10 +19,12 @@
package org.jclouds.http.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.io.ByteStreams.copy;
import static com.google.common.io.ByteStreams.nullOutputStream;
import static org.jclouds.http.HttpUtils.checkRequestHasContentLengthOrChunkedEncoding;
import static org.jclouds.http.HttpUtils.wirePayloadIfEnabled;
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
import java.io.FilterInputStream;
import java.io.IOException;
@ -46,7 +48,6 @@ import org.jclouds.http.handlers.DelegatingErrorHandler;
import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.io.ContentMetadataCodec;
import org.jclouds.logging.Logger;
import org.jclouds.util.Throwables2;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
@ -58,11 +59,11 @@ import com.google.common.util.concurrent.ListeningExecutorService;
public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandExecutorService {
protected final HttpUtils utils;
protected final ContentMetadataCodec contentMetadataCodec;
private final DelegatingRetryHandler retryHandler;
private final IOExceptionRetryHandler ioRetryHandler;
private final DelegatingErrorHandler errorHandler;
private final ListeningExecutorService ioExecutor;
protected final DelegatingRetryHandler retryHandler;
protected final IOExceptionRetryHandler ioRetryHandler;
protected final DelegatingErrorHandler errorHandler;
protected final ListeningExecutorService ioExecutor;
@Resource
protected Logger logger = Logger.NULL;
@ -74,9 +75,9 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
@Inject
protected BaseHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire) {
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire) {
this.utils = checkNotNull(utils, "utils");
this.contentMetadataCodec = checkNotNull(contentMetadataCodec, "contentMetadataCodec");
this.retryHandler = checkNotNull(retryHandler, "retryHandler");
@ -123,12 +124,71 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
}
@Override
public HttpResponse invoke(HttpCommand command) {
HttpResponse response = null;
for (;;) {
HttpRequest request = command.getCurrentRequest();
Q nativeRequest = null;
try {
for (HttpRequestFilter filter : request.getFilters()) {
request = filter.filter(request);
}
checkRequestHasContentLengthOrChunkedEncoding(request,
"After filtering, the request has neither chunked encoding nor content length: " + request);
logger.debug("Sending request %s: %s", request.hashCode(), request.getRequestLine());
wirePayloadIfEnabled(wire, request);
utils.logRequest(headerLog, request, ">>");
nativeRequest = convert(request);
response = invoke(nativeRequest);
logger.debug("Receiving response %s: %s", request.hashCode(), response.getStatusLine());
utils.logResponse(headerLog, response, "<<");
if (response.getPayload() != null && wire.enabled())
wire.input(response);
nativeRequest = null; // response took ownership of streams
int statusCode = response.getStatusCode();
if (statusCode >= 300) {
if (shouldContinue(command, response))
continue;
else
break;
} else {
break;
}
} catch (Exception e) {
IOException ioe = getFirstThrowableOfType(e, IOException.class);
if (ioe != null && ioRetryHandler.shouldRetryRequest(command, ioe)) {
continue;
}
command.setException(new HttpResponseException(e.getMessage() + " connecting to "
+ command.getCurrentRequest().getRequestLine(), command, null, e));
break;
} finally {
cleanup(nativeRequest);
}
}
if (command.getException() != null)
throw propagate(command.getException());
return response;
}
private boolean shouldContinue(HttpCommand command, HttpResponse response) {
boolean shouldContinue = false;
if (retryHandler.shouldRetryRequest(command, response)) {
shouldContinue = true;
} else {
errorHandler.handleError(command, response);
}
return shouldContinue;
}
@Override
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
HttpRequest request = command.getCurrentRequest();
checkRequestHasContentLengthOrChunkedEncoding(request,
"if the request has a payload, it must be set to chunked encoding or specify a content length: "
+ request);
"if the request has a payload, it must be set to chunked encoding or specify a content length: " + request);
return ioExecutor.submit(new HttpResponseCallable(command));
}
@ -140,63 +200,12 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
}
public HttpResponse call() throws Exception {
HttpResponse response = null;
for (;;) {
HttpRequest request = command.getCurrentRequest();
Q nativeRequest = null;
try {
for (HttpRequestFilter filter : request.getFilters()) {
request = filter.filter(request);
}
checkRequestHasContentLengthOrChunkedEncoding(request,
"After filtering, the request has neither chunked encoding nor content length: " + request);
logger.debug("Sending request %s: %s", request.hashCode(), request.getRequestLine());
wirePayloadIfEnabled(wire, request);
utils.logRequest(headerLog, request, ">>");
nativeRequest = convert(request);
response = invoke(nativeRequest);
logger.debug("Receiving response %s: %s", request.hashCode(), response.getStatusLine());
utils.logResponse(headerLog, response, "<<");
if (response.getPayload() != null && wire.enabled())
wire.input(response);
nativeRequest = null; // response took ownership of streams
int statusCode = response.getStatusCode();
if (statusCode >= 300) {
if (shouldContinue(response))
continue;
else
break;
} else {
break;
}
} catch (Exception e) {
IOException ioe = Throwables2.getFirstThrowableOfType(e, IOException.class);
if (ioe != null && ioRetryHandler.shouldRetryRequest(command, ioe)) {
continue;
}
command.setException(new HttpResponseException(e.getMessage() + " connecting to "
+ command.getCurrentRequest().getRequestLine(), command, null, e));
break;
} finally {
cleanup(nativeRequest);
}
try {
return invoke(command);
} finally {
if (command.getException() != null)
throw command.getException();
}
if (command.getException() != null)
throw command.getException();
return response;
}
private boolean shouldContinue(HttpResponse response) {
boolean shouldContinue = false;
if (retryHandler.shouldRetryRequest(command, response)) {
shouldContinue = true;
} else {
errorHandler.handleError(command, response);
}
return shouldContinue;
}
@Override

View File

@ -19,7 +19,6 @@
package org.jclouds.rest;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Collections2.filter;
import java.util.List;
@ -29,7 +28,6 @@ import org.jclouds.predicates.Validator;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.annotations.ParamValidators;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.reflect.Parameter;

View File

@ -24,10 +24,9 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.common.util.concurrent.FutureFallback;
/**
* Annotates the appropriate {@link FutureFallback} which propagates the exception or returns a valid fallback value.
* Annotates the appropriate {@link org.jclouds.Fallback} which propagates
* the exception or returns a valid fallback value.
*
* @since 1.6
* @author Adrian Cole
@ -35,5 +34,5 @@ import com.google.common.util.concurrent.FutureFallback;
@Target(METHOD)
@Retention(RUNTIME)
public @interface Fallback {
Class<? extends FutureFallback<?>> value();
Class<? extends org.jclouds.Fallback<?>> value();
}

View File

@ -0,0 +1,55 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy current the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.config;
import org.jclouds.Fallback;
import org.jclouds.reflect.Invocation;
import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.UncheckedTimeoutException;
import com.google.inject.ImplementedBy;
/**
* Provides the ability to decouple timeouts and fallbacks from what's built-in.
*
* @author Adrian Cole
*/
@Beta
@ImplementedBy(ReadAnnotationsAndProperties.class)
public interface InvocationConfig {
/**
* If this is present, Sync method calls will block up to the specified nanos
* and throw an {@linkplain UncheckedTimeoutException}. If this is not
* present, Sync method calls will be invoked directly, typically through
* {@linkplain HttpCommandExecutorService#invoke}.
*/
Optional<Long> getTimeoutNanos(Invocation in);
/**
* command named used in logging and configuration keys.
*/
String getCommandName(Invocation invocation);
/**
* fallback used for Sync or Async commands.
*/
Fallback<?> getFallback(Invocation invocation);
}

View File

@ -0,0 +1,118 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy current the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.config;
import static com.google.common.base.Optional.fromNullable;
import static com.google.common.collect.Maps.transformValues;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.util.Maps2.transformKeys;
import static org.jclouds.util.Predicates2.startsWith;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.annotations.Fallback;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.reflect.Invokable;
import com.google.inject.Injector;
@Beta
@Singleton
public class ReadAnnotationsAndProperties implements InvocationConfig {
private final Injector injector;
private final org.jclouds.Fallback<Object> defaultFallback;
private final Map<String, Long> timeouts;
@Inject
ReadAnnotationsAndProperties(Injector injector,
Function<Predicate<String>, Map<String, String>> filterStringsBoundByName,
org.jclouds.Fallback<Object> defaultFallback) {
this.injector = injector;
this.defaultFallback = defaultFallback;
this.timeouts = timeouts(filterStringsBoundByName);
}
@Override
public Optional<Long> getTimeoutNanos(Invocation in) {
String commandName = getCommandName(in);
Optional<Long> defaultMillis = fromNullable(timeouts.get("default"));
Optional<Long> timeoutMillis = fromNullable(timeouts.get(commandName));
Invokable<?, ?> invoked = in.getInvokable();
if (invoked.isAnnotationPresent(Named.class)) {
timeoutMillis = timeoutMillis.or(defaultMillis);
} else {
// TODO: remove old logic once Named annotations are on all methods
String className = invoked.getOwnerType().getRawType().getSimpleName().replace("AsyncClient", "Client")
.replace("AsyncApi", "Api");
timeoutMillis = timeoutMillis.or(fromNullable(timeouts.get(className))).or(defaultMillis);
}
if (timeoutMillis.isPresent())
return Optional.of(MILLISECONDS.toNanos(timeoutMillis.get()));
return Optional.absent();
}
@Override
public String getCommandName(Invocation invocation) {
Invokable<?, ?> invoked = invocation.getInvokable();
if (invoked.isAnnotationPresent(Named.class)) {
return invoked.getAnnotation(Named.class).value();
} else {
// TODO: remove old logic once Named annotations are on all methods
String className = invoked.getOwnerType().getRawType().getSimpleName().replace("AsyncClient", "Client")
.replace("AsyncApi", "Api");
return className + "." + invoked.getName();
}
}
@Override
public org.jclouds.Fallback<?> getFallback(Invocation invocation) {
Fallback fallback = invocation.getInvokable().getAnnotation(Fallback.class);
if (fallback != null) {
return injector.getInstance(fallback.value());
}
return defaultFallback;
}
/**
* override timeout by values configured in properties(in ms)
*/
static Map<String, Long> timeouts(Function<Predicate<String>, Map<String, String>> filterStringsBoundByName) {
Map<String, String> stringBoundWithTimeoutPrefix = filterStringsBoundByName
.apply(startsWith(PROPERTY_TIMEOUTS_PREFIX));
Map<String, Long> longsByName = transformValues(stringBoundWithTimeoutPrefix, new Function<String, Long>() {
public Long apply(String input) {
return Long.valueOf(String.valueOf(input));
}
});
return transformKeys(longsByName, new Function<String, String>() {
public String apply(String input) {
return input.replaceFirst(PROPERTY_TIMEOUTS_PREFIX, "");
}
});
}
}

View File

@ -22,34 +22,34 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.toArray;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Maps.transformValues;
import static com.google.common.util.concurrent.Atomics.newReference;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.reflect.Reflection2.method;
import static org.jclouds.reflect.Reflection2.methods;
import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
import static org.jclouds.util.Maps2.transformKeys;
import static org.jclouds.util.Predicates2.startsWith;
import java.net.Proxy;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
import org.jclouds.functions.IdentityFunction;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.config.SaxParserModule;
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
import org.jclouds.json.config.GsonModule;
import org.jclouds.location.config.LocationModule;
import org.jclouds.proxy.ProxyForURI;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.HttpAsyncClient;
import org.jclouds.rest.HttpClient;
import org.jclouds.rest.binders.BindToJsonPayloadWrappedWith;
import org.jclouds.rest.internal.BlockOnFuture;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.rest.internal.TransformerForRequest;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
@ -90,6 +90,21 @@ public class RestModule extends AbstractModule {
return seedKnownSync2AsyncInvokables(sync2Async);
}
/**
* function view of above
*/
@Provides
@Singleton
protected Function<Invocation, Invocation> sync2async(final Cache<Invokable<?, ?>, Invokable<?, ?>> cache) {
return new Function<Invocation, Invocation>() {
public Invocation apply(Invocation in) {
return Invocation.create(
checkNotNull(cache.getIfPresent(in.getInvokable()), "invokable %s not in %s", in.getInvokable(),
cache), in.getArgs());
}
};
}
@VisibleForTesting
static Cache<Invokable<?, ?>, Invokable<?, ?>> seedKnownSync2AsyncInvokables(Map<Class<?>, Class<?>> sync2Async) {
Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncBuilder = CacheBuilder.newBuilder().build();
@ -133,7 +148,12 @@ public class RestModule extends AbstractModule {
install(new GsonModule());
install(new SetCaller.Module());
install(new FactoryModuleBuilder().build(BindToJsonPayloadWrappedWith.Factory.class));
install(new FactoryModuleBuilder().build(BlockOnFuture.Factory.class));
bind(new TypeLiteral<Function<HttpRequest, Function<HttpResponse, ?>>>() {
}).to(TransformerForRequest.class);
bind(new TypeLiteral<org.jclouds.Fallback<Object>>() {
}).to(MapHttp4xxCodesToExceptions.class);
bind(new TypeLiteral<Function<Invocation, HttpRequest>>() {
}).to(RestAnnotationProcessor.class);
bind(IdentityFunction.class).toInstance(IdentityFunction.INSTANCE);
bindHttpApi(binder(), HttpClient.class, HttpAsyncClient.class);
// this will help short circuit scenarios that can otherwise lock out users
@ -145,23 +165,4 @@ public class RestModule extends AbstractModule {
}).to(ProxyForURI.class);
installLocations();
}
@Provides
@Singleton
@Named("TIMEOUTS")
protected Map<String, Long> timeouts(Function<Predicate<String>, Map<String, String>> filterStringsBoundByName) {
Map<String, String> stringBoundWithTimeoutPrefix = filterStringsBoundByName
.apply(startsWith(PROPERTY_TIMEOUTS_PREFIX));
Map<String, Long> longsByName = transformValues(stringBoundWithTimeoutPrefix, new Function<String, Long>() {
public Long apply(String input) {
return Long.valueOf(String.valueOf(input));
}
});
return transformKeys(longsByName, new Function<String, String>() {
public String apply(String input) {
return input.replaceFirst(PROPERTY_TIMEOUTS_PREFIX, "");
}
});
}
}

View File

@ -1,132 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.internal;
import static com.google.common.base.Optional.fromNullable;
import static com.google.common.collect.ObjectArrays.concat;
import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.logging.Logger;
import org.jclouds.reflect.Invocation;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.reflect.Invokable;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.common.util.concurrent.UncheckedTimeoutException;
import com.google.inject.assistedinject.Assisted;
public class BlockOnFuture implements Function<ListenableFuture<?>, Object> {
public static interface Factory {
/**
* @param invocation
* context for how the future was created
*/
BlockOnFuture create(Invocation invocation);
}
@Resource
private Logger logger = Logger.NULL;
private final Map<String, Long> timeouts;
private final Invocation invocation;
@Inject
@VisibleForTesting
BlockOnFuture(@Named("TIMEOUTS") Map<String, Long> timeouts, @Assisted Invocation invocation) {
this.timeouts = timeouts;
this.invocation = invocation;
}
@Override
public Object apply(ListenableFuture<?> future) {
Optional<Long> timeoutNanos = timeoutInNanos(invocation.getInvokable(), timeouts);
return block(future, timeoutNanos);
}
private Object block(ListenableFuture<?> future, Optional<Long> timeoutNanos) {
try {
if (timeoutNanos.isPresent()) {
logger.debug(">> blocking on %s for %s", future, timeoutNanos);
return getUninterruptibly(future, timeoutNanos.get(), NANOSECONDS);
} else {
logger.debug(">> blocking on %s", future);
return getUninterruptibly(future);
}
} catch (ExecutionException e) {
throw propagateCause(e);
} catch (TimeoutException e) {
future.cancel(true);
throw new UncheckedTimeoutException(e);
}
}
private static RuntimeException propagateCause(Exception e) {
Throwable cause = e.getCause();
if (cause == null) {
UncheckedExecutionException unchecked = new UncheckedExecutionException(e.getMessage()) {
private static final long serialVersionUID = 1L;
};
unchecked.setStackTrace(e.getStackTrace());
throw unchecked;
}
StackTraceElement[] combined = concat(cause.getStackTrace(), e.getStackTrace(), StackTraceElement.class);
cause.setStackTrace(combined);
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
if (cause instanceof Error) {
throw (Error) cause;
}
// The cause is a weird kind of Throwable, so throw the outer exception.
throw new RuntimeException(e);
}
// override timeout by values configured in properties(in ms)
private Optional<Long> timeoutInNanos(Invokable<?, ?> invoked, Map<String, Long> timeouts) {
Optional<Long> defaultMillis = fromNullable(timeouts.get("default"));
Optional<Long> timeoutMillis;
if (invoked.isAnnotationPresent(Named.class)) {
String commandName = invoked.getAnnotation(Named.class).value();
timeoutMillis = fromNullable(timeouts.get(commandName)).or(defaultMillis);
} else {
// TODO: remove old logic, once Named annotations are present on all methods
String className = invoked.getOwnerType().getRawType().getSimpleName().replace("AsyncClient", "Client")
.replace("AsyncApi", "Api");
timeoutMillis = fromNullable(timeouts.get(className + "." + invoked.getName())).or(
fromNullable(timeouts.get(className))).or(defaultMillis);
}
if (timeoutMillis.isPresent())
return Optional.of(TimeUnit.MILLISECONDS.toNanos(timeoutMillis.get()));
return Optional.absent();
}
}

View File

@ -18,7 +18,6 @@
*/
package org.jclouds.rest.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.util.concurrent.Futures.getUnchecked;
@ -32,7 +31,6 @@ import org.jclouds.reflect.Invocation;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.cache.Cache;
import com.google.common.reflect.Invokable;
import com.google.common.util.concurrent.ListenableFuture;
@ -45,7 +43,7 @@ public final class InvokeAndCallGetOnFutures<R> implements Function<Invocation,
@Resource
private Logger logger = Logger.NULL;
private final Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncInvokables;
private final Function<Invocation, Invocation> sync2async;
private final R receiver;
/**
@ -55,8 +53,8 @@ public final class InvokeAndCallGetOnFutures<R> implements Function<Invocation,
*/
@Inject
@VisibleForTesting
InvokeAndCallGetOnFutures(Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncInvokables, R receiver) {
this.sync2AsyncInvokables = sync2AsyncInvokables;
InvokeAndCallGetOnFutures(Function<Invocation, Invocation> sync2async, R receiver) {
this.sync2async = sync2async;
this.receiver = receiver;
}
@ -64,8 +62,7 @@ public final class InvokeAndCallGetOnFutures<R> implements Function<Invocation,
@Override
public Object apply(Invocation in) {
@SuppressWarnings("rawtypes")
Invokable target = checkNotNull(sync2AsyncInvokables.getIfPresent(in.getInvokable()), "invokable %s not in %s",
in.getInvokable(), sync2AsyncInvokables);
Invokable target = sync2async.apply(in).getInvokable();
Object returnVal;
try {
returnVal = target.invoke(receiver, in.getArgs().toArray());

View File

@ -19,114 +19,240 @@
package org.jclouds.rest.internal;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.util.concurrent.Futures.transform;
import static com.google.common.util.concurrent.Futures.withFallback;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpCommandExecutorService;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.logging.Logger;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.config.InvocationConfig;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.base.Optional;
import com.google.common.reflect.Invokable;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Injector;
import com.google.common.util.concurrent.TimeLimiter;
import com.google.common.util.concurrent.UncheckedTimeoutException;
/**
* @author Adrian Cole
*/
public class InvokeHttpMethod implements Function<Invocation, Object> {
@Resource
private Logger logger = Logger.NULL;
private final Injector injector;
private final Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncInvokables;
private final RestAnnotationProcessor annotationProcessor;
private final Function<Invocation, Invocation> sync2async;
private final Function<Invocation, HttpRequest> annotationProcessor;
private final HttpCommandExecutorService http;
private final TransformerForRequest transformerForRequest;
private final ListeningExecutorService userExecutor;
private final BlockOnFuture.Factory blocker;
private final TimeLimiter timeLimiter;
private final Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest;
private final InvocationConfig config;
@Inject
private InvokeHttpMethod(Injector injector, Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncInvokables,
RestAnnotationProcessor annotationProcessor, HttpCommandExecutorService http,
TransformerForRequest transformerForRequest,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, BlockOnFuture.Factory blocker) {
this.injector = injector;
this.sync2AsyncInvokables = sync2AsyncInvokables;
@VisibleForTesting
InvokeHttpMethod(Function<Invocation, Invocation> sync2async, Function<Invocation, HttpRequest> annotationProcessor,
HttpCommandExecutorService http, Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest,
TimeLimiter timeLimiter, InvocationConfig config,
@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.sync2async = sync2async;
this.annotationProcessor = annotationProcessor;
this.http = http;
this.userExecutor = userExecutor;
this.blocker = blocker;
this.timeLimiter = timeLimiter;
this.transformerForRequest = transformerForRequest;
this.config = config;
}
private final LoadingCache<Invokable<?, ?>, FutureFallback<?>> fallbacks = CacheBuilder.newBuilder().build(
new CacheLoader<Invokable<?, ?>, FutureFallback<?>>() {
@Override
public FutureFallback<?> load(Invokable<?, ?> key) throws Exception {
Fallback annotation = key.getAnnotation(Fallback.class);
if (annotation != null) {
return injector.getInstance(annotation.value());
}
return injector.getInstance(MapHttp4xxCodesToExceptions.class);
}
});
@Override
public Object apply(Invocation in) {
if (isFuture(in.getInvokable())) {
return createFuture(in);
return submit(in);
}
Invocation async = Invocation.create(
checkNotNull(sync2AsyncInvokables.getIfPresent(in.getInvokable()), "invokable %s not in %s",
in.getInvokable(), sync2AsyncInvokables), in.getArgs());
Invocation async = toAsync(in);
Optional<Long> timeoutNanos = config.getTimeoutNanos(async);
if (timeoutNanos.isPresent()) {
return invokeWithTimeout(async, timeoutNanos.get());
}
return invoke(async);
}
/**
* submits the {@linkplain HttpCommand} associated with {@code invocation},
* {@link #getTransformer(String, HttpCommand) parses its response}, and
* applies a {@link #getFallback(String, Invocation, HttpCommand) fallback}
* if a {@code Throwable} is encountered. Parsing and Fallback occur on the
* {@code userExecutor} thread.
*/
public ListenableFuture<?> submit(Invocation invocation) {
String commandName = config.getCommandName(invocation);
HttpCommand command = toCommand(commandName, invocation);
Function<HttpResponse, ?> transformer = getTransformer(commandName, command);
org.jclouds.Fallback<?> fallback = getFallback(commandName, invocation, command);
logger.debug(">> submitting %s", commandName);
return withFallback(transform(http.submit(command), transformer, userExecutor), fallback);
}
/**
* invokes the {@linkplain HttpCommand} associated with {@code invocation},
* {@link #getTransformer(String, HttpCommand) parses its response}, and
* applies a {@link #getFallback(String, Invocation, HttpCommand) fallback}
* if a {@code Throwable} is encountered.
*/
public Object invoke(Invocation invocation) {
String commandName = config.getCommandName(invocation);
HttpCommand command = toCommand(commandName, invocation);
Function<HttpResponse, ?> transformer = getTransformer(commandName, command);
org.jclouds.Fallback<?> fallback = getFallback(commandName, invocation, command);
logger.debug(">> invoking %s", commandName);
try {
return transformer.apply(http.invoke(command));
} catch (Throwable t) {
try {
return fallback.createOrPropagate(t);
} catch (Exception e) {
throw propagate(e);
}
}
}
/**
* calls {@link #invoke(Invocation)}, timing out after the specified time
* limit. If the target method call finished before the limit is reached, the
* return value or exception is propagated to the caller exactly as-is. If,
* on the other hand, the time limit is reached, we attempt to abort the call
* to the target, and throw an {@link UncheckedTimeoutException} to the
* caller.
*
* @param invocation
* the Invocation to invoke via {@link #invoke(Invocation)}
* @param limitNanos
* with timeoutUnit, the maximum length of time to wait in
* nanoseconds
* @throws InterruptedException
* if our thread is interrupted during execution
* @throws UncheckedTimeoutException
* if the time limit is reached
* @see TimeLimiter#callWithTimeout(Callable, long, TimeUnit, boolean)
*/
public Object invokeWithTimeout(final Invocation invocation, final long limitNanos) {
String commandName = config.getCommandName(invocation);
HttpCommand command = toCommand(commandName, invocation);
org.jclouds.Fallback<?> fallback = getFallback(commandName, invocation, command);
logger.debug(">> blocking on %s for %s", invocation, limitNanos);
try {
return timeLimiter
.callWithTimeout(new InvokeAndTransform(commandName, command), limitNanos, NANOSECONDS, true);
} catch (Throwable t) {
try {
return fallback.createOrPropagate(t);
} catch (Exception e) {
throw propagate(e);
}
}
}
private org.jclouds.Fallback<?> getFallback(String commandName, Invocation invocation, HttpCommand command) {
HttpRequest request = command.getCurrentRequest();
org.jclouds.Fallback<?> fallback = config.getFallback(invocation);
if (fallback instanceof InvocationContext)
InvocationContext.class.cast(fallback).setContext(request);
logger.trace("<< exceptions from %s are parsed by %s", commandName, fallback.getClass().getSimpleName());
return fallback;
}
@VisibleForTesting
final class InvokeAndTransform implements Callable<Object> {
private final String commandName;
private final HttpCommand command;
private final Function<HttpResponse, ?> transformer;
InvokeAndTransform(String commandName, HttpCommand command) {
this.commandName = commandName;
this.command = command;
this.transformer = getTransformer(commandName, command);
}
@Override
public Object call() throws Exception {
return transformer.apply(http.invoke(command));
}
@Override
public int hashCode() {
return Objects.hashCode(commandName, command, transformer);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
InvokeAndTransform that = InvokeAndTransform.class.cast(obj);
return equal(this.commandName, that.commandName) && equal(this.command, that.command)
&& equal(this.transformer, that.transformer);
}
@Override
public String toString() {
return toStringHelper(this).add("commandName", commandName).add("command", command)
.add("transformer", transformer).toString();
}
}
/**
* looks up the corresponding {@code Invocation} that returns a
* {@code Future}. Only Invokables that return {@code Futures} are annotated
* in a way that can be parsed into an {@linkplain HttpRequest}.
*/
private Invocation toAsync(Invocation in) {
Invocation async = sync2async.apply(in);
checkState(isFuture(async.getInvokable()), "not a future: %s", async);
return blocker.create(async).apply(createFuture(async));
return async;
}
private HttpCommand toCommand(String commandName, Invocation invocation) {
logger.trace(">> converting %s", commandName);
HttpRequest request = annotationProcessor.apply(invocation);
logger.trace("<< converted %s to %s", commandName, request.getRequestLine());
return new HttpCommand(request);
}
private Function<HttpResponse, ?> getTransformer(String commandName, HttpCommand command) {
HttpRequest request = command.getCurrentRequest();
Function<HttpResponse, ?> transformer = transformerForRequest.apply(request);
logger.trace("<< response from %s is parsed by %s", commandName, transformer.getClass().getSimpleName());
return transformer;
}
private boolean isFuture(Invokable<?, ?> in) {
return in.getReturnType().getRawType().equals(ListenableFuture.class);
}
public ListenableFuture<?> createFuture(Invocation invocation) {
String name = invocation.getInvokable().toString();
logger.trace(">> converting %s", name);
GeneratedHttpRequest request = annotationProcessor.apply(invocation);
logger.trace("<< converted %s to %s", name, request.getRequestLine());
Function<HttpResponse, ?> transformer = transformerForRequest.apply(request);
logger.trace("<< response from %s is parsed by %s", name, transformer.getClass().getSimpleName());
logger.debug(">> invoking %s", name);
ListenableFuture<?> result = transform(http.submit(new HttpCommand(request)), transformer, userExecutor);
FutureFallback<?> fallback = fallbacks.getUnchecked(invocation.getInvokable());
if (fallback instanceof InvocationContext) {
InvocationContext.class.cast(fallback).setContext(request);
}
logger.trace("<< exceptions from %s are parsed by %s", name, fallback.getClass().getSimpleName());
return withFallback(result, fallback);
}
@Override
public boolean equals(Object o) {
if (this == o)

View File

@ -131,7 +131,7 @@ import com.google.inject.TypeLiteral;
*
* @author Adrian Cole
*/
public class RestAnnotationProcessor implements Function<Invocation, GeneratedHttpRequest> {
public class RestAnnotationProcessor implements Function<Invocation, HttpRequest> {
@Resource
protected Logger logger = Logger.NULL;

View File

@ -35,6 +35,7 @@ import javax.lang.model.type.NullType;
import org.jclouds.functions.IdentityFunction;
import org.jclouds.functions.OnlyElementOrNull;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
import org.jclouds.http.functions.ParseJson;
@ -69,7 +70,7 @@ import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
public class TransformerForRequest implements Function<GeneratedHttpRequest, Function<HttpResponse, ?>> {
public class TransformerForRequest implements Function<HttpRequest, Function<HttpResponse, ?>> {
private final ParseSax.Factory parserFactory;
private final Injector injector;
private final GetAcceptHeaders getAcceptHeaders;
@ -83,7 +84,8 @@ public class TransformerForRequest implements Function<GeneratedHttpRequest, Fun
@SuppressWarnings("unchecked")
@Override
public Function<HttpResponse, ?> apply(GeneratedHttpRequest request) {
public Function<HttpResponse, ?> apply(HttpRequest in) {
GeneratedHttpRequest request = GeneratedHttpRequest.class.cast(in);
Function<HttpResponse, ?> transformer;
Class<? extends HandlerWithResult<?>> handler = getSaxResponseParserClassOrNull(request.getInvocation()
.getInvokable());
@ -93,7 +95,7 @@ public class TransformerForRequest implements Function<GeneratedHttpRequest, Fun
transformer = getTransformerForMethod(request.getInvocation(), injector);
}
if (transformer instanceof InvocationContext<?>) {
((InvocationContext<?>) transformer).setContext(request);
InvocationContext.class.cast(transformer).setContext(request);
}
if (request.getInvocation().getInvokable().isAnnotationPresent(Transform.class)) {
Function<?, ?> wrappingTransformer = injector.getInstance(request.getInvocation().getInvokable()

View File

@ -1,3 +1,21 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy current the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.fallbacks;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

View File

@ -36,27 +36,27 @@ import com.google.common.net.HttpHeaders;
public class MapHttp4xxCodesToExceptionsTest {
@Test(expectedExceptions = AuthorizationException.class)
public void test401ToAuthorizationException() {
public void test401ToAuthorizationException() throws Exception {
fn.create(new HttpResponseException(command, HttpResponse.builder().statusCode(401).build()));
}
@Test(expectedExceptions = AuthorizationException.class)
public void test403ToAuthorizationException() {
public void test403ToAuthorizationException() throws Exception {
fn.create(new HttpResponseException(command, HttpResponse.builder().statusCode(403).build()));
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void test404ToResourceNotFoundException() {
public void test404ToResourceNotFoundException() throws Exception {
fn.create(new HttpResponseException(command, HttpResponse.builder().statusCode(404).build()));
}
@Test(expectedExceptions = IllegalStateException.class)
public void test409ToIllegalStateException() {
public void test409ToIllegalStateException() throws Exception {
fn.create(new HttpResponseException(command, HttpResponse.builder().statusCode(409).build()));
}
@Test(expectedExceptions = RetryAfterException.class, expectedExceptionsMessageRegExp = "retry now")
public void testHttpResponseExceptionWithRetryAfterDate() {
public void testHttpResponseExceptionWithRetryAfterDate() throws Exception {
fn.create(new HttpResponseException(command,
HttpResponse.builder()
.statusCode(503)
@ -64,7 +64,7 @@ public class MapHttp4xxCodesToExceptionsTest {
}
@Test(expectedExceptions = RetryAfterException.class, expectedExceptionsMessageRegExp = "retry in 700 seconds")
public void testHttpResponseExceptionWithRetryAfterOffset(){
public void testHttpResponseExceptionWithRetryAfterOffset() throws Exception {
fn.create(new HttpResponseException(command,
HttpResponse.builder()
.statusCode(503)
@ -72,7 +72,7 @@ public class MapHttp4xxCodesToExceptionsTest {
}
@Test(expectedExceptions = RetryAfterException.class, expectedExceptionsMessageRegExp = "retry in 86400 seconds")
public void testHttpResponseExceptionWithRetryAfterPastIsZero(){
public void testHttpResponseExceptionWithRetryAfterPastIsZero() throws Exception {
fn.create(new HttpResponseException(command,
HttpResponse.builder()
.statusCode(503)

View File

@ -52,7 +52,6 @@ import org.jclouds.util.Strings2;
import com.google.common.base.Function;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Provides;
@ -92,13 +91,14 @@ public interface IntegrationTestAsyncClient {
@Fallback(FooOnException.class)
ListenableFuture<String> downloadException(@PathParam("id") String id, HttpRequestOptions options);
static class FooOnException implements FutureFallback<String> {
@Override
static class FooOnException implements org.jclouds.Fallback<String> {
public ListenableFuture<String> create(Throwable t) throws Exception {
return immediateFuture("foo");
}
public String createOrPropagate(Throwable t) throws Exception {
return "foo";
}
}
@GET

View File

@ -27,6 +27,7 @@ import java.util.Properties;
import org.jclouds.http.BaseJettyTest;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.IntegrationTestAsyncClient;
import org.jclouds.io.Payloads;
@ -34,6 +35,7 @@ import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.Invokable;
@ -122,7 +124,7 @@ public class BackoffLimitedRetryHandlerTest {
assertEquals(response.getPayload().getInput().read(), -1);
}
private final RestAnnotationProcessor processor = BaseJettyTest.newBuilder(8100, new Properties()).buildInjector()
private final Function<Invocation, HttpRequest> processor = BaseJettyTest.newBuilder(8100, new Properties()).buildInjector()
.getInstance(RestAnnotationProcessor.class);
private HttpCommand createCommand() throws SecurityException, NoSuchMethodException {

View File

@ -24,6 +24,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.PathParam;
import org.jclouds.ContextBuilder;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.IntegrationTestAsyncClient;
import org.jclouds.http.IntegrationTestClient;
import org.jclouds.predicates.validators.AllLowerCaseValidator;
@ -35,6 +36,7 @@ import org.testng.TestException;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.Invokable;
import com.google.inject.Injector;
@ -105,7 +107,7 @@ public class InputParamValidatorTest {
}
Injector injector;
RestAnnotationProcessor restAnnotationProcessor;
Function<Invocation, HttpRequest> restAnnotationProcessor;
@BeforeClass
void setupFactory() {

View File

@ -0,0 +1,135 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy current the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.config;
import static org.jclouds.reflect.Reflection2.method;
import static org.testng.Assert.assertEquals;
import java.util.Properties;
import javax.inject.Named;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.http.HttpResponse;
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.annotations.Fallback;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.name.Names;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", singleThreaded = true)
public class ReadAnnotationsAndPropertiesTest {
public static interface ThingApi {
HttpResponse get();
HttpResponse namedGet();
}
public static interface ThingAsyncApi {
ListenableFuture<HttpResponse> get();
@Named("ns:get")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<HttpResponse> namedGet();
}
private Invocation asyncGet;
private Invocation asyncNamedGet;
private org.jclouds.Fallback<Object> defaultFallback;
@BeforeClass
void setupInvocations() throws SecurityException, NoSuchMethodException {
asyncGet = Invocation.create(method(ThingAsyncApi.class, "get"), ImmutableList.of());
asyncNamedGet = Invocation.create(method(ThingAsyncApi.class, "namedGet"), ImmutableList.of());
defaultFallback = new NullOnNotFoundOr404();
}
/**
* this functionality will be removed once Named annotations are on all async
* classes.
*/
public void testInvocationsSetDefaultTimeoutOnAsyncMethods() throws Exception {
final Properties props = new Properties();
props.setProperty("jclouds.timeouts.default", "250");
Injector injector = Guice.createInjector(new AbstractModule() {
protected void configure() {
Names.bindProperties(binder(), props);
}
});
ReadAnnotationsAndProperties config = new ReadAnnotationsAndProperties(injector,
new FilterStringsBoundToInjectorByName(injector), defaultFallback);
assertEquals(config.getTimeoutNanos(asyncGet), Optional.of(250000000l));
assertEquals(config.getTimeoutNanos(asyncNamedGet), Optional.of(250000000l));
}
public void testNamedInvocationGetsTimeoutOverrideOnAsyncMethods() throws Exception {
final Properties props = new Properties();
props.setProperty("jclouds.timeouts.default", "50");
props.setProperty("jclouds.timeouts.ThingApi", "100");
props.setProperty("jclouds.timeouts.ns:get", "250");
Injector injector = Guice.createInjector(new AbstractModule() {
protected void configure() {
Names.bindProperties(binder(), props);
}
});
ReadAnnotationsAndProperties config = new ReadAnnotationsAndProperties(injector,
new FilterStringsBoundToInjectorByName(injector), defaultFallback);
assertEquals(config.getTimeoutNanos(asyncNamedGet), Optional.of(250000000l));
}
/**
* this functionality will be removed once Named annotations are on all async
* classes.
*/
public void testNamingConventionOfUnnamedMethods() throws Exception {
Injector injector = Guice.createInjector();
ReadAnnotationsAndProperties config = new ReadAnnotationsAndProperties(injector,
new FilterStringsBoundToInjectorByName(injector), defaultFallback);
assertEquals(config.getCommandName(asyncGet), "ThingApi.get");
}
public void testNamingConventionOfNamedAsyncMethods() throws Exception {
Injector injector = Guice.createInjector();
ReadAnnotationsAndProperties config = new ReadAnnotationsAndProperties(injector,
new FilterStringsBoundToInjectorByName(injector), defaultFallback);
assertEquals(config.getCommandName(asyncNamedGet), "ns:get");
}
public void testFallbackOverride() throws Exception {
Injector injector = Guice.createInjector();
ReadAnnotationsAndProperties config = new ReadAnnotationsAndProperties(injector,
new FilterStringsBoundToInjectorByName(injector), defaultFallback);
assertEquals(config.getFallback(asyncNamedGet).getClass(), FalseOnNotFoundOr404.class);
assertEquals(config.getFallback(asyncGet), defaultFallback);
}
}

View File

@ -84,12 +84,15 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.InputSupplier;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.SimpleTimeLimiter;
import com.google.common.util.concurrent.TimeLimiter;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/**
@ -236,6 +239,12 @@ public abstract class BaseRestApiExpectTest<S> {
}).toInstance(fn);
bind(HttpCommandExecutorService.class).to(ExpectHttpCommandExecutorService.class);
}
@Provides
@Singleton
TimeLimiter timeLimiter(@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor){
return new SimpleTimeLimiter(userExecutor);
}
}
/**

View File

@ -33,6 +33,9 @@ import java.io.IOException;
import java.util.Date;
import java.util.Map.Entry;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
import org.jclouds.http.HttpCommandExecutorService;
@ -51,8 +54,11 @@ import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;
import com.google.common.reflect.Invokable;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.SimpleTimeLimiter;
import com.google.common.util.concurrent.TimeLimiter;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.Provides;
/**
*
@ -83,6 +89,12 @@ public abstract class BaseRestApiTest {
bind(ListeningExecutorService.class).annotatedWith(named(PROPERTY_IO_WORKER_THREADS)).toInstance(sameThreadExecutor());
bind(HttpCommandExecutorService.class).toInstance(mock);
}
@Provides
@Singleton
TimeLimiter timeLimiter(@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor){
return new SimpleTimeLimiter(userExecutor);
}
}
protected void assertPayloadEquals(HttpRequest request, String toMatch, String contentType, boolean contentMD5) {

View File

@ -1,138 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.internal;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.jclouds.reflect.Reflection2.method;
import static org.testng.Assert.assertEquals;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.inject.Named;
import org.jclouds.reflect.Invocation;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ListenableFuture;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", singleThreaded = true)
public class BlockOnFutureTest {
static ListenableFuture<String> future;
public static class ThingAsyncApi {
public ListenableFuture<String> get() {
return future;
}
@Named("ns:get")
public ListenableFuture<String> namedGet() {
return future;
}
}
private Invocation get;
private Invocation namedGet;
@BeforeClass
void setupInvocations() throws SecurityException, NoSuchMethodException {
get = Invocation.create(method(ThingAsyncApi.class, "get"), ImmutableList.of());
namedGet = Invocation.create(method(ThingAsyncApi.class, "namedGet"), ImmutableList.of());
}
@SuppressWarnings("unchecked")
@BeforeMethod
void createMockedFuture() throws InterruptedException, ExecutionException, TimeoutException {
future = createMock(ListenableFuture.class);
expect(future.get(250000000, TimeUnit.NANOSECONDS)).andReturn("foo");
replay(future);
}
public void testUnnamedMethodWithDefaultPropTimeout() throws Exception {
Function<ListenableFuture<?>, Object> withOverride = new BlockOnFuture(ImmutableMap.of("default", 250L), get);
assertEquals(withOverride.apply(future), "foo");
verify(future);
}
public void testUnnamedMethodWithClassPropTimeout() throws Exception {
Function<ListenableFuture<?>, Object> withOverride = new BlockOnFuture(ImmutableMap.of("default", 50L,
"ThingApi", 250L), get);
assertEquals(withOverride.apply(future), "foo");
verify(future);
}
public void testUnnamedMethodWithMethodPropTimeout() throws Exception {
Function<ListenableFuture<?>, Object> withOverride = new BlockOnFuture(ImmutableMap.of("default", 50L,
"ThingApi", 100L, "ThingApi.get", 250L), get);
assertEquals(withOverride.apply(future), "foo");
verify(future);
}
@SuppressWarnings("unchecked")
public void testUnnamedMethodWithNoTimeoutsCallGetDirectly() throws Exception {
future = createMock(ListenableFuture.class);
expect(future.get()).andReturn("foo");
replay(future);
Function<ListenableFuture<?>, Object> noOverrides = new BlockOnFuture(ImmutableMap.<String, Long> of(), get);
assertEquals(noOverrides.apply(future), "foo");
verify(future);
}
public void testNamedMethodWithDefaultPropTimeout() throws Exception {
Function<ListenableFuture<?>, Object> withOverride = new BlockOnFuture(ImmutableMap.of("default", 250L), namedGet);
assertEquals(withOverride.apply(future), "foo");
verify(future);
}
public void testNamedMethodWithMethodPropTimeout() throws Exception {
Function<ListenableFuture<?>, Object> withOverride = new BlockOnFuture(ImmutableMap.of("default", 50L,
"ThingApi", 100L, "ns:get", 250L), namedGet);
assertEquals(withOverride.apply(future), "foo");
verify(future);
}
@SuppressWarnings("unchecked")
public void testNamedMethodWithNoTimeoutsCallGetDirectly() throws Exception {
future = createMock(ListenableFuture.class);
expect(future.get()).andReturn("foo");
replay(future);
Function<ListenableFuture<?>, Object> noOverrides = new BlockOnFuture(ImmutableMap.<String, Long> of(), namedGet);
assertEquals(noOverrides.apply(future), "foo");
verify(future);
}
}

View File

@ -0,0 +1,177 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.internal;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.jclouds.reflect.Reflection2.method;
import static org.testng.Assert.assertEquals;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpCommandExecutorService;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.config.InvocationConfig;
import org.jclouds.rest.internal.InvokeHttpMethod.InvokeAndTransform;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.TimeLimiter;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", singleThreaded = true)
public class InvokeHttpMethodTest {
public static interface ThingApi {
HttpResponse get();
}
public static interface ThingAsyncApi {
@Named("ns:get")
ListenableFuture<HttpResponse> get();
}
private Invocation get;
private Invocation asyncGet;
private Function<Invocation, Invocation> sync2async;
private HttpRequest getRequest = HttpRequest.builder().method("GET").endpoint("http://get").build();
private HttpCommand getCommand = new HttpCommand(getRequest);
private Function<Invocation, HttpRequest> toRequest;
@BeforeClass
void setupInvocations() throws SecurityException, NoSuchMethodException {
get = Invocation.create(method(ThingApi.class, "get"), ImmutableList.of());
asyncGet = Invocation.create(method(ThingAsyncApi.class, "get"), ImmutableList.of());
sync2async = Functions.forMap(ImmutableMap.of(get, asyncGet));
toRequest = Functions.forMap(ImmutableMap.of(asyncGet, getRequest));
}
@SuppressWarnings("unchecked")
private Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest = Function.class.cast(Functions
.constant(Functions.identity()));
private ListeningExecutorService userThreads = MoreExecutors.sameThreadExecutor();
private HttpResponse response = HttpResponse.builder().statusCode(200).payload("foo").build();
private HttpCommandExecutorService http;
private TimeLimiter timeLimiter;
@SuppressWarnings("rawtypes")
private org.jclouds.Fallback fallback;
private InvocationConfig config;
private InvokeHttpMethod invokeHttpMethod;
private ListenableFuture<HttpResponse> future;
@SuppressWarnings("unchecked")
@BeforeMethod
void createMocks() {
http = createMock(HttpCommandExecutorService.class);
timeLimiter = createMock(TimeLimiter.class);
fallback = createMock(org.jclouds.Fallback.class);
config = createMock(InvocationConfig.class);
future = createMock(ListenableFuture.class);
invokeHttpMethod = new InvokeHttpMethod(sync2async, toRequest, http, transformerForRequest, timeLimiter, config,
userThreads);
expect(config.getCommandName(asyncGet)).andReturn("ns:get");
expect(config.getFallback(asyncGet)).andReturn(fallback);
}
@AfterMethod
void verifyMocks() {
verify(http, timeLimiter, fallback, config, future);
}
public void testMethodWithTimeoutRunsTimeLimiter() throws Exception {
expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.of(250000000l));
InvokeAndTransform invoke = invokeHttpMethod.new InvokeAndTransform("ns:get", getCommand);
expect(timeLimiter.callWithTimeout(invoke, 250000000, TimeUnit.NANOSECONDS, true)).andReturn(response);
replay(http, timeLimiter, fallback, config, future);
invokeHttpMethod.apply(get);
}
public void testMethodWithNoTimeoutCallGetDirectly() throws Exception {
expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.<Long> absent());
expect(http.invoke(new HttpCommand(getRequest))).andReturn(response);
replay(http, timeLimiter, fallback, config, future);
invokeHttpMethod.apply(get);
}
public void testAsyncMethodSubmitsRequest() throws Exception {
expect(http.submit(new HttpCommand(getRequest))).andReturn(future);
future.addListener(anyObject(Runnable.class), eq(userThreads));
replay(http, timeLimiter, fallback, config, future);
invokeHttpMethod.apply(asyncGet);
}
private HttpResponse fallbackResponse = HttpResponse.builder().statusCode(200).payload("bar").build();
public void testDirectCallRunsFallbackCreateOrPropagate() throws Exception {
IllegalStateException exception = new IllegalStateException();
expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.<Long> absent());
expect(http.invoke(new HttpCommand(getRequest))).andThrow(exception);
expect(fallback.createOrPropagate(exception)).andReturn(fallbackResponse);
replay(http, timeLimiter, fallback, config, future);
assertEquals(invokeHttpMethod.apply(get), fallbackResponse);
}
public void testTimeLimitedRunsFallbackCreateOrPropagate() throws Exception {
IllegalStateException exception = new IllegalStateException();
expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.of(250000000l));
InvokeAndTransform invoke = invokeHttpMethod.new InvokeAndTransform("ns:get", getCommand);
expect(timeLimiter.callWithTimeout(invoke, 250000000, TimeUnit.NANOSECONDS, true)).andThrow(exception);
expect(fallback.createOrPropagate(exception)).andReturn(fallbackResponse);
replay(http, timeLimiter, fallback, config, future);
assertEquals(invokeHttpMethod.apply(get), fallbackResponse);
}
@SuppressWarnings("unchecked")
public void testSubmitRunsFallbackCreateOnGet() throws Exception {
IllegalStateException exception = new IllegalStateException();
expect(http.submit(new HttpCommand(getRequest))).andReturn(
Futures.<HttpResponse> immediateFailedFuture(exception));
expect(fallback.create(exception)).andReturn(Futures.<HttpResponse> immediateFuture(fallbackResponse));
// not using the field, as you can see above we are making an immediate
// failed future instead.
future = createMock(ListenableFuture.class);
replay(http, timeLimiter, fallback, config, future);
assertEquals(ListenableFuture.class.cast(invokeHttpMethod.apply(asyncGet)).get(), fallbackResponse);
}
}

View File

@ -249,9 +249,14 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
@Override
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
return Futures.immediateFuture(invoke(command));
}
@Override
public HttpResponse invoke(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(),
"GET http://localhost:9999/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
return HttpResponse.builder().build();
}
});
@ -274,6 +279,11 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
@Override
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
return Futures.immediateFuture(invoke(command));
}
@Override
public HttpResponse invoke(HttpCommand command) {
if (callCounter == 1)
assertEquals(command.getCurrentRequest().getRequestLine(),
"GET http://localhost:1111/client/1/bar/2 HTTP/1.1");
@ -281,7 +291,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
assertEquals(command.getCurrentRequest().getRequestLine(),
"GET http://localhost:1111/client/1/foo HTTP/1.1");
callCounter++;
return Futures.immediateFuture(HttpResponse.builder().build());
return HttpResponse.builder().build();
}
});
@ -304,8 +314,13 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
@Override
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
return Futures.immediateFuture(invoke(command));
}
@Override
public HttpResponse invoke(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
return HttpResponse.builder().build();
}
});
@ -329,9 +344,14 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
@Override
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
return Futures.immediateFuture(invoke(command));
}
@Override
public HttpResponse invoke(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(),
"GET http://howdyboys/testing/testing/thepathparam/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
return HttpResponse.builder().build();
}
});
@ -355,8 +375,13 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
@Override
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
return Futures.immediateFuture(invoke(command));
}
@Override
public HttpResponse invoke(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
return HttpResponse.builder().build();
}
});
@ -380,8 +405,13 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
@Override
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
return Futures.immediateFuture(invoke(command));
}
@Override
public HttpResponse invoke(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
return HttpResponse.builder().build();
}
}, new AbstractModule() {
@ -419,8 +449,13 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
@Override
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
return Futures.immediateFuture(invoke(command));
}
@Override
public HttpResponse invoke(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
return HttpResponse.builder().build();
}
});

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

@ -18,9 +18,7 @@
*/
package org.jclouds.abiquo;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_MAX_REDIRECTS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.abiquo.config.AbiquoProperties.ASYNC_TASK_MONITOR_DELAY;
import static org.jclouds.abiquo.config.AbiquoProperties.CREDENTIAL_IS_TOKEN;
import static org.jclouds.reflect.Reflection2.typeToken;
@ -67,7 +65,6 @@ public class AbiquoApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(90) + "");
// By default redirects will be handled in the domain objects
properties.setProperty(PROPERTY_MAX_REDIRECTS, "0");
// The default polling delay between AsyncTask monitor requests

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

@ -17,8 +17,6 @@
* under the License.
*/
package org.jclouds.azure.management;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.azure.management.config.AzureManagementProperties.SUBSCRIPTION_ID;
import static org.jclouds.reflect.Reflection2.typeToken;
@ -66,7 +64,6 @@ public class AzureManagementApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
return properties;
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.snia.cdmi.v1;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import java.net.URI;
import java.util.Properties;
@ -59,8 +56,6 @@ public class CDMIApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "DataNonCDMIContentTypeApi", MINUTES.toMillis(10) + "");
return properties;
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.cloudstack.ec2;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import java.net.URI;
import java.util.Properties;
@ -57,7 +54,6 @@ public class CloudStackEC2ApiMetadata extends EC2ApiMetadata {
public static Properties defaultProperties() {
Properties properties = EC2ApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ec2:DescribeImages", MINUTES.toMillis(15) + "");
return properties;
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.dynect.v3;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import java.net.URI;
import java.util.Properties;
@ -62,7 +59,6 @@ public class DynECTApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
return properties;
}

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

@ -18,8 +18,6 @@
*/
package org.jclouds.elb;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
@ -63,7 +61,6 @@ public class ELBApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
return properties;

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.fujitsu.fgcp;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI;
@ -57,7 +55,6 @@ public class FGCPApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(1) + "");
// enables peer verification using the CAs bundled with the JRE (or
// value of javax.net.ssl.trustStore if set)
properties.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "false");

View File

@ -18,9 +18,13 @@
*/
package org.jclouds.googlecompute;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Module;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.googlecompute.config.GoogleComputeParserModule;
import org.jclouds.googlecompute.config.GoogleComputeRestClientModule;
@ -29,14 +33,9 @@ import org.jclouds.oauth.v2.config.OAuthAuthenticationModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
import java.net.URI;
import java.util.Properties;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Module;
/**
* Implementation of {@link ApiMetadata} for GoogleCompute v1beta13 API
@ -64,7 +63,6 @@ public class GoogleComputeApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(1) + "");
properties.put("oauth.endpoint", "https://accounts.google.com/o/oauth2/token");
properties.put(AUDIENCE, "https://accounts.google.com/o/oauth2/token");
properties.put(SIGNATURE_OR_MAC_ALGORITHM, "RS256");

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.iam;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
@ -59,7 +57,6 @@ public class IAMApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
return properties;

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.jenkins.v1;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import java.net.URI;
import java.util.Properties;
@ -61,7 +58,6 @@ public class JenkinsApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
return properties;
}

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

@ -17,8 +17,6 @@
* under the License.
*/
package org.jclouds.joyent.cloudapi.v6_5;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI;
@ -63,7 +61,6 @@ public class JoyentCloudApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
// auth fail sometimes happens, as the rc.local script that injects the
// authorized key executes after ssh has started.
properties.setProperty("jclouds.ssh.max-retries", "7");

View File

@ -18,22 +18,21 @@
*/
package org.jclouds.oauth.v2;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Module;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.oauth.v2.config.OAuthModule;
import org.jclouds.oauth.v2.config.OAuthRestClientModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
import java.net.URI;
import java.util.Properties;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Module;
/**
* Implementation of {@link ApiMetadata} for OAuth 2 API
@ -61,7 +60,6 @@ public class OAuthApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(1) + "");
properties.put(SIGNATURE_OR_MAC_ALGORITHM, "RS256");
properties.put(PROPERTY_SESSION_INTERVAL, 3600);
return properties;

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.openstack.glance.v1_0;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
@ -65,7 +63,6 @@ public class GlanceApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
properties.setProperty(SERVICE_TYPE, ServiceType.IMAGE);
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
return properties;

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.openstack.quantum.v1_0;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
@ -65,7 +63,6 @@ public class QuantumApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
properties.setProperty(SERVICE_TYPE, ServiceType.NETWORK);
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
return properties;

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.openstack.swift.v1;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
@ -65,7 +63,6 @@ public class SwiftApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
properties.setProperty(SERVICE_TYPE, ServiceType.OBJECT_STORE);
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
return properties;

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.opsource.servers;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import java.net.URI;
import java.util.Properties;
@ -57,7 +54,6 @@ public class OpSourceServersApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
return properties;
}

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.rds;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
@ -61,7 +59,6 @@ public class RDSApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
return properties;

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

@ -27,9 +27,9 @@ import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.route53.config.Route53RestClientModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
import org.jclouds.route53.config.Route53RestClientModule;
import com.google.common.reflect.TypeToken;
@ -59,7 +59,6 @@ public class Route53ApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
return properties;

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.savvis.vpdc;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.reflect.Reflection2.typeToken;
import static org.jclouds.savvis.vpdc.reference.VPDCConstants.PROPERTY_VPDC_TIMEOUT_TASK_COMPLETED;
@ -62,8 +60,6 @@ public class VPDCApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(5) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "LoginApi.login", MINUTES.toMillis(3) + "");
properties.setProperty(PROPERTY_VPDC_TIMEOUT_TASK_COMPLETED, 600l * 1000l + "");
return properties;
}

View File

@ -18,9 +18,7 @@
*/
package org.jclouds.vcloud.director.v1_5;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.reflect.Reflection2.typeToken;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorConstants.PROPERTY_VCLOUD_DIRECTOR_TIMEOUT_TASK_COMPLETED;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorConstants.PROPERTY_VCLOUD_DIRECTOR_VERSION_SCHEMA;
@ -62,7 +60,6 @@ public class VCloudDirectorApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
/** FIXME this should not be the default */
properties.setProperty(PROPERTY_SESSION_INTERVAL, Integer.toString(30 * 60));

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.aws.ec2;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
import java.util.Properties;
@ -63,9 +60,6 @@ public class AWSEC2ApiMetadata extends EC2ApiMetadata {
public static Properties defaultProperties() {
Properties properties = EC2ApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(90) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ec2:DescribeImages", MINUTES.toMillis(5) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ec2:DescribeSpotInstanceRequests", MINUTES.toMillis(2) + "");
properties.remove(PROPERTY_EC2_AMI_OWNERS);
// auth fail sometimes happens in EC2, as the rc.local script that injects the
// authorized key executes after ssh has started.

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.azureblob;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.reflect.Reflection2.typeToken;
@ -67,10 +65,6 @@ public class AzureBlobApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(2) + "");
// 10 minutes per MB * max size of 64M
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "AzureBlobClient.putBlob", MINUTES.toMillis(10 * 64) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "AzureBlobClient.getBlob", MINUTES.toMillis(10 * 64) + "");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "x-ms-meta-");
return properties;
}

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

@ -18,9 +18,6 @@
*/
package org.jclouds.glesys;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI;
@ -63,9 +60,6 @@ public class GleSYSApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ServerApi.createWithHostnameAndRootPassword", MINUTES.toMillis(3) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ServerApi.clone", MINUTES.toMillis(3) + "");
properties.setProperty("jclouds.ssh.max-retries", "5");
properties.setProperty("jclouds.ssh.retry-auth", "true");
return properties;

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.gogrid;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI;
@ -62,7 +60,6 @@ public class GoGridApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(90) + "");
properties.setProperty("jclouds.ssh.max-retries", "5");
properties.setProperty("jclouds.ssh.retry-auth", "true");
return properties;

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));
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.softlayer;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI;
@ -63,8 +60,6 @@ public class SoftLayerApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(90) + "");
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ProductPackageClient", MINUTES.toMillis(3) + "");
properties.setProperty("jclouds.ssh.max-retries", "5");
properties.setProperty("jclouds.ssh.retry-auth", "true");
return properties;