From 09ba1d1360b4bec3fcac36d978577465df08f1d1 Mon Sep 17 00:00:00 2001 From: "adrian.f.cole" Date: Fri, 12 Jun 2009 16:47:40 +0000 Subject: [PATCH] Issue 61: refactored core S3 to allow different error handling and xml parsing git-svn-id: http://jclouds.googlecode.com/svn/trunk@1428 3d8758e0-26b5-11de-8745-db77d3ebf521 --- .../org/jclouds/aws/s3/S3ContextFactory.java | 110 +++++++++--------- .../s3/commands/config/S3CommandsModule.java | 60 +++++----- .../aws/s3/config/LiveS3ConnectionModule.java | 13 ++- .../aws/s3/xml/config/S3ParserModule.java | 35 +++--- .../aws/s3/commands/S3CommandFactoryTest.java | 3 +- .../aws/s3/config/S3ContextModuleTest.java | 37 +++--- 6 files changed, 129 insertions(+), 129 deletions(-) diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3ContextFactory.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3ContextFactory.java index 5796eb6217..cc93d2c76f 100644 --- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3ContextFactory.java +++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3ContextFactory.java @@ -44,6 +44,7 @@ import java.util.Properties; import org.jclouds.aws.s3.config.LiveS3ConnectionModule; import org.jclouds.aws.s3.config.S3ConnectionModule; import org.jclouds.aws.s3.config.S3ContextModule; +import org.jclouds.aws.s3.xml.config.S3ParserModule; import org.jclouds.http.config.HttpFutureCommandClientModule; import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule; import org.jclouds.logging.config.LoggingModule; @@ -73,13 +74,13 @@ import com.google.inject.name.Names; * @see S3Context */ public class S3ContextFactory { - + private static final String DEFAULT_SECURE_HTTP_PORT = "443"; private static final String DEFAULT_NON_SECURE_HTTP_PORT = "80"; - - private final Properties properties; + + private final Properties properties; private final List modules = new ArrayList(3); - + private S3ContextFactory(Properties properties) { this.properties = properties; } @@ -87,9 +88,11 @@ public class S3ContextFactory { public static S3ContextFactory createContext(String awsAccessKeyId, String awsSecretAccessKey) { Properties properties = new Properties(); - properties.setProperty(PROPERTY_AWS_ACCESSKEYID, checkNotNull(awsAccessKeyId, "awsAccessKeyId")); - properties.setProperty(PROPERTY_AWS_SECRETACCESSKEY, checkNotNull(awsSecretAccessKey,"awsSecretAccessKey")); - + properties.setProperty(PROPERTY_AWS_ACCESSKEYID, checkNotNull(awsAccessKeyId, + "awsAccessKeyId")); + properties.setProperty(PROPERTY_AWS_SECRETACCESSKEY, checkNotNull(awsSecretAccessKey, + "awsSecretAccessKey")); + properties.setProperty(PROPERTY_HTTP_ADDRESS, "s3.amazonaws.com"); properties.setProperty(PROPERTY_HTTP_SECURE, "true"); properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, "5"); @@ -98,89 +101,68 @@ public class S3ContextFactory { properties.setProperty(PROPERTY_POOL_REQUEST_INVOKER_THREADS, "1"); properties.setProperty(PROPERTY_POOL_IO_WORKER_THREADS, "2"); properties.setProperty(PROPERTY_POOL_MAX_CONNECTIONS, "12"); - + return new S3ContextFactory(properties); } public S3Context build() { return createInjector().getInstance(S3Context.class); } - + public static Injector createInjector(String awsAccessKeyId, String awsSecretAccessKey, Module... modules) { - return createContext(awsAccessKeyId, awsSecretAccessKey) - .withModules(modules) + return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules) .createInjector(); } public static S3Context createS3Context(String awsAccessKeyId, String awsSecretAccessKey, Module... modules) { - return createContext(awsAccessKeyId, awsSecretAccessKey) - .withModules(modules) - .build(); + return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).build(); } public static Injector createInjector(String awsAccessKeyId, String awsSecretAccessKey, boolean isSecure, Module... modules) { - return createContext(awsAccessKeyId, awsSecretAccessKey) - .withModules(modules) - .withHttpSecure(isSecure) - .createInjector(); + return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).withHttpSecure( + isSecure).createInjector(); } public static S3Context createS3Context(String awsAccessKeyId, String awsSecretAccessKey, boolean isSecure, Module... modules) { - - return createContext(awsAccessKeyId, awsSecretAccessKey) - .withModules(modules) - .withHttpSecure(isSecure) - .build(); + + return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).withHttpSecure( + isSecure).build(); } public static Injector createInjector(String awsAccessKeyId, String awsSecretAccessKey, boolean isSecure, String server, Module... modules) { - return createContext(awsAccessKeyId, awsSecretAccessKey) - .withModules(modules) - .withHttpSecure(isSecure) - .withHttpAddress(server) - .createInjector(); + return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).withHttpSecure( + isSecure).withHttpAddress(server).createInjector(); } public static S3Context createS3Context(String awsAccessKeyId, String awsSecretAccessKey, boolean isSecure, String server, Module... modules) { - return createContext(awsAccessKeyId, awsSecretAccessKey) - .withModules(modules) - .withHttpSecure(isSecure) - .withHttpAddress(server) - .build(); + return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).withHttpSecure( + isSecure).withHttpAddress(server).build(); } public static S3Context createS3Context(String awsAccessKeyId, String awsSecretAccessKey, boolean isSecure, String server, int port, Module... modules) { - return createContext(awsAccessKeyId, awsSecretAccessKey) - .withModules(modules) - .withHttpSecure(isSecure) - .withHttpAddress(server) - .withHttpPort(port) - .build(); + return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).withHttpSecure( + isSecure).withHttpAddress(server).withHttpPort(port).build(); } public static Injector createInjector(String awsAccessKeyId, String awsSecretAccessKey, boolean isSecure, String server, int port, Module... modules) { - return createContext(awsAccessKeyId, awsSecretAccessKey) - .withModules(modules) - .withHttpSecure(isSecure) - .withHttpAddress(server) - .withHttpPort(port) - .createInjector(); + return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).withHttpSecure( + isSecure).withHttpAddress(server).withHttpPort(port).createInjector(); } public S3ContextFactory withHttpAddress(String httpAddress) { properties.setProperty(PROPERTY_HTTP_ADDRESS, httpAddress); return this; } - + public S3ContextFactory withHttpMaxRetries(int httpMaxRetries) { properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, Integer.toString(httpMaxRetries)); return this; @@ -197,25 +179,29 @@ public class S3ContextFactory { } public S3ContextFactory withPoolMaxConnectionReuse(int poolMaxConnectionReuse) { - properties.setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, Integer.toString(poolMaxConnectionReuse)); + properties.setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, Integer + .toString(poolMaxConnectionReuse)); return this; } public S3ContextFactory withPoolMaxSessionFailures(int poolMaxSessionFailures) { - properties.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, Integer.toString(poolMaxSessionFailures)); + properties.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, Integer + .toString(poolMaxSessionFailures)); return this; } public S3ContextFactory withPoolRequestInvokerThreads(int poolRequestInvokerThreads) { - properties.setProperty(PROPERTY_POOL_REQUEST_INVOKER_THREADS, Integer.toString(poolRequestInvokerThreads)); + properties.setProperty(PROPERTY_POOL_REQUEST_INVOKER_THREADS, Integer + .toString(poolRequestInvokerThreads)); return this; } public S3ContextFactory withPoolIoWorkerThreads(int poolIoWorkerThreads) { - properties.setProperty(PROPERTY_POOL_IO_WORKER_THREADS, Integer.toString(poolIoWorkerThreads)); + properties + .setProperty(PROPERTY_POOL_IO_WORKER_THREADS, Integer.toString(poolIoWorkerThreads)); return this; } @@ -224,30 +210,32 @@ public class S3ContextFactory { properties.setProperty(PROPERTY_POOL_MAX_CONNECTIONS, Integer.toString(poolMaxConnections)); return this; } - + public S3ContextFactory withModule(Module module) { modules.add(module); return this; } - + public S3ContextFactory withModules(Module... modules) { this.modules.addAll(Arrays.asList(modules)); return this; } - + private Injector createInjector() { /* Use 80 or 443 as the default port if one hasn't been set? */ - if(!properties.containsKey(PROPERTY_HTTP_PORT)) { - if(Boolean.parseBoolean(properties.getProperty(PROPERTY_HTTP_SECURE))) { + if (!properties.containsKey(PROPERTY_HTTP_PORT)) { + if (Boolean.parseBoolean(properties.getProperty(PROPERTY_HTTP_SECURE))) { properties.setProperty(PROPERTY_HTTP_PORT, DEFAULT_SECURE_HTTP_PORT); } else { properties.setProperty(PROPERTY_HTTP_PORT, DEFAULT_NON_SECURE_HTTP_PORT); } } - + addLoggingModuleIfNotPresent(modules); + addS3ParserModuleIfNotPresent(modules); + addS3ConnectionModuleIfNotPresent(modules); addHttpModuleIfNeededAndNotPresent(modules); @@ -262,6 +250,16 @@ public class S3ContextFactory { }, new S3ContextModule()); } + @VisibleForTesting + static void addS3ParserModuleIfNotPresent(List modules) { + if (!Iterables.any(modules, new Predicate() { + public boolean apply(Module input) { + return input instanceof S3ParserModule; + } + + })) + modules.add(new S3ParserModule()); + } @VisibleForTesting static void addHttpModuleIfNeededAndNotPresent(final List modules) { diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/commands/config/S3CommandsModule.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/commands/config/S3CommandsModule.java index cc51b6030b..64b4c73101 100644 --- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/commands/config/S3CommandsModule.java +++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/commands/config/S3CommandsModule.java @@ -31,7 +31,6 @@ import org.jclouds.aws.s3.commands.HeadObject; import org.jclouds.aws.s3.commands.PutBucket; import org.jclouds.aws.s3.commands.PutObject; import org.jclouds.aws.s3.commands.S3CommandFactory; -import org.jclouds.aws.s3.xml.config.S3ParserModule; import com.google.inject.AbstractModule; import com.google.inject.assistedinject.FactoryProvider; @@ -42,45 +41,40 @@ import com.google.inject.assistedinject.FactoryProvider; * @author Adrian Cole */ public class S3CommandsModule extends AbstractModule { - @Override - protected void configure() { - install(new S3ParserModule()); + @Override + protected void configure() { - bind(S3CommandFactory.DeleteBucketFactory.class).toProvider( - FactoryProvider.newFactory( - S3CommandFactory.DeleteBucketFactory.class, - DeleteBucket.class)); + bind(S3CommandFactory.DeleteBucketFactory.class).toProvider( + FactoryProvider.newFactory(S3CommandFactory.DeleteBucketFactory.class, + DeleteBucket.class)); - bind(S3CommandFactory.DeleteObjectFactory.class).toProvider( - FactoryProvider.newFactory( - S3CommandFactory.DeleteObjectFactory.class, - DeleteObject.class)); + bind(S3CommandFactory.DeleteObjectFactory.class).toProvider( + FactoryProvider.newFactory(S3CommandFactory.DeleteObjectFactory.class, + DeleteObject.class)); - bind(S3CommandFactory.BucketExistsFactory.class).toProvider( - FactoryProvider.newFactory( - S3CommandFactory.BucketExistsFactory.class, - BucketExists.class)); + bind(S3CommandFactory.BucketExistsFactory.class).toProvider( + FactoryProvider.newFactory(S3CommandFactory.BucketExistsFactory.class, + BucketExists.class)); - bind(S3CommandFactory.PutBucketFactory.class).toProvider( - FactoryProvider.newFactory( - S3CommandFactory.PutBucketFactory.class, - PutBucket.class)); + bind(S3CommandFactory.PutBucketFactory.class) + .toProvider( + FactoryProvider.newFactory(S3CommandFactory.PutBucketFactory.class, + PutBucket.class)); - bind(S3CommandFactory.PutObjectFactory.class).toProvider( - FactoryProvider.newFactory( - S3CommandFactory.PutObjectFactory.class, - PutObject.class)); + bind(S3CommandFactory.PutObjectFactory.class) + .toProvider( + FactoryProvider.newFactory(S3CommandFactory.PutObjectFactory.class, + PutObject.class)); - bind(S3CommandFactory.GetObjectFactory.class).toProvider( - FactoryProvider.newFactory( - S3CommandFactory.GetObjectFactory.class, - GetObject.class)); + bind(S3CommandFactory.GetObjectFactory.class) + .toProvider( + FactoryProvider.newFactory(S3CommandFactory.GetObjectFactory.class, + GetObject.class)); - bind(S3CommandFactory.HeadMetadataFactory.class).toProvider( - FactoryProvider.newFactory( - S3CommandFactory.HeadMetadataFactory.class, - HeadObject.class)); + bind(S3CommandFactory.HeadMetadataFactory.class).toProvider( + FactoryProvider.newFactory(S3CommandFactory.HeadMetadataFactory.class, + HeadObject.class)); - } + } } \ No newline at end of file diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/LiveS3ConnectionModule.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/LiveS3ConnectionModule.java index 454236c675..53c987faa1 100644 --- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/LiveS3ConnectionModule.java +++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/LiveS3ConnectionModule.java @@ -73,17 +73,22 @@ public class LiveS3ConnectionModule extends AbstractModule { @Override protected void configure() { + bindResponseHandlers(); + bind(S3Connection.class).to(LiveS3Connection.class).in(Scopes.SINGLETON); + bind(HttpRetryHandler.class).annotatedWith(RetryHandler.class).to( + BackoffLimitedRetryHandler.class).in(Scopes.SINGLETON); + requestInjection(this); + logger.info("S3 Context = %1$s://%2$s:%3$s", (isSecure ? "https" : "http"), address, port); + } + + protected void bindResponseHandlers() { bind(HttpResponseHandler.class).annotatedWith(RedirectHandler.class).to( CloseContentAndSetExceptionHandler.class).in(Scopes.SINGLETON); bind(HttpResponseHandler.class).annotatedWith(ClientErrorHandler.class).to( ParseAWSErrorFromXmlContent.class).in(Scopes.SINGLETON); bind(HttpResponseHandler.class).annotatedWith(ServerErrorHandler.class).to( ParseAWSErrorFromXmlContent.class).in(Scopes.SINGLETON); - bind(HttpRetryHandler.class).annotatedWith(RetryHandler.class).to( - BackoffLimitedRetryHandler.class).in(Scopes.SINGLETON); - requestInjection(this); - logger.info("S3 Context = %1$s://%2$s:%3$s", (isSecure ? "https" : "http"), address, port); } @Provides diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java index e2734cff23..be03ffcc79 100644 --- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java +++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java @@ -48,34 +48,30 @@ import com.google.inject.assistedinject.FactoryProvider; * @author Adrian Cole */ public class S3ParserModule extends AbstractModule { - private final TypeLiteral>> listBucketsTypeLiteral = - new TypeLiteral>>() { + protected final TypeLiteral> errorTypeLiteral = new TypeLiteral>() { }; - private final TypeLiteral> bucketTypeLiteral = - new TypeLiteral>() { + protected final TypeLiteral>> listBucketsTypeLiteral = new TypeLiteral>>() { }; - private final TypeLiteral> objectMetadataTypeLiteral = - new TypeLiteral>() { + protected final TypeLiteral> bucketTypeLiteral = new TypeLiteral>() { }; - private final TypeLiteral> errorTypeLiteral = - new TypeLiteral>() { + protected final TypeLiteral> objectMetadataTypeLiteral = new TypeLiteral>() { }; - private final TypeLiteral> accessControlListTypeLiteral = - new TypeLiteral>() { + protected final TypeLiteral> accessControlListTypeLiteral = new TypeLiteral>() { }; @Override protected void configure() { install(new SaxModule()); + bindErrorHandler(); bindCallablesThatReturnParseResults(); bindParserImplementationsToReturnTypes(); } + protected void bindErrorHandler() { + bind(new TypeLiteral>() { + }).to(ErrorHandler.class); + } + private void bindParserImplementationsToReturnTypes() { bind(new TypeLiteral>>() { }).to(ListAllMyBucketsHandler.class); @@ -83,8 +79,6 @@ public class S3ParserModule extends AbstractModule { }).to(ListBucketHandler.class); bind(new TypeLiteral>() { }).to(CopyObjectHandler.class); - bind(new TypeLiteral>() { - }).to(ErrorHandler.class); bind(new TypeLiteral>() { }).to(AccessControlListHandler.class); } @@ -101,12 +95,13 @@ public class S3ParserModule extends AbstractModule { FactoryProvider.newFactory(objectMetadataTypeLiteral, new TypeLiteral>() { })); + bind(accessControlListTypeLiteral).toProvider( + FactoryProvider.newFactory(accessControlListTypeLiteral, + new TypeLiteral>() { + })); bind(errorTypeLiteral).toProvider( FactoryProvider.newFactory(errorTypeLiteral, new TypeLiteral>() { })); - bind(accessControlListTypeLiteral).toProvider( - FactoryProvider.newFactory(accessControlListTypeLiteral, - new TypeLiteral>() {})); } } \ No newline at end of file diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/S3CommandFactoryTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/S3CommandFactoryTest.java index 592bd4b60a..5d7f57a855 100644 --- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/S3CommandFactoryTest.java +++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/S3CommandFactoryTest.java @@ -35,6 +35,7 @@ import org.jclouds.aws.s3.commands.options.PutBucketOptions; import org.jclouds.aws.s3.commands.options.PutObjectOptions; import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; +import org.jclouds.aws.s3.xml.config.S3ParserModule; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; @@ -56,7 +57,7 @@ public class S3CommandFactoryTest { @BeforeTest void setUpInjector() { - injector = Guice.createInjector(new S3CommandsModule() { + injector = Guice.createInjector(new S3ParserModule(), new S3CommandsModule() { @Override protected void configure() { bindConstant().annotatedWith(Names.named("jclouds.http.address")).to("localhost"); diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/config/S3ContextModuleTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/config/S3ContextModuleTest.java index bae2774933..8236f6bace 100644 --- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/config/S3ContextModuleTest.java +++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/config/S3ContextModuleTest.java @@ -27,6 +27,7 @@ import static org.testng.Assert.assertEquals; import org.jclouds.aws.s3.handlers.ParseAWSErrorFromXmlContent; import org.jclouds.aws.s3.reference.S3Constants; +import org.jclouds.aws.s3.xml.config.S3ParserModule; import org.jclouds.http.HttpResponseHandler; import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.annotation.ClientErrorHandler; @@ -50,21 +51,27 @@ import com.google.inject.name.Names; public class S3ContextModuleTest { Injector createInjector() { - return Guice.createInjector(new LiveS3ConnectionModule(), new S3ContextModule() { - @Override - protected void configure() { - bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to( - "localhost"); - bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)).to( - "localhost"); - bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_ADDRESS)).to( - "localhost"); - bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_PORT)).to("1000"); - bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_SECURE)).to("false"); - bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_MAX_RETRIES)).to("5"); - super.configure(); - } - }, new JavaUrlHttpFutureCommandClientModule()); + return Guice.createInjector(new LiveS3ConnectionModule(), new S3ParserModule(), + new S3ContextModule() { + @Override + protected void configure() { + bindConstant() + .annotatedWith(Names.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to( + "localhost"); + bindConstant().annotatedWith( + Names.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)) + .to("localhost"); + bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_ADDRESS)) + .to("localhost"); + bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_PORT)).to( + "1000"); + bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_SECURE)) + .to("false"); + bindConstant().annotatedWith( + Names.named(S3Constants.PROPERTY_HTTP_MAX_RETRIES)).to("5"); + super.configure(); + } + }, new JavaUrlHttpFutureCommandClientModule()); } private static class ClientErrorHandlerTest {