diff --git a/aws/core/src/main/java/org/jclouds/aws/handlers/AWSRedirectionRetryHandler.java b/aws/core/src/main/java/org/jclouds/aws/handlers/AWSRedirectionRetryHandler.java index 942076d845..dd4a9674ed 100755 --- a/aws/core/src/main/java/org/jclouds/aws/handlers/AWSRedirectionRetryHandler.java +++ b/aws/core/src/main/java/org/jclouds/aws/handlers/AWSRedirectionRetryHandler.java @@ -57,7 +57,7 @@ public class AWSRedirectionRetryHandler extends RedirectionRetryHandler { && (response.getStatusCode() == 301 || response.getStatusCode() == 307)) { byte[] content = Utils.closeClientButKeepContentStream(response); if (command.getRequest().getMethod() == HttpMethod.HEAD) { - command.setMethod(HttpMethod.GET); + command.redirectAsGet(); return true; } else { command.incrementRedirectCount(); @@ -71,7 +71,7 @@ public class AWSRedirectionRetryHandler extends RedirectionRetryHandler { // http://developer.amazonwebservices.com/connect/thread.jspa?messageID=72287𑩟 return backoffHandler.shouldRetryRequest(command, response); } else { - command.setHostAndPort(host, command.getRequest().getEndpoint().getPort()); + command.redirect(host, command.getRequest().getEndpoint().getPort()); } return true; } else { diff --git a/aws/core/src/test/java/org/jclouds/aws/s3/util/S3UtilsTest.java b/aws/core/src/test/java/org/jclouds/aws/s3/util/S3UtilsTest.java index 15f55e8df3..089cc1daaf 100644 --- a/aws/core/src/test/java/org/jclouds/aws/s3/util/S3UtilsTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/s3/util/S3UtilsTest.java @@ -68,7 +68,7 @@ public class S3UtilsTest { @Override protected void configure() { bind(ExecutorService.class).toInstance(Executors.newCachedThreadPool()); -// bind(new TypeLiteral>(){}).to + // bind(new TypeLiteral>(){}).to bindConstant().annotatedWith( Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to("user"); bindConstant().annotatedWith( @@ -99,12 +99,10 @@ public class S3UtilsTest { return false; } - public HttpRequest setHostAndPort(String host, int port) { - return null; + public void redirect(String host, int port) { } - public HttpRequest setMethod(String method) { - return null; + public void redirectAsGet() { } public Exception getException() { @@ -126,6 +124,10 @@ public class S3UtilsTest { public void setException(Exception exception) { } + + @Override + public void redirectPath(String newPath) { + } }; } diff --git a/core/src/main/java/org/jclouds/http/HttpCommand.java b/core/src/main/java/org/jclouds/http/HttpCommand.java index 9de3d4209d..e60194af5b 100644 --- a/core/src/main/java/org/jclouds/http/HttpCommand.java +++ b/core/src/main/java/org/jclouds/http/HttpCommand.java @@ -43,10 +43,15 @@ public interface HttpCommand extends EndpointCommand implements TransformingHttpCommand transformer; private final Function exceptionTransformer; - private HttpRequest request; + private GeneratedHttpRequest request; private volatile int failureCount; @Resource @@ -63,7 +65,7 @@ public class TransformingHttpCommandImpl implements TransformingHttpCommand transformer, + GeneratedHttpRequest request, Function transformer, @Nullable Function exceptionTransformer) { this.request = request; this.executorService = executorService; @@ -91,13 +93,12 @@ public class TransformingHttpCommandImpl implements TransformingHttpCommand * This also removes the Host header in order to avoid ssl problems. */ - public HttpRequest setHostAndPort(String host, int port) { + public void redirect(String host, int port) { UriBuilder builder = UriBuilder.fromUri(request.getEndpoint()); builder.host(host); builder.port(port); request.setEndpoint(builder.build()); request.getHeaders().replaceValues(HttpHeaders.HOST, Collections.singletonList(host)); - return request; } /** @@ -105,9 +106,8 @@ public class TransformingHttpCommandImpl implements TransformingHttpCommand implements TransformingHttpCommand create(HttpRequest request, + public TransformingHttpCommand create(GeneratedHttpRequest request, Function transformer, Function exceptionTransformer) { return new TransformingHttpCommandImpl(executorService, request, transformer, exceptionTransformer); diff --git a/core/src/main/java/org/jclouds/rest/domain/NamedResource.java b/core/src/main/java/org/jclouds/rest/domain/NamedResource.java new file mode 100644 index 0000000000..16cc978bb7 --- /dev/null +++ b/core/src/main/java/org/jclouds/rest/domain/NamedResource.java @@ -0,0 +1,16 @@ +package org.jclouds.rest.domain; + +import org.jclouds.rest.internal.NamedResourceImpl; + +import com.google.inject.ImplementedBy; + +/** + * Location of a Rest resource + * + * @author Adrian Cole + * + */ +@ImplementedBy(NamedResourceImpl.class) +public interface NamedResource extends NamedLink, Comparable { + String getId(); +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java b/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java index 1080b6975f..318b61ea08 100755 --- a/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java +++ b/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java @@ -41,7 +41,6 @@ import javax.inject.Singleton; import org.jclouds.concurrent.FutureExceptionParser; import org.jclouds.http.HttpConstants; -import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.http.TransformingHttpCommand; import org.jclouds.logging.Logger; @@ -169,7 +168,7 @@ public class AsyncRestClientProxy implements InvocationHandler { } public static interface Factory { - public TransformingHttpCommand create(HttpRequest request, + public TransformingHttpCommand create(GeneratedHttpRequest request, Function transformer, @Nullable Function exceptionTransformer); } diff --git a/core/src/main/java/org/jclouds/rest/internal/NamedResourceImpl.java b/core/src/main/java/org/jclouds/rest/internal/NamedResourceImpl.java new file mode 100644 index 0000000000..f5bd11f769 --- /dev/null +++ b/core/src/main/java/org/jclouds/rest/internal/NamedResourceImpl.java @@ -0,0 +1,60 @@ +package org.jclouds.rest.internal; + +import java.net.URI; + +import org.jclouds.rest.domain.NamedResource; +import org.jclouds.rest.domain.internal.NamedLinkImpl; + +/** + * Location of a Rest resource + * + * @author Adrian Cole + * + */ +public class NamedResourceImpl extends NamedLinkImpl implements NamedResource { + private final String id; + + public NamedResourceImpl(String id, String name, String type, URI location) { + super(name, type, location); + this.id = id; + } + + public String getId() { + return id; + } + + public int compareTo(NamedResource that) { + return (this == that) ? 0 : this.id.compareTo(that.getId()); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + NamedResourceImpl other = (NamedResourceImpl) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + + @Override + public String toString() { + return "NamedResourceImpl [id=" + id + ", name=" + getName() + ", location=" + + getLocation() + ", type=" + getType() + "]"; + } +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/rest/util/Utils.java b/core/src/main/java/org/jclouds/rest/util/Utils.java index bce73c5e33..651a574330 100644 --- a/core/src/main/java/org/jclouds/rest/util/Utils.java +++ b/core/src/main/java/org/jclouds/rest/util/Utils.java @@ -28,8 +28,10 @@ import java.util.Map; import org.jclouds.rest.domain.Link; import org.jclouds.rest.domain.NamedLink; +import org.jclouds.rest.domain.NamedResource; import org.jclouds.rest.domain.internal.LinkImpl; import org.jclouds.rest.domain.internal.NamedLinkImpl; +import org.jclouds.rest.internal.NamedResourceImpl; import org.xml.sax.Attributes; /** @@ -52,4 +54,15 @@ public class Utils { .getValue(attributes.getIndex("type")), URI.create(attributes.getValue(attributes .getIndex("href")))); } + + public static NamedResource newNamedResource(Attributes attributes) { + String uri = attributes.getValue(attributes.getIndex("href")); + String id = uri.substring(uri.lastIndexOf('/') + 1); + return new NamedResourceImpl(id, attributes.getValue(attributes.getIndex("name")), attributes + .getValue(attributes.getIndex("type")), URI.create(uri)); + } + + public static void putNamedResource(Map map, Attributes attributes) { + map.put(attributes.getValue(attributes.getIndex("name")), newNamedResource(attributes)); + } } diff --git a/core/src/test/java/org/jclouds/blobstore/integration/internal/StubAsyncBlobStore.java b/core/src/test/java/org/jclouds/blobstore/integration/internal/StubAsyncBlobStore.java index cc95dde8a7..738a6fd8a0 100755 --- a/core/src/test/java/org/jclouds/blobstore/integration/internal/StubAsyncBlobStore.java +++ b/core/src/test/java/org/jclouds/blobstore/integration/internal/StubAsyncBlobStore.java @@ -452,12 +452,10 @@ public class StubAsyncBlobStore implements AsyncBlobStore { return false; } - public HttpRequest setHostAndPort(String host, int port) { - return null; + public void redirect(String host, int port) { } - public HttpRequest setMethod(String method) { - return null; + public void redirectAsGet() { } public Exception getException() { @@ -479,6 +477,10 @@ public class StubAsyncBlobStore implements AsyncBlobStore { public void setException(Exception exception) { } + + @Override + public void redirectPath(String newPath) { + } }, response)); } diff --git a/core/src/test/java/org/jclouds/http/BaseJettyTest.java b/core/src/test/java/org/jclouds/http/BaseJettyTest.java index ab28449b99..89d487f054 100644 --- a/core/src/test/java/org/jclouds/http/BaseJettyTest.java +++ b/core/src/test/java/org/jclouds/http/BaseJettyTest.java @@ -66,22 +66,42 @@ import com.google.inject.TypeLiteral; public abstract class BaseJettyTest { + public static final class IntegrationContextBuilder extends + RestContextBuilder { + private final int testPort; + + public IntegrationContextBuilder(Properties properties, int testPort) { + super(new TypeLiteral() { + }, new TypeLiteral() { + }, properties); + this.testPort = testPort; + } + + @Override + protected void addContextModule(List modules) { + modules.add(new JettyContextModule(properties, testPort)); + } + + @Override + protected void addClientModule(List modules) { + modules.add(new RestIntegrationTestClientModule()); + } + } + @ConfiguresRestClient @RequiresHttp - private final class RestIntegrationTestClientModule extends AbstractModule { + public static class RestIntegrationTestClientModule extends AbstractModule { @Override protected void configure() { } - @SuppressWarnings("unused") @Provides @Singleton public IntegrationTestAsyncClient provideAsyncClient(RestClientFactory factory) { return factory.create(IntegrationTestAsyncClient.class); } - @SuppressWarnings("unused") @Provides @Singleton public IntegrationTestClient provideClient(IntegrationTestAsyncClient client) @@ -90,7 +110,7 @@ public abstract class BaseJettyTest { } } - private final class JettyContextModule extends AbstractModule { + public static class JettyContextModule extends AbstractModule { private final Properties properties; private final int testPort; @@ -106,7 +126,7 @@ public abstract class BaseJettyTest { URI.create("http://localhost:" + testPort)); } - @SuppressWarnings( { "unchecked", "unused" }) + @SuppressWarnings( { "unchecked" }) @Provides @Singleton RestContext provideContext(Closer closer, @@ -214,27 +234,18 @@ public abstract class BaseJettyTest { final Properties properties = new Properties(); addConnectionProperties(properties); - context = new RestContextBuilder( - new TypeLiteral() { - }, new TypeLiteral() { - }, properties) { - - @Override - protected void addContextModule(List modules) { - modules.add(new JettyContextModule(properties, testPort)); - } - - @Override - protected void addClientModule(List modules) { - modules.add(new RestIntegrationTestClientModule()); - } - }.withModules(createConnectionModule()).buildContext(); + context = newBuilder(testPort, properties, createConnectionModule()).buildContext(); client = context.getApi(); assert client != null; assert client.newStringBuffer() != null; } + public static RestContextBuilder newBuilder( + final int testPort, final Properties properties, Module connectionModule) { + return new IntegrationContextBuilder(properties, testPort).withModules(connectionModule); + } + @AfterTest public void tearDownJetty() throws Exception { context.close(); diff --git a/core/src/test/java/org/jclouds/http/handlers/BackoffLimitedRetryHandlerTest.java b/core/src/test/java/org/jclouds/http/handlers/BackoffLimitedRetryHandlerTest.java index 15d1facc0b..5e80ac33f9 100644 --- a/core/src/test/java/org/jclouds/http/handlers/BackoffLimitedRetryHandlerTest.java +++ b/core/src/test/java/org/jclouds/http/handlers/BackoffLimitedRetryHandlerTest.java @@ -28,24 +28,30 @@ import static org.testng.Assert.assertTrue; import java.io.IOException; import java.io.InputStream; -import java.net.URI; +import java.lang.reflect.Method; +import java.util.Properties; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.jclouds.http.BaseJettyTest; import org.jclouds.http.HttpCommand; -import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; +import org.jclouds.http.IntegrationTestAsyncClient; import org.jclouds.http.TransformingHttpCommandExecutorServiceImpl; import org.jclouds.http.TransformingHttpCommandImpl; import org.jclouds.http.functions.ReturnStringIf200; -import org.jclouds.http.internal.JavaUrlHttpCommandExecutorService; import org.jclouds.http.internal.HttpWire; +import org.jclouds.http.internal.JavaUrlHttpCommandExecutorService; import org.jclouds.logging.Logger; import org.jclouds.logging.Logger.LoggerFactory; +import org.jclouds.rest.internal.RestAnnotationProcessor; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.common.base.Function; +import com.google.inject.AbstractModule; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; @Test(groups = "unit", testName = "core.BackoffLimitedRetryHandler") public class BackoffLimitedRetryHandlerTest { @@ -58,32 +64,32 @@ public class BackoffLimitedRetryHandlerTest { long startTime = System.nanoTime(); handler.imposeBackoffExponentialDelay(1, "TEST FAILURE: 1"); - long elapsedTime = (System.nanoTime() - startTime)/1000000; + long elapsedTime = (System.nanoTime() - startTime) / 1000000; assertTrue(elapsedTime >= 50); assertTrue(elapsedTime < 50 + acceptableDelay); startTime = System.nanoTime(); handler.imposeBackoffExponentialDelay(2, "TEST FAILURE: 2"); - elapsedTime = (System.nanoTime() - startTime)/1000000; + elapsedTime = (System.nanoTime() - startTime) / 1000000; assertTrue(elapsedTime >= 200); assertTrue(elapsedTime < 200 + acceptableDelay); startTime = System.nanoTime(); handler.imposeBackoffExponentialDelay(3, "TEST FAILURE: 3"); - elapsedTime = (System.nanoTime() - startTime)/1000000; + elapsedTime = (System.nanoTime() - startTime) / 1000000; assertTrue(elapsedTime >= 450); assertTrue(elapsedTime < 450 + acceptableDelay); startTime = System.nanoTime(); handler.imposeBackoffExponentialDelay(4, "TEST FAILURE: 4"); - elapsedTime = (System.nanoTime() - startTime)/1000000; + elapsedTime = (System.nanoTime() - startTime) / 1000000; assertTrue(elapsedTime >= 800); assertTrue(elapsedTime < 800 + acceptableDelay); startTime = System.nanoTime(); handler.imposeBackoffExponentialDelay(5, "TEST FAILURE: 5"); - elapsedTime = (System.nanoTime() - startTime)/1000000; - assert (elapsedTime >= 1249) : elapsedTime ; + elapsedTime = (System.nanoTime() - startTime) / 1000000; + assert (elapsedTime >= 1249) : elapsedTime; assertTrue(elapsedTime < 1250 + acceptableDelay); } @@ -93,8 +99,8 @@ public class BackoffLimitedRetryHandlerTest { void setupExecutorService() throws Exception { ExecutorService execService = Executors.newCachedThreadPool(); JavaUrlHttpCommandExecutorService httpService = new JavaUrlHttpCommandExecutorService( - execService, new DelegatingRetryHandler(), new DelegatingErrorHandler(), new HttpWire( - Executors.newCachedThreadPool())); + execService, new DelegatingRetryHandler(), new DelegatingErrorHandler(), + new HttpWire(Executors.newCachedThreadPool())); executorService = new TransformingHttpCommandExecutorServiceImpl(httpService, execService, new LoggerFactory() { @@ -106,7 +112,8 @@ public class BackoffLimitedRetryHandlerTest { } @Test - void testClosesInputStream() throws InterruptedException, IOException { + void testClosesInputStream() throws InterruptedException, IOException, SecurityException, + NoSuchMethodException { HttpCommand command = createCommand(); HttpResponse response = new HttpResponse(); @@ -145,11 +152,26 @@ public class BackoffLimitedRetryHandlerTest { assertEquals(response.getContent().read(), -1); } - private final HttpRequest request = new HttpRequest("GET", URI.create("http://localhost")); + private final RestAnnotationProcessor processor = BaseJettyTest + .newBuilder(8100, new Properties(), new AbstractModule() { - private HttpCommand createCommand() { - HttpCommand command = new TransformingHttpCommandImpl(executorService, request, - new ReturnStringIf200(), new Function() { + @Override + protected void configure() { + + } + }) + .buildInjector() + .getInstance( + Key + .get(new TypeLiteral>() { + })); + + private HttpCommand createCommand() throws SecurityException, NoSuchMethodException { + Method method = IntegrationTestAsyncClient.class.getMethod("download", String.class); + + HttpCommand command = new TransformingHttpCommandImpl(executorService, processor + .createRequest(method, "1"), new ReturnStringIf200(), + new Function() { public String apply(Exception from) { return null; } @@ -158,7 +180,8 @@ public class BackoffLimitedRetryHandlerTest { } @Test - void testIncrementsFailureCount() throws InterruptedException, IOException { + void testIncrementsFailureCount() throws InterruptedException, IOException, SecurityException, + NoSuchMethodException { HttpCommand command = createCommand(); HttpResponse response = new HttpResponse(); @@ -173,7 +196,8 @@ public class BackoffLimitedRetryHandlerTest { } @Test - void testDisallowsExcessiveRetries() throws InterruptedException, IOException { + void testDisallowsExcessiveRetries() throws InterruptedException, IOException, + SecurityException, NoSuchMethodException { HttpCommand command = createCommand(); HttpResponse response = new HttpResponse(); diff --git a/extensions/gae/src/main/java/org/jclouds/gae/GaeHttpCommandExecutorService.java b/extensions/gae/src/main/java/org/jclouds/gae/GaeHttpCommandExecutorService.java index 4e19b9092f..a227785dca 100644 --- a/extensions/gae/src/main/java/org/jclouds/gae/GaeHttpCommandExecutorService.java +++ b/extensions/gae/src/main/java/org/jclouds/gae/GaeHttpCommandExecutorService.java @@ -158,7 +158,7 @@ public class GaeHttpCommandExecutorService extends BaseHttpCommandExecutorServic HttpRequest request = command.getRequest(); String hostHeader = request.getFirstHeaderOrNull(HttpHeaders.HOST); if (hostHeader != null) { - command.setHostAndPort(hostHeader, request.getEndpoint().getPort()); + command.redirect(hostHeader, request.getEndpoint().getPort()); } }