mirror of https://github.com/apache/jclouds.git
Merge pull request #1260 from jclouds/sync-http
Synchronous commands now use calling thread
This commit is contained in:
commit
9f7507b1e8
|
@ -17,8 +17,6 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.atmos;
|
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.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
||||||
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
@ -69,10 +67,6 @@ public class AtmosApiMetadata extends BaseRestApiMetadata {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_REGIONS, "DEFAULT");
|
properties.setProperty(PROPERTY_REGIONS, "DEFAULT");
|
||||||
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "X-Object-Meta-");
|
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;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,9 @@ import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.options.GetOptions;
|
import org.jclouds.http.options.GetOptions;
|
||||||
import org.jclouds.reflect.Invocation;
|
import org.jclouds.reflect.Invocation;
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.reflect.Invokable;
|
import com.google.common.reflect.Invokable;
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ import com.google.common.reflect.Invokable;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class AtmosBlobRequestSigner implements BlobRequestSigner {
|
public class AtmosBlobRequestSigner implements BlobRequestSigner {
|
||||||
private final RestAnnotationProcessor processor;
|
private final Function<Invocation, HttpRequest> processor;
|
||||||
private final BlobToObject blobToObject;
|
private final BlobToObject blobToObject;
|
||||||
private final BlobToHttpGetOptions blob2ObjectGetOptions;
|
private final BlobToHttpGetOptions blob2ObjectGetOptions;
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ public class AtmosBlobRequestSigner implements BlobRequestSigner {
|
||||||
private final Invokable<?, ?> createMethod;
|
private final Invokable<?, ?> createMethod;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AtmosBlobRequestSigner(RestAnnotationProcessor processor, BlobToObject blobToObject,
|
public AtmosBlobRequestSigner(Function<Invocation, HttpRequest> processor, BlobToObject blobToObject,
|
||||||
BlobToHttpGetOptions blob2ObjectGetOptions) throws SecurityException, NoSuchMethodException {
|
BlobToHttpGetOptions blob2ObjectGetOptions) throws SecurityException, NoSuchMethodException {
|
||||||
this.processor = checkNotNull(processor, "processor");
|
this.processor = checkNotNull(processor, "processor");
|
||||||
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
|
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
|
||||||
|
|
|
@ -24,27 +24,32 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
import org.jclouds.blobstore.KeyAlreadyExistsException;
|
import org.jclouds.blobstore.KeyAlreadyExistsException;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.rest.InvocationContext;
|
import org.jclouds.rest.InvocationContext;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class EndpointIfAlreadyExists implements FutureFallback<URI>, InvocationContext<EndpointIfAlreadyExists> {
|
public class EndpointIfAlreadyExists implements Fallback<URI>, InvocationContext<EndpointIfAlreadyExists> {
|
||||||
|
|
||||||
private URI endpoint;
|
private URI endpoint;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<URI> create(Throwable t) {
|
public ListenableFuture<URI> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URI createOrPropagate(Throwable t) throws Exception {
|
||||||
if (checkNotNull(t, "throwable") instanceof KeyAlreadyExistsException) {
|
if (checkNotNull(t, "throwable") instanceof KeyAlreadyExistsException) {
|
||||||
return immediateFuture(endpoint);
|
return endpoint;
|
||||||
}
|
}
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,24 +35,24 @@ import org.testng.annotations.Test;
|
||||||
public class EndpointIfAlreadyExistsTest {
|
public class EndpointIfAlreadyExistsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFoundIsNullWhenEndpointNotSet() {
|
public void testFoundIsNullWhenEndpointNotSet() throws Exception {
|
||||||
assertNull(getUnchecked(new EndpointIfAlreadyExists().create(new KeyAlreadyExistsException())));
|
assertNull(getUnchecked(new EndpointIfAlreadyExists().create(new KeyAlreadyExistsException())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFoundIsEndpointWhenSet() {
|
public void testFoundIsEndpointWhenSet() throws Exception {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
getUnchecked(new EndpointIfAlreadyExists().setEndpoint(URI.create("foo")).create(
|
getUnchecked(new EndpointIfAlreadyExists().setEndpoint(URI.create("foo")).create(
|
||||||
new KeyAlreadyExistsException())), URI.create("foo"));
|
new KeyAlreadyExistsException())), URI.create("foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = RuntimeException.class)
|
@Test(expectedExceptions = RuntimeException.class)
|
||||||
public void testNotFoundPropagates() {
|
public void testNotFoundPropagates() throws Exception {
|
||||||
new EndpointIfAlreadyExists().create(new RuntimeException());
|
new EndpointIfAlreadyExists().create(new RuntimeException());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = NullPointerException.class)
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
public void testNullIsBad() {
|
public void testNullIsBad() throws Exception {
|
||||||
new EndpointIfAlreadyExists().create(null);
|
new EndpointIfAlreadyExists().create(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.cloudfiles;
|
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.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@ -65,7 +62,6 @@ public class CloudFilesApiMetadata extends SwiftApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = SwiftApiMetadata.defaultProperties();
|
Properties properties = SwiftApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "OpenStackAuthClient.authenticate", SECONDS.toMillis(30) + "");
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.cloudservers;
|
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 static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -63,8 +60,6 @@ public class CloudServersApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.cloudsigma;
|
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.cloudsigma.reference.CloudSigmaConstants.PROPERTY_VNC_PASSWORD;
|
||||||
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
|
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
@ -63,8 +61,6 @@ public class CloudSigmaApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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");
|
properties.setProperty(PROPERTY_VNC_PASSWORD, "IL9vs34d");
|
||||||
// passwords are set post-boot, so auth failures are possible
|
// passwords are set post-boot, so auth failures are possible
|
||||||
// from a race condition applying the password set script
|
// from a race condition applying the password set script
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.cloudstack;
|
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 static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -60,9 +58,6 @@ public class CloudStackApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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.max-retries", "7");
|
||||||
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -20,11 +20,11 @@ package org.jclouds.cloudstack.functions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
import static org.jclouds.Fallbacks.valOnNotFoundOr404;
|
||||||
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
|
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
|
||||||
|
|
||||||
import org.jclouds.Fallbacks;
|
import org.jclouds.Fallback;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
public final class CloudStackFallbacks {
|
public final class CloudStackFallbacks {
|
||||||
|
@ -35,14 +35,19 @@ public final class CloudStackFallbacks {
|
||||||
* CloudStack is currently sending 431 errors with the text "Unable to find account owner for ip ". In this case, we
|
* CloudStack is currently sending 431 errors with the text "Unable to find account owner for ip ". In this case, we
|
||||||
* have to ignore as there's no means for us to avoid the problem, or action to take.
|
* have to ignore as there's no means for us to avoid the problem, or action to take.
|
||||||
*/
|
*/
|
||||||
public static final class VoidOnNotFoundOr404OrUnableToFindAccountOwner implements FutureFallback<Void> {
|
public static final class VoidOnNotFoundOr404OrUnableToFindAccountOwner implements Fallback<Void> {
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Void> create(final Throwable t) {
|
public ListenableFuture<Void> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void createOrPropagate(Throwable t) throws Exception {
|
||||||
IllegalStateException e = getFirstThrowableOfType(checkNotNull(t, "throwable"), IllegalStateException.class);
|
IllegalStateException e = getFirstThrowableOfType(checkNotNull(t, "throwable"), IllegalStateException.class);
|
||||||
if (e != null && e.getMessage().indexOf("Unable to find account owner for") != -1) {
|
if (e != null && e.getMessage().indexOf("Unable to find account owner for") != -1) {
|
||||||
return immediateFuture(null);
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return Fallbacks.valOnNotFoundOr404(null, t);
|
return valOnNotFoundOr404(null, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.cloudwatch;
|
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_AUTH_TAG;
|
||||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||||
|
|
||||||
|
@ -59,7 +57,6 @@ public class CloudWatchApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
|
|
||||||
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
||||||
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.ec2;
|
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_AUTH_TAG;
|
||||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||||
import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
|
import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
|
||||||
|
@ -81,8 +79,6 @@ public class EC2ApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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_AUTH_TAG, "AWS");
|
||||||
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
||||||
properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "*");
|
properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "*");
|
||||||
|
|
|
@ -23,24 +23,29 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Throwables.propagate;
|
import static com.google.common.base.Throwables.propagate;
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
import org.jclouds.aws.AWSResponseException;
|
import org.jclouds.aws.AWSResponseException;
|
||||||
|
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
public final class EC2Fallbacks {
|
public final class EC2Fallbacks {
|
||||||
private EC2Fallbacks() {
|
private EC2Fallbacks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class VoidOnVolumeAvailable implements FutureFallback<Object> {
|
public static final class VoidOnVolumeAvailable implements Fallback<Void> {
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Object> create(final Throwable t) {
|
public ListenableFuture<Void> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void createOrPropagate(Throwable t) throws Exception {
|
||||||
if (checkNotNull(t, "throwable") instanceof AWSResponseException) {
|
if (checkNotNull(t, "throwable") instanceof AWSResponseException) {
|
||||||
AWSResponseException e = AWSResponseException.class.cast(t);
|
AWSResponseException e = AWSResponseException.class.cast(t);
|
||||||
if (Predicates.in(ImmutableSet.of("IncorrectState", "available")).apply(e.getError().getCode()))
|
if (Predicates.in(ImmutableSet.of("IncorrectState", "available")).apply(e.getError().getCode()))
|
||||||
return immediateFuture(null);
|
return null;
|
||||||
}
|
}
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.elasticstack;
|
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.elasticstack.reference.ElasticStackConstants.PROPERTY_VNC_PASSWORD;
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
|
||||||
|
@ -63,10 +61,6 @@ public class ElasticStackApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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");
|
properties.setProperty(PROPERTY_VNC_PASSWORD, "IL9vs34d");
|
||||||
// passwords are set post-boot, so auth failures are possible
|
// passwords are set post-boot, so auth failures are possible
|
||||||
// from a race condition applying the password set script
|
// from a race condition applying the password set script
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.cinder.v1;
|
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.CREDENTIAL_TYPE;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_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() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
|
|
||||||
properties.setProperty(SERVICE_TYPE, ServiceType.BLOCK_STORAGE);
|
properties.setProperty(SERVICE_TYPE, ServiceType.BLOCK_STORAGE);
|
||||||
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0;
|
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.CREDENTIAL_TYPE;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_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() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
||||||
properties.setProperty(SERVICE_TYPE, ServiceType.IDENTITY);
|
properties.setProperty(SERVICE_TYPE, ServiceType.IDENTITY);
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,27 +18,33 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0;
|
package org.jclouds.openstack.keystone.v2_0;
|
||||||
|
|
||||||
import org.jclouds.Fallbacks;
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
import static org.jclouds.Fallbacks.valOnNotFoundOr404;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
|
import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
|
||||||
import org.jclouds.openstack.v2_0.domain.Link;
|
import org.jclouds.openstack.v2_0.domain.Link;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
public final class KeystoneFallbacks {
|
public final class KeystoneFallbacks {
|
||||||
private KeystoneFallbacks() {
|
private KeystoneFallbacks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class EmptyPaginatedCollectionOnNotFoundOr404 implements
|
public static final class EmptyPaginatedCollectionOnNotFoundOr404 implements Fallback<PaginatedCollection<Object>> {
|
||||||
FutureFallback<PaginatedCollection<Object>> {
|
|
||||||
private static final PaginatedCollection<Object> EMPTY = new PaginatedCollection<Object>(
|
private static final PaginatedCollection<Object> EMPTY = new PaginatedCollection<Object>(
|
||||||
ImmutableSet.<Object> of(), ImmutableSet.<Link> of()) {
|
ImmutableSet.<Object> of(), ImmutableSet.<Link> of()) {
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<PaginatedCollection<Object>> create(Throwable t) {
|
public ListenableFuture<PaginatedCollection<Object>> create(Throwable t) throws Exception {
|
||||||
return Fallbacks.valOnNotFoundOr404(EMPTY, t);
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PaginatedCollection<Object> createOrPropagate(Throwable t) throws Exception {
|
||||||
|
return valOnNotFoundOr404(EMPTY, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.nova.v2_0;
|
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.CREDENTIAL_TYPE;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_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;
|
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() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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
|
// auth fail can happen while cloud-init applies keypair updates
|
||||||
properties.setProperty("jclouds.ssh.max-retries", "7");
|
properties.setProperty("jclouds.ssh.max-retries", "7");
|
||||||
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rackspace.cloudloadbalancers;
|
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.CREDENTIAL_TYPE;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
|
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
@ -67,7 +65,6 @@ public class CloudLoadBalancersApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(1) + "");
|
|
||||||
properties.setProperty(SERVICE_TYPE, ServiceType.LOAD_BALANCERS);
|
properties.setProperty(SERVICE_TYPE, ServiceType.LOAD_BALANCERS);
|
||||||
properties.setProperty(CREDENTIAL_TYPE, CloudIdentityCredentialTypes.API_KEY_CREDENTIALS);
|
properties.setProperty(CREDENTIAL_TYPE, CloudIdentityCredentialTypes.API_KEY_CREDENTIALS);
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,10 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.s3;
|
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_API_VERSION;
|
||||||
import static org.jclouds.Constants.PROPERTY_RELAX_HOSTNAME;
|
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_AUTH_TAG;
|
||||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||||
import static org.jclouds.blobstore.reference.BlobStoreConstants.DIRECTORY_SUFFIX_FOLDER;
|
import static org.jclouds.blobstore.reference.BlobStoreConstants.DIRECTORY_SUFFIX_FOLDER;
|
||||||
|
@ -84,11 +82,6 @@ public class S3ApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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_API_VERSION, S3AsyncClient.VERSION);
|
||||||
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
||||||
properties.setProperty(PROPERTY_HEADER_TAG, S3Headers.DEFAULT_AMAZON_HEADERTAG);
|
properties.setProperty(PROPERTY_HEADER_TAG, S3Headers.DEFAULT_AMAZON_HEADERTAG);
|
||||||
|
|
|
@ -25,24 +25,29 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
|
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
|
||||||
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
|
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
import org.jclouds.blobstore.ContainerNotFoundException;
|
import org.jclouds.blobstore.ContainerNotFoundException;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
public final class S3Fallbacks {
|
public final class S3Fallbacks {
|
||||||
private S3Fallbacks() {
|
private S3Fallbacks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class TrueOn404OrNotFoundFalseOnIllegalState implements FutureFallback<Boolean> {
|
public static final class TrueOn404OrNotFoundFalseOnIllegalState implements Fallback<Boolean> {
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Boolean> create(final Throwable t) {
|
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean createOrPropagate(Throwable t) throws Exception {
|
||||||
if (getFirstThrowableOfType(checkNotNull(t, "throwable"), IllegalStateException.class) != null)
|
if (getFirstThrowableOfType(checkNotNull(t, "throwable"), IllegalStateException.class) != null)
|
||||||
return immediateFuture(false);
|
return false;
|
||||||
if (getFirstThrowableOfType(t, ContainerNotFoundException.class) != null)
|
if (getFirstThrowableOfType(t, ContainerNotFoundException.class) != null)
|
||||||
return immediateFuture(true);
|
return true;
|
||||||
if (returnValueOnCodeOrNull(t, true, equalTo(404)) != null)
|
if (returnValueOnCodeOrNull(t, true, equalTo(404)) != null)
|
||||||
return immediateFuture(true);
|
return true;
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,20 +26,20 @@ import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
import org.jclouds.aws.AWSResponseException;
|
import org.jclouds.aws.AWSResponseException;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.rest.InvocationContext;
|
import org.jclouds.rest.InvocationContext;
|
||||||
import org.jclouds.s3.S3Client;
|
import org.jclouds.s3.S3Client;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists implements FutureFallback<Boolean>,
|
public class FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists implements Fallback<Boolean>,
|
||||||
InvocationContext<FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists> {
|
InvocationContext<FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists> {
|
||||||
|
|
||||||
private final S3Client client;
|
private final S3Client client;
|
||||||
|
@ -51,14 +51,19 @@ public class FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists im
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Boolean> create(final Throwable t) {
|
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean createOrPropagate(Throwable t) throws Exception {
|
||||||
AWSResponseException exception = getFirstThrowableOfType(checkNotNull(t, "throwable"), AWSResponseException.class);
|
AWSResponseException exception = getFirstThrowableOfType(checkNotNull(t, "throwable"), AWSResponseException.class);
|
||||||
if (exception != null && exception.getError() != null && exception.getError().getCode() != null) {
|
if (exception != null && exception.getError() != null && exception.getError().getCode() != null) {
|
||||||
String code = exception.getError().getCode();
|
String code = exception.getError().getCode();
|
||||||
if (code.equals("BucketAlreadyOwnedByYou"))
|
if (code.equals("BucketAlreadyOwnedByYou"))
|
||||||
return immediateFuture(false);
|
return false;
|
||||||
else if (code.equals("OperationAborted") && bucket != null && client.bucketExists(bucket))
|
else if (code.equals("OperationAborted") && bucket != null && client.bucketExists(bucket))
|
||||||
return immediateFuture(false);
|
return false;
|
||||||
}
|
}
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.sqs;
|
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_AUTH_TAG;
|
||||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||||
import static org.jclouds.sqs.config.SQSProperties.CREATE_QUEUE_MAX_RETRIES;
|
import static org.jclouds.sqs.config.SQSProperties.CREATE_QUEUE_MAX_RETRIES;
|
||||||
|
@ -63,9 +61,6 @@ public class SQSApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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_MAX_RETRIES, "60");
|
||||||
properties.setProperty(CREATE_QUEUE_RETRY_INTERVAL, "1000");
|
properties.setProperty(CREATE_QUEUE_RETRY_INTERVAL, "1000");
|
||||||
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.sts;
|
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_AUTH_TAG;
|
||||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||||
|
|
||||||
|
@ -27,9 +25,9 @@ import java.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.apis.ApiMetadata;
|
import org.jclouds.apis.ApiMetadata;
|
||||||
import org.jclouds.sts.config.STSRestClientModule;
|
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
||||||
|
import org.jclouds.sts.config.STSRestClientModule;
|
||||||
|
|
||||||
import com.google.common.reflect.TypeToken;
|
import com.google.common.reflect.TypeToken;
|
||||||
|
|
||||||
|
@ -59,7 +57,6 @@ public class STSApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
|
|
||||||
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
||||||
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.swift;
|
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.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
||||||
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
@ -67,12 +64,6 @@ public class SwiftApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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_USER_METADATA_PREFIX, "X-Object-Meta-");
|
||||||
properties.setProperty(PROPERTY_REGIONS, "DEFAULT");
|
properties.setProperty(PROPERTY_REGIONS, "DEFAULT");
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -25,20 +25,26 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
import static org.jclouds.http.HttpUtils.contains404;
|
import static org.jclouds.http.HttpUtils.contains404;
|
||||||
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
|
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
import org.jclouds.Fallback;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
public final class SwiftFallbacks {
|
public final class SwiftFallbacks {
|
||||||
private SwiftFallbacks() {
|
private SwiftFallbacks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class TrueOn404FalseOn409 implements FutureFallback<Boolean> {
|
public static final class TrueOn404FalseOn409 implements Fallback<Boolean> {
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Boolean> create(final Throwable t) {
|
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean createOrPropagate(Throwable t) throws Exception {
|
||||||
if (contains404(checkNotNull(t, "throwable")))
|
if (contains404(checkNotNull(t, "throwable")))
|
||||||
return immediateFuture(true);
|
return true;
|
||||||
if (returnValueOnCodeOrNull(t, false, equalTo(409)) != null)
|
if (returnValueOnCodeOrNull(t, false, equalTo(409)) != null)
|
||||||
return immediateFuture(false);
|
return false;
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,9 +47,8 @@ import org.jclouds.openstack.swift.TemporaryUrlKey;
|
||||||
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
|
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
|
||||||
import org.jclouds.openstack.swift.domain.SwiftObject;
|
import org.jclouds.openstack.swift.domain.SwiftObject;
|
||||||
import org.jclouds.reflect.Invocation;
|
import org.jclouds.reflect.Invocation;
|
||||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
@ -64,7 +63,7 @@ import com.google.inject.Provider;
|
||||||
@Singleton
|
@Singleton
|
||||||
public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRequestSigner {
|
public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRequestSigner {
|
||||||
|
|
||||||
private final RestAnnotationProcessor processor;
|
private final Function<Invocation, HttpRequest> processor;
|
||||||
private final Crypto crypto;
|
private final Crypto crypto;
|
||||||
|
|
||||||
private final Provider<Long> unixEpochTimestampProvider;
|
private final Provider<Long> unixEpochTimestampProvider;
|
||||||
|
@ -86,8 +85,9 @@ public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRe
|
||||||
@Inject
|
@Inject
|
||||||
protected SwiftBlobSigner(BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto,
|
protected SwiftBlobSigner(BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto,
|
||||||
@TimeStamp Provider<Long> unixEpochTimestampProvider,
|
@TimeStamp Provider<Long> unixEpochTimestampProvider,
|
||||||
@TemporaryUrlKey Supplier<String> temporaryUrlKeySupplier, RestAnnotationProcessor processor,
|
@TemporaryUrlKey Supplier<String> temporaryUrlKeySupplier,
|
||||||
Class<T> ownerType) throws SecurityException, NoSuchMethodException {
|
Function<Invocation, HttpRequest> processor, Class<T> ownerType) throws SecurityException,
|
||||||
|
NoSuchMethodException {
|
||||||
this.processor = checkNotNull(processor, "processor");
|
this.processor = checkNotNull(processor, "processor");
|
||||||
this.crypto = checkNotNull(crypto, "crypto");
|
this.crypto = checkNotNull(crypto, "crypto");
|
||||||
|
|
||||||
|
@ -112,8 +112,7 @@ public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRe
|
||||||
public HttpRequest signGetBlob(String container, String name, long timeInSeconds) {
|
public HttpRequest signGetBlob(String container, String name, long timeInSeconds) {
|
||||||
checkNotNull(container, "container");
|
checkNotNull(container, "container");
|
||||||
checkNotNull(name, "name");
|
checkNotNull(name, "name");
|
||||||
GeneratedHttpRequest request = processor.apply(Invocation.create(getMethod,
|
HttpRequest request = processor.apply(Invocation.create(getMethod, ImmutableList.<Object> of(container, name)));
|
||||||
ImmutableList.<Object> of(container, name)));
|
|
||||||
return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
|
return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +136,7 @@ public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRe
|
||||||
public HttpRequest signPutBlob(String container, Blob blob, long timeInSeconds) {
|
public HttpRequest signPutBlob(String container, Blob blob, long timeInSeconds) {
|
||||||
checkNotNull(container, "container");
|
checkNotNull(container, "container");
|
||||||
checkNotNull(blob, "blob");
|
checkNotNull(blob, "blob");
|
||||||
GeneratedHttpRequest request = processor.apply(Invocation.create(createMethod,
|
HttpRequest request = processor.apply(Invocation.create(createMethod,
|
||||||
ImmutableList.<Object> of(container, blobToObject.apply(blob))));
|
ImmutableList.<Object> of(container, blobToObject.apply(blob))));
|
||||||
return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
|
return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,7 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.vcloud;
|
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_SESSION_INTERVAL;
|
||||||
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
|
|
||||||
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
|
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_FENCEMODE;
|
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_FENCEMODE;
|
||||||
|
@ -69,9 +67,6 @@ public class VCloudApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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_VERSION_SCHEMA, "1");
|
||||||
properties.setProperty(PROPERTY_VCLOUD_XML_NAMESPACE,
|
properties.setProperty(PROPERTY_VCLOUD_XML_NAMESPACE,
|
||||||
String.format("http://www.vmware.com/vcloud/v${%s}", PROPERTY_VCLOUD_VERSION_SCHEMA));
|
String.format("http://www.vmware.com/vcloud/v${%s}", PROPERTY_VCLOUD_VERSION_SCHEMA));
|
||||||
|
|
|
@ -23,20 +23,20 @@ import static com.google.common.base.Throwables.propagate;
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
import static org.jclouds.http.HttpUtils.contains404;
|
import static org.jclouds.http.HttpUtils.contains404;
|
||||||
|
|
||||||
import org.jclouds.blobstore.ContainerNotFoundException;
|
import org.jclouds.Fallback;
|
||||||
import org.jclouds.blobstore.KeyNotFoundException;
|
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
public final class BlobStoreFallbacks {
|
public final class BlobStoreFallbacks {
|
||||||
private BlobStoreFallbacks() {
|
private BlobStoreFallbacks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class ThrowContainerNotFoundOn404 implements FutureFallback<Object> {
|
public static final class ThrowContainerNotFoundOn404 implements Fallback<Object> {
|
||||||
|
public ListenableFuture<Object> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public Object createOrPropagate(Throwable t) throws Exception {
|
||||||
public ListenableFuture<Object> create(Throwable t) {
|
|
||||||
if (contains404(checkNotNull(t, "throwable")))
|
if (contains404(checkNotNull(t, "throwable")))
|
||||||
throw new ContainerNotFoundException(t);
|
throw new ContainerNotFoundException(t);
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
|
@ -44,10 +44,12 @@ public final class BlobStoreFallbacks {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class ThrowKeyNotFoundOn404 implements FutureFallback<Object> {
|
public static final class ThrowKeyNotFoundOn404 implements Fallback<Object> {
|
||||||
|
public ListenableFuture<Object> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public Object createOrPropagate(Throwable t) throws Exception {
|
||||||
public ListenableFuture<Object> create(Throwable t) {
|
|
||||||
if (contains404(checkNotNull(t, "throwable")))
|
if (contains404(checkNotNull(t, "throwable")))
|
||||||
throw new KeyNotFoundException(t);
|
throw new KeyNotFoundException(t);
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
|
@ -55,45 +57,53 @@ public final class BlobStoreFallbacks {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class FalseOnContainerNotFound implements FutureFallback<Boolean> {
|
public static final class FalseOnContainerNotFound implements Fallback<Boolean> {
|
||||||
|
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public Boolean createOrPropagate(Throwable t) throws Exception {
|
||||||
public ListenableFuture<Boolean> create(Throwable t) {
|
|
||||||
if (checkNotNull(t, "throwable") instanceof ContainerNotFoundException) {
|
if (checkNotNull(t, "throwable") instanceof ContainerNotFoundException) {
|
||||||
return immediateFuture(false);
|
return false;
|
||||||
}
|
}
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class FalseOnKeyNotFound implements FutureFallback<Boolean> {
|
public static final class FalseOnKeyNotFound implements Fallback<Boolean> {
|
||||||
|
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public Boolean createOrPropagate(Throwable t) throws Exception {
|
||||||
public ListenableFuture<Boolean> create(Throwable t) {
|
|
||||||
if (checkNotNull(t, "throwable") instanceof KeyNotFoundException) {
|
if (checkNotNull(t, "throwable") instanceof KeyNotFoundException) {
|
||||||
return immediateFuture(false);
|
return false;
|
||||||
}
|
}
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class NullOnContainerNotFound implements FutureFallback<Object> {
|
public static final class NullOnContainerNotFound implements Fallback<Object> {
|
||||||
|
public ListenableFuture<Object> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public Object createOrPropagate(Throwable t) throws Exception {
|
||||||
public ListenableFuture<Object> create(Throwable t) {
|
|
||||||
if (checkNotNull(t, "throwable") instanceof ContainerNotFoundException) {
|
if (checkNotNull(t, "throwable") instanceof ContainerNotFoundException) {
|
||||||
return immediateFuture(null);
|
return null;
|
||||||
}
|
}
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class NullOnKeyNotFound implements FutureFallback<Object> {
|
public static final class NullOnKeyNotFound implements Fallback<Object> {
|
||||||
|
public ListenableFuture<Object> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public Object createOrPropagate(Throwable t) throws Exception {
|
||||||
public ListenableFuture<Object> create(Throwable t) {
|
|
||||||
if (checkNotNull(t, "throwable") instanceof KeyNotFoundException) {
|
if (checkNotNull(t, "throwable") instanceof KeyNotFoundException) {
|
||||||
return immediateFuture(null);
|
return null;
|
||||||
}
|
}
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,10 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
public final class TerremarkVCloudFallbacks {
|
public final class TerremarkVCloudFallbacks {
|
||||||
|
@ -40,19 +40,24 @@ public final class TerremarkVCloudFallbacks {
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public static final class VoidOnDeleteDefaultIp implements FutureFallback<Void> {
|
public static final class VoidOnDeleteDefaultIp implements Fallback<Void> {
|
||||||
public static final Pattern MESSAGE_PATTERN = Pattern
|
public static final Pattern MESSAGE_PATTERN = Pattern
|
||||||
.compile(".*Cannot release this Public IP as it is default oubound IP.*");
|
.compile(".*Cannot release this Public IP as it is default oubound IP.*");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Void> create(final Throwable t) {
|
public ListenableFuture<Void> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void createOrPropagate(Throwable t) throws Exception {
|
||||||
if (checkNotNull(t, "throwable") instanceof HttpResponseException) {
|
if (checkNotNull(t, "throwable") instanceof HttpResponseException) {
|
||||||
HttpResponseException hre = HttpResponseException.class.cast(t);
|
HttpResponseException hre = HttpResponseException.class.cast(t);
|
||||||
if (hre.getResponse().getStatusCode() == 503 || hre.getResponse().getStatusCode() == 401
|
if (hre.getResponse().getStatusCode() == 503 || hre.getResponse().getStatusCode() == 401
|
||||||
|| MESSAGE_PATTERN.matcher(hre.getMessage()).matches())
|
|| MESSAGE_PATTERN.matcher(hre.getMessage()).matches())
|
||||||
return immediateFuture(null);
|
return null;
|
||||||
} else if (t instanceof AuthorizationException) {
|
} else if (t instanceof AuthorizationException) {
|
||||||
return immediateFuture(null);
|
return null;
|
||||||
}
|
}
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package org.jclouds.trmk.vcloud_0_8.internal;
|
package org.jclouds.trmk.vcloud_0_8.internal;
|
||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
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_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_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_NS;
|
||||||
import static org.jclouds.trmk.vcloud_0_8.reference.TerremarkConstants.PROPERTY_TERREMARK_EXTENSION_VERSION;
|
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() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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_VCLOUD_VERSION_SCHEMA, "0.8");
|
||||||
properties.setProperty(PROPERTY_SESSION_INTERVAL, 8 * 60 + "");
|
properties.setProperty(PROPERTY_SESSION_INTERVAL, 8 * 60 + "");
|
||||||
properties.setProperty(PROPERTY_VCLOUD_XML_SCHEMA, "http://vcloud.safesecureweb.com/ns/vcloud.xsd");
|
properties.setProperty(PROPERTY_VCLOUD_XML_SCHEMA, "http://vcloud.safesecureweb.com/ns/vcloud.xsd");
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -40,7 +40,6 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,123 +50,153 @@ public final class Fallbacks {
|
||||||
private Fallbacks() {
|
private Fallbacks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class NullOnNotFoundOr404 implements FutureFallback<Object> {
|
public static final class NullOnNotFoundOr404 implements Fallback<Object> {
|
||||||
|
public ListenableFuture<Object> create(Throwable t) throws Exception {
|
||||||
@Override
|
return immediateFuture(createOrPropagate(t));
|
||||||
public ListenableFuture<Object> create(Throwable t) {
|
|
||||||
return valOnNotFoundOr404(null, checkNotNull(t, "throwable"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
public Object createOrPropagate(Throwable t) throws Exception {
|
||||||
|
|
||||||
public static final class VoidOnNotFoundOr404 implements FutureFallback<Void> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ListenableFuture<Void> create(Throwable t) {
|
|
||||||
return valOnNotFoundOr404(null, checkNotNull(t, "throwable"));
|
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 Void createOrPropagate(Throwable t) throws Exception {
|
||||||
public ListenableFuture<Boolean> create(Throwable t) {
|
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"));
|
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 Boolean createOrPropagate(Throwable t) throws Exception {
|
||||||
public ListenableFuture<Boolean> create(Throwable t) {
|
|
||||||
return valOnNotFoundOr404(false, checkNotNull(t, "throwable"));
|
return valOnNotFoundOr404(false, checkNotNull(t, "throwable"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class FalseOnNotFoundOr422 implements FutureFallback<Boolean> {
|
public static final class FalseOnNotFoundOr422 implements Fallback<Boolean> {
|
||||||
|
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
|
||||||
@Override
|
return immediateFuture(createOrPropagate(t));
|
||||||
public ListenableFuture<Boolean> create(Throwable t) {
|
|
||||||
if (containsResourceNotFoundException(checkNotNull(t, "throwable"))
|
|
||||||
|| returnValueOnCodeOrNull(t, true, equalTo(422)) != null)
|
|
||||||
return immediateFuture(false);
|
|
||||||
throw propagate(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
|
* @author Leander Beernaert
|
||||||
*/
|
*/
|
||||||
public static final class AbsentOn403Or404Or500 implements FutureFallback<Optional<Object>> {
|
public static final class AbsentOn403Or404Or500 implements Fallback<Optional<Object>> {
|
||||||
@Override
|
public ListenableFuture<Optional<Object>> create(Throwable t) throws Exception {
|
||||||
public ListenableFuture<Optional<Object>> create(Throwable t) {
|
return immediateFuture(createOrPropagate(t));
|
||||||
Boolean returnVal = returnValueOnCodeOrNull(checkNotNull(t, "throwable"), true, in(asList(403, 404, 500)));
|
|
||||||
if (returnVal != null)
|
|
||||||
return immediateFuture(Optional.absent());
|
|
||||||
throw propagate(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>> {
|
public static final class EmptyFluentIterableOnNotFoundOr404 implements Fallback<FluentIterable<Object>> {
|
||||||
@Override
|
public ListenableFuture<FluentIterable<Object>> create(Throwable t) throws Exception {
|
||||||
public ListenableFuture<FluentIterable<Object>> create(Throwable t) {
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
public FluentIterable<Object> createOrPropagate(Throwable t) throws Exception {
|
||||||
return valOnNotFoundOr404(FluentIterable.from(ImmutableSet.of()), checkNotNull(t, "throwable"));
|
return valOnNotFoundOr404(FluentIterable.from(ImmutableSet.of()), checkNotNull(t, "throwable"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class EmptyIterableWithMarkerOnNotFoundOr404 implements
|
public static final class EmptyIterableWithMarkerOnNotFoundOr404 implements Fallback<IterableWithMarker<Object>> {
|
||||||
FutureFallback<IterableWithMarker<Object>> {
|
public ListenableFuture<IterableWithMarker<Object>> create(Throwable t) throws Exception {
|
||||||
@Override
|
return immediateFuture(createOrPropagate(t));
|
||||||
public ListenableFuture<IterableWithMarker<Object>> create(Throwable t) {
|
}
|
||||||
|
|
||||||
|
public IterableWithMarker<Object> createOrPropagate(Throwable t) throws Exception {
|
||||||
return valOnNotFoundOr404(IterableWithMarkers.from(ImmutableSet.of()), checkNotNull(t, "throwable"));
|
return valOnNotFoundOr404(IterableWithMarkers.from(ImmutableSet.of()), checkNotNull(t, "throwable"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class EmptyPagedIterableOnNotFoundOr404 implements FutureFallback<PagedIterable<Object>> {
|
public static final class EmptyPagedIterableOnNotFoundOr404 implements Fallback<PagedIterable<Object>> {
|
||||||
@Override
|
public ListenableFuture<PagedIterable<Object>> create(Throwable t) throws Exception {
|
||||||
public ListenableFuture<PagedIterable<Object>> create(Throwable t) {
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PagedIterable<Object> createOrPropagate(Throwable t) throws Exception {
|
||||||
return valOnNotFoundOr404(PagedIterables.of(IterableWithMarkers.from(ImmutableSet.of())),
|
return valOnNotFoundOr404(PagedIterables.of(IterableWithMarkers.from(ImmutableSet.of())),
|
||||||
checkNotNull(t, "throwable"));
|
checkNotNull(t, "throwable"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class EmptyListOnNotFoundOr404 implements FutureFallback<ImmutableList<Object>> { // NO_UCD (unused code)
|
public static final class EmptyListOnNotFoundOr404 implements Fallback<ImmutableList<Object>> { // NO_UCD
|
||||||
@Override
|
// (unused
|
||||||
public ListenableFuture<ImmutableList<Object>> create(Throwable t) {
|
// 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"));
|
return valOnNotFoundOr404(ImmutableList.of(), checkNotNull(t, "throwable"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class EmptySetOnNotFoundOr404 implements FutureFallback<ImmutableSet<Object>> {
|
public static final class EmptySetOnNotFoundOr404 implements Fallback<ImmutableSet<Object>> {
|
||||||
@Override
|
public ListenableFuture<ImmutableSet<Object>> create(Throwable t) throws Exception {
|
||||||
public ListenableFuture<ImmutableSet<Object>> create(Throwable t) {
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImmutableSet<Object> createOrPropagate(Throwable t) throws Exception {
|
||||||
return valOnNotFoundOr404(ImmutableSet.of(), checkNotNull(t, "throwable"));
|
return valOnNotFoundOr404(ImmutableSet.of(), checkNotNull(t, "throwable"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class EmptyMapOnNotFoundOr404 implements FutureFallback<ImmutableMap<Object, Object>> {
|
public static final class EmptyMapOnNotFoundOr404 implements Fallback<ImmutableMap<Object, Object>> {
|
||||||
@Override
|
public ListenableFuture<ImmutableMap<Object, Object>> create(Throwable t) throws Exception {
|
||||||
public ListenableFuture<ImmutableMap<Object, Object>> create(Throwable t) {
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImmutableMap<Object, Object> createOrPropagate(Throwable t) throws Exception {
|
||||||
return valOnNotFoundOr404(ImmutableMap.of(), checkNotNull(t, "throwable"));
|
return valOnNotFoundOr404(ImmutableMap.of(), checkNotNull(t, "throwable"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class EmptyMultimapOnNotFoundOr404 implements FutureFallback<ImmutableMultimap<Object, Object>> { // NO_UCD (unused code)
|
public static final class EmptyMultimapOnNotFoundOr404 implements Fallback<ImmutableMultimap<Object, Object>> { // NO_UCD
|
||||||
@Override
|
// (unused
|
||||||
public ListenableFuture<ImmutableMultimap<Object, Object>> create(Throwable t) {
|
// 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"));
|
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))
|
if (containsResourceNotFoundException(checkNotNull(t, "throwable")) || contains404(t))
|
||||||
return immediateFuture(val);
|
return val;
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,9 @@ import org.jclouds.lifecycle.Closer;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
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.ThreadFactoryBuilder;
|
||||||
|
import com.google.common.util.concurrent.TimeLimiter;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
@ -98,6 +100,12 @@ public class ExecutorServiceModule extends AbstractModule {
|
||||||
protected void configure() { // NO_UCD
|
protected void configure() { // NO_UCD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
TimeLimiter timeLimiter(@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor){
|
||||||
|
return new SimpleTimeLimiter(userExecutor);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named(PROPERTY_USER_THREADS)
|
@Named(PROPERTY_USER_THREADS)
|
||||||
|
|
|
@ -20,15 +20,16 @@ package org.jclouds.fallbacks;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Throwables.propagate;
|
import static com.google.common.base.Throwables.propagate;
|
||||||
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.jclouds.rest.ResourceNotFoundException;
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,7 +37,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public final class MapHttp4xxCodesToExceptions implements FutureFallback<Object> {
|
public final class MapHttp4xxCodesToExceptions implements Fallback<Object> {
|
||||||
|
|
||||||
private final PropagateIfRetryAfter propagateIfRetryAfter;
|
private final PropagateIfRetryAfter propagateIfRetryAfter;
|
||||||
|
|
||||||
|
@ -46,7 +47,12 @@ public final class MapHttp4xxCodesToExceptions implements FutureFallback<Object>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
propagateIfRetryAfter.create(t); // if we pass here, we aren't a retry-after exception
|
||||||
if (t instanceof HttpResponseException) {
|
if (t instanceof HttpResponseException) {
|
||||||
HttpResponseException responseException = HttpResponseException.class.cast(t);
|
HttpResponseException responseException = HttpResponseException.class.cast(t);
|
||||||
|
|
|
@ -27,15 +27,21 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public interface HttpCommandExecutorService {
|
public interface HttpCommandExecutorService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks the command to build a request relevant for an endpoint that produces responses of
|
* Returns a potentially deferred {@code HttpResponse} from a server responding to the
|
||||||
* generic type {@code HttpResponse}. and invokes it on the endpoint, returning a future
|
* {@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);
|
ListenableFuture<HttpResponse> submit(HttpCommand command);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code HttpResponse} from the server which responded to the
|
||||||
|
* {@code command}.
|
||||||
|
*/
|
||||||
|
HttpResponse invoke(HttpCommand command);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,12 @@
|
||||||
package org.jclouds.http.internal;
|
package org.jclouds.http.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
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.copy;
|
||||||
import static com.google.common.io.ByteStreams.nullOutputStream;
|
import static com.google.common.io.ByteStreams.nullOutputStream;
|
||||||
import static org.jclouds.http.HttpUtils.checkRequestHasContentLengthOrChunkedEncoding;
|
import static org.jclouds.http.HttpUtils.checkRequestHasContentLengthOrChunkedEncoding;
|
||||||
import static org.jclouds.http.HttpUtils.wirePayloadIfEnabled;
|
import static org.jclouds.http.HttpUtils.wirePayloadIfEnabled;
|
||||||
|
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
|
||||||
|
|
||||||
import java.io.FilterInputStream;
|
import java.io.FilterInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -46,7 +48,6 @@ import org.jclouds.http.handlers.DelegatingErrorHandler;
|
||||||
import org.jclouds.http.handlers.DelegatingRetryHandler;
|
import org.jclouds.http.handlers.DelegatingRetryHandler;
|
||||||
import org.jclouds.io.ContentMetadataCodec;
|
import org.jclouds.io.ContentMetadataCodec;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.util.Throwables2;
|
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
@ -58,11 +59,11 @@ import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandExecutorService {
|
public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandExecutorService {
|
||||||
protected final HttpUtils utils;
|
protected final HttpUtils utils;
|
||||||
protected final ContentMetadataCodec contentMetadataCodec;
|
protected final ContentMetadataCodec contentMetadataCodec;
|
||||||
|
|
||||||
private final DelegatingRetryHandler retryHandler;
|
protected final DelegatingRetryHandler retryHandler;
|
||||||
private final IOExceptionRetryHandler ioRetryHandler;
|
protected final IOExceptionRetryHandler ioRetryHandler;
|
||||||
private final DelegatingErrorHandler errorHandler;
|
protected final DelegatingErrorHandler errorHandler;
|
||||||
private final ListeningExecutorService ioExecutor;
|
protected final ListeningExecutorService ioExecutor;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
@ -74,9 +75,9 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected BaseHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
|
protected BaseHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
|
||||||
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
|
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
|
||||||
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
|
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
|
||||||
DelegatingErrorHandler errorHandler, HttpWire wire) {
|
DelegatingErrorHandler errorHandler, HttpWire wire) {
|
||||||
this.utils = checkNotNull(utils, "utils");
|
this.utils = checkNotNull(utils, "utils");
|
||||||
this.contentMetadataCodec = checkNotNull(contentMetadataCodec, "contentMetadataCodec");
|
this.contentMetadataCodec = checkNotNull(contentMetadataCodec, "contentMetadataCodec");
|
||||||
this.retryHandler = checkNotNull(retryHandler, "retryHandler");
|
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
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||||
HttpRequest request = command.getCurrentRequest();
|
HttpRequest request = command.getCurrentRequest();
|
||||||
checkRequestHasContentLengthOrChunkedEncoding(request,
|
checkRequestHasContentLengthOrChunkedEncoding(request,
|
||||||
"if the request has a payload, it must be set to chunked encoding or specify a content length: "
|
"if the request has a payload, it must be set to chunked encoding or specify a content length: " + request);
|
||||||
+ request);
|
|
||||||
return ioExecutor.submit(new HttpResponseCallable(command));
|
return ioExecutor.submit(new HttpResponseCallable(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,63 +200,12 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpResponse call() throws Exception {
|
public HttpResponse call() throws Exception {
|
||||||
|
try {
|
||||||
HttpResponse response = null;
|
return invoke(command);
|
||||||
for (;;) {
|
} finally {
|
||||||
HttpRequest request = command.getCurrentRequest();
|
if (command.getException() != null)
|
||||||
Q nativeRequest = null;
|
throw command.getException();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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
|
@Override
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
package org.jclouds.rest;
|
package org.jclouds.rest;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.collect.Collections2.filter;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -29,7 +28,6 @@ import org.jclouds.predicates.Validator;
|
||||||
import org.jclouds.reflect.Invocation;
|
import org.jclouds.reflect.Invocation;
|
||||||
import org.jclouds.rest.annotations.ParamValidators;
|
import org.jclouds.rest.annotations.ParamValidators;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.reflect.Parameter;
|
import com.google.common.reflect.Parameter;
|
||||||
|
|
|
@ -24,10 +24,9 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.Target;
|
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
|
* @since 1.6
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -35,5 +34,5 @@ import com.google.common.util.concurrent.FutureFallback;
|
||||||
@Target(METHOD)
|
@Target(METHOD)
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public @interface Fallback {
|
public @interface Fallback {
|
||||||
Class<? extends FutureFallback<?>> value();
|
Class<? extends org.jclouds.Fallback<?>> value();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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, "");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.collect.Iterables.toArray;
|
import static com.google.common.collect.Iterables.toArray;
|
||||||
import static com.google.common.collect.Iterables.transform;
|
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 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.method;
|
||||||
import static org.jclouds.reflect.Reflection2.methods;
|
import static org.jclouds.reflect.Reflection2.methods;
|
||||||
import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
|
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.Proxy;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import javax.inject.Named;
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
|
||||||
import org.jclouds.functions.IdentityFunction;
|
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.http.functions.config.SaxParserModule;
|
||||||
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
|
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
|
||||||
import org.jclouds.json.config.GsonModule;
|
import org.jclouds.json.config.GsonModule;
|
||||||
import org.jclouds.location.config.LocationModule;
|
import org.jclouds.location.config.LocationModule;
|
||||||
import org.jclouds.proxy.ProxyForURI;
|
import org.jclouds.proxy.ProxyForURI;
|
||||||
|
import org.jclouds.reflect.Invocation;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.jclouds.rest.HttpAsyncClient;
|
import org.jclouds.rest.HttpAsyncClient;
|
||||||
import org.jclouds.rest.HttpClient;
|
import org.jclouds.rest.HttpClient;
|
||||||
import org.jclouds.rest.binders.BindToJsonPayloadWrappedWith;
|
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.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
@ -90,6 +90,21 @@ public class RestModule extends AbstractModule {
|
||||||
return seedKnownSync2AsyncInvokables(sync2Async);
|
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
|
@VisibleForTesting
|
||||||
static Cache<Invokable<?, ?>, Invokable<?, ?>> seedKnownSync2AsyncInvokables(Map<Class<?>, Class<?>> sync2Async) {
|
static Cache<Invokable<?, ?>, Invokable<?, ?>> seedKnownSync2AsyncInvokables(Map<Class<?>, Class<?>> sync2Async) {
|
||||||
Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncBuilder = CacheBuilder.newBuilder().build();
|
Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncBuilder = CacheBuilder.newBuilder().build();
|
||||||
|
@ -133,7 +148,12 @@ public class RestModule extends AbstractModule {
|
||||||
install(new GsonModule());
|
install(new GsonModule());
|
||||||
install(new SetCaller.Module());
|
install(new SetCaller.Module());
|
||||||
install(new FactoryModuleBuilder().build(BindToJsonPayloadWrappedWith.Factory.class));
|
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);
|
bind(IdentityFunction.class).toInstance(IdentityFunction.INSTANCE);
|
||||||
bindHttpApi(binder(), HttpClient.class, HttpAsyncClient.class);
|
bindHttpApi(binder(), HttpClient.class, HttpAsyncClient.class);
|
||||||
// this will help short circuit scenarios that can otherwise lock out users
|
// this will help short circuit scenarios that can otherwise lock out users
|
||||||
|
@ -145,23 +165,4 @@ public class RestModule extends AbstractModule {
|
||||||
}).to(ProxyForURI.class);
|
}).to(ProxyForURI.class);
|
||||||
installLocations();
|
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, "");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rest.internal;
|
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.base.Throwables.propagate;
|
||||||
import static com.google.common.util.concurrent.Futures.getUnchecked;
|
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.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.cache.Cache;
|
|
||||||
import com.google.common.reflect.Invokable;
|
import com.google.common.reflect.Invokable;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
@ -45,7 +43,7 @@ public final class InvokeAndCallGetOnFutures<R> implements Function<Invocation,
|
||||||
@Resource
|
@Resource
|
||||||
private Logger logger = Logger.NULL;
|
private Logger logger = Logger.NULL;
|
||||||
|
|
||||||
private final Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncInvokables;
|
private final Function<Invocation, Invocation> sync2async;
|
||||||
private final R receiver;
|
private final R receiver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,8 +53,8 @@ public final class InvokeAndCallGetOnFutures<R> implements Function<Invocation,
|
||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
InvokeAndCallGetOnFutures(Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncInvokables, R receiver) {
|
InvokeAndCallGetOnFutures(Function<Invocation, Invocation> sync2async, R receiver) {
|
||||||
this.sync2AsyncInvokables = sync2AsyncInvokables;
|
this.sync2async = sync2async;
|
||||||
this.receiver = receiver;
|
this.receiver = receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,8 +62,7 @@ public final class InvokeAndCallGetOnFutures<R> implements Function<Invocation,
|
||||||
@Override
|
@Override
|
||||||
public Object apply(Invocation in) {
|
public Object apply(Invocation in) {
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
Invokable target = checkNotNull(sync2AsyncInvokables.getIfPresent(in.getInvokable()), "invokable %s not in %s",
|
Invokable target = sync2async.apply(in).getInvokable();
|
||||||
in.getInvokable(), sync2AsyncInvokables);
|
|
||||||
Object returnVal;
|
Object returnVal;
|
||||||
try {
|
try {
|
||||||
returnVal = target.invoke(receiver, in.getArgs().toArray());
|
returnVal = target.invoke(receiver, in.getArgs().toArray());
|
||||||
|
|
|
@ -19,114 +19,240 @@
|
||||||
package org.jclouds.rest.internal;
|
package org.jclouds.rest.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Objects.equal;
|
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.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.transform;
|
||||||
import static com.google.common.util.concurrent.Futures.withFallback;
|
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.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
|
||||||
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
|
|
||||||
import org.jclouds.http.HttpCommand;
|
import org.jclouds.http.HttpCommand;
|
||||||
import org.jclouds.http.HttpCommandExecutorService;
|
import org.jclouds.http.HttpCommandExecutorService;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.reflect.Invocation;
|
import org.jclouds.reflect.Invocation;
|
||||||
import org.jclouds.rest.InvocationContext;
|
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.Function;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.cache.Cache;
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import com.google.common.cache.CacheLoader;
|
|
||||||
import com.google.common.cache.LoadingCache;
|
|
||||||
import com.google.common.reflect.Invokable;
|
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.ListenableFuture;
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
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> {
|
public class InvokeHttpMethod implements Function<Invocation, Object> {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private Logger logger = Logger.NULL;
|
private Logger logger = Logger.NULL;
|
||||||
|
|
||||||
private final Injector injector;
|
private final Function<Invocation, Invocation> sync2async;
|
||||||
private final Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncInvokables;
|
private final Function<Invocation, HttpRequest> annotationProcessor;
|
||||||
private final RestAnnotationProcessor annotationProcessor;
|
|
||||||
private final HttpCommandExecutorService http;
|
private final HttpCommandExecutorService http;
|
||||||
private final TransformerForRequest transformerForRequest;
|
|
||||||
private final ListeningExecutorService userExecutor;
|
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
|
@Inject
|
||||||
private InvokeHttpMethod(Injector injector, Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncInvokables,
|
@VisibleForTesting
|
||||||
RestAnnotationProcessor annotationProcessor, HttpCommandExecutorService http,
|
InvokeHttpMethod(Function<Invocation, Invocation> sync2async, Function<Invocation, HttpRequest> annotationProcessor,
|
||||||
TransformerForRequest transformerForRequest,
|
HttpCommandExecutorService http, Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, BlockOnFuture.Factory blocker) {
|
TimeLimiter timeLimiter, InvocationConfig config,
|
||||||
this.injector = injector;
|
@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
|
||||||
this.sync2AsyncInvokables = sync2AsyncInvokables;
|
this.sync2async = sync2async;
|
||||||
this.annotationProcessor = annotationProcessor;
|
this.annotationProcessor = annotationProcessor;
|
||||||
this.http = http;
|
this.http = http;
|
||||||
this.userExecutor = userExecutor;
|
this.userExecutor = userExecutor;
|
||||||
this.blocker = blocker;
|
this.timeLimiter = timeLimiter;
|
||||||
this.transformerForRequest = transformerForRequest;
|
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
|
@Override
|
||||||
public Object apply(Invocation in) {
|
public Object apply(Invocation in) {
|
||||||
if (isFuture(in.getInvokable())) {
|
if (isFuture(in.getInvokable())) {
|
||||||
return createFuture(in);
|
return submit(in);
|
||||||
}
|
}
|
||||||
Invocation async = Invocation.create(
|
Invocation async = toAsync(in);
|
||||||
checkNotNull(sync2AsyncInvokables.getIfPresent(in.getInvokable()), "invokable %s not in %s",
|
Optional<Long> timeoutNanos = config.getTimeoutNanos(async);
|
||||||
in.getInvokable(), sync2AsyncInvokables), in.getArgs());
|
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);
|
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) {
|
private boolean isFuture(Invokable<?, ?> in) {
|
||||||
return in.getReturnType().getRawType().equals(ListenableFuture.class);
|
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
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o)
|
if (this == o)
|
||||||
|
|
|
@ -131,7 +131,7 @@ import com.google.inject.TypeLiteral;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class RestAnnotationProcessor implements Function<Invocation, GeneratedHttpRequest> {
|
public class RestAnnotationProcessor implements Function<Invocation, HttpRequest> {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
|
@ -35,6 +35,7 @@ import javax.lang.model.type.NullType;
|
||||||
|
|
||||||
import org.jclouds.functions.IdentityFunction;
|
import org.jclouds.functions.IdentityFunction;
|
||||||
import org.jclouds.functions.OnlyElementOrNull;
|
import org.jclouds.functions.OnlyElementOrNull;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
|
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
|
||||||
import org.jclouds.http.functions.ParseJson;
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
@ -69,7 +70,7 @@ import com.google.inject.Injector;
|
||||||
import com.google.inject.Key;
|
import com.google.inject.Key;
|
||||||
import com.google.inject.TypeLiteral;
|
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 ParseSax.Factory parserFactory;
|
||||||
private final Injector injector;
|
private final Injector injector;
|
||||||
private final GetAcceptHeaders getAcceptHeaders;
|
private final GetAcceptHeaders getAcceptHeaders;
|
||||||
|
@ -83,7 +84,8 @@ public class TransformerForRequest implements Function<GeneratedHttpRequest, Fun
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public Function<HttpResponse, ?> apply(GeneratedHttpRequest request) {
|
public Function<HttpResponse, ?> apply(HttpRequest in) {
|
||||||
|
GeneratedHttpRequest request = GeneratedHttpRequest.class.cast(in);
|
||||||
Function<HttpResponse, ?> transformer;
|
Function<HttpResponse, ?> transformer;
|
||||||
Class<? extends HandlerWithResult<?>> handler = getSaxResponseParserClassOrNull(request.getInvocation()
|
Class<? extends HandlerWithResult<?>> handler = getSaxResponseParserClassOrNull(request.getInvocation()
|
||||||
.getInvokable());
|
.getInvokable());
|
||||||
|
@ -93,7 +95,7 @@ public class TransformerForRequest implements Function<GeneratedHttpRequest, Fun
|
||||||
transformer = getTransformerForMethod(request.getInvocation(), injector);
|
transformer = getTransformerForMethod(request.getInvocation(), injector);
|
||||||
}
|
}
|
||||||
if (transformer instanceof InvocationContext<?>) {
|
if (transformer instanceof InvocationContext<?>) {
|
||||||
((InvocationContext<?>) transformer).setContext(request);
|
InvocationContext.class.cast(transformer).setContext(request);
|
||||||
}
|
}
|
||||||
if (request.getInvocation().getInvokable().isAnnotationPresent(Transform.class)) {
|
if (request.getInvocation().getInvokable().isAnnotationPresent(Transform.class)) {
|
||||||
Function<?, ?> wrappingTransformer = injector.getInstance(request.getInvocation().getInvokable()
|
Function<?, ?> wrappingTransformer = injector.getInstance(request.getInvocation().getInvokable()
|
||||||
|
|
|
@ -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;
|
package org.jclouds.fallbacks;
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
|
|
||||||
|
|
|
@ -36,27 +36,27 @@ import com.google.common.net.HttpHeaders;
|
||||||
public class MapHttp4xxCodesToExceptionsTest {
|
public class MapHttp4xxCodesToExceptionsTest {
|
||||||
|
|
||||||
@Test(expectedExceptions = AuthorizationException.class)
|
@Test(expectedExceptions = AuthorizationException.class)
|
||||||
public void test401ToAuthorizationException() {
|
public void test401ToAuthorizationException() throws Exception {
|
||||||
fn.create(new HttpResponseException(command, HttpResponse.builder().statusCode(401).build()));
|
fn.create(new HttpResponseException(command, HttpResponse.builder().statusCode(401).build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = AuthorizationException.class)
|
@Test(expectedExceptions = AuthorizationException.class)
|
||||||
public void test403ToAuthorizationException() {
|
public void test403ToAuthorizationException() throws Exception {
|
||||||
fn.create(new HttpResponseException(command, HttpResponse.builder().statusCode(403).build()));
|
fn.create(new HttpResponseException(command, HttpResponse.builder().statusCode(403).build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = ResourceNotFoundException.class)
|
@Test(expectedExceptions = ResourceNotFoundException.class)
|
||||||
public void test404ToResourceNotFoundException() {
|
public void test404ToResourceNotFoundException() throws Exception {
|
||||||
fn.create(new HttpResponseException(command, HttpResponse.builder().statusCode(404).build()));
|
fn.create(new HttpResponseException(command, HttpResponse.builder().statusCode(404).build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalStateException.class)
|
@Test(expectedExceptions = IllegalStateException.class)
|
||||||
public void test409ToIllegalStateException() {
|
public void test409ToIllegalStateException() throws Exception {
|
||||||
fn.create(new HttpResponseException(command, HttpResponse.builder().statusCode(409).build()));
|
fn.create(new HttpResponseException(command, HttpResponse.builder().statusCode(409).build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = RetryAfterException.class, expectedExceptionsMessageRegExp = "retry now")
|
@Test(expectedExceptions = RetryAfterException.class, expectedExceptionsMessageRegExp = "retry now")
|
||||||
public void testHttpResponseExceptionWithRetryAfterDate() {
|
public void testHttpResponseExceptionWithRetryAfterDate() throws Exception {
|
||||||
fn.create(new HttpResponseException(command,
|
fn.create(new HttpResponseException(command,
|
||||||
HttpResponse.builder()
|
HttpResponse.builder()
|
||||||
.statusCode(503)
|
.statusCode(503)
|
||||||
|
@ -64,7 +64,7 @@ public class MapHttp4xxCodesToExceptionsTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = RetryAfterException.class, expectedExceptionsMessageRegExp = "retry in 700 seconds")
|
@Test(expectedExceptions = RetryAfterException.class, expectedExceptionsMessageRegExp = "retry in 700 seconds")
|
||||||
public void testHttpResponseExceptionWithRetryAfterOffset(){
|
public void testHttpResponseExceptionWithRetryAfterOffset() throws Exception {
|
||||||
fn.create(new HttpResponseException(command,
|
fn.create(new HttpResponseException(command,
|
||||||
HttpResponse.builder()
|
HttpResponse.builder()
|
||||||
.statusCode(503)
|
.statusCode(503)
|
||||||
|
@ -72,7 +72,7 @@ public class MapHttp4xxCodesToExceptionsTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = RetryAfterException.class, expectedExceptionsMessageRegExp = "retry in 86400 seconds")
|
@Test(expectedExceptions = RetryAfterException.class, expectedExceptionsMessageRegExp = "retry in 86400 seconds")
|
||||||
public void testHttpResponseExceptionWithRetryAfterPastIsZero(){
|
public void testHttpResponseExceptionWithRetryAfterPastIsZero() throws Exception {
|
||||||
fn.create(new HttpResponseException(command,
|
fn.create(new HttpResponseException(command,
|
||||||
HttpResponse.builder()
|
HttpResponse.builder()
|
||||||
.statusCode(503)
|
.statusCode(503)
|
||||||
|
|
|
@ -52,7 +52,6 @@ import org.jclouds.util.Strings2;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
@ -92,13 +91,14 @@ public interface IntegrationTestAsyncClient {
|
||||||
@Fallback(FooOnException.class)
|
@Fallback(FooOnException.class)
|
||||||
ListenableFuture<String> downloadException(@PathParam("id") String id, HttpRequestOptions options);
|
ListenableFuture<String> downloadException(@PathParam("id") String id, HttpRequestOptions options);
|
||||||
|
|
||||||
static class FooOnException implements FutureFallback<String> {
|
static class FooOnException implements org.jclouds.Fallback<String> {
|
||||||
|
|
||||||
@Override
|
|
||||||
public ListenableFuture<String> create(Throwable t) throws Exception {
|
public ListenableFuture<String> create(Throwable t) throws Exception {
|
||||||
return immediateFuture("foo");
|
return immediateFuture("foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String createOrPropagate(Throwable t) throws Exception {
|
||||||
|
return "foo";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.http.BaseJettyTest;
|
import org.jclouds.http.BaseJettyTest;
|
||||||
import org.jclouds.http.HttpCommand;
|
import org.jclouds.http.HttpCommand;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
import org.jclouds.http.IntegrationTestAsyncClient;
|
||||||
import org.jclouds.io.Payloads;
|
import org.jclouds.io.Payloads;
|
||||||
|
@ -34,6 +35,7 @@ import org.jclouds.reflect.Invocation;
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.reflect.Invokable;
|
import com.google.common.reflect.Invokable;
|
||||||
|
|
||||||
|
@ -122,7 +124,7 @@ public class BackoffLimitedRetryHandlerTest {
|
||||||
assertEquals(response.getPayload().getInput().read(), -1);
|
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);
|
.getInstance(RestAnnotationProcessor.class);
|
||||||
|
|
||||||
private HttpCommand createCommand() throws SecurityException, NoSuchMethodException {
|
private HttpCommand createCommand() throws SecurityException, NoSuchMethodException {
|
||||||
|
|
|
@ -24,6 +24,7 @@ import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
|
|
||||||
import org.jclouds.ContextBuilder;
|
import org.jclouds.ContextBuilder;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
import org.jclouds.http.IntegrationTestAsyncClient;
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
import org.jclouds.http.IntegrationTestClient;
|
||||||
import org.jclouds.predicates.validators.AllLowerCaseValidator;
|
import org.jclouds.predicates.validators.AllLowerCaseValidator;
|
||||||
|
@ -35,6 +36,7 @@ import org.testng.TestException;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.reflect.Invokable;
|
import com.google.common.reflect.Invokable;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
@ -105,7 +107,7 @@ public class InputParamValidatorTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
Injector injector;
|
Injector injector;
|
||||||
RestAnnotationProcessor restAnnotationProcessor;
|
Function<Invocation, HttpRequest> restAnnotationProcessor;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
void setupFactory() {
|
void setupFactory() {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -84,12 +84,15 @@ import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.io.InputSupplier;
|
import com.google.common.io.InputSupplier;
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
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.JsonElement;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Binder;
|
import com.google.inject.Binder;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -236,6 +239,12 @@ public abstract class BaseRestApiExpectTest<S> {
|
||||||
}).toInstance(fn);
|
}).toInstance(fn);
|
||||||
bind(HttpCommandExecutorService.class).to(ExpectHttpCommandExecutorService.class);
|
bind(HttpCommandExecutorService.class).to(ExpectHttpCommandExecutorService.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
TimeLimiter timeLimiter(@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor){
|
||||||
|
return new SimpleTimeLimiter(userExecutor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,6 +33,9 @@ import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.concurrent.config.ConfiguresExecutorService;
|
import org.jclouds.concurrent.config.ConfiguresExecutorService;
|
||||||
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
|
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
|
||||||
import org.jclouds.http.HttpCommandExecutorService;
|
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.collect.TreeMultimap;
|
||||||
import com.google.common.reflect.Invokable;
|
import com.google.common.reflect.Invokable;
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
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.AbstractModule;
|
||||||
import com.google.inject.Injector;
|
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(ListeningExecutorService.class).annotatedWith(named(PROPERTY_IO_WORKER_THREADS)).toInstance(sameThreadExecutor());
|
||||||
bind(HttpCommandExecutorService.class).toInstance(mock);
|
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) {
|
protected void assertPayloadEquals(HttpRequest request, String toMatch, String contentType, boolean contentMD5) {
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -249,9 +249,14 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||||
|
return Futures.immediateFuture(invoke(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpResponse invoke(HttpCommand command) {
|
||||||
assertEquals(command.getCurrentRequest().getRequestLine(),
|
assertEquals(command.getCurrentRequest().getRequestLine(),
|
||||||
"GET http://localhost:9999/client/1/foo HTTP/1.1");
|
"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
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||||
|
return Futures.immediateFuture(invoke(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpResponse invoke(HttpCommand command) {
|
||||||
if (callCounter == 1)
|
if (callCounter == 1)
|
||||||
assertEquals(command.getCurrentRequest().getRequestLine(),
|
assertEquals(command.getCurrentRequest().getRequestLine(),
|
||||||
"GET http://localhost:1111/client/1/bar/2 HTTP/1.1");
|
"GET http://localhost:1111/client/1/bar/2 HTTP/1.1");
|
||||||
|
@ -281,7 +291,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
assertEquals(command.getCurrentRequest().getRequestLine(),
|
assertEquals(command.getCurrentRequest().getRequestLine(),
|
||||||
"GET http://localhost:1111/client/1/foo HTTP/1.1");
|
"GET http://localhost:1111/client/1/foo HTTP/1.1");
|
||||||
callCounter++;
|
callCounter++;
|
||||||
return Futures.immediateFuture(HttpResponse.builder().build());
|
return HttpResponse.builder().build();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -304,8 +314,13 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
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");
|
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
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||||
|
return Futures.immediateFuture(invoke(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpResponse invoke(HttpCommand command) {
|
||||||
assertEquals(command.getCurrentRequest().getRequestLine(),
|
assertEquals(command.getCurrentRequest().getRequestLine(),
|
||||||
"GET http://howdyboys/testing/testing/thepathparam/client/1/foo HTTP/1.1");
|
"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
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
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");
|
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
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
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");
|
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() {
|
}, new AbstractModule() {
|
||||||
|
@ -419,8 +449,13 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
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");
|
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
|
||||||
return Futures.immediateFuture(HttpResponse.builder().build());
|
return HttpResponse.builder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,12 +26,12 @@ import static org.jclouds.http.HttpUtils.wirePayloadIfEnabled;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.JcloudsVersion;
|
||||||
import org.jclouds.http.HttpCommand;
|
import org.jclouds.http.HttpCommand;
|
||||||
import org.jclouds.http.HttpCommandExecutorService;
|
import org.jclouds.http.HttpCommandExecutorService;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
@ -42,58 +42,72 @@ import org.jclouds.http.HttpUtils;
|
||||||
import org.jclouds.http.IOExceptionRetryHandler;
|
import org.jclouds.http.IOExceptionRetryHandler;
|
||||||
import org.jclouds.http.handlers.DelegatingErrorHandler;
|
import org.jclouds.http.handlers.DelegatingErrorHandler;
|
||||||
import org.jclouds.http.handlers.DelegatingRetryHandler;
|
import org.jclouds.http.handlers.DelegatingRetryHandler;
|
||||||
|
import org.jclouds.http.internal.BaseHttpCommandExecutorService;
|
||||||
import org.jclouds.http.internal.HttpWire;
|
import org.jclouds.http.internal.HttpWire;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.io.ContentMetadataCodec;
|
||||||
import org.jclouds.util.Throwables2;
|
import org.jclouds.util.Throwables2;
|
||||||
|
|
||||||
import com.google.appengine.api.urlfetch.HTTPRequest;
|
import com.google.appengine.api.urlfetch.HTTPRequest;
|
||||||
|
import com.google.appengine.api.urlfetch.HTTPResponse;
|
||||||
import com.google.appengine.api.urlfetch.URLFetchService;
|
import com.google.appengine.api.urlfetch.URLFetchService;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Google App Engine version of {@link HttpCommandExecutorService} using their fetchAsync call
|
* Google App Engine version of {@link HttpCommandExecutorService} using their
|
||||||
|
* fetchAsync call
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class AsyncGaeHttpCommandExecutorService implements HttpCommandExecutorService {
|
public class AsyncGaeHttpCommandExecutorService extends BaseHttpCommandExecutorService<HTTPRequest> {
|
||||||
private final ListeningExecutorService ioExecutor;
|
// TODO: look up gae version
|
||||||
|
public static final String USER_AGENT = String.format("jclouds/%s urlfetch/%s", JcloudsVersion.get(), "1.6.5");
|
||||||
|
|
||||||
private final URLFetchService urlFetchService;
|
private final URLFetchService urlFetchService;
|
||||||
private final ConvertToGaeRequest convertToGaeRequest;
|
private final ConvertToGaeRequest convertToGaeRequest;
|
||||||
private final ConvertToJcloudsResponse convertToJcloudsResponse;
|
private final ConvertToJcloudsResponse convertToJcloudsResponse;
|
||||||
private final DelegatingRetryHandler retryHandler;
|
private final ListeningExecutorService ioExecutor;
|
||||||
private final IOExceptionRetryHandler ioRetryHandler;
|
|
||||||
private final DelegatingErrorHandler errorHandler;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
protected Logger logger = Logger.NULL;
|
|
||||||
@Resource
|
|
||||||
@Named(Constants.LOGGER_HTTP_HEADERS)
|
|
||||||
protected Logger headerLog = Logger.NULL;
|
|
||||||
protected final HttpWire wire;
|
|
||||||
protected final HttpUtils utils;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AsyncGaeHttpCommandExecutorService(
|
public AsyncGaeHttpCommandExecutorService(URLFetchService urlFetchService, HttpUtils utils,
|
||||||
|
ContentMetadataCodec contentMetadataCodec,
|
||||||
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
|
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
|
||||||
URLFetchService urlFetchService, ConvertToGaeRequest convertToGaeRequest,
|
IOExceptionRetryHandler ioRetryHandler, DelegatingRetryHandler retryHandler,
|
||||||
ConvertToJcloudsResponse convertToJcloudsResponse, DelegatingRetryHandler retryHandler,
|
DelegatingErrorHandler errorHandler, HttpWire wire, ConvertToGaeRequest convertToGaeRequest,
|
||||||
IOExceptionRetryHandler ioRetryHandler, DelegatingErrorHandler errorHandler, HttpUtils utils, HttpWire wire) {
|
ConvertToJcloudsResponse convertToJcloudsResponse) {
|
||||||
|
super(utils, contentMetadataCodec, ioExecutor, retryHandler, ioRetryHandler, errorHandler, wire);
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
this.urlFetchService = urlFetchService;
|
this.urlFetchService = urlFetchService;
|
||||||
this.convertToGaeRequest = convertToGaeRequest;
|
this.convertToGaeRequest = convertToGaeRequest;
|
||||||
this.convertToJcloudsResponse = convertToJcloudsResponse;
|
this.convertToJcloudsResponse = convertToJcloudsResponse;
|
||||||
this.retryHandler = retryHandler;
|
}
|
||||||
this.ioRetryHandler = ioRetryHandler;
|
|
||||||
this.errorHandler = errorHandler;
|
@VisibleForTesting
|
||||||
this.utils = utils;
|
protected HttpResponse convert(HTTPResponse gaeResponse) {
|
||||||
this.wire = wire;
|
return convertToJcloudsResponse.apply(gaeResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
protected HTTPRequest convert(HttpRequest request) throws IOException {
|
||||||
|
return convertToGaeRequest.apply(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nothing to clean up.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void cleanup(HTTPRequest nativeRequest) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HttpResponse invoke(HTTPRequest request) throws IOException {
|
||||||
|
return convert(urlFetchService.fetch(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
public HTTPRequest filterLogAndConvertRe(HttpRequest request) {
|
public HTTPRequest filterLogAndConvertRe(HttpRequest request) {
|
||||||
|
|
||||||
for (HttpRequestFilter filter : request.getFilters()) {
|
for (HttpRequestFilter filter : request.getFilters()) {
|
||||||
request = filter.filter(request);
|
request = filter.filter(request);
|
||||||
}
|
}
|
||||||
|
@ -108,61 +122,59 @@ public class AsyncGaeHttpCommandExecutorService implements HttpCommandExecutorSe
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(final HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(final HttpCommand command) {
|
||||||
|
|
||||||
HTTPRequest nativeRequest = filterLogAndConvertRe(command.getCurrentRequest());
|
HTTPRequest nativeRequest = filterLogAndConvertRe(command.getCurrentRequest());
|
||||||
|
|
||||||
ListenableFuture<HttpResponse> response = transform(
|
ListenableFuture<HttpResponse> response = transform(
|
||||||
listenInPoolThread(urlFetchService.fetchAsync(nativeRequest)), convertToJcloudsResponse);
|
listenInPoolThread(urlFetchService.fetchAsync(nativeRequest)), convertToJcloudsResponse);
|
||||||
|
|
||||||
return transform(response, new Function<HttpResponse, HttpResponse>() {
|
return transform(response, new Function<HttpResponse, HttpResponse>() {
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpResponse apply(HttpResponse response) {
|
public HttpResponse apply(HttpResponse response) {
|
||||||
try {
|
return receiveResponse(command, response);
|
||||||
logger.debug("Receiving response %s: %s", command.getCurrentRequest().hashCode(),
|
|
||||||
response.getStatusLine());
|
|
||||||
utils.logResponse(headerLog, response, "<<");
|
|
||||||
if (response.getPayload() != null && wire.enabled())
|
|
||||||
wire.input(response);
|
|
||||||
int statusCode = response.getStatusCode();
|
|
||||||
if (statusCode >= 300) {
|
|
||||||
if (shouldContinue(response))
|
|
||||||
return submit(command).get();
|
|
||||||
else
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
} catch (Exception e) {
|
|
||||||
IOException ioe = Throwables2.getFirstThrowableOfType(e, IOException.class);
|
|
||||||
if (ioe != null && ioRetryHandler.shouldRetryRequest(command, ioe)) {
|
|
||||||
try {
|
|
||||||
return submit(command).get();
|
|
||||||
} catch (Exception e1) {
|
|
||||||
command.setException(e1);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
command.setException(new HttpResponseException(e.getMessage() + " connecting to "
|
|
||||||
+ command.getCurrentRequest().getRequestLine(), command, null, e));
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (command.getException() != null)
|
|
||||||
propagate(command.getException());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldContinue(HttpResponse response) {
|
|
||||||
boolean shouldContinue = false;
|
|
||||||
if (retryHandler.shouldRetryRequest(command, response)) {
|
|
||||||
shouldContinue = true;
|
|
||||||
} else {
|
|
||||||
errorHandler.handleError(command, response);
|
|
||||||
}
|
|
||||||
return shouldContinue;
|
|
||||||
}
|
|
||||||
}, ioExecutor);
|
}, ioExecutor);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HttpResponse receiveResponse(HttpCommand command, HttpResponse response) {
|
||||||
|
try {
|
||||||
|
logger.debug("Receiving response %s: %s", command.getCurrentRequest().hashCode(), response.getStatusLine());
|
||||||
|
utils.logResponse(headerLog, response, "<<");
|
||||||
|
if (response.getPayload() != null && wire.enabled())
|
||||||
|
wire.input(response);
|
||||||
|
int statusCode = response.getStatusCode();
|
||||||
|
if (statusCode >= 300) {
|
||||||
|
if (shouldContinue(command, response))
|
||||||
|
return submit(command).get();
|
||||||
|
else
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
} catch (Exception e) {
|
||||||
|
IOException ioe = Throwables2.getFirstThrowableOfType(e, IOException.class);
|
||||||
|
if (ioe != null && ioRetryHandler.shouldRetryRequest(command, ioe)) {
|
||||||
|
try {
|
||||||
|
return submit(command).get();
|
||||||
|
} catch (Exception e1) {
|
||||||
|
command.setException(e1);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
command.setException(new HttpResponseException(e.getMessage() + " connecting to "
|
||||||
|
+ command.getCurrentRequest().getRequestLine(), command, null, e));
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (command.getException() != null)
|
||||||
|
propagate(command.getException());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldContinue(HttpCommand command, HttpResponse response) {
|
||||||
|
boolean shouldContinue = false;
|
||||||
|
if (retryHandler.shouldRetryRequest(command, response)) {
|
||||||
|
shouldContinue = true;
|
||||||
|
} else {
|
||||||
|
errorHandler.handleError(command, response);
|
||||||
|
}
|
||||||
|
return shouldContinue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
@Singleton
|
@Singleton
|
||||||
public class GaeHttpCommandExecutorService extends BaseHttpCommandExecutorService<HTTPRequest> {
|
public class GaeHttpCommandExecutorService extends BaseHttpCommandExecutorService<HTTPRequest> {
|
||||||
//TODO: look up gae version
|
//TODO: look up gae version
|
||||||
public static final String USER_AGENT = String.format("jclouds/%s urlfetch/%s", JcloudsVersion.get(), "1.4.3");
|
public static final String USER_AGENT = String.format("jclouds/%s urlfetch/%s", JcloudsVersion.get(), "1.6.5");
|
||||||
|
|
||||||
private final URLFetchService urlFetchService;
|
private final URLFetchService urlFetchService;
|
||||||
private final ConvertToGaeRequest convertToGaeRequest;
|
private final ConvertToGaeRequest convertToGaeRequest;
|
||||||
|
|
|
@ -18,9 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jclouds.abiquo;
|
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_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.ASYNC_TASK_MONITOR_DELAY;
|
||||||
import static org.jclouds.abiquo.config.AbiquoProperties.CREDENTIAL_IS_TOKEN;
|
import static org.jclouds.abiquo.config.AbiquoProperties.CREDENTIAL_IS_TOKEN;
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
@ -67,7 +65,6 @@ public class AbiquoApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(90) + "");
|
|
||||||
// By default redirects will be handled in the domain objects
|
// By default redirects will be handled in the domain objects
|
||||||
properties.setProperty(PROPERTY_MAX_REDIRECTS, "0");
|
properties.setProperty(PROPERTY_MAX_REDIRECTS, "0");
|
||||||
// The default polling delay between AsyncTask monitor requests
|
// The default polling delay between AsyncTask monitor requests
|
||||||
|
|
|
@ -26,13 +26,13 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
|
||||||
import javax.ws.rs.core.Response.Status;
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
import org.jclouds.abiquo.domain.exception.AbiquoException;
|
import org.jclouds.abiquo.domain.exception.AbiquoException;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.rest.ResourceNotFoundException;
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,22 +47,30 @@ public final class AbiquoFallbacks {
|
||||||
/**
|
/**
|
||||||
* Return an Abiquo Exception on not found errors.
|
* Return an Abiquo Exception on not found errors.
|
||||||
*/
|
*/
|
||||||
public static final class PropagateAbiquoExceptionOnNotFoundOr4xx implements FutureFallback<Object> {
|
public static final class PropagateAbiquoExceptionOnNotFoundOr4xx implements Fallback<Object> {
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Object> create(final Throwable from) {
|
public ListenableFuture<Object> create(Throwable from) throws Exception {
|
||||||
Throwable exception = find(getCausalChain(from), isNotFoundAndHasAbiquoException(from), null);
|
return immediateFuture(createOrPropagate(from));
|
||||||
|
|
||||||
throw propagate(exception == null ? from : exception.getCause());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object createOrPropagate(Throwable from) throws Exception {
|
||||||
|
Throwable exception = find(getCausalChain(from), isNotFoundAndHasAbiquoException(from), null);
|
||||||
|
throw propagate(exception == null ? from : exception.getCause());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return <code>null</code> on 303 response codes when requesting a task.
|
* Return <code>null</code> on 303 response codes when requesting a task.
|
||||||
*/
|
*/
|
||||||
public static final class NullOn303 implements FutureFallback<Object> {
|
public static final class NullOn303 implements Fallback<Object> {
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Object> create(final Throwable from) {
|
public ListenableFuture<Object> create(Throwable from) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(from));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object createOrPropagate(Throwable from) throws Exception {
|
||||||
Throwable exception = find(getCausalChain(from), hasResponse(from), null);
|
Throwable exception = find(getCausalChain(from), hasResponse(from), null);
|
||||||
|
|
||||||
if (exception != null) {
|
if (exception != null) {
|
||||||
|
@ -70,7 +78,7 @@ public final class AbiquoFallbacks {
|
||||||
HttpResponse response = responseException.getResponse();
|
HttpResponse response = responseException.getResponse();
|
||||||
|
|
||||||
if (response != null && response.getStatusCode() == Status.SEE_OTHER.getStatusCode()) {
|
if (response != null && response.getStatusCode() == Status.SEE_OTHER.getStatusCode()) {
|
||||||
return immediateFuture(null);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,9 +90,14 @@ public final class AbiquoFallbacks {
|
||||||
/**
|
/**
|
||||||
* Return false on service error exceptions.
|
* Return false on service error exceptions.
|
||||||
*/
|
*/
|
||||||
public static final class FalseOn5xx implements FutureFallback<Boolean> {
|
public static final class FalseOn5xx implements Fallback<Boolean> {
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Boolean> create(final Throwable from) {
|
public ListenableFuture<Boolean> create(Throwable from) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(from));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean createOrPropagate(Throwable from) throws Exception {
|
||||||
Throwable exception = find(getCausalChain(from), hasResponse(from), null);
|
Throwable exception = find(getCausalChain(from), hasResponse(from), null);
|
||||||
|
|
||||||
if (exception != null) {
|
if (exception != null) {
|
||||||
|
@ -92,7 +105,7 @@ public final class AbiquoFallbacks {
|
||||||
HttpResponse response = responseException.getResponse();
|
HttpResponse response = responseException.getResponse();
|
||||||
|
|
||||||
if (response != null && response.getStatusCode() >= 500 && response.getStatusCode() < 600) {
|
if (response != null && response.getStatusCode() >= 500 && response.getStatusCode() < 600) {
|
||||||
return immediateFuture(false);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +117,14 @@ public final class AbiquoFallbacks {
|
||||||
/**
|
/**
|
||||||
* Return false on service error exceptions.
|
* Return false on service error exceptions.
|
||||||
*/
|
*/
|
||||||
public static final class FalseIfNotAvailable implements FutureFallback<Boolean> {
|
public static final class FalseIfNotAvailable implements Fallback<Boolean> {
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Boolean> create(final Throwable from) {
|
public ListenableFuture<Boolean> create(Throwable from) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(from));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean createOrPropagate(Throwable from) throws Exception {
|
||||||
Throwable exception = find(getCausalChain(from), isNotAvailableException(from), null);
|
Throwable exception = find(getCausalChain(from), isNotAvailableException(from), null);
|
||||||
|
|
||||||
if (exception != null) {
|
if (exception != null) {
|
||||||
|
@ -115,11 +133,11 @@ public final class AbiquoFallbacks {
|
||||||
HttpResponse response = responseException.getResponse();
|
HttpResponse response = responseException.getResponse();
|
||||||
|
|
||||||
if (response != null && response.getStatusCode() >= 500 && response.getStatusCode() < 600) {
|
if (response != null && response.getStatusCode() >= 500 && response.getStatusCode() < 600) {
|
||||||
return immediateFuture(false);
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Will enter here when exception is a ResourceNotFoundException
|
// Will enter here when exception is a ResourceNotFoundException
|
||||||
return immediateFuture(false);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.ws.rs.core.Response.Status;
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.http.functions.ParseXMLWithJAXB;
|
import org.jclouds.http.functions.ParseXMLWithJAXB;
|
||||||
|
@ -37,7 +38,6 @@ import com.abiquo.server.core.infrastructure.storage.MovedVolumeDto;
|
||||||
import com.abiquo.server.core.infrastructure.storage.VolumeManagementDto;
|
import com.abiquo.server.core.infrastructure.storage.VolumeManagementDto;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ import com.google.inject.TypeLiteral;
|
||||||
* @author Ignasi Barrera
|
* @author Ignasi Barrera
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class MovedVolume implements FutureFallback<VolumeManagementDto> {
|
public class MovedVolume implements Fallback<VolumeManagementDto> {
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
@ -67,14 +67,19 @@ public class MovedVolume implements FutureFallback<VolumeManagementDto> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<VolumeManagementDto> create(final Throwable from) {
|
public ListenableFuture<VolumeManagementDto> create(Throwable from) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(from));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VolumeManagementDto createOrPropagate(Throwable from) throws Exception {
|
||||||
Throwable exception = find(getCausalChain(from), isMovedException(from), null);
|
Throwable exception = find(getCausalChain(from), isMovedException(from), null);
|
||||||
|
|
||||||
if (exception != null) {
|
if (exception != null) {
|
||||||
HttpResponseException responseException = (HttpResponseException) exception;
|
HttpResponseException responseException = (HttpResponseException) exception;
|
||||||
HttpResponse response = responseException.getResponse();
|
HttpResponse response = responseException.getResponse();
|
||||||
|
|
||||||
return immediateFuture(parser.apply(response).getVolume());
|
return parser.apply(response).getVolume();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw propagate(from);
|
throw propagate(from);
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.jclouds.abiquo.fallbacks;
|
package org.jclouds.abiquo.fallbacks;
|
||||||
|
|
||||||
import static com.google.common.util.concurrent.Futures.getUnchecked;
|
|
||||||
import static org.easymock.EasyMock.expect;
|
import static org.easymock.EasyMock.expect;
|
||||||
import static org.easymock.EasyMock.replay;
|
import static org.easymock.EasyMock.replay;
|
||||||
import static org.easymock.EasyMock.verify;
|
import static org.easymock.EasyMock.verify;
|
||||||
|
@ -45,13 +44,13 @@ public class FalseIfNotAvailableTest {
|
||||||
RuntimeException exception = new RuntimeException();
|
RuntimeException exception = new RuntimeException();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
function.create(exception);
|
function.createOrPropagate(exception);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
assertEquals(ex, exception);
|
assertEquals(ex, exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFalseIf5xx() {
|
public void testFalseIf5xx() throws Exception {
|
||||||
FalseIfNotAvailable function = new FalseIfNotAvailable();
|
FalseIfNotAvailable function = new FalseIfNotAvailable();
|
||||||
HttpResponse response = EasyMock.createMock(HttpResponse.class);
|
HttpResponse response = EasyMock.createMock(HttpResponse.class);
|
||||||
HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);
|
HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);
|
||||||
|
@ -68,7 +67,7 @@ public class FalseIfNotAvailableTest {
|
||||||
replay(response);
|
replay(response);
|
||||||
replay(exception);
|
replay(exception);
|
||||||
|
|
||||||
assertFalse(getUnchecked(function.create(exception)));
|
assertFalse(function.createOrPropagate(exception));
|
||||||
|
|
||||||
verify(response);
|
verify(response);
|
||||||
verify(exception);
|
verify(exception);
|
||||||
|
@ -92,7 +91,7 @@ public class FalseIfNotAvailableTest {
|
||||||
replay(exception);
|
replay(exception);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
function.create(exception);
|
function.createOrPropagate(exception);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
assertEquals(ex, exception);
|
assertEquals(ex, exception);
|
||||||
}
|
}
|
||||||
|
@ -101,11 +100,11 @@ public class FalseIfNotAvailableTest {
|
||||||
verify(exception);
|
verify(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFalseIfResourceNotFound() {
|
public void testFalseIfResourceNotFound() throws Exception {
|
||||||
FalseIfNotAvailable function = new FalseIfNotAvailable();
|
FalseIfNotAvailable function = new FalseIfNotAvailable();
|
||||||
ResourceNotFoundException exception = new ResourceNotFoundException();
|
ResourceNotFoundException exception = new ResourceNotFoundException();
|
||||||
|
|
||||||
assertFalse(getUnchecked(function.create(exception)));
|
assertFalse(function.createOrPropagate(exception));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.jclouds.abiquo.fallbacks;
|
package org.jclouds.abiquo.fallbacks;
|
||||||
|
|
||||||
import static com.google.common.util.concurrent.Futures.getUnchecked;
|
|
||||||
import static org.easymock.EasyMock.expect;
|
import static org.easymock.EasyMock.expect;
|
||||||
import static org.easymock.EasyMock.replay;
|
import static org.easymock.EasyMock.replay;
|
||||||
import static org.easymock.EasyMock.verify;
|
import static org.easymock.EasyMock.verify;
|
||||||
|
@ -44,13 +43,13 @@ public class FalseOn5xxTest {
|
||||||
RuntimeException exception = new RuntimeException();
|
RuntimeException exception = new RuntimeException();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
function.create(exception);
|
function.createOrPropagate(exception);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
assertEquals(ex, exception);
|
assertEquals(ex, exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFalseIf5xx() {
|
public void testFalseIf5xx() throws Exception {
|
||||||
FalseOn5xx function = new FalseOn5xx();
|
FalseOn5xx function = new FalseOn5xx();
|
||||||
HttpResponse response = EasyMock.createMock(HttpResponse.class);
|
HttpResponse response = EasyMock.createMock(HttpResponse.class);
|
||||||
HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);
|
HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);
|
||||||
|
@ -67,7 +66,7 @@ public class FalseOn5xxTest {
|
||||||
replay(response);
|
replay(response);
|
||||||
replay(exception);
|
replay(exception);
|
||||||
|
|
||||||
assertFalse(getUnchecked(function.create(exception)));
|
assertFalse(function.createOrPropagate(exception));
|
||||||
|
|
||||||
verify(response);
|
verify(response);
|
||||||
verify(exception);
|
verify(exception);
|
||||||
|
@ -91,7 +90,7 @@ public class FalseOn5xxTest {
|
||||||
replay(exception);
|
replay(exception);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
function.create(exception);
|
function.createOrPropagate(exception);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
assertEquals(ex, exception);
|
assertEquals(ex, exception);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,6 @@ import static org.easymock.EasyMock.replay;
|
||||||
import static org.easymock.EasyMock.verify;
|
import static org.easymock.EasyMock.verify;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.ws.rs.core.Response.Status;
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
import org.easymock.EasyMock;
|
import org.easymock.EasyMock;
|
||||||
|
@ -61,7 +59,7 @@ public class MovedVolumeTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReturnVolume() throws IOException {
|
public void testReturnVolume() throws Exception {
|
||||||
JAXBParser xmlParser = new JAXBParser("false");
|
JAXBParser xmlParser = new JAXBParser("false");
|
||||||
MovedVolume function = new MovedVolume(new ReturnMoveVolumeReference(
|
MovedVolume function = new MovedVolume(new ReturnMoveVolumeReference(
|
||||||
new JAXBParser("false"), TypeLiteral.get(MovedVolumeDto.class)));
|
new JAXBParser("false"), TypeLiteral.get(MovedVolumeDto.class)));
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.jclouds.abiquo.fallbacks;
|
package org.jclouds.abiquo.fallbacks;
|
||||||
|
|
||||||
import static com.google.common.util.concurrent.Futures.getUnchecked;
|
|
||||||
import static org.easymock.EasyMock.expect;
|
import static org.easymock.EasyMock.expect;
|
||||||
import static org.easymock.EasyMock.replay;
|
import static org.easymock.EasyMock.replay;
|
||||||
import static org.easymock.EasyMock.verify;
|
import static org.easymock.EasyMock.verify;
|
||||||
|
@ -44,13 +43,13 @@ public class NullOn303Test {
|
||||||
RuntimeException exception = new RuntimeException();
|
RuntimeException exception = new RuntimeException();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
function.create(exception);
|
function.createOrPropagate(exception);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
assertEquals(ex, exception);
|
assertEquals(ex, exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNullIf303() {
|
public void testNullIf303() throws Exception {
|
||||||
NullOn303 function = new NullOn303();
|
NullOn303 function = new NullOn303();
|
||||||
HttpResponse response = EasyMock.createMock(HttpResponse.class);
|
HttpResponse response = EasyMock.createMock(HttpResponse.class);
|
||||||
HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);
|
HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);
|
||||||
|
@ -66,7 +65,7 @@ public class NullOn303Test {
|
||||||
replay(response);
|
replay(response);
|
||||||
replay(exception);
|
replay(exception);
|
||||||
|
|
||||||
assertNull(getUnchecked(function.create(exception)));
|
assertNull(function.createOrPropagate(exception));
|
||||||
|
|
||||||
verify(response);
|
verify(response);
|
||||||
verify(exception);
|
verify(exception);
|
||||||
|
@ -89,7 +88,7 @@ public class NullOn303Test {
|
||||||
replay(exception);
|
replay(exception);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
function.create(exception);
|
function.createOrPropagate(exception);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
assertEquals(ex, exception);
|
assertEquals(ex, exception);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.azure.management;
|
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.azure.management.config.AzureManagementProperties.SUBSCRIPTION_ID;
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
|
||||||
|
@ -66,7 +64,6 @@ public class AzureManagementApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.snia.cdmi.v1;
|
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.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@ -59,8 +56,6 @@ public class CDMIApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.cloudstack.ec2;
|
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.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@ -57,7 +54,6 @@ public class CloudStackEC2ApiMetadata extends EC2ApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = EC2ApiMetadata.defaultProperties();
|
Properties properties = EC2ApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ec2:DescribeImages", MINUTES.toMillis(15) + "");
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.dynect.v3;
|
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.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@ -62,7 +59,6 @@ public class DynECTApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,8 @@ import static com.google.common.base.Throwables.propagate;
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
|
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
import org.jclouds.Fallback;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,10 +35,16 @@ public final class DynECTFallbacks {
|
||||||
private DynECTFallbacks() {
|
private DynECTFallbacks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FalseOn400 implements FutureFallback<Boolean> {
|
public static class FalseOn400 implements Fallback<Boolean> {
|
||||||
public ListenableFuture<Boolean> create(Throwable t) {
|
@Override
|
||||||
|
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean createOrPropagate(Throwable t) throws Exception {
|
||||||
if (returnValueOnCodeOrNull(t, false, equalTo(400)) != null)
|
if (returnValueOnCodeOrNull(t, false, equalTo(400)) != null)
|
||||||
return immediateFuture(false);
|
return false;
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.elb;
|
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_AUTH_TAG;
|
||||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||||
|
|
||||||
|
@ -63,7 +61,6 @@ public class ELBApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
|
|
||||||
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
||||||
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.fujitsu.fgcp;
|
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 static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -57,7 +55,6 @@ public class FGCPApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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
|
// enables peer verification using the CAs bundled with the JRE (or
|
||||||
// value of javax.net.ssl.trustStore if set)
|
// value of javax.net.ssl.trustStore if set)
|
||||||
properties.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "false");
|
properties.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "false");
|
||||||
|
|
|
@ -18,9 +18,13 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.googlecompute;
|
package org.jclouds.googlecompute;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
||||||
import com.google.common.reflect.TypeToken;
|
import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
|
||||||
import com.google.inject.Module;
|
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.apis.ApiMetadata;
|
||||||
import org.jclouds.googlecompute.config.GoogleComputeParserModule;
|
import org.jclouds.googlecompute.config.GoogleComputeParserModule;
|
||||||
import org.jclouds.googlecompute.config.GoogleComputeRestClientModule;
|
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.RestContext;
|
||||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
||||||
|
|
||||||
import java.net.URI;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import java.util.Properties;
|
import com.google.common.reflect.TypeToken;
|
||||||
|
import com.google.inject.Module;
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link ApiMetadata} for GoogleCompute v1beta13 API
|
* Implementation of {@link ApiMetadata} for GoogleCompute v1beta13 API
|
||||||
|
@ -64,7 +63,6 @@ public class GoogleComputeApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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("oauth.endpoint", "https://accounts.google.com/o/oauth2/token");
|
||||||
properties.put(AUDIENCE, "https://accounts.google.com/o/oauth2/token");
|
properties.put(AUDIENCE, "https://accounts.google.com/o/oauth2/token");
|
||||||
properties.put(SIGNATURE_OR_MAC_ALGORITHM, "RS256");
|
properties.put(SIGNATURE_OR_MAC_ALGORITHM, "RS256");
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.iam;
|
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_AUTH_TAG;
|
||||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||||
|
|
||||||
|
@ -59,7 +57,6 @@ public class IAMApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
|
|
||||||
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
||||||
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.jenkins.v1;
|
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.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@ -61,7 +58,6 @@ public class JenkinsApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,9 @@ import static com.google.common.base.Throwables.propagate;
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
|
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
|
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,13 +37,18 @@ public final class JenkinsFallbacks {
|
||||||
private JenkinsFallbacks() {
|
private JenkinsFallbacks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class VoidOn302Or404 implements FutureFallback<Void> {
|
public static final class VoidOn302Or404 implements Fallback<Void> {
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Void> create(final Throwable t) {
|
public ListenableFuture<Void> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void createOrPropagate(Throwable t) throws Exception {
|
||||||
Boolean returnVal = returnValueOnCodeOrNull(checkNotNull(t, "throwable"), true,
|
Boolean returnVal = returnValueOnCodeOrNull(checkNotNull(t, "throwable"), true,
|
||||||
Predicates.<Integer> or(equalTo(302), equalTo(404)));
|
Predicates.<Integer> or(equalTo(302), equalTo(404)));
|
||||||
if (returnVal != null && returnVal)
|
if (returnVal != null && returnVal)
|
||||||
return immediateFuture(null);
|
return null;
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.joyent.cloudapi.v6_5;
|
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 static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -63,7 +61,6 @@ public class JoyentCloudApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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
|
// auth fail sometimes happens, as the rc.local script that injects the
|
||||||
// authorized key executes after ssh has started.
|
// authorized key executes after ssh has started.
|
||||||
properties.setProperty("jclouds.ssh.max-retries", "7");
|
properties.setProperty("jclouds.ssh.max-retries", "7");
|
||||||
|
|
|
@ -18,22 +18,21 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.oauth.v2;
|
package org.jclouds.oauth.v2;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
||||||
import com.google.common.reflect.TypeToken;
|
import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
|
||||||
import com.google.inject.Module;
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.apis.ApiMetadata;
|
import org.jclouds.apis.ApiMetadata;
|
||||||
import org.jclouds.oauth.v2.config.OAuthModule;
|
import org.jclouds.oauth.v2.config.OAuthModule;
|
||||||
import org.jclouds.oauth.v2.config.OAuthRestClientModule;
|
import org.jclouds.oauth.v2.config.OAuthRestClientModule;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
||||||
|
|
||||||
import java.net.URI;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import java.util.Properties;
|
import com.google.common.reflect.TypeToken;
|
||||||
|
import com.google.inject.Module;
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link ApiMetadata} for OAuth 2 API
|
* Implementation of {@link ApiMetadata} for OAuth 2 API
|
||||||
|
@ -61,7 +60,6 @@ public class OAuthApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(1) + "");
|
|
||||||
properties.put(SIGNATURE_OR_MAC_ALGORITHM, "RS256");
|
properties.put(SIGNATURE_OR_MAC_ALGORITHM, "RS256");
|
||||||
properties.put(PROPERTY_SESSION_INTERVAL, 3600);
|
properties.put(PROPERTY_SESSION_INTERVAL, 3600);
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.glance.v1_0;
|
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.CREDENTIAL_TYPE;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_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() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
|
|
||||||
properties.setProperty(SERVICE_TYPE, ServiceType.IMAGE);
|
properties.setProperty(SERVICE_TYPE, ServiceType.IMAGE);
|
||||||
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.quantum.v1_0;
|
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.CREDENTIAL_TYPE;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_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() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
|
|
||||||
properties.setProperty(SERVICE_TYPE, ServiceType.NETWORK);
|
properties.setProperty(SERVICE_TYPE, ServiceType.NETWORK);
|
||||||
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.swift.v1;
|
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.CREDENTIAL_TYPE;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_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() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
|
|
||||||
properties.setProperty(SERVICE_TYPE, ServiceType.OBJECT_STORE);
|
properties.setProperty(SERVICE_TYPE, ServiceType.OBJECT_STORE);
|
||||||
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.opsource.servers;
|
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.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@ -57,7 +54,6 @@ public class OpSourceServersApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rds;
|
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_AUTH_TAG;
|
||||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||||
|
|
||||||
|
@ -61,7 +59,6 @@ public class RDSApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
|
|
||||||
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
||||||
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -22,23 +22,28 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
import static org.jclouds.Fallbacks.valOnNotFoundOr404;
|
import static org.jclouds.Fallbacks.valOnNotFoundOr404;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
import org.jclouds.aws.AWSResponseException;
|
import org.jclouds.aws.AWSResponseException;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
public final class RDSFallbacks {
|
public final class RDSFallbacks {
|
||||||
private RDSFallbacks() {
|
private RDSFallbacks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class NullOnStateDeletingNotFoundOr404 implements FutureFallback<Object> {
|
public static final class NullOnStateDeletingNotFoundOr404 implements Fallback<Object> {
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Object> create(final Throwable t) {
|
public ListenableFuture<Object> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object createOrPropagate(Throwable t) throws Exception {
|
||||||
if (checkNotNull(t, "throwable") instanceof AWSResponseException) {
|
if (checkNotNull(t, "throwable") instanceof AWSResponseException) {
|
||||||
AWSResponseException e = AWSResponseException.class.cast(t);
|
AWSResponseException e = AWSResponseException.class.cast(t);
|
||||||
if ("InvalidDBInstanceState".equals(e.getError().getCode())
|
if ("InvalidDBInstanceState".equals(e.getError().getCode())
|
||||||
&& e.getError().getMessage().contains("has state: deleting"))
|
&& e.getError().getMessage().contains("has state: deleting"))
|
||||||
return immediateFuture(null);
|
return null;
|
||||||
}
|
}
|
||||||
return valOnNotFoundOr404(null, t);
|
return valOnNotFoundOr404(null, t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,9 @@ import java.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.apis.ApiMetadata;
|
import org.jclouds.apis.ApiMetadata;
|
||||||
import org.jclouds.route53.config.Route53RestClientModule;
|
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
||||||
|
import org.jclouds.route53.config.Route53RestClientModule;
|
||||||
|
|
||||||
import com.google.common.reflect.TypeToken;
|
import com.google.common.reflect.TypeToken;
|
||||||
|
|
||||||
|
@ -59,7 +59,6 @@ public class Route53ApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
|
|
||||||
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
|
||||||
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.savvis.vpdc;
|
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.reflect.Reflection2.typeToken;
|
||||||
import static org.jclouds.savvis.vpdc.reference.VPDCConstants.PROPERTY_VPDC_TIMEOUT_TASK_COMPLETED;
|
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() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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 + "");
|
properties.setProperty(PROPERTY_VPDC_TIMEOUT_TASK_COMPLETED, 600l * 1000l + "");
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.vcloud.director.v1_5;
|
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_SESSION_INTERVAL;
|
||||||
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
|
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
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_TIMEOUT_TASK_COMPLETED;
|
||||||
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorConstants.PROPERTY_VCLOUD_DIRECTOR_VERSION_SCHEMA;
|
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() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
|
|
||||||
/** FIXME this should not be the default */
|
/** FIXME this should not be the default */
|
||||||
properties.setProperty(PROPERTY_SESSION_INTERVAL, Integer.toString(30 * 60));
|
properties.setProperty(PROPERTY_SESSION_INTERVAL, Integer.toString(30 * 60));
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.aws.ec2;
|
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 static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
@ -63,9 +60,6 @@ public class AWSEC2ApiMetadata extends EC2ApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = EC2ApiMetadata.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);
|
properties.remove(PROPERTY_EC2_AMI_OWNERS);
|
||||||
// auth fail sometimes happens in EC2, as the rc.local script that injects the
|
// auth fail sometimes happens in EC2, as the rc.local script that injects the
|
||||||
// authorized key executes after ssh has started.
|
// authorized key executes after ssh has started.
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.azureblob;
|
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.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
|
||||||
|
@ -67,10 +65,6 @@ public class AzureBlobApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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-");
|
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "x-ms-meta-");
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Throwables.propagate;
|
import static com.google.common.base.Throwables.propagate;
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
import org.jclouds.azure.storage.AzureStorageResponseException;
|
import org.jclouds.azure.storage.AzureStorageResponseException;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureFallback;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,14 +35,18 @@ public final class AzureBlobFallbacks {
|
||||||
private AzureBlobFallbacks() {
|
private AzureBlobFallbacks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class FalseIfContainerAlreadyExists implements FutureFallback<Boolean> {
|
public static final class FalseIfContainerAlreadyExists implements Fallback<Boolean> {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Boolean> create(Throwable t) {
|
public Boolean createOrPropagate(Throwable t) throws Exception {
|
||||||
if (checkNotNull(t, "throwable") instanceof AzureStorageResponseException) {
|
if (checkNotNull(t, "throwable") instanceof AzureStorageResponseException) {
|
||||||
AzureStorageResponseException responseException = AzureStorageResponseException.class.cast(t);
|
AzureStorageResponseException responseException = AzureStorageResponseException.class.cast(t);
|
||||||
if ("ContainerAlreadyExists".equals(responseException.getError().getCode())) {
|
if ("ContainerAlreadyExists".equals(responseException.getError().getCode())) {
|
||||||
return immediateFuture(false);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw propagate(t);
|
throw propagate(t);
|
||||||
|
|
|
@ -34,8 +34,9 @@ import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.options.GetOptions;
|
import org.jclouds.http.options.GetOptions;
|
||||||
import org.jclouds.reflect.Invocation;
|
import org.jclouds.reflect.Invocation;
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.reflect.Invokable;
|
import com.google.common.reflect.Invokable;
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ import com.google.common.reflect.Invokable;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class AzureBlobRequestSigner implements BlobRequestSigner {
|
public class AzureBlobRequestSigner implements BlobRequestSigner {
|
||||||
private final RestAnnotationProcessor processor;
|
private final Function<Invocation, HttpRequest> processor;
|
||||||
private final BlobToAzureBlob blobToBlob;
|
private final BlobToAzureBlob blobToBlob;
|
||||||
private final BlobToHttpGetOptions blob2HttpGetOptions;
|
private final BlobToHttpGetOptions blob2HttpGetOptions;
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ public class AzureBlobRequestSigner implements BlobRequestSigner {
|
||||||
private final Invokable<?, ?> createMethod;
|
private final Invokable<?, ?> createMethod;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AzureBlobRequestSigner(RestAnnotationProcessor processor, BlobToAzureBlob blobToBlob,
|
public AzureBlobRequestSigner(Function<Invocation, HttpRequest> processor, BlobToAzureBlob blobToBlob,
|
||||||
BlobToHttpGetOptions blob2HttpGetOptions) throws SecurityException, NoSuchMethodException {
|
BlobToHttpGetOptions blob2HttpGetOptions) throws SecurityException, NoSuchMethodException {
|
||||||
this.processor = checkNotNull(processor, "processor");
|
this.processor = checkNotNull(processor, "processor");
|
||||||
this.blobToBlob = checkNotNull(blobToBlob, "blobToBlob");
|
this.blobToBlob = checkNotNull(blobToBlob, "blobToBlob");
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.glesys;
|
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 static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -63,9 +60,6 @@ public class GleSYSApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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.max-retries", "5");
|
||||||
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.gogrid;
|
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 static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -62,7 +60,6 @@ public class GoGridApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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.max-retries", "5");
|
||||||
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -51,9 +51,8 @@ import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
||||||
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
|
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
|
||||||
import org.jclouds.openstack.swift.domain.SwiftObject;
|
import org.jclouds.openstack.swift.domain.SwiftObject;
|
||||||
import org.jclouds.reflect.Invocation;
|
import org.jclouds.reflect.Invocation;
|
||||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
@ -69,7 +68,7 @@ import com.google.inject.Provider;
|
||||||
@Singleton
|
@Singleton
|
||||||
public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner {
|
public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner {
|
||||||
|
|
||||||
private final RestAnnotationProcessor processor;
|
private final Function<Invocation, HttpRequest> processor;
|
||||||
private final Crypto crypto;
|
private final Crypto crypto;
|
||||||
|
|
||||||
private final Provider<Long> unixEpochTimestampProvider;
|
private final Provider<Long> unixEpochTimestampProvider;
|
||||||
|
@ -84,7 +83,7 @@ public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner
|
||||||
private final Invokable<?, ?> createMethod;
|
private final Invokable<?, ?> createMethod;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public HPCloudObjectStorageBlobRequestSigner(RestAnnotationProcessor processor,
|
public HPCloudObjectStorageBlobRequestSigner(Function<Invocation, HttpRequest> processor,
|
||||||
BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto,
|
BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto,
|
||||||
@TimeStamp Provider<Long> unixEpochTimestampProvider, Supplier<Access> access,
|
@TimeStamp Provider<Long> unixEpochTimestampProvider, Supplier<Access> access,
|
||||||
@org.jclouds.location.Provider final Supplier<Credentials> creds) throws SecurityException,
|
@org.jclouds.location.Provider final Supplier<Credentials> creds) throws SecurityException,
|
||||||
|
@ -115,8 +114,7 @@ public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner
|
||||||
public HttpRequest signGetBlob(String container, String name, long timeInSeconds) {
|
public HttpRequest signGetBlob(String container, String name, long timeInSeconds) {
|
||||||
checkNotNull(container, "container");
|
checkNotNull(container, "container");
|
||||||
checkNotNull(name, "name");
|
checkNotNull(name, "name");
|
||||||
GeneratedHttpRequest request = processor.apply(Invocation.create(getMethod,
|
HttpRequest request = processor.apply(Invocation.create(getMethod, ImmutableList.<Object> of(container, name)));
|
||||||
ImmutableList.<Object> of(container, name)));
|
|
||||||
return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
|
return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +138,7 @@ public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner
|
||||||
public HttpRequest signPutBlob(String container, Blob blob, long timeInSeconds) {
|
public HttpRequest signPutBlob(String container, Blob blob, long timeInSeconds) {
|
||||||
checkNotNull(container, "container");
|
checkNotNull(container, "container");
|
||||||
checkNotNull(blob, "blob");
|
checkNotNull(blob, "blob");
|
||||||
GeneratedHttpRequest request = processor.apply(Invocation.create(createMethod,
|
HttpRequest request = processor.apply(Invocation.create(createMethod,
|
||||||
ImmutableList.<Object> of(container, blobToObject.apply(blob))));
|
ImmutableList.<Object> of(container, blobToObject.apply(blob))));
|
||||||
return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
|
return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.softlayer;
|
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 static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -63,8 +60,6 @@ public class SoftLayerApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseRestApiMetadata.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.max-retries", "5");
|
||||||
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
||||||
return properties;
|
return properties;
|
||||||
|
|
Loading…
Reference in New Issue