diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3Context.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3Context.java index bb7018683e..711d0d7fda 100644 --- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3Context.java +++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3Context.java @@ -23,11 +23,13 @@ */ package org.jclouds.aws.s3; +import org.jclouds.cloud.CloudContext; + /** * Represents an authenticated context to S3. * - *

Note

Please issue {@link #close()} when you are finished with this - * context in order to release resources. + *

Note

Please issue {@link #close()} when you are finished with this context in order to + * release resources. * * * @see S3Connection @@ -36,33 +38,20 @@ package org.jclouds.aws.s3; * @author Adrian Cole * */ -public interface S3Context { +public interface S3Context extends CloudContext { - /** - * low-level api to S3. Threadsafe implementations will return a singleton. - * - * @return a connection to S3 - */ - S3Connection getConnection(); + /** + * Creates a Map view of the specified bucket. + * + * @param bucket + */ + S3InputStreamMap createInputStreamMap(String bucket); - /** - * Creates a Map view of the specified - * bucket. - * - * @param bucket - */ - S3InputStreamMap createInputStreamMap(String bucket); - - /** - * Creates a Map view of the specified bucket. - * - * @param bucket - */ - S3ObjectMap createS3ObjectMap(String bucket); - - /** - * Closes all connections to S3. - */ - void close(); + /** + * Creates a Map view of the specified bucket. + * + * @param bucket + */ + S3ObjectMap createS3ObjectMap(String bucket); } \ No newline at end of file diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3ContextBuilder.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3ContextBuilder.java new file mode 100644 index 0000000000..6d7a484ab3 --- /dev/null +++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/S3ContextBuilder.java @@ -0,0 +1,113 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.aws.s3; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID; +import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY; +import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_IO_WORKER_THREADS; +import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS; +import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE; +import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES; +import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_REQUEST_INVOKER_THREADS; +import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_ADDRESS; +import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_REDIRECTS; +import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_RETRIES; +import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_SECURE; +import static org.jclouds.http.HttpConstants.PROPERTY_SAX_DEBUG; + +import java.util.List; +import java.util.Properties; + +import org.jclouds.aws.s3.config.LiveS3ConnectionModule; +import org.jclouds.aws.s3.config.S3ContextModule; +import org.jclouds.aws.s3.xml.config.S3ParserModule; +import org.jclouds.cloud.CloudContextBuilder; +import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule; +import org.jclouds.logging.jdk.config.JDKLoggingModule; + +import com.google.inject.Injector; +import com.google.inject.Module; + +/** + * Creates {@link S3Context} or {@link Injector} instances based on the most commonly requested + * arguments. + *

+ * Note that Threadsafe objects will be bound as singletons to the Injector or Context provided. + *

+ *

+ * If no Modules are specified, the default {@link JDKLoggingModule logging} and + * {@link JavaUrlHttpFutureCommandClientModule http transports} will be installed. + * + * @author Adrian Cole, Andrew Newdigate + * @see S3Context + */ +public class S3ContextBuilder extends CloudContextBuilder { + + public S3ContextBuilder(Properties props) { + super(props); + } + + public static S3ContextBuilder newBuilder(String id, String secret) { + Properties properties = new Properties(); + + properties.setProperty(PROPERTY_HTTP_ADDRESS, "s3.amazonaws.com"); + properties.setProperty(PROPERTY_SAX_DEBUG, "false"); + properties.setProperty(PROPERTY_HTTP_SECURE, "true"); + properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, "5"); + properties.setProperty(PROPERTY_HTTP_MAX_REDIRECTS, "5"); + properties.setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, "75"); + properties.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, "2"); + properties.setProperty(PROPERTY_POOL_REQUEST_INVOKER_THREADS, "1"); + properties.setProperty(PROPERTY_POOL_IO_WORKER_THREADS, "2"); + properties.setProperty(PROPERTY_POOL_MAX_CONNECTIONS, "12"); + + S3ContextBuilder builder = new S3ContextBuilder(properties); + builder.authenticate(id, secret); + return builder; + } + + public void authenticate(String id, String secret) { + properties.setProperty(PROPERTY_AWS_ACCESSKEYID, checkNotNull(id, "awsAccessKeyId")); + properties.setProperty(PROPERTY_AWS_SECRETACCESSKEY, checkNotNull(secret, + "awsSecretAccessKey")); + } + + public S3Context buildContext() { + return buildInjector().getInstance(S3Context.class); + } + + protected void addParserModule(List modules) { + modules.add(new S3ParserModule()); + } + + protected void addContextModule(List modules) { + modules.add(new S3ContextModule()); + } + + protected void addConnectionModule(List modules) { + modules.add(new LiveS3ConnectionModule()); + } + +} 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 2a7224b011..a04420e8ea 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 @@ -23,47 +23,13 @@ */ package org.jclouds.aws.s3; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID; -import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY; -import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_IO_WORKER_THREADS; -import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS; -import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE; -import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES; -import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_REQUEST_INVOKER_THREADS; -import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_ADDRESS; -import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_REDIRECTS; -import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_RETRIES; -import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_PORT; -import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_SECURE; -import static org.jclouds.http.HttpConstants.PROPERTY_SAX_DEBUG; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -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; import org.jclouds.logging.jdk.config.JDKLoggingModule; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.collect.Iterables; -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Injector; import com.google.inject.Module; -import com.google.inject.name.Names; /** - * Creates {@link S3Context} or {@link Injector} instances based on the most commonly requested + * Creates {@link S3Context} instances based on the most commonly requested * arguments. *

* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided. @@ -77,245 +43,10 @@ import com.google.inject.name.Names; */ 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 List modules = new ArrayList(3); - - private S3ContextFactory(Properties properties) { - this.properties = properties; - } - - 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_SAX_DEBUG, "false"); - properties.setProperty(PROPERTY_HTTP_ADDRESS, "s3.amazonaws.com"); - properties.setProperty(PROPERTY_HTTP_SECURE, "true"); - properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, "5"); - properties.setProperty(PROPERTY_HTTP_MAX_REDIRECTS, "5"); - properties.setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, "75"); - properties.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, "2"); - 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) - .createInjector(); - } - public static S3Context createS3Context(String awsAccessKeyId, String awsSecretAccessKey, Module... modules) { - return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).build(); - + return S3ContextBuilder.newBuilder(awsAccessKeyId, awsSecretAccessKey).withModules(modules) + .buildContext(); } - public static Injector createInjector(String awsAccessKeyId, String awsSecretAccessKey, - boolean isSecure, Module... modules) { - 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(); - } - - 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(); - } - - 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(); - } - - 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(); - } - - 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(); - } - - public S3ContextFactory withHttpAddress(String httpAddress) { - properties.setProperty(PROPERTY_HTTP_ADDRESS, httpAddress); - return this; - } - - public S3ContextFactory withSaxDebug() { - properties.setProperty(PROPERTY_SAX_DEBUG, "true"); - return this; - } - - public S3ContextFactory withHttpMaxRetries(int httpMaxRetries) { - properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, Integer.toString(httpMaxRetries)); - return this; - } - - public S3ContextFactory withHttpMaxRedirects(int httpMaxRedirects) { - properties.setProperty(PROPERTY_HTTP_MAX_REDIRECTS, Integer.toString(httpMaxRedirects)); - return this; - } - - public S3ContextFactory withHttpPort(int httpPort) { - properties.setProperty(PROPERTY_HTTP_PORT, Integer.toString(httpPort)); - return this; - } - - public S3ContextFactory withHttpSecure(boolean httpSecure) { - properties.setProperty(PROPERTY_HTTP_SECURE, Boolean.toString(httpSecure)); - return this; - } - - public S3ContextFactory withPoolMaxConnectionReuse(int 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)); - return this; - - } - - public S3ContextFactory withPoolRequestInvokerThreads(int 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)); - return this; - - } - - public S3ContextFactory withPoolMaxConnections(int poolMaxConnections) { - 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() { - - useDefaultPortIfNotPresent(properties); - - addLoggingModuleIfNotPresent(modules); - - addS3ParserModuleIfNotPresent(modules); - - addS3ConnectionModuleIfNotPresent(modules); - - addHttpModuleIfNeededAndNotPresent(modules); - - modules.add(new AbstractModule() { - @Override - protected void configure() { - Names.bindProperties(binder(), checkNotNull(properties, "properties")); - } - }); - modules.add(new S3ContextModule()); - - return Guice.createInjector(modules); - } - - private void useDefaultPortIfNotPresent(Properties properties) { - /* 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))) { - properties.setProperty(PROPERTY_HTTP_PORT, DEFAULT_SECURE_HTTP_PORT); - } else { - properties.setProperty(PROPERTY_HTTP_PORT, DEFAULT_NON_SECURE_HTTP_PORT); - } - } - } - - @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) { - if (Iterables.any(modules, new Predicate() { - public boolean apply(Module input) { - return input instanceof LiveS3ConnectionModule; - } - - }) && (!Iterables.any(modules, new Predicate() { - public boolean apply(Module input) { - return input.getClass().isAnnotationPresent(HttpFutureCommandClientModule.class); - } - - }))) - modules.add(new JavaUrlHttpFutureCommandClientModule()); - } - - @VisibleForTesting - static void addS3ConnectionModuleIfNotPresent(final List modules) { - if (!Iterables.any(modules, new Predicate() { - public boolean apply(Module input) { - return input.getClass().isAnnotationPresent(S3ConnectionModule.class); - } - - })) { - modules.add(0, new LiveS3ConnectionModule()); - } - } - - @VisibleForTesting - static void addLoggingModuleIfNotPresent(final List modules) { - if (!Iterables.any(modules, Predicates.instanceOf(LoggingModule.class))) - modules.add(new JDKLoggingModule()); - } - - @VisibleForTesting - Properties getProperties() { - return properties; - } } 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 e139990273..08aeaedb3c 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 @@ -36,10 +36,12 @@ import org.jclouds.aws.s3.handlers.AWSClientErrorRetryHandler; import org.jclouds.aws.s3.handlers.AWSRedirectionRetryHandler; import org.jclouds.aws.s3.handlers.ParseAWSErrorFromXmlContent; import org.jclouds.aws.s3.internal.LiveS3Connection; +import org.jclouds.cloud.ConfiguresCloudConnection; import org.jclouds.http.HttpConstants; import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRetryHandler; +import org.jclouds.http.RequiresHttp; import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; @@ -57,7 +59,8 @@ import com.google.inject.name.Named; * * @author Adrian Cole */ -@S3ConnectionModule +@ConfiguresCloudConnection +@RequiresHttp public class LiveS3ConnectionModule extends AbstractModule { @Resource protected Logger logger = Logger.NULL; diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java index 71ee591a6d..b01356c7fa 100644 --- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java +++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java @@ -68,14 +68,14 @@ public abstract class BaseS3Map implements S3Map { * maximum duration of an S3 Request */ @Inject(optional = true) - @Named(S3Constants.PROPERTY_S3_MAP_TIMEOUT) + @Named(S3Constants.PROPERTY_OBJECTMAP_TIMEOUT) protected long requestTimeoutMilliseconds = 10000; /** * time to pause before retrying a transient failure */ @Inject(optional = true) - @Named(S3Constants.PROPERTY_S3_MAP_RETRY) + @Named(S3Constants.PROPERTY_OBJECTMAP_RETRY) protected long requestRetryMilliseconds = 10; @Inject diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/reference/S3Constants.java b/aws/s3/core/src/main/java/org/jclouds/aws/s3/reference/S3Constants.java index 7a94859ac5..212b987db3 100644 --- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/reference/S3Constants.java +++ b/aws/s3/core/src/main/java/org/jclouds/aws/s3/reference/S3Constants.java @@ -24,22 +24,14 @@ package org.jclouds.aws.s3.reference; import org.jclouds.aws.reference.AWSConstants; +import org.jclouds.objectstore.reference.ObjectStoreConstants; /** * Configuration properties and constants used in S3 connections. * * @author Adrian Cole */ -public interface S3Constants extends AWSConstants, S3Headers { - - /** - * longest time a single Map operation can take before throwing an exception. - */ - public static final String PROPERTY_S3_MAP_TIMEOUT = "jclouds.s3.map.timeout"; - /** - * time to pause before retrying a transient failure - */ - public static final String PROPERTY_S3_MAP_RETRY = "jclouds.s3.map.retry"; +public interface S3Constants extends AWSConstants, S3Headers, ObjectStoreConstants { /** * S3 service's XML Namespace, as used in XML request and response documents. 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 be03ffcc79..f6419b4fd6 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 @@ -35,6 +35,7 @@ import org.jclouds.aws.s3.xml.ListAllMyBucketsHandler; import org.jclouds.aws.s3.xml.ListBucketHandler; import org.jclouds.aws.s3.xml.S3ParserFactory; import org.jclouds.aws.xml.ErrorHandler; +import org.jclouds.command.ConfiguresResponseParser; import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.config.SaxModule; @@ -47,6 +48,7 @@ import com.google.inject.assistedinject.FactoryProvider; * * @author Adrian Cole */ +@ConfiguresResponseParser public class S3ParserModule extends AbstractModule { protected final TypeLiteral> errorTypeLiteral = new TypeLiteral>() { }; diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3ContextBuilderTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3ContextBuilderTest.java new file mode 100644 index 0000000000..f4313b3962 --- /dev/null +++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3ContextBuilderTest.java @@ -0,0 +1,94 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.aws.s3; + +import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID; +import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY; +import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_ADDRESS; +import static org.testng.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.jclouds.aws.s3.config.LiveS3ConnectionModule; +import org.jclouds.aws.s3.config.S3ContextModule; +import org.jclouds.aws.s3.internal.GuiceS3Context; +import org.jclouds.aws.s3.xml.config.S3ParserModule; +import org.jclouds.cloud.CloudContext; +import org.testng.annotations.Test; + +import com.google.inject.Injector; +import com.google.inject.Module; + +/** + * Tests behavior of modules configured in S3ContextBuilder + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "s3.S3ContextBuilderTest") +public class S3ContextBuilderTest { + + public void testNewBuilder() { + S3ContextBuilder builder = S3ContextBuilder.newBuilder("id", "secret"); + assertEquals(builder.getProperties().getProperty(PROPERTY_HTTP_ADDRESS), "s3.amazonaws.com"); + assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_ACCESSKEYID), "id"); + assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_SECRETACCESSKEY), "secret"); + } + + public void testBuildContext() { + CloudContext context = S3ContextBuilder.newBuilder("id", "secret") + .buildContext(); + assertEquals(context.getClass(), GuiceS3Context.class); + } + + public void testBuildInjector() { + Injector i = S3ContextBuilder.newBuilder("id", "secret").buildInjector(); + assert i.getInstance(S3Context.class) != null; + } + + protected void testAddParserModule() { + List modules = new ArrayList(); + S3ContextBuilder builder = S3ContextBuilder.newBuilder("id", "secret"); + builder.addParserModule(modules); + assertEquals(modules.size(), 1); + assertEquals(modules.get(0).getClass(), S3ParserModule.class); + } + + protected void testAddContextModule() { + List modules = new ArrayList(); + S3ContextBuilder builder = S3ContextBuilder.newBuilder("id", "secret"); + builder.addContextModule(modules); + assertEquals(modules.size(), 1); + assertEquals(modules.get(0).getClass(), S3ContextModule.class); + } + + protected void addConnectionModule() { + List modules = new ArrayList(); + S3ContextBuilder builder = S3ContextBuilder.newBuilder("id", "secret"); + builder.addConnectionModule(modules); + assertEquals(modules.size(), 1); + assertEquals(modules.get(0).getClass(), LiveS3ConnectionModule.class); + } + +} diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java index d2f48f1bcd..ee1a5f6618 100644 --- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java +++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java @@ -174,14 +174,13 @@ public class S3IntegrationTest { } protected void createStubS3Context() { - context = S3ContextFactory.createContext("stub", "stub").withHttpAddress("stub").withModule( - new StubS3ConnectionModule()).build(); + context = S3ContextFactory.createS3Context("stub", "stub", new StubS3ConnectionModule()); SANITY_CHECK_RETURNED_BUCKET_NAME = true; } protected void createLiveS3Context(String AWSAccessKeyId, String AWSSecretAccessKey) { - context = buildS3ContextFactory(AWSAccessKeyId, AWSSecretAccessKey).withModule( - createHttpModule()).withModule(new Log4JLoggingModule()).build(); + context = S3ContextFactory.createS3Context(AWSAccessKeyId, AWSSecretAccessKey, + createHttpModule(), new Log4JLoggingModule()); } public String getBucketName() throws InterruptedException, ExecutionException, TimeoutException { @@ -261,9 +260,9 @@ public class S3IntegrationTest { } } - protected S3ContextFactory buildS3ContextFactory(String AWSAccessKeyId, String AWSSecretAccessKey) { - return S3ContextFactory.createContext(AWSAccessKeyId, AWSSecretAccessKey).withSaxDebug() - .withHttpSecure(false).withHttpPort(80); + protected S3ContextBuilder buildS3ContextFactory(String AWSAccessKeyId, String AWSSecretAccessKey) { + return (S3ContextBuilder) S3ContextBuilder.newBuilder(AWSAccessKeyId, AWSSecretAccessKey) + .withSaxDebug().withHttpSecure(false).withHttpPort(80); } protected Module createHttpModule() { diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/SecureS3ConnectionLiveTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/SecureS3ConnectionLiveTest.java index b12f6b63eb..8eac2e7a46 100644 --- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/SecureS3ConnectionLiveTest.java +++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/SecureS3ConnectionLiveTest.java @@ -27,17 +27,15 @@ import org.testng.annotations.Test; /** * This performs the same test as {@link S3ConnectionLiveTest}, except using SSL. - * + * * @author Adrian Cole */ -@Test(groups = {"live"}, testName = "s3.SecureS3ConnectionLiveTest") +@Test(groups = { "live" }, testName = "s3.SecureS3ConnectionLiveTest") public class SecureS3ConnectionLiveTest extends S3ConnectionLiveTest { - @Override - protected S3ContextFactory buildS3ContextFactory(String AWSAccessKeyId, - String AWSSecretAccessKey) { - return S3ContextFactory.createContext(AWSAccessKeyId, AWSSecretAccessKey) - .withHttpSecure(true) - .withHttpPort(443); - } + @Override + protected S3ContextBuilder buildS3ContextFactory(String AWSAccessKeyId, String AWSSecretAccessKey) { + return (S3ContextBuilder) S3ContextBuilder.newBuilder(AWSAccessKeyId, AWSSecretAccessKey) + .withHttpSecure(true).withHttpPort(443); + } } diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/callables/ParseObjectFromHeadersAndHttpContentTest.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/callables/ParseObjectFromHeadersAndHttpContentTest.java index f0f1f1b327..dd6e2a0f96 100644 --- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/callables/ParseObjectFromHeadersAndHttpContentTest.java +++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/commands/callables/ParseObjectFromHeadersAndHttpContentTest.java @@ -26,21 +26,16 @@ package org.jclouds.aws.s3.commands.callables; import static org.easymock.EasyMock.expect; import static org.easymock.classextension.EasyMock.createMock; import static org.easymock.classextension.EasyMock.replay; -import static org.easymock.classextension.EasyMock.reset; import static org.testng.Assert.assertEquals; import org.apache.commons.io.IOUtils; import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object.Metadata; -import org.jclouds.aws.util.DateService; import org.jclouds.http.HttpException; import org.jclouds.http.HttpHeaders; import org.jclouds.http.HttpResponse; import org.testng.annotations.Test; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; - /** * @author Adrian Cole */ @@ -91,22 +86,5 @@ public class ParseObjectFromHeadersAndHttpContentTest { assertEquals(object.getContentRange(), "0-10485759/20232760"); } - - private void buildDefaultResponseMock(HttpResponse response) { - reset(response); - - // Headers required for the parse classes to work, but we don't care about this data. - String data = "test data"; - expect(response.getStatusCode()).andReturn(200).atLeastOnce(); - Multimap emptyHeaders = HashMultimap.create(); - expect(response.getHeaders()).andReturn(emptyHeaders).atLeastOnce(); - expect(response.getContent()).andReturn(IOUtils.toInputStream(data)).atLeastOnce(); - expect(response.getFirstHeaderOrNull(HttpHeaders.LAST_MODIFIED)) - .andReturn(new DateService().rfc822DateFormat()).atLeastOnce(); - expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE)) - .andReturn("text/plain").atLeastOnce(); - expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH)) - .andReturn("" + data.length()).atLeastOnce(); - } } diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/config/StubS3ConnectionModule.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/config/StubS3ConnectionModule.java index 35891b7497..cb697f2d5e 100644 --- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/config/StubS3ConnectionModule.java +++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/config/StubS3ConnectionModule.java @@ -27,6 +27,7 @@ import java.net.URI; import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.internal.StubS3Connection; +import org.jclouds.cloud.ConfiguresCloudConnection; import com.google.inject.AbstractModule; @@ -35,7 +36,7 @@ import com.google.inject.AbstractModule; * * @author Adrian Cole */ -@S3ConnectionModule +@ConfiguresCloudConnection public class StubS3ConnectionModule extends AbstractModule { protected void configure() { bind(S3Connection.class).to(StubS3Connection.class); diff --git a/aws/s3/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java b/aws/s3/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java index f404ae2d9e..dcc06011c6 100644 --- a/aws/s3/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java +++ b/aws/s3/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java @@ -33,7 +33,7 @@ import java.util.concurrent.TimeUnit; import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Context; -import org.jclouds.aws.s3.S3ContextFactory; +import org.jclouds.aws.s3.S3ContextBuilder; import org.jclouds.aws.s3.commands.options.CopyObjectOptions; import org.jclouds.aws.s3.commands.options.GetObjectOptions; import org.jclouds.aws.s3.commands.options.ListBucketOptions; @@ -79,8 +79,8 @@ public class JCloudsS3Service extends S3Service { protected JCloudsS3Service(AWSCredentials awsCredentials, Module... modules) throws S3ServiceException { super(awsCredentials); - context = S3ContextFactory.createS3Context(awsCredentials.getAccessKey(), awsCredentials - .getSecretKey(), modules); + context = S3ContextBuilder.newBuilder(awsCredentials.getAccessKey(), + awsCredentials.getSecretKey()).withModules(modules).buildContext(); connection = context.getConnection(); } @@ -98,17 +98,14 @@ public class JCloudsS3Service extends S3Service { protected Map copyObjectImpl(String sourceBucketName, String sourceObjectKey, String destinationBucketName, String destinationObjectKey, AccessControlList acl, Map destinationMetadata, Calendar ifModifiedSince, Calendar ifUnmodifiedSince, - String[] ifMatchTags, String[] ifNoneMatchTags) throws S3ServiceException - { + String[] ifMatchTags, String[] ifNoneMatchTags) throws S3ServiceException { try { - CopyObjectOptions options = Util.convertCopyObjectOptions(acl, - destinationMetadata, ifModifiedSince, ifUnmodifiedSince, - ifMatchTags, ifNoneMatchTags); - org.jclouds.aws.s3.domain.S3Object.Metadata jcObjectMetadata = - connection.copyObject(sourceBucketName, sourceObjectKey, - destinationBucketName, destinationObjectKey, options) - .get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); - + CopyObjectOptions options = Util.convertCopyObjectOptions(acl, destinationMetadata, + ifModifiedSince, ifUnmodifiedSince, ifMatchTags, ifNoneMatchTags); + org.jclouds.aws.s3.domain.S3Object.Metadata jcObjectMetadata = connection.copyObject( + sourceBucketName, sourceObjectKey, destinationBucketName, destinationObjectKey, + options).get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); + Map map = new HashMap(); // Result fields returned when copy is successful. map.put("Last-Modified", jcObjectMetadata.getLastModified().toDate()); @@ -129,8 +126,8 @@ public class JCloudsS3Service extends S3Service { throw new UnsupportedOperationException("Bucket ACL is not yet supported"); try { - if (connection.putBucketIfNotExists(bucketName) - .get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)) { + if (connection.putBucketIfNotExists(bucketName).get(requestTimeoutMilliseconds, + TimeUnit.MILLISECONDS)) { // Bucket created. } } catch (Exception e) { @@ -176,9 +173,8 @@ public class JCloudsS3Service extends S3Service { @Override protected AccessControlList getBucketAclImpl(String bucketName) throws S3ServiceException { try { - org.jclouds.aws.s3.domain.AccessControlList jcACL = - connection.getBucketACL(bucketName) - .get(requestTimeoutMilliseconds,TimeUnit.MILLISECONDS); + org.jclouds.aws.s3.domain.AccessControlList jcACL = connection.getBucketACL(bucketName) + .get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); return Util.convertAccessControlList(jcACL); } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); @@ -203,9 +199,8 @@ public class JCloudsS3Service extends S3Service { protected AccessControlList getObjectAclImpl(String bucketName, String objectKey) throws S3ServiceException { try { - org.jclouds.aws.s3.domain.AccessControlList jcACL = - connection.getObjectACL(bucketName, objectKey) - .get(requestTimeoutMilliseconds,TimeUnit.MILLISECONDS); + org.jclouds.aws.s3.domain.AccessControlList jcACL = connection.getObjectACL(bucketName, + objectKey).get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); return Util.convertAccessControlList(jcACL); } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); @@ -240,8 +235,8 @@ public class JCloudsS3Service extends S3Service { Calendar ifUnmodifiedSince, String[] ifMatchTags, String[] ifNoneMatchTags, Long byteRangeStart, Long byteRangeEnd) throws S3ServiceException { try { - GetObjectOptions options = Util.convertGetObjectOptions(ifModifiedSince, - ifUnmodifiedSince, ifMatchTags, ifNoneMatchTags); + GetObjectOptions options = Util.convertGetObjectOptions(ifModifiedSince, + ifUnmodifiedSince, ifMatchTags, ifNoneMatchTags); return Util.convertObject(connection.getObject(bucketName, objectKey, options).get()); } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); @@ -278,16 +273,16 @@ public class JCloudsS3Service extends S3Service { protected S3ObjectsChunk listObjectsChunkedImpl(String bucketName, String prefix, String delimiter, long maxListingLength, String priorLastKey, boolean completeListing) throws S3ServiceException { - try { + try { List jsObjects = new ArrayList(); List commonPrefixes = new ArrayList(); org.jclouds.aws.s3.domain.S3Bucket jcBucket = null; - do { - ListBucketOptions options = Util.convertListObjectOptions(prefix, priorLastKey, - delimiter, maxListingLength); - - jcBucket = connection.listBucket(bucketName, options) - .get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); + do { + ListBucketOptions options = Util.convertListObjectOptions(prefix, priorLastKey, + delimiter, maxListingLength); + + jcBucket = connection.listBucket(bucketName, options).get(requestTimeoutMilliseconds, + TimeUnit.MILLISECONDS); jsObjects.addAll(Arrays.asList(Util.convertObjectHeads(jcBucket.getContents()))); commonPrefixes.addAll(jcBucket.getCommonPrefixes()); @@ -296,30 +291,28 @@ public class JCloudsS3Service extends S3Service { } else { priorLastKey = null; } - } while (completeListing && jcBucket.isTruncated()); // Build entire listing if requested + } while (completeListing && jcBucket.isTruncated()); // Build entire listing if requested - return new S3ObjectsChunk( - prefix, // Return the supplied prefix, not the one in the S3 response. - jcBucket.getDelimiter(), - (S3Object[]) jsObjects.toArray(new S3Object[jsObjects.size()]), - (String[]) commonPrefixes.toArray(new String[commonPrefixes.size()]), - priorLastKey); + return new S3ObjectsChunk(prefix, // Return the supplied prefix, not the one in the S3 + // response. + jcBucket.getDelimiter(), (S3Object[]) jsObjects.toArray(new S3Object[jsObjects + .size()]), (String[]) commonPrefixes.toArray(new String[commonPrefixes + .size()]), priorLastKey); } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); - throw new S3ServiceException("error listing objects in bucket " + bucketName, e); + throw new S3ServiceException("error listing objects in bucket " + bucketName, e); } } @Override protected S3Object[] listObjectsImpl(String bucketName, String prefix, String delimiter, - long maxListingLength) throws S3ServiceException - { + long maxListingLength) throws S3ServiceException { try { return listObjectsChunked(bucketName, prefix, delimiter, maxListingLength, null, true) - .getObjects(); + .getObjects(); } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); - throw new S3ServiceException("error listing objects in bucket " + bucketName, e); + throw new S3ServiceException("error listing objects in bucket " + bucketName, e); } } @@ -328,8 +321,8 @@ public class JCloudsS3Service extends S3Service { throws S3ServiceException { try { org.jclouds.aws.s3.domain.AccessControlList jcACL = Util.convertAccessControlList(jsACL); - connection.putBucketACL(bucketName, jcACL) - .get(requestTimeoutMilliseconds,TimeUnit.MILLISECONDS); + connection.putBucketACL(bucketName, jcACL).get(requestTimeoutMilliseconds, + TimeUnit.MILLISECONDS); } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3ServiceException("error putting bucket's ACL: " + bucketName, e); @@ -341,8 +334,8 @@ public class JCloudsS3Service extends S3Service { throws S3ServiceException { try { org.jclouds.aws.s3.domain.AccessControlList jcACL = Util.convertAccessControlList(jsACL); - connection.putObjectACL(bucketName, objectKey, jcACL) - .get(requestTimeoutMilliseconds,TimeUnit.MILLISECONDS); + connection.putObjectACL(bucketName, objectKey, jcACL).get(requestTimeoutMilliseconds, + TimeUnit.MILLISECONDS); } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3ServiceException("error putting object's ACL", e); @@ -351,16 +344,16 @@ public class JCloudsS3Service extends S3Service { @Override protected S3Object putObjectImpl(String bucketName, S3Object jsObject) throws S3ServiceException { - try { + try { PutObjectOptions options = Util.convertPutObjectOptions(jsObject.getAcl()); org.jclouds.aws.s3.domain.S3Object jcObject = Util.convertObject(jsObject); - byte md5[] = connection.putObject(bucketName, jcObject, options) - .get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); + byte md5[] = connection.putObject(bucketName, jcObject, options).get( + requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); jsObject.setMd5Hash(md5); return jsObject; } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); - throw new S3ServiceException("error putting object", e); + throw new S3ServiceException("error putting object", e); } } diff --git a/aws/s3/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceIntegrationTest.java b/aws/s3/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceIntegrationTest.java index 349fb918e9..b3285ba45d 100644 --- a/aws/s3/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceIntegrationTest.java +++ b/aws/s3/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceIntegrationTest.java @@ -61,7 +61,6 @@ import org.jets3t.service.multithread.CreateObjectsEvent; import org.jets3t.service.multithread.S3ServiceEventAdaptor; import org.jets3t.service.multithread.S3ServiceEventListener; import org.jets3t.service.multithread.S3ServiceMulti; -import org.jets3t.service.multithread.S3ServiceSimpleMulti; import org.jets3t.service.security.AWSCredentials; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; diff --git a/aws/s3/extensions/suncloud/src/main/java/org/jclouds/aws/s3/suncloud/config/SunCloudS3ConnectionModule.java b/aws/s3/extensions/suncloud/src/main/java/org/jclouds/aws/s3/suncloud/config/SunCloudS3ConnectionModule.java index 7d4145387c..a7fe4f8e81 100644 --- a/aws/s3/extensions/suncloud/src/main/java/org/jclouds/aws/s3/suncloud/config/SunCloudS3ConnectionModule.java +++ b/aws/s3/extensions/suncloud/src/main/java/org/jclouds/aws/s3/suncloud/config/SunCloudS3ConnectionModule.java @@ -24,8 +24,8 @@ package org.jclouds.aws.s3.suncloud.config; import org.jclouds.aws.s3.config.LiveS3ConnectionModule; -import org.jclouds.aws.s3.config.S3ConnectionModule; import org.jclouds.aws.s3.suncloud.handlers.ParseSunCloudS3ErrorFromXmlContent; +import org.jclouds.cloud.ConfiguresCloudConnection; import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.ServerError; @@ -37,7 +37,7 @@ import com.google.inject.Scopes; * * @author Adrian Cole */ -@S3ConnectionModule +@ConfiguresCloudConnection public class SunCloudS3ConnectionModule extends LiveS3ConnectionModule { protected void bindErrorHandlers() { diff --git a/aws/s3/extensions/suncloud/src/test/java/org/jclouds/aws/s3/suncloud/SunCloudS3ConnectionLiveTest.java b/aws/s3/extensions/suncloud/src/test/java/org/jclouds/aws/s3/suncloud/SunCloudS3ConnectionLiveTest.java index 4644f58815..7de39e37c2 100644 --- a/aws/s3/extensions/suncloud/src/test/java/org/jclouds/aws/s3/suncloud/SunCloudS3ConnectionLiveTest.java +++ b/aws/s3/extensions/suncloud/src/test/java/org/jclouds/aws/s3/suncloud/SunCloudS3ConnectionLiveTest.java @@ -24,7 +24,7 @@ package org.jclouds.aws.s3.suncloud; import org.jclouds.aws.s3.S3ConnectionLiveTest; -import org.jclouds.aws.s3.S3ContextFactory; +import org.jclouds.aws.s3.S3ContextBuilder; import org.jclouds.aws.s3.suncloud.config.SunCloudS3ConnectionModule; import org.jclouds.aws.s3.suncloud.xml.config.SunCloudS3ParserModule; import org.testng.annotations.Test; @@ -38,11 +38,11 @@ import org.testng.annotations.Test; public class SunCloudS3ConnectionLiveTest extends S3ConnectionLiveTest { @Override - protected S3ContextFactory buildS3ContextFactory(String AWSAccessKeyId, String AWSSecretAccessKey) { - return S3ContextFactory.createContext(AWSAccessKeyId, AWSSecretAccessKey).withModules( - new SunCloudS3ConnectionModule(), new SunCloudS3ParserModule()).withHttpAddress( - "object.storage.network.com").withHttpSecure(false).withHttpPort(80); - + protected S3ContextBuilder buildS3ContextFactory(String AWSAccessKeyId, String AWSSecretAccessKey) { + return (S3ContextBuilder) S3ContextBuilder.newBuilder(AWSAccessKeyId, AWSSecretAccessKey) + .withModules(new SunCloudS3ConnectionModule(), new SunCloudS3ParserModule()) + .withHttpAddress("object.storage.network.com").withHttpSecure(false) + .withHttpPort(80); } } diff --git a/aws/s3/perftest/src/test/java/org/jclouds/aws/s3/JCloudsNioPerformanceLiveTest.java b/aws/s3/perftest/src/test/java/org/jclouds/aws/s3/JCloudsNioPerformanceLiveTest.java index 1c2837e0b2..458fb082bf 100644 --- a/aws/s3/perftest/src/test/java/org/jclouds/aws/s3/JCloudsNioPerformanceLiveTest.java +++ b/aws/s3/perftest/src/test/java/org/jclouds/aws/s3/JCloudsNioPerformanceLiveTest.java @@ -28,22 +28,11 @@ import org.testng.annotations.Test; import com.google.inject.Module; -@Test(sequential = true, testName = "s3.JCloudsNioPerformanceLiveTest", groups = {"live"}) +@Test(sequential = true, testName = "s3.JCloudsNioPerformanceLiveTest", groups = { "live" }) public class JCloudsNioPerformanceLiveTest extends BaseJCloudsPerformance { - @Override - protected S3ContextFactory buildS3ContextFactory(String AWSAccessKeyId, - String AWSSecretAccessKey) { - return super.buildS3ContextFactory(AWSAccessKeyId, AWSSecretAccessKey) - .withPoolMaxConnectionReuse(75) - .withPoolMaxSessionFailures(2) - .withPoolRequestInvokerThreads(1) - .withPoolIoWorkerThreads(2) - .withPoolMaxConnections(12); - } - - @Override - protected Module createHttpModule() { - return new HttpNioConnectionPoolClientModule(); - } + @Override + protected Module createHttpModule() { + return new HttpNioConnectionPoolClientModule(); + } } \ No newline at end of file diff --git a/aws/s3/pom.xml b/aws/s3/pom.xml index 866531369e..d4f69fe663 100644 --- a/aws/s3/pom.xml +++ b/aws/s3/pom.xml @@ -43,6 +43,11 @@ samples + + ${project.groupId} + jclouds-objectstore-core + ${project.version} + ${project.groupId} jclouds-aws-core diff --git a/aws/s3/samples/createandlistbuckets/src/main/java/org/jclouds/aws/s3/samples/MainApp.java b/aws/s3/samples/createandlistbuckets/src/main/java/org/jclouds/aws/s3/samples/MainApp.java index e1453e4d46..207b62c933 100644 --- a/aws/s3/samples/createandlistbuckets/src/main/java/org/jclouds/aws/s3/samples/MainApp.java +++ b/aws/s3/samples/createandlistbuckets/src/main/java/org/jclouds/aws/s3/samples/MainApp.java @@ -32,7 +32,6 @@ import javax.annotation.Resource; import org.jclouds.aws.s3.CreateListOwnedBuckets; import org.jclouds.aws.s3.S3Context; import org.jclouds.aws.s3.S3ContextFactory; -import org.jclouds.aws.s3.config.LiveS3ConnectionModule; import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.logging.Logger; @@ -69,8 +68,7 @@ public class MainApp { String bucketName = args[2]; // Init - context = S3ContextFactory.createS3Context(accesskeyid, secretkey, - new LiveS3ConnectionModule()); + context = S3ContextFactory.createS3Context(accesskeyid, secretkey); listMyOwnBuckets = new CreateListOwnedBuckets(context); try { diff --git a/aws/s3/samples/createandlistbuckets/src/test/java/org/jclouds/aws/s3/samples/test/CreateListOwnedBucketsIntegrationTest.java b/aws/s3/samples/createandlistbuckets/src/test/java/org/jclouds/aws/s3/samples/test/CreateListOwnedBucketsIntegrationTest.java index 829cabf1ec..502de655e8 100644 --- a/aws/s3/samples/createandlistbuckets/src/test/java/org/jclouds/aws/s3/samples/test/CreateListOwnedBucketsIntegrationTest.java +++ b/aws/s3/samples/createandlistbuckets/src/test/java/org/jclouds/aws/s3/samples/test/CreateListOwnedBucketsIntegrationTest.java @@ -28,7 +28,6 @@ import java.util.concurrent.TimeUnit; import org.jclouds.aws.s3.CreateListOwnedBuckets; import org.jclouds.aws.s3.S3Context; import org.jclouds.aws.s3.S3ContextFactory; -import org.jclouds.aws.s3.config.LiveS3ConnectionModule; import org.jclouds.aws.s3.config.StubS3ConnectionModule; import org.jclouds.aws.s3.reference.S3Constants; import org.testng.annotations.AfterClass; @@ -61,11 +60,10 @@ public class CreateListOwnedBucketsIntegrationTest { AWSSecretAccessKey = AWSSecretAccessKey != null ? AWSSecretAccessKey : sysAWSSecretAccessKey; if ((AWSAccessKeyId != null) && (AWSSecretAccessKey != null)) - context = S3ContextFactory.createS3Context(AWSAccessKeyId, AWSSecretAccessKey, - new LiveS3ConnectionModule()); + context = S3ContextFactory.createS3Context(AWSAccessKeyId, AWSSecretAccessKey); else - context = S3ContextFactory.createContext("stub", "stub").withHttpAddress("stub") - .withModule(new StubS3ConnectionModule()).build(); + context = S3ContextFactory.createS3Context("stub", "stub", new StubS3ConnectionModule()); + } @Test(groups = { "integration", "live" }) diff --git a/aws/s3/samples/createandlistbuckets/src/test/java/org/jclouds/aws/s3/samples/test/CreateListOwnedBucketsLiveTest.java b/aws/s3/samples/createandlistbuckets/src/test/java/org/jclouds/aws/s3/samples/test/CreateListOwnedBucketsLiveTest.java index b2206a1e9e..eed08289f5 100644 --- a/aws/s3/samples/createandlistbuckets/src/test/java/org/jclouds/aws/s3/samples/test/CreateListOwnedBucketsLiveTest.java +++ b/aws/s3/samples/createandlistbuckets/src/test/java/org/jclouds/aws/s3/samples/test/CreateListOwnedBucketsLiveTest.java @@ -28,7 +28,6 @@ import java.util.concurrent.TimeUnit; import org.jclouds.aws.s3.CreateListOwnedBuckets; import org.jclouds.aws.s3.S3Context; import org.jclouds.aws.s3.S3ContextFactory; -import org.jclouds.aws.s3.config.LiveS3ConnectionModule; import org.jclouds.aws.s3.reference.S3Constants; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -59,8 +58,7 @@ public class CreateListOwnedBucketsLiveTest { AWSAccessKeyId = AWSAccessKeyId != null ? AWSAccessKeyId : sysAWSAccessKeyId; AWSSecretAccessKey = AWSSecretAccessKey != null ? AWSSecretAccessKey : sysAWSSecretAccessKey; - context = S3ContextFactory.createS3Context(AWSAccessKeyId, AWSSecretAccessKey, - new LiveS3ConnectionModule()); + context = S3ContextFactory.createS3Context(AWSAccessKeyId, AWSSecretAccessKey); } diff --git a/aws/s3/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/config/GuiceServletConfig.java b/aws/s3/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/config/GuiceServletConfig.java index 85a59c2b8e..0f3cdf2c2a 100644 --- a/aws/s3/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/config/GuiceServletConfig.java +++ b/aws/s3/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/config/GuiceServletConfig.java @@ -29,7 +29,7 @@ import com.google.inject.servlet.GuiceServletContextListener; import com.google.inject.servlet.ServletModule; import org.apache.commons.io.IOUtils; import org.jclouds.aws.s3.S3Context; -import org.jclouds.aws.s3.S3ContextFactory; +import org.jclouds.aws.s3.S3ContextBuilder; import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.gae.config.URLFetchServiceClientModule; import org.jclouds.samples.googleappengine.GetAllBucketsController; @@ -41,56 +41,52 @@ import java.util.Properties; /** * Setup Logging and create Injector for use in testing S3. - * + * * @author Adrian Cole */ public class GuiceServletConfig extends GuiceServletContextListener { - @Inject - S3Context context; - String accessKeyId; - String secretAccessKey; + @Inject + S3Context context; + String accessKeyId; + String secretAccessKey; - @Override - public void contextInitialized(ServletContextEvent servletContextEvent) { - Properties props = loadJCloudsProperties(servletContextEvent); - this.accessKeyId = props - .getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID); - this.secretAccessKey = props - .getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY); - super.contextInitialized(servletContextEvent); - } + @Override + public void contextInitialized(ServletContextEvent servletContextEvent) { + Properties props = loadJCloudsProperties(servletContextEvent); + this.accessKeyId = props.getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID); + this.secretAccessKey = props.getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY); + super.contextInitialized(servletContextEvent); + } - private Properties loadJCloudsProperties( - ServletContextEvent servletContextEvent) { - InputStream input = servletContextEvent.getServletContext() - .getResourceAsStream("/WEB-INF/jclouds.properties"); - Properties props = new Properties(); - try { - props.load(input); - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - IOUtils.closeQuietly(input); - } - return props; - } + private Properties loadJCloudsProperties(ServletContextEvent servletContextEvent) { + InputStream input = servletContextEvent.getServletContext().getResourceAsStream( + "/WEB-INF/jclouds.properties"); + Properties props = new Properties(); + try { + props.load(input); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + IOUtils.closeQuietly(input); + } + return props; + } - @Override - protected Injector getInjector() { - return S3ContextFactory.createInjector(accessKeyId, secretAccessKey, - false, new URLFetchServiceClientModule(), - new ServletModule() { - @Override - protected void configureServlets() { - serve("*.s3").with(GetAllBucketsController.class); - requestInjection(this); - } - }); - } + @Override + protected Injector getInjector() { + return S3ContextBuilder.newBuilder(accessKeyId, secretAccessKey).withHttpSecure(false) + .withModules(new URLFetchServiceClientModule(), new ServletModule() { + @Override + protected void configureServlets() { + serve("*.s3").with(GetAllBucketsController.class); + requestInjection(this); + } + }).buildInjector(); + } - @Override - public void contextDestroyed(ServletContextEvent servletContextEvent) { - context.close(); - super.contextDestroyed(servletContextEvent); - } + @Override + public void contextDestroyed(ServletContextEvent servletContextEvent) { + context.close(); + super.contextDestroyed(servletContextEvent); + } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/cloud/CloudContext.java b/core/src/main/java/org/jclouds/cloud/CloudContext.java new file mode 100644 index 0000000000..ecc6c9d376 --- /dev/null +++ b/core/src/main/java/org/jclouds/cloud/CloudContext.java @@ -0,0 +1,50 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.cloud; + +/** + * Represents an authenticated context to the cloud. + * + *

Note

Please issue {@link #close()} when you are finished with this context in order to + * release resources. + * + * + * @author Adrian Cole + * + */ +public interface CloudContext { + + /** + * low-level api to the cloud. Threadsafe implementations will return a singleton. + * + * @return a connection to the cloud + */ + C getConnection(); + + /** + * Closes all connections to Cloud Files. + */ + void close(); + +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/cloud/CloudContextBuilder.java b/core/src/main/java/org/jclouds/cloud/CloudContextBuilder.java new file mode 100644 index 0000000000..fe0576bbcc --- /dev/null +++ b/core/src/main/java/org/jclouds/cloud/CloudContextBuilder.java @@ -0,0 +1,249 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.cloud; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_IO_WORKER_THREADS; +import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS; +import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE; +import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES; +import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_REQUEST_INVOKER_THREADS; +import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_ADDRESS; +import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_REDIRECTS; +import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_RETRIES; +import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_PORT; +import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_SECURE; +import static org.jclouds.http.HttpConstants.PROPERTY_SAX_DEBUG; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; + +import org.jclouds.command.ConfiguresResponseParser; +import org.jclouds.http.RequiresHttp; +import org.jclouds.http.config.ConfiguresHttpFutureCommandClient; +import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule; +import org.jclouds.logging.config.LoggingModule; +import org.jclouds.logging.jdk.config.JDKLoggingModule; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.Iterables; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Module; +import com.google.inject.name.Names; + +/** + * Creates {@link CloudContext} or {@link Injector} instances based on the most commonly requested + * arguments. + *

+ * Note that Threadsafe objects will be bound as singletons to the Injector or Context provided. + *

+ *

+ * If no Modules are specified, the default {@link JDKLoggingModule logging} and + * {@link JavaUrlHttpFutureCommandClientModule http transports} will be installed. + * + * @author Adrian Cole, Andrew Newdigate + * @see CloudContext + */ +public abstract class CloudContextBuilder> { + + private static final String DEFAULT_SECURE_HTTP_PORT = "443"; + private static final String DEFAULT_NON_SECURE_HTTP_PORT = "80"; + + protected final Properties properties; + private final List modules = new ArrayList(3); + + protected CloudContextBuilder(Properties properties) { + this.properties = properties; + } + + public CloudContextBuilder withHttpAddress(String httpAddress) { + properties.setProperty(PROPERTY_HTTP_ADDRESS, httpAddress); + return this; + } + + public CloudContextBuilder withSaxDebug() { + properties.setProperty(PROPERTY_SAX_DEBUG, "true"); + return this; + } + + public CloudContextBuilder withHttpMaxRetries(int httpMaxRetries) { + properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, Integer.toString(httpMaxRetries)); + return this; + } + + public CloudContextBuilder withHttpMaxRedirects(int httpMaxRedirects) { + properties.setProperty(PROPERTY_HTTP_MAX_REDIRECTS, Integer.toString(httpMaxRedirects)); + return this; + } + + public CloudContextBuilder withHttpPort(int httpPort) { + properties.setProperty(PROPERTY_HTTP_PORT, Integer.toString(httpPort)); + return this; + } + + public CloudContextBuilder withHttpSecure(boolean httpSecure) { + properties.setProperty(PROPERTY_HTTP_SECURE, Boolean.toString(httpSecure)); + return this; + } + + public CloudContextBuilder withPoolMaxConnectionReuse(int poolMaxConnectionReuse) { + properties.setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, Integer + .toString(poolMaxConnectionReuse)); + return this; + + } + + public CloudContextBuilder withPoolMaxSessionFailures(int poolMaxSessionFailures) { + properties.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, Integer + .toString(poolMaxSessionFailures)); + return this; + + } + + public CloudContextBuilder withPoolRequestInvokerThreads(int poolRequestInvokerThreads) { + properties.setProperty(PROPERTY_POOL_REQUEST_INVOKER_THREADS, Integer + .toString(poolRequestInvokerThreads)); + return this; + + } + + public CloudContextBuilder withPoolIoWorkerThreads(int poolIoWorkerThreads) { + properties + .setProperty(PROPERTY_POOL_IO_WORKER_THREADS, Integer.toString(poolIoWorkerThreads)); + return this; + + } + + public CloudContextBuilder withPoolMaxConnections(int poolMaxConnections) { + properties.setProperty(PROPERTY_POOL_MAX_CONNECTIONS, Integer.toString(poolMaxConnections)); + return this; + } + + public CloudContextBuilder withModule(Module module) { + modules.add(module); + return this; + } + + public CloudContextBuilder withModules(Module... modules) { + this.modules.addAll(Arrays.asList(modules)); + return this; + } + + public Injector buildInjector() { + + useDefaultPortIfNotPresent(properties); + + addLoggingModuleIfNotPresent(modules); + + addParserModuleIfNotPresent(modules); + + addConnectionModuleIfNotPresent(modules); + + addHttpModuleIfNeededAndNotPresent(modules); + + modules.add(new AbstractModule() { + @Override + protected void configure() { + Names.bindProperties(binder(), checkNotNull(properties, "properties")); + } + }); + addContextModule(modules); + + return Guice.createInjector(modules); + } + + private void useDefaultPortIfNotPresent(Properties properties) { + /* 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))) { + properties.setProperty(PROPERTY_HTTP_PORT, DEFAULT_SECURE_HTTP_PORT); + } else { + properties.setProperty(PROPERTY_HTTP_PORT, DEFAULT_NON_SECURE_HTTP_PORT); + } + } + } + + protected void addLoggingModuleIfNotPresent(final List modules) { + if (!Iterables.any(modules, Predicates.instanceOf(LoggingModule.class))) + modules.add(new JDKLoggingModule()); + } + + protected void addHttpModuleIfNeededAndNotPresent(final List modules) { + if (Iterables.any(modules, new Predicate() { + public boolean apply(Module input) { + return input.getClass().isAnnotationPresent(RequiresHttp.class); + } + + }) && (!Iterables.any(modules, new Predicate() { + public boolean apply(Module input) { + return input.getClass().isAnnotationPresent(ConfiguresHttpFutureCommandClient.class); + } + + }))) + modules.add(new JavaUrlHttpFutureCommandClientModule()); + } + + protected void addConnectionModuleIfNotPresent(final List modules) { + if (!Iterables.any(modules, new Predicate() { + public boolean apply(Module input) { + return input.getClass().isAnnotationPresent(ConfiguresCloudConnection.class); + } + + })) { + addConnectionModule(modules); + } + } + + protected void addParserModuleIfNotPresent(List modules) { + if (!Iterables.any(modules, new Predicate() { + public boolean apply(Module input) { + return input.getClass().isAnnotationPresent(ConfiguresResponseParser.class); + } + + })) + addParserModule(modules); + } + + @VisibleForTesting + public Properties getProperties() { + return properties; + } + + public abstract X buildContext(); + + public abstract void authenticate(String id, String secret); + + protected abstract void addParserModule(List modules); + + protected abstract void addContextModule(List modules); + + protected abstract void addConnectionModule(List modules); + +} diff --git a/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/S3ConnectionModule.java b/core/src/main/java/org/jclouds/cloud/ConfiguresCloudConnection.java similarity index 89% rename from aws/s3/core/src/main/java/org/jclouds/aws/s3/config/S3ConnectionModule.java rename to core/src/main/java/org/jclouds/cloud/ConfiguresCloudConnection.java index 4bed5e78d1..d5048165b1 100644 --- a/aws/s3/core/src/main/java/org/jclouds/aws/s3/config/S3ConnectionModule.java +++ b/core/src/main/java/org/jclouds/cloud/ConfiguresCloudConnection.java @@ -21,7 +21,7 @@ * under the License. * ==================================================================== */ -package org.jclouds.aws.s3.config; +package org.jclouds.cloud; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; @@ -30,13 +30,13 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; /** - * designates the the module configures a {@link org.jclouds.aws.s3.S3Connection} + * designates the module configures a Connection to a cloud. * * @author Adrian Cole * */ @Retention(RUNTIME) @Target(TYPE) -public @interface S3ConnectionModule { +public @interface ConfiguresCloudConnection { } diff --git a/core/src/main/java/org/jclouds/command/ConfiguresResponseParser.java b/core/src/main/java/org/jclouds/command/ConfiguresResponseParser.java new file mode 100644 index 0000000000..6844c9df09 --- /dev/null +++ b/core/src/main/java/org/jclouds/command/ConfiguresResponseParser.java @@ -0,0 +1,42 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.command; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * designates the module configures a Connection to a cloud. + * + * @author Adrian Cole + * + */ +@Retention(RUNTIME) +@Target(TYPE) +public @interface ConfiguresResponseParser { + +} diff --git a/core/src/main/java/org/jclouds/command/FutureCommand.java b/core/src/main/java/org/jclouds/command/FutureCommand.java index aaeb4a6314..8d5d3b9653 100644 --- a/core/src/main/java/org/jclouds/command/FutureCommand.java +++ b/core/src/main/java/org/jclouds/command/FutureCommand.java @@ -127,16 +127,16 @@ public class FutureCommand, R, T> implements Future { } public interface ResponseRunnableFuture extends Response, Runnable, Future { - public void setException(Throwable throwable); + void setException(Throwable throwable); } public interface ResponseCallable extends Response, Callable { } public interface Response { - public R getResponse(); + R getResponse(); - public void setResponse(R response); + void setResponse(R response); } } diff --git a/core/src/main/java/org/jclouds/command/pool/config/FutureCommandConnectionPoolClientModule.java b/core/src/main/java/org/jclouds/command/pool/config/FutureCommandConnectionPoolClientModule.java index ec747602e8..cccce296cc 100644 --- a/core/src/main/java/org/jclouds/command/pool/config/FutureCommandConnectionPoolClientModule.java +++ b/core/src/main/java/org/jclouds/command/pool/config/FutureCommandConnectionPoolClientModule.java @@ -38,33 +38,30 @@ import com.google.inject.name.Named; * * @author Adrian Cole */ -public abstract class FutureCommandConnectionPoolClientModule extends - AbstractModule { - protected void configure() { - install(new LifeCycleModule()); - bind(AtomicInteger.class).toInstance(new AtomicInteger());// max errors - } +public abstract class FutureCommandConnectionPoolClientModule extends AbstractModule { - @Provides - // @Singleton per uri... - public abstract BlockingQueue provideAvailablePool( - @Named(PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS) int max) - throws Exception; + protected void configure() { + install(new LifeCycleModule()); + bind(AtomicInteger.class).toInstance(new AtomicInteger());// max errors + } - /** - * controls production and destruction of real connections. - *

- * aquire before a new connection is created release after an error has - * occurred - * - * @param max - * @throws Exception - */ - @Provides - // @Singleton per uri... - public Semaphore provideTotalConnectionSemaphore( - @Named(PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS) int max) - throws Exception { - return new Semaphore(max, true); - } + @Provides + // @Singleton per uri... + public abstract BlockingQueue provideAvailablePool( + @Named(PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS) int max) throws Exception; + + /** + * controls production and destruction of real connections. + *

+ * aquire before a new connection is created release after an error has occurred + * + * @param max + * @throws Exception + */ + @Provides + // @Singleton per uri... + public Semaphore provideTotalConnectionSemaphore( + @Named(PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS) int max) throws Exception { + return new Semaphore(max, true); + } } diff --git a/core/src/main/java/org/jclouds/http/RequiresHttp.java b/core/src/main/java/org/jclouds/http/RequiresHttp.java new file mode 100644 index 0000000000..2d8411783c --- /dev/null +++ b/core/src/main/java/org/jclouds/http/RequiresHttp.java @@ -0,0 +1,42 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.http; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * designates the cloud has an HTTP API + * + * @author Adrian Cole + * + */ +@Retention(RUNTIME) +@Target(TYPE) +public @interface RequiresHttp { + +} diff --git a/core/src/main/java/org/jclouds/http/commands/callables/ReturnStringIf200.java b/core/src/main/java/org/jclouds/http/commands/callables/ReturnStringIf200.java index 8c9279e425..d7736ce56c 100644 --- a/core/src/main/java/org/jclouds/http/commands/callables/ReturnStringIf200.java +++ b/core/src/main/java/org/jclouds/http/commands/callables/ReturnStringIf200.java @@ -30,39 +30,29 @@ import org.jclouds.http.HttpException; import org.jclouds.http.HttpFutureCommand; import org.jclouds.util.Utils; -import com.google.inject.Inject; - /** * // TODO: Adrian: Document this! * * @author Adrian Cole */ -public class ReturnStringIf200 extends - HttpFutureCommand.ResponseCallable { +public class ReturnStringIf200 extends HttpFutureCommand.ResponseCallable { - @Inject - public ReturnStringIf200() { - super(); - } - - public String call() throws HttpException { - checkCode(); - if (getResponse().getStatusCode() == 200) { - InputStream entity = getResponse().getContent(); - if (entity == null) - throw new HttpException("no content"); - String toReturn = null; - try { - toReturn = Utils.toStringAndClose(entity); - } catch (IOException e) { - throw new HttpException(String.format( - "Couldn't receive response %1$s, entity: %2$s ", - getResponse(), toReturn), e); - } - return toReturn; - } else { - throw new HttpException(String.format( - "Unhandled status code - %1$s", getResponse())); - } - } + public String call() throws HttpException { + checkCode(); + if (getResponse().getStatusCode() == 200) { + InputStream entity = getResponse().getContent(); + if (entity == null) + throw new HttpException("no content"); + String toReturn = null; + try { + toReturn = Utils.toStringAndClose(entity); + } catch (IOException e) { + throw new HttpException(String.format("Couldn't receive response %1$s, entity: %2$s ", + getResponse(), toReturn), e); + } + return toReturn; + } else { + throw new HttpException(String.format("Unhandled status code - %1$s", getResponse())); + } + } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/commands/callables/ReturnTrueIf2xx.java b/core/src/main/java/org/jclouds/http/commands/callables/ReturnTrueIf2xx.java index e60fc99e84..66d769e1a8 100644 --- a/core/src/main/java/org/jclouds/http/commands/callables/ReturnTrueIf2xx.java +++ b/core/src/main/java/org/jclouds/http/commands/callables/ReturnTrueIf2xx.java @@ -27,24 +27,19 @@ import org.apache.commons.io.IOUtils; import org.jclouds.http.HttpException; import org.jclouds.http.HttpFutureCommand; -import com.google.inject.Inject; - /** * Simply returns true when the http response code is in the range 200-299. * * @author Adrian Cole */ -public class ReturnTrueIf2xx extends - HttpFutureCommand.ResponseCallable { +public class ReturnTrueIf2xx extends HttpFutureCommand.ResponseCallable { - @Inject - public ReturnTrueIf2xx() { - super(); - } - - public Boolean call() throws HttpException { - checkCode(); - IOUtils.closeQuietly(getResponse().getContent()); - return true; - } + public Boolean call() throws HttpException { + IOUtils.closeQuietly(getResponse().getContent()); + int code = getResponse().getStatusCode(); + if (code >= 300 || code < 200) { + throw new IllegalStateException("incorrect code for this operation: " + getResponse()); + } + return true; + } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/config/HttpFutureCommandClientModule.java b/core/src/main/java/org/jclouds/http/config/ConfiguresHttpFutureCommandClient.java similarity index 96% rename from core/src/main/java/org/jclouds/http/config/HttpFutureCommandClientModule.java rename to core/src/main/java/org/jclouds/http/config/ConfiguresHttpFutureCommandClient.java index 31bc0e8449..c43e1f2d80 100644 --- a/core/src/main/java/org/jclouds/http/config/HttpFutureCommandClientModule.java +++ b/core/src/main/java/org/jclouds/http/config/ConfiguresHttpFutureCommandClient.java @@ -39,6 +39,6 @@ import org.jclouds.http.HttpFutureCommandClient; */ @Retention(RUNTIME) @Target(TYPE) -public @interface HttpFutureCommandClientModule { +public @interface ConfiguresHttpFutureCommandClient { } diff --git a/core/src/main/java/org/jclouds/http/config/JavaUrlHttpFutureCommandClientModule.java b/core/src/main/java/org/jclouds/http/config/JavaUrlHttpFutureCommandClientModule.java index 764980661c..4506c78628 100644 --- a/core/src/main/java/org/jclouds/http/config/JavaUrlHttpFutureCommandClientModule.java +++ b/core/src/main/java/org/jclouds/http/config/JavaUrlHttpFutureCommandClientModule.java @@ -33,7 +33,7 @@ import com.google.inject.AbstractModule; * * @author Adrian Cole */ -@HttpFutureCommandClientModule +@ConfiguresHttpFutureCommandClient public class JavaUrlHttpFutureCommandClientModule extends AbstractModule { @Override diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3ContextFactoryTest.java b/core/src/test/java/org/jclouds/cloud/CloudContextBuilderTest.java similarity index 51% rename from aws/s3/core/src/test/java/org/jclouds/aws/s3/S3ContextFactoryTest.java rename to core/src/test/java/org/jclouds/cloud/CloudContextBuilderTest.java index c8bbd766e9..9d28772493 100644 --- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/S3ContextFactoryTest.java +++ b/core/src/test/java/org/jclouds/cloud/CloudContextBuilderTest.java @@ -21,15 +21,16 @@ * under the License. * ==================================================================== */ -package org.jclouds.aws.s3; +package org.jclouds.cloud; import static org.testng.Assert.assertEquals; import java.util.ArrayList; import java.util.List; +import java.util.Properties; -import org.jclouds.aws.s3.config.LiveS3ConnectionModule; -import org.jclouds.http.config.HttpFutureCommandClientModule; +import org.jclouds.http.RequiresHttp; +import org.jclouds.http.config.ConfiguresHttpFutureCommandClient; import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule; import org.jclouds.logging.config.LoggingModule; import org.jclouds.logging.config.NullLoggingModule; @@ -37,17 +38,18 @@ import org.jclouds.logging.jdk.config.JDKLoggingModule; import org.testng.annotations.Test; import com.google.inject.AbstractModule; +import com.google.inject.Binder; import com.google.inject.Module; /** - * Tests behavior of modules configured in S3ContextFactory + * Tests behavior of modules configured in CloudContextBuilder * * @author Adrian Cole */ -@Test(groups = "unit", testName = "s3.S3ContextFactoryTest") -public class S3ContextFactoryTest { +@Test(groups = "unit", testName = "s3.CloudContextBuilderTest") +public class CloudContextBuilderTest { - @HttpFutureCommandClientModule + @ConfiguresHttpFutureCommandClient static class HttpModule extends AbstractModule { @Override @@ -56,12 +58,65 @@ public class S3ContextFactoryTest { } } + class TestCloudContext implements CloudContext { + + public void close() { + + } + + public String getConnection() { + return ""; + } + + } + + class TestCloudContextBuilder extends CloudContextBuilder { + + protected TestCloudContextBuilder(Properties properties) { + super(properties); + } + + @Override + public TestCloudContext buildContext() { + return new TestCloudContext(); + } + + @Override + protected void addConnectionModule(List modules) { + modules.add(new Module() { + public void configure(Binder arg0) { + } + }); + } + + @Override + protected void addContextModule(List modules) { + modules.add(new Module() { + public void configure(Binder arg0) { + } + }); + } + + @Override + protected void addParserModule(List modules) { + modules.add(new Module() { + public void configure(Binder arg0) { + } + }); + } + + @Override + public void authenticate(String id, String secret) { + } + + } + @Test public void testAddHttpModuleIfNotPresent() { List modules = new ArrayList(); HttpModule module = new HttpModule(); modules.add(module); - S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules); + new TestCloudContextBuilder(new Properties()).addHttpModuleIfNeededAndNotPresent(modules); assertEquals(modules.size(), 1); assertEquals(modules.remove(0), module); } @@ -71,7 +126,7 @@ public class S3ContextFactoryTest { List modules = new ArrayList(); LoggingModule module = new NullLoggingModule(); modules.add(module); - S3ContextFactory.addLoggingModuleIfNotPresent(modules); + new TestCloudContextBuilder(new Properties()).addLoggingModuleIfNotPresent(modules); assertEquals(modules.size(), 1); assertEquals(modules.remove(0), module); } @@ -83,47 +138,58 @@ public class S3ContextFactoryTest { modules.add(loggingModule); HttpModule httpModule = new HttpModule(); modules.add(httpModule); - S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules); - S3ContextFactory.addLoggingModuleIfNotPresent(modules); + TestCloudContextBuilder builder = new TestCloudContextBuilder(new Properties()); + builder.addHttpModuleIfNeededAndNotPresent(modules); + builder.addLoggingModuleIfNotPresent(modules); assertEquals(modules.size(), 2); assertEquals(modules.remove(0), loggingModule); assertEquals(modules.remove(0), httpModule); } @Test - public void testAddBothWhenNotLive() { + public void testAddBothWhenDoesntRequireHttp() { List modules = new ArrayList(); - S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules); - S3ContextFactory.addLoggingModuleIfNotPresent(modules); + TestCloudContextBuilder builder = new TestCloudContextBuilder(new Properties()); + builder.addHttpModuleIfNeededAndNotPresent(modules); + builder.addLoggingModuleIfNotPresent(modules); assertEquals(modules.size(), 1); assert modules.remove(0) instanceof JDKLoggingModule; } + @RequiresHttp + class RequiresHttpModule implements Module { + + public void configure(Binder arg0) { + } + + } + @Test public void testAddBothWhenLive() { List modules = new ArrayList(); - modules.add(new LiveS3ConnectionModule()); - S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules); - S3ContextFactory.addLoggingModuleIfNotPresent(modules); + modules.add(new RequiresHttpModule()); + TestCloudContextBuilder builder = new TestCloudContextBuilder(new Properties()); + builder.addHttpModuleIfNeededAndNotPresent(modules); + builder.addLoggingModuleIfNotPresent(modules); assertEquals(modules.size(), 3); - assert modules.remove(0) instanceof LiveS3ConnectionModule; + assert modules.remove(0) instanceof RequiresHttpModule; assert modules.remove(0) instanceof JavaUrlHttpFutureCommandClientModule; assert modules.remove(0) instanceof JDKLoggingModule; } public void testBuilder() { - String awsAccessKeyId = "awsAccessKeyId"; - String awsSecretAccessKey = "awsSecretAccessKey"; + String id = "awsAccessKeyId"; + String secret = "awsSecretAccessKey"; String httpAddress = "httpAddress"; int httpMaxRetries = 9875; int httpPort = 3827; boolean httpSecure = false; - int poolIoWorkerThreads= 2727; + int poolIoWorkerThreads = 2727; int poolMaxConnectionReuse = 3932; int poolMaxConnections = 3382; int poolMaxSessionFailures = 857; int poolRequestInvokerThreads = 8362; - + AbstractModule module1 = new AbstractModule() { @Override @@ -131,23 +197,23 @@ public class S3ContextFactoryTest { } }; AbstractModule module2 = new AbstractModule() { - + @Override protected void configure() { } }; - - S3ContextFactory factory = S3ContextFactory.createContext(awsAccessKeyId, awsSecretAccessKey); - factory.withHttpAddress(httpAddress); - factory.withHttpMaxRetries(httpMaxRetries); - factory.withHttpPort(httpPort); - factory.withHttpSecure(httpSecure); - factory.withModule(module1); - factory.withModules(module2); - factory.withPoolIoWorkerThreads(poolIoWorkerThreads); - factory.withPoolMaxConnectionReuse(poolMaxConnectionReuse); - factory.withPoolMaxConnections(poolMaxConnections); - factory.withPoolMaxSessionFailures(poolMaxSessionFailures); - factory.withPoolRequestInvokerThreads(poolRequestInvokerThreads); + TestCloudContextBuilder builder = new TestCloudContextBuilder(new Properties()); + builder.authenticate(id, secret); + builder.withHttpAddress(httpAddress); + builder.withHttpMaxRetries(httpMaxRetries); + builder.withHttpPort(httpPort); + builder.withHttpSecure(httpSecure); + builder.withModule(module1); + builder.withModules(module2); + builder.withPoolIoWorkerThreads(poolIoWorkerThreads); + builder.withPoolMaxConnectionReuse(poolMaxConnectionReuse); + builder.withPoolMaxConnections(poolMaxConnections); + builder.withPoolMaxSessionFailures(poolMaxSessionFailures); + builder.withPoolRequestInvokerThreads(poolRequestInvokerThreads); } } diff --git a/objectstore/core/pom.xml b/objectstore/core/pom.xml new file mode 100644 index 0000000000..2a6224086d --- /dev/null +++ b/objectstore/core/pom.xml @@ -0,0 +1,48 @@ + + + + + org.jclouds + jclouds-objectstore-project + 1.0-SNAPSHOT + ../pom.xml + + 4.0.0 + org.jclouds + jclouds-objectstore-core + jclouds objectstore Components Core + jar + jclouds Core components to access objectstores + + + scm:svn:http://jclouds.googlecode.com/svn/trunk/objectstore/core + scm:svn:https://jclouds.googlecode.com/svn/trunk/objectstore/core + http://jclouds.googlecode.com/svn/trunk/objectstore/core + + + diff --git a/objectstore/core/src/main/java/org/jclouds/objectstore/reference/ObjectStoreConstants.java b/objectstore/core/src/main/java/org/jclouds/objectstore/reference/ObjectStoreConstants.java new file mode 100644 index 0000000000..84ddce187e --- /dev/null +++ b/objectstore/core/src/main/java/org/jclouds/objectstore/reference/ObjectStoreConstants.java @@ -0,0 +1,42 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.objectstore.reference; + +/** + * Configuration properties and constants used in ObjectStore connections. + * + * @author Adrian Cole + */ +public interface ObjectStoreConstants { + + /** + * longest time a single Map operation can take before throwing an exception. + */ + public static final String PROPERTY_OBJECTMAP_TIMEOUT = "jclouds.objectmap.timeout"; + /** + * time to pause before retrying a transient failure + */ + public static final String PROPERTY_OBJECTMAP_RETRY = "jclouds.objectmap.retry"; + +} diff --git a/objectstore/core/src/main/java/org/jclouds/objectstore/reference/package-info.java b/objectstore/core/src/main/java/org/jclouds/objectstore/reference/package-info.java new file mode 100644 index 0000000000..2592fb31b1 --- /dev/null +++ b/objectstore/core/src/main/java/org/jclouds/objectstore/reference/package-info.java @@ -0,0 +1,28 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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. + * ==================================================================== + */ +/** + * This package contains properties and reference data used in S3. + * @author Adrian Cole + */ +package org.jclouds.objectstore.reference; \ No newline at end of file diff --git a/objectstore/pom.xml b/objectstore/pom.xml new file mode 100644 index 0000000000..570207074e --- /dev/null +++ b/objectstore/pom.xml @@ -0,0 +1,68 @@ + + + + + jclouds-project + org.jclouds + 1.0-SNAPSHOT + ../project/pom.xml + + 4.0.0 + jclouds-objectstore-project + pom + jclouds objectstore project + + core + + + + ${project.groupId} + jclouds-core + ${project.version} + + + ${project.groupId} + jclouds-core + ${project.version} + test-jar + test + + + log4j + log4j + 1.2.14 + test + + + ${project.groupId} + jclouds-log4j + ${project.version} + test + + +