From c8b3240d04d069e3ee6eaab71b9a696fc2f16ba2 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Tue, 6 Jul 2010 13:33:07 -0700 Subject: [PATCH] updated tweetstore demos to include googlestorage and latest api --- demos/gae-tweetstore-spring/pom.xml | 36 +++-- .../config/SpringServletConfig.java | 13 +- .../controller/StoreTweetsController.java | 134 +++++++-------- .../reference/TweetStoreConstants.java | 6 +- .../controller/AddTweetsControllerTest.java | 5 +- .../controller/StoreTweetsControllerTest.java | 22 +-- .../functions/KeyToStoredTweetStatusTest.java | 5 +- .../ServiceToStoredTweetStatusesTest.java | 5 +- .../integration/TweetStoreLiveTest.java | 148 ++++++++++------- demos/gae-tweetstore/pom.xml | 82 +++++----- .../tweetstore/config/GuiceServletConfig.java | 22 ++- .../controller/StoreTweetsController.java | 17 +- .../reference/TweetStoreConstants.java | 6 +- .../controller/AddTweetsControllerTest.java | 4 +- .../controller/StoreTweetsControllerTest.java | 22 +-- .../functions/KeyToStoredTweetStatusTest.java | 4 +- .../ServiceToStoredTweetStatusesTest.java | 5 +- .../integration/TweetStoreLiveTest.java | 153 +++++++++++------- 18 files changed, 396 insertions(+), 293 deletions(-) diff --git a/demos/gae-tweetstore-spring/pom.xml b/demos/gae-tweetstore-spring/pom.xml index 0e8b66ded5..1c62a3f573 100644 --- a/demos/gae-tweetstore-spring/pom.xml +++ b/demos/gae-tweetstore-spring/pom.xml @@ -64,6 +64,18 @@ test-jar test + + ${project.groupId} + jclouds-log4j + ${project.version} + test + + + log4j + log4j + 1.2.14 + test + ${project.groupId} jclouds-twitter @@ -242,43 +254,43 @@ - jclouds.twitter.user + twitter.identity ${jclouds.twitter.user} - jclouds.twitter.password + twitter.credential ${jclouds.twitter.password} - jclouds.azure.storage.account + azureblob.identity ${jclouds.azure.storage.account} - jclouds.azure.storage.key + azureblob.credential ${jclouds.azure.storage.key} - jclouds.rackspace.user + cloudfiles.identity ${jclouds.rackspace.user} - jclouds.rackspace.key + cloudfiles.credential ${jclouds.rackspace.key} - jclouds.emcsaas.uid - ${jclouds.emcsaas.uid} + googlestorage.identity + ${jclouds.googlestorage.accesskeyid} - jclouds.emcsaas.key - ${jclouds.emcsaas.key} + googlestorage.credential + ${jclouds.googlestorage.secretaccesskey} - jclouds.aws.accesskeyid + s3.identity ${jclouds.aws.accesskeyid} - jclouds.aws.secretaccesskey + s3.credential ${jclouds.aws.secretaccesskey} diff --git a/demos/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java b/demos/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java index 42bd275025..9359cab6ad 100644 --- a/demos/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java +++ b/demos/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java @@ -40,6 +40,7 @@ import org.jclouds.demo.tweetstore.controller.AddTweetsController; import org.jclouds.demo.tweetstore.controller.StoreTweetsController; import org.jclouds.demo.tweetstore.functions.ServiceToStoredTweetStatuses; import org.jclouds.gae.config.GoogleAppEngineConfigurationModule; +import org.jclouds.rest.RestContextFactory; import org.jclouds.twitter.TwitterClient; import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.annotation.Bean; @@ -77,18 +78,26 @@ public class SpringServletConfig extends LoggingConfig implements ServletConfigA @PostConstruct public void initialize() throws IOException { + BlobStoreContextFactory blobStoreContextFactory = new BlobStoreContextFactory(); + Properties props = loadJCloudsProperties(); logger.trace("About to initialize members."); Module googleModule = new GoogleAppEngineConfigurationModule(); Set modules = ImmutableSet. of(googleModule); // shared across all blobstores and used to retrieve tweets -//TODO twitterClient = TwitterContextFactory.createContext(props, googleModule).getApi(); + try { + twitterClient = (TwitterClient) new RestContextFactory().createContext("twitter", modules, + props).getApi(); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("properties for twitter not configured properly in " + + props.toString(), e); + } // common namespace for storing tweets container = checkNotNull(props.getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER); - BlobStoreContextFactory blobStoreContextFactory = new BlobStoreContextFactory(); + // instantiate and store references to all blobstores by provider name providerTypeToBlobStoreMap = Maps.newHashMap(); for (String hint : Splitter.on(',').split( diff --git a/demos/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java b/demos/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java index b3392bc6ea..be2a051d43 100644 --- a/demos/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java +++ b/demos/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java @@ -39,6 +39,7 @@ import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; import org.jclouds.logging.Logger; +import org.jclouds.rest.AuthorizationException; import org.jclouds.twitter.TwitterClient; import org.jclouds.twitter.domain.Status; @@ -53,78 +54,81 @@ import com.google.common.base.Function; @Singleton public class StoreTweetsController extends HttpServlet { - private static final class StatusToBlob implements Function { - private final BlobMap map; + private static final class StatusToBlob implements Function { + private final BlobMap map; - private StatusToBlob(BlobMap map) { - this.map = map; - } + private StatusToBlob(BlobMap map) { + this.map = map; + } - public Blob apply(Status from) { - Blob to = map.newBlob(from.getId() + ""); - to.getMetadata().setContentType(MediaType.TEXT_PLAIN); - to.getMetadata().setName(from.getId() + ""); - to.setPayload(from.getText()); - to.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, - from.getUser().getScreenName()); - return to; - } - } + public Blob apply(Status from) { + Blob to = map.newBlob(from.getId() + ""); + to.getMetadata().setContentType(MediaType.TEXT_PLAIN); + to.setPayload(from.getText()); + to.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, + from.getUser().getScreenName()); + return to; + } + } - /** The serialVersionUID */ - private static final long serialVersionUID = 7215420527854203714L; + /** The serialVersionUID */ + private static final long serialVersionUID = 7215420527854203714L; - private final Map contexts; - private final TwitterClient client; - private final String container; + private final Map contexts; + private final TwitterClient client; + private final String container; - @Resource - protected Logger logger = Logger.NULL; + @Resource + protected Logger logger = Logger.NULL; - @Inject - public StoreTweetsController( - Map contexts, - @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) final String container, + @Inject + @VisibleForTesting + public StoreTweetsController(Map contexts, + @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container, TwitterClient client) { - this.container = container; - this.contexts = contexts; - this.client = client; - } + this.container = container; + this.contexts = contexts; + this.client = client; + } - @VisibleForTesting - void addMyTweets(String contextName, SortedSet allAboutMe) { - BlobStoreContext context = checkNotNull(contexts.get(contextName), - "no context for " + contextName + " in " + contexts.keySet()); - BlobMap map = context.createBlobMap(container); - for (Status status : allAboutMe) { - try { - map.put(status.getId() + "", new StatusToBlob(map).apply(status)); - } catch (Exception e) { - logger.error(e, "Error storing tweet %s on map %s/%s", status.getId(), - context, container); - } - } - } + @VisibleForTesting + public void addMyTweets(String contextName, SortedSet allAboutMe) { + BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + + contextName + " in " + contexts.keySet()); + BlobMap map = context.createBlobMap(container); + for (Status status : allAboutMe) { + Blob blob = null; + try { + blob = new StatusToBlob(map).apply(status); + map.put(status.getId() + "", blob); + } catch (AuthorizationException e) { + throw e; + } catch (Exception e) { + logger.error(e, "Error storing tweet %s (blob[%s]) on map %s/%s", status.getId(), blob, + context, container); + } + } + } - @Override - protected void doGet(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - if (request.getHeader("X-AppEngine-QueueName") != null - && request.getHeader("X-AppEngine-QueueName").equals("twitter")) { - try { - String contextName = - checkNotNull(request.getHeader("context"), "missing header context"); - logger.info("retrieving tweets"); - addMyTweets(contextName, client.getMyMentions()); - logger.debug("done storing tweets"); - response.setContentType(MediaType.TEXT_PLAIN); - response.getWriter().println("Done!"); - } catch (Exception e) { - logger.error(e, "Error storing tweets"); - throw new ServletException(e); - } - } else { - response.sendError(401); - } - } + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + if (request.getHeader("X-AppEngine-QueueName") != null + && request.getHeader("X-AppEngine-QueueName").equals("twitter")) { + try { + String contextName = checkNotNull(request.getHeader("context"), + "missing header context"); + logger.info("retrieving tweets"); + addMyTweets(contextName, client.getMyMentions()); + logger.debug("done storing tweets"); + response.setContentType(MediaType.TEXT_PLAIN); + response.getWriter().println("Done!"); + } catch (Exception e) { + logger.error(e, "Error storing tweets"); + throw new ServletException(e); + } + } else { + response.sendError(401); + } + } } \ No newline at end of file diff --git a/demos/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/reference/TweetStoreConstants.java b/demos/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/reference/TweetStoreConstants.java index 354b16a9d5..11fe6aae72 100644 --- a/demos/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/reference/TweetStoreConstants.java +++ b/demos/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/reference/TweetStoreConstants.java @@ -25,5 +25,9 @@ package org.jclouds.demo.tweetstore.reference; */ public interface TweetStoreConstants { public static final String PROPERTY_TWEETSTORE_CONTAINER = "jclouds.tweetstore.container"; - public static final String SENDER_NAME = "jclouds.tweetstore.sendername"; + /** + * Note that this has to conform to restrictions of all blobstores. for example, azure doesn't + * support periods. + */ + public static final String SENDER_NAME = "sendername"; } diff --git a/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java b/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java index 86ff724206..ff8a9f969b 100644 --- a/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java +++ b/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java @@ -26,7 +26,7 @@ import java.util.Map; import java.util.concurrent.ExecutionException; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.TransientBlobStoreContextBuilder; +import org.jclouds.blobstore.BlobStoreContextFactory; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; import org.jclouds.demo.tweetstore.functions.ServiceToStoredTweetStatuses; @@ -49,7 +49,8 @@ public class AddTweetsControllerTest { ExecutionException { Map services = Maps.newHashMap(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = new TransientBlobStoreContextBuilder().buildBlobStoreContext(); + BlobStoreContext context = new BlobStoreContextFactory().createContext("transient", + "dummy", "dummy"); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().newBlob("1"); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); diff --git a/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java b/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java index 0b3c143180..677342e8c9 100644 --- a/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java +++ b/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java @@ -30,7 +30,7 @@ import java.util.concurrent.ExecutionException; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.TransientBlobStoreContextBuilder; +import org.jclouds.blobstore.BlobStoreContextFactory; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; import org.jclouds.twitter.TwitterClient; @@ -56,8 +56,8 @@ public class StoreTweetsControllerTest { Map createBlobStores() throws InterruptedException, ExecutionException { Map contexts = ImmutableMap. of("test1", - new TransientBlobStoreContextBuilder().buildBlobStoreContext(), "test2", - new TransientBlobStoreContextBuilder().buildBlobStoreContext()); + new BlobStoreContextFactory().createContext("transient", "dummy", "dummy"), "test2", + new BlobStoreContextFactory().createContext("transient", "dummy", "dummy")); for (BlobStoreContext blobstore : contexts.values()) { blobstore.getAsyncBlobStore().createContainerInLocation(null, "favo").get(); } @@ -70,19 +70,11 @@ public class StoreTweetsControllerTest { createTwitterClient()); SortedSet allAboutMe = Sets.newTreeSet(); - User frank = new User(); - frank.setScreenName("frank"); - Status frankStatus = new Status(); - frankStatus.setId(1); - frankStatus.setUser(frank); - frankStatus.setText("I love beans!"); + User frank = new User(1l, "frank"); + Status frankStatus = new Status(1l, frank, "I love beans!"); - User jimmy = new User(); - jimmy.setScreenName("jimmy"); - Status jimmyStatus = new Status(); - jimmyStatus.setId(2); - jimmyStatus.setUser(jimmy); - jimmyStatus.setText("cloud is king"); + User jimmy = new User(2l, "jimmy"); + Status jimmyStatus = new Status(2l, jimmy, "cloud is king"); allAboutMe.add(frankStatus); allAboutMe.add(jimmyStatus); diff --git a/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java b/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java index 6fa7670f06..51906e2f66 100644 --- a/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java +++ b/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java @@ -25,7 +25,7 @@ import java.util.concurrent.ExecutionException; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.TransientBlobStoreContextBuilder; +import org.jclouds.blobstore.BlobStoreContextFactory; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; @@ -40,7 +40,8 @@ import org.testng.annotations.Test; public class KeyToStoredTweetStatusTest { BlobMap createMap() throws InterruptedException, ExecutionException { - BlobStoreContext context = new TransientBlobStoreContextBuilder().buildBlobStoreContext(); + BlobStoreContext context = new BlobStoreContextFactory().createContext("transient", "dummy", + "dummy"); context.getBlobStore().createContainerInLocation(null, "test1"); return context.createBlobMap("test1"); } diff --git a/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java b/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java index 2e755e580f..6217a38eb2 100644 --- a/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java +++ b/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java @@ -25,7 +25,7 @@ import java.util.Map; import java.util.concurrent.ExecutionException; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.TransientBlobStoreContextBuilder; +import org.jclouds.blobstore.BlobStoreContextFactory; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; @@ -46,7 +46,8 @@ public class ServiceToStoredTweetStatusesTest { ExecutionException { Map services = Maps.newHashMap(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = new TransientBlobStoreContextBuilder().buildBlobStoreContext(); + BlobStoreContext context = new BlobStoreContextFactory().createContext("transient", + "dummy", "dummy"); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().newBlob("1"); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); diff --git a/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java b/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java index e0120220c7..e4fe678b14 100644 --- a/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java +++ b/demos/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java @@ -20,23 +20,40 @@ package org.jclouds.demo.tweetstore.integration; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER; +import static org.jclouds.rest.RestContextFactory.contextSpec; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; +import java.util.Map; import java.util.Properties; +import java.util.Set; +import java.util.SortedSet; +import java.util.Map.Entry; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import org.jclouds.blobstore.BlobStoreContext; +import org.jclouds.blobstore.BlobStoreContextFactory; import org.jclouds.demo.tweetstore.config.SpringServletConfig; +import org.jclouds.demo.tweetstore.controller.StoreTweetsController; +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.rest.RestContext; +import org.jclouds.rest.RestContextFactory; +import org.jclouds.twitter.TwitterAsyncClient; +import org.jclouds.twitter.TwitterClient; +import org.jclouds.twitter.domain.Status; import org.jclouds.util.Utils; -import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeTest; import org.testng.annotations.Parameters; import org.testng.annotations.Test; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.inject.Module; + /** * Starts up the Google App Engine for Java Development environment and deploys an application which * tests accesses twitter and blobstores. @@ -48,67 +65,48 @@ public class TweetStoreLiveTest { GoogleDevServer server; private URL url; - private Iterable contexts; + private Map contexts; private String container; + private static final Iterable blobstores = ImmutableSet.of("cloudfiles", + "googlestorage", "s3", "azureblob"); + private static final Properties props = new Properties(); + @BeforeTest - @Parameters( { "warfile", "devappserver.address", "devappserver.port" }) - public void startDevAppServer(final String warfile, final String address, final String port) - throws Exception { - url = new URL(String.format("http://%s:%s", address, port)); - Properties props = new Properties(); - props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, checkNotNull(System - .getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER)); - - // WATCH THIS.. when adding a new context, you must update the string - props.setProperty(SpringServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, "cloudfiles,s3,azureblob"); - // TODO - // props = new TwitterPropertiesBuilder(props).withCredentials( - // checkNotNull(System.getProperty(PROPERTY_TWITTER_USER), PROPERTY_TWITTER_USER), - // System.getProperty(PROPERTY_TWITTER_PASSWORD, PROPERTY_TWITTER_PASSWORD)).build(); - // TODO FIX - - // props = new S3PropertiesBuilder(props) - // .withCredentials( - // checkNotNull(System.getProperty(PROPERTY_AWS_ACCESSKEYID), - // PROPERTY_AWS_ACCESSKEYID), - // System.getProperty(PROPERTY_AWS_SECRETACCESSKEY, - // PROPERTY_AWS_SECRETACCESSKEY)).build(); - // - // props = new CloudFilesPropertiesBuilder(props).withCredentials( - // checkNotNull(System.getProperty(PROPERTY_RACKSPACE_USER), PROPERTY_RACKSPACE_USER), - // System.getProperty(PROPERTY_RACKSPACE_KEY, PROPERTY_RACKSPACE_KEY)).build(); - // - // props = new AzureBlobPropertiesBuilder(props).withCredentials( - // checkNotNull(System.getProperty(PROPERTY_AZURESTORAGE_ACCOUNT), - // PROPERTY_AZURESTORAGE_ACCOUNT), - // System.getProperty(PROPERTY_AZURESTORAGE_KEY, PROPERTY_AZURESTORAGE_KEY)).build(); - - server = new GoogleDevServer(); - server.writePropertiesAndStartServer(address, port, warfile, props); - } - - @BeforeClass void clearAndCreateContainers() throws InterruptedException, ExecutionException, TimeoutException, IOException { container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER)); - // TODO FIX - // BlobStoreContextFactory factory = new BlobStoreContextFactory(); - // BlobStoreContext s3Context = factory.createContext("s3", checkNotNull(System - // .getProperty(PROPERTY_AWS_ACCESSKEYID), PROPERTY_AWS_ACCESSKEYID), System - // .getProperty(PROPERTY_AWS_SECRETACCESSKEY, PROPERTY_AWS_SECRETACCESSKEY)); - // - // BlobStoreContext cfContext = factory.createContext("cloudfiles", checkNotNull(System - // .getProperty(PROPERTY_RACKSPACE_USER), PROPERTY_RACKSPACE_USER), System.getProperty( - // PROPERTY_RACKSPACE_KEY, PROPERTY_RACKSPACE_KEY)); - // - // BlobStoreContext azContext = factory.createContext("azureblob", checkNotNull(System - // .getProperty(PROPERTY_AZURESTORAGE_ACCOUNT), PROPERTY_AZURESTORAGE_ACCOUNT), System - // .getProperty(PROPERTY_AZURESTORAGE_KEY, PROPERTY_AZURESTORAGE_KEY)); - // - // this.contexts = ImmutableList.of(s3Context, cfContext, azContext); + + props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, checkNotNull(System + .getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER)); + + props.setProperty(SpringServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, Joiner.on(',').join( + blobstores)); + + // put all identity/credential pairs into the client + addCredentialsForBlobStores(props); + + // example of an ad-hoc client configuration + addConfigurationForTwitter(props); + + final BlobStoreContextFactory factory = new BlobStoreContextFactory(); + // for testing, capture logs. + final Set wiring = ImmutableSet. of(new Log4JLoggingModule()); + this.contexts = Maps.newConcurrentMap(); + + for (String provider : blobstores) { + contexts.put(provider, factory.createContext(provider, wiring, props)); + } + + RestContext twitterContext = new RestContextFactory() + .createContext("twitter", wiring, props); + StoreTweetsController controller = new StoreTweetsController(contexts, container, + twitterContext.getApi()); + + SortedSet statuses = twitterContext.getApi().getMyMentions(); + boolean deleted = false; - for (BlobStoreContext context : contexts) { + for (BlobStoreContext context : contexts.values()) { if (context.getBlobStore().containerExists(container)) { System.err.printf("deleting container %s at %s%n", container, context .getProviderSpecificContext().getEndpoint()); @@ -120,15 +118,49 @@ public class TweetStoreLiveTest { System.err.println("sleeping 60 seconds to allow containers to clear"); Thread.sleep(60000); } - for (BlobStoreContext context : contexts) { + for (BlobStoreContext context : contexts.values()) { System.err.printf("creating container %s at %s%n", container, context .getProviderSpecificContext().getEndpoint()); context.getBlobStore().createContainerInLocation(null, container); } if (deleted) { System.err.println("sleeping 5 seconds to allow containers to create"); - Thread.sleep(30000); + Thread.sleep(5000); } + + for (Entry entry : contexts.entrySet()) { + System.err.printf("filling container %s at %s%n", container, entry.getKey()); + controller.addMyTweets(entry.getKey(), statuses); + } + } + + private void addConfigurationForTwitter(Properties props) { + String twitterIdentity = checkNotNull(System.getProperty("twitter.identity"), + "twitter.identity"); + String twitterCredential = checkNotNull(System.getProperty("twitter.credential"), + "twitter.credential"); + + props.putAll(RestContextFactory.toProperties(contextSpec("twitter", "http://twitter.com", + "1", twitterIdentity, twitterCredential, TwitterClient.class, + TwitterAsyncClient.class))); + } + + private void addCredentialsForBlobStores(Properties props) { + for (String provider : blobstores) { + props.setProperty(provider + ".identity", checkNotNull(System.getProperty(provider + + ".identity"), provider + ".identity")); + props.setProperty(provider + ".credential", checkNotNull(System.getProperty(provider + + ".credential"), provider + ".credential")); + } + } + + @BeforeTest + @Parameters( { "warfile", "devappserver.address", "devappserver.port" }) + public void startDevAppServer(final String warfile, final String address, final String port) + throws Exception { + url = new URL(String.format("http://%s:%s", address, port)); + server = new GoogleDevServer(); + server.writePropertiesAndStartServer(address, port, warfile, props); } @Test @@ -160,7 +192,7 @@ public class TweetStoreLiveTest { System.err.println("sleeping 20 seconds to allow for eventual consistency delay"); Thread.sleep(20000); - for (BlobStoreContext context : contexts) { + for (BlobStoreContext context : contexts.values()) { assert context.createInputStreamMap(container).size() > 0 : context .getProviderSpecificContext().getEndpoint(); } diff --git a/demos/gae-tweetstore/pom.xml b/demos/gae-tweetstore/pom.xml index 3a9888adaa..3758077b6d 100644 --- a/demos/gae-tweetstore/pom.xml +++ b/demos/gae-tweetstore/pom.xml @@ -1,29 +1,28 @@ - + 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. + ==================================================================== + --> 4.0.0 - org.jclouds + org.jclouds jclouds-demos-project 1.0-SNAPSHOT @@ -64,6 +63,18 @@ test-jar test + + ${project.groupId} + jclouds-log4j + ${project.version} + test + + + log4j + log4j + 1.2.14 + test + ${project.groupId} jclouds-twitter @@ -74,11 +85,6 @@ jclouds-aws ${project.version} - - ${project.groupId} - jclouds-atmos - ${project.version} - ${project.groupId} jclouds-azure @@ -232,45 +238,45 @@ - jclouds.twitter.user + twitter.identity ${jclouds.twitter.user} - jclouds.twitter.password + twitter.credential ${jclouds.twitter.password} - jclouds.azure.storage.account + azureblob.identity ${jclouds.azure.storage.account} - jclouds.azure.storage.key + azureblob.credential ${jclouds.azure.storage.key} - jclouds.rackspace.user + cloudfiles.identity ${jclouds.rackspace.user} - jclouds.rackspace.key + cloudfiles.credential ${jclouds.rackspace.key} - jclouds.emcsaas.uid - ${jclouds.emcsaas.uid} - - - jclouds.emcsaas.key - ${jclouds.emcsaas.key} - - - jclouds.aws.accesskeyid + s3.identity ${jclouds.aws.accesskeyid} - jclouds.aws.secretaccesskey + s3.credential ${jclouds.aws.secretaccesskey} + + googlestorage.identity + ${jclouds.googlestorage.accesskeyid} + + + googlestorage.credential + ${jclouds.googlestorage.secretaccesskey} + appengine.home ${appengine.home} diff --git a/demos/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java b/demos/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java index b8bab4c583..d41252efce 100755 --- a/demos/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java +++ b/demos/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java @@ -35,6 +35,7 @@ import org.jclouds.blobstore.BlobStoreContextFactory; import org.jclouds.demo.tweetstore.controller.AddTweetsController; import org.jclouds.demo.tweetstore.controller.StoreTweetsController; import org.jclouds.gae.config.GoogleAppEngineConfigurationModule; +import org.jclouds.rest.RestContextFactory; import org.jclouds.twitter.TwitterClient; import com.google.appengine.api.labs.taskqueue.Queue; @@ -67,19 +68,24 @@ public class GuiceServletConfig extends GuiceServletContextListener { @Override public void contextInitialized(ServletContextEvent servletContextEvent) { - BlobStoreContextFactory blobStoreContextFactory = null; - blobStoreContextFactory = new BlobStoreContextFactory(); + BlobStoreContextFactory blobStoreContextFactory = new BlobStoreContextFactory(); Properties props = loadJCloudsProperties(servletContextEvent); Module googleModule = new GoogleAppEngineConfigurationModule(); Set modules = ImmutableSet. of(googleModule); -// // shared across all blobstores and used to retrieve tweets -// twitterClient = TwitterContextFactory.createContext(props, googleModule).getApi(); -// -// // common namespace for storing tweets -// container = checkNotNull(props.getProperty(PROPERTY_TWEETSTORE_CONTAINER), -// PROPERTY_TWEETSTORE_CONTAINER); + // shared across all blobstores and used to retrieve tweets + try { + twitterClient = (TwitterClient) new RestContextFactory().createContext("twitter", modules, + props).getApi(); + + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("properties for twitter not configured properly in " + + props.toString(), e); + } + // common namespace for storing tweets + container = checkNotNull(props.getProperty(PROPERTY_TWEETSTORE_CONTAINER), + PROPERTY_TWEETSTORE_CONTAINER); // instantiate and store references to all blobstores by provider name providerTypeToBlobStoreMap = Maps.newHashMap(); diff --git a/demos/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java b/demos/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java index 521a56647a..be2a051d43 100644 --- a/demos/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java +++ b/demos/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java @@ -39,6 +39,7 @@ import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; import org.jclouds.logging.Logger; +import org.jclouds.rest.AuthorizationException; import org.jclouds.twitter.TwitterClient; import org.jclouds.twitter.domain.Status; @@ -82,8 +83,8 @@ public class StoreTweetsController extends HttpServlet { @Inject @VisibleForTesting - StoreTweetsController(Map contexts, - @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) final String container, + public StoreTweetsController(Map contexts, + @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container, TwitterClient client) { this.container = container; this.contexts = contexts; @@ -91,16 +92,20 @@ public class StoreTweetsController extends HttpServlet { } @VisibleForTesting - void addMyTweets(String contextName, SortedSet allAboutMe) { + public void addMyTweets(String contextName, SortedSet allAboutMe) { BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in " + contexts.keySet()); BlobMap map = context.createBlobMap(container); for (Status status : allAboutMe) { + Blob blob = null; try { - map.put(status.getId() + "", new StatusToBlob(map).apply(status)); + blob = new StatusToBlob(map).apply(status); + map.put(status.getId() + "", blob); + } catch (AuthorizationException e) { + throw e; } catch (Exception e) { - logger.error(e, "Error storing tweet %s on map %s/%s", status.getId(), context, - container); + logger.error(e, "Error storing tweet %s (blob[%s]) on map %s/%s", status.getId(), blob, + context, container); } } } diff --git a/demos/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/reference/TweetStoreConstants.java b/demos/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/reference/TweetStoreConstants.java index 354b16a9d5..11fe6aae72 100644 --- a/demos/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/reference/TweetStoreConstants.java +++ b/demos/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/reference/TweetStoreConstants.java @@ -25,5 +25,9 @@ package org.jclouds.demo.tweetstore.reference; */ public interface TweetStoreConstants { public static final String PROPERTY_TWEETSTORE_CONTAINER = "jclouds.tweetstore.container"; - public static final String SENDER_NAME = "jclouds.tweetstore.sendername"; + /** + * Note that this has to conform to restrictions of all blobstores. for example, azure doesn't + * support periods. + */ + public static final String SENDER_NAME = "sendername"; } diff --git a/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java b/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java index 86ff724206..893e19c8e0 100644 --- a/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java +++ b/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java @@ -26,7 +26,7 @@ import java.util.Map; import java.util.concurrent.ExecutionException; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.TransientBlobStoreContextBuilder; +import org.jclouds.blobstore.BlobStoreContextFactory; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; import org.jclouds.demo.tweetstore.functions.ServiceToStoredTweetStatuses; @@ -49,7 +49,7 @@ public class AddTweetsControllerTest { ExecutionException { Map services = Maps.newHashMap(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = new TransientBlobStoreContextBuilder().buildBlobStoreContext(); + BlobStoreContext context = new BlobStoreContextFactory().createContext("transient", "dummy", "dummy"); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().newBlob("1"); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); diff --git a/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java b/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java index 0b3c143180..677342e8c9 100644 --- a/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java +++ b/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java @@ -30,7 +30,7 @@ import java.util.concurrent.ExecutionException; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.TransientBlobStoreContextBuilder; +import org.jclouds.blobstore.BlobStoreContextFactory; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; import org.jclouds.twitter.TwitterClient; @@ -56,8 +56,8 @@ public class StoreTweetsControllerTest { Map createBlobStores() throws InterruptedException, ExecutionException { Map contexts = ImmutableMap. of("test1", - new TransientBlobStoreContextBuilder().buildBlobStoreContext(), "test2", - new TransientBlobStoreContextBuilder().buildBlobStoreContext()); + new BlobStoreContextFactory().createContext("transient", "dummy", "dummy"), "test2", + new BlobStoreContextFactory().createContext("transient", "dummy", "dummy")); for (BlobStoreContext blobstore : contexts.values()) { blobstore.getAsyncBlobStore().createContainerInLocation(null, "favo").get(); } @@ -70,19 +70,11 @@ public class StoreTweetsControllerTest { createTwitterClient()); SortedSet allAboutMe = Sets.newTreeSet(); - User frank = new User(); - frank.setScreenName("frank"); - Status frankStatus = new Status(); - frankStatus.setId(1); - frankStatus.setUser(frank); - frankStatus.setText("I love beans!"); + User frank = new User(1l, "frank"); + Status frankStatus = new Status(1l, frank, "I love beans!"); - User jimmy = new User(); - jimmy.setScreenName("jimmy"); - Status jimmyStatus = new Status(); - jimmyStatus.setId(2); - jimmyStatus.setUser(jimmy); - jimmyStatus.setText("cloud is king"); + User jimmy = new User(2l, "jimmy"); + Status jimmyStatus = new Status(2l, jimmy, "cloud is king"); allAboutMe.add(frankStatus); allAboutMe.add(jimmyStatus); diff --git a/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java b/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java index 6fa7670f06..6079c8a31a 100644 --- a/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java +++ b/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java @@ -25,7 +25,7 @@ import java.util.concurrent.ExecutionException; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.TransientBlobStoreContextBuilder; +import org.jclouds.blobstore.BlobStoreContextFactory; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; @@ -40,7 +40,7 @@ import org.testng.annotations.Test; public class KeyToStoredTweetStatusTest { BlobMap createMap() throws InterruptedException, ExecutionException { - BlobStoreContext context = new TransientBlobStoreContextBuilder().buildBlobStoreContext(); + BlobStoreContext context = new BlobStoreContextFactory().createContext("transient", "dummy", "dummy"); context.getBlobStore().createContainerInLocation(null, "test1"); return context.createBlobMap("test1"); } diff --git a/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java b/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java index 2e755e580f..6217a38eb2 100644 --- a/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java +++ b/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java @@ -25,7 +25,7 @@ import java.util.Map; import java.util.concurrent.ExecutionException; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.TransientBlobStoreContextBuilder; +import org.jclouds.blobstore.BlobStoreContextFactory; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; @@ -46,7 +46,8 @@ public class ServiceToStoredTweetStatusesTest { ExecutionException { Map services = Maps.newHashMap(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = new TransientBlobStoreContextBuilder().buildBlobStoreContext(); + BlobStoreContext context = new BlobStoreContextFactory().createContext("transient", + "dummy", "dummy"); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().newBlob("1"); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); diff --git a/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java b/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java index ec46b8170a..5363ededbc 100755 --- a/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java +++ b/demos/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java @@ -20,23 +20,40 @@ package org.jclouds.demo.tweetstore.integration; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER; +import static org.jclouds.rest.RestContextFactory.contextSpec; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; +import java.util.Map; import java.util.Properties; +import java.util.Set; +import java.util.SortedSet; +import java.util.Map.Entry; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import org.jclouds.blobstore.BlobStoreContext; +import org.jclouds.blobstore.BlobStoreContextFactory; import org.jclouds.demo.tweetstore.config.GuiceServletConfig; +import org.jclouds.demo.tweetstore.controller.StoreTweetsController; +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.rest.RestContext; +import org.jclouds.rest.RestContextFactory; +import org.jclouds.twitter.TwitterAsyncClient; +import org.jclouds.twitter.TwitterClient; +import org.jclouds.twitter.domain.Status; import org.jclouds.util.Utils; -import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeTest; import org.testng.annotations.Parameters; import org.testng.annotations.Test; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.inject.Module; + /** * Starts up the Google App Engine for Java Development environment and deploys an application which * tests accesses twitter and blobstores. @@ -48,67 +65,48 @@ public class TweetStoreLiveTest { GoogleDevServer server; private URL url; - private Iterable contexts; + private Map contexts; private String container; + private static final Iterable blobstores = ImmutableSet.of("cloudfiles", + "googlestorage", "s3", "azureblob"); + private static final Properties props = new Properties(); + @BeforeTest - @Parameters( { "warfile", "devappserver.address", "devappserver.port" }) - public void startDevAppServer(final String warfile, final String address, final String port) - throws Exception { - url = new URL(String.format("http://%s:%s", address, port)); - Properties props = new Properties(); - props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, checkNotNull(System - .getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER)); - - // WATCH THIS.. when adding a new context, you must update the string - props.setProperty(GuiceServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, "cloudfiles,s3,azureblob"); - - // props = new TwitterPropertiesBuilder(props).withCredentials( - // checkNotNull(System.getProperty(PROPERTY_TWITTER_USER), PROPERTY_TWITTER_USER), - // System.getProperty(PROPERTY_TWITTER_PASSWORD, PROPERTY_TWITTER_PASSWORD)).build(); - // TODO FIX - // - // props = new S3PropertiesBuilder(props) - // .withCredentials( - // checkNotNull(System.getProperty(PROPERTY_AWS_ACCESSKEYID), - // PROPERTY_AWS_ACCESSKEYID), - // System.getProperty(PROPERTY_AWS_SECRETACCESSKEY, - // PROPERTY_AWS_SECRETACCESSKEY)).build(); - // - // props = new CloudFilesPropertiesBuilder(props).withCredentials( - // checkNotNull(System.getProperty(PROPERTY_RACKSPACE_USER), PROPERTY_RACKSPACE_USER), - // System.getProperty(PROPERTY_RACKSPACE_KEY, PROPERTY_RACKSPACE_KEY)).build(); - // - // props = new AzureBlobPropertiesBuilder(props).withCredentials( - // checkNotNull(System.getProperty(PROPERTY_AZURESTORAGE_ACCOUNT), - // PROPERTY_AZURESTORAGE_ACCOUNT), - // System.getProperty(PROPERTY_AZURESTORAGE_KEY, PROPERTY_AZURESTORAGE_KEY)).build(); - - server = new GoogleDevServer(); - server.writePropertiesAndStartServer(address, port, warfile, props); - } - - @BeforeClass void clearAndCreateContainers() throws InterruptedException, ExecutionException, TimeoutException, IOException { container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER)); - // BlobStoreContextFactory factory = new BlobStoreContextFactory(); - // TODO FIX - // BlobStoreContext s3Context = factory.createContext("s3", checkNotNull(System - // .getProperty(PROPERTY_AWS_ACCESSKEYID), PROPERTY_AWS_ACCESSKEYID), System - // .getProperty(PROPERTY_AWS_SECRETACCESSKEY, PROPERTY_AWS_SECRETACCESSKEY)); - // - // BlobStoreContext cfContext = factory.createContext("cloudfiles", checkNotNull(System - // .getProperty(PROPERTY_RACKSPACE_USER), PROPERTY_RACKSPACE_USER), System.getProperty( - // PROPERTY_RACKSPACE_KEY, PROPERTY_RACKSPACE_KEY)); - // - // BlobStoreContext azContext = factory.createContext("azureblob", checkNotNull(System - // .getProperty(PROPERTY_AZURESTORAGE_ACCOUNT), PROPERTY_AZURESTORAGE_ACCOUNT), System - // .getProperty(PROPERTY_AZURESTORAGE_KEY, PROPERTY_AZURESTORAGE_KEY)); - // - // this.contexts = ImmutableList.of(s3Context, cfContext, azContext); + + props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, checkNotNull(System + .getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER)); + + props.setProperty(GuiceServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, Joiner.on(',').join( + blobstores)); + + // put all identity/credential pairs into the client + addCredentialsForBlobStores(props); + + // example of an ad-hoc client configuration + addConfigurationForTwitter(props); + + final BlobStoreContextFactory factory = new BlobStoreContextFactory(); + // for testing, capture logs. + final Set wiring = ImmutableSet. of(new Log4JLoggingModule()); + this.contexts = Maps.newConcurrentMap(); + + for (String provider : blobstores) { + contexts.put(provider, factory.createContext(provider, wiring, props)); + } + + RestContext twitterContext = new RestContextFactory() + .createContext("twitter", wiring, props); + StoreTweetsController controller = new StoreTweetsController(contexts, container, + twitterContext.getApi()); + + SortedSet statuses = twitterContext.getApi().getMyMentions(); + boolean deleted = false; - for (BlobStoreContext context : contexts) { + for (BlobStoreContext context : contexts.values()) { if (context.getBlobStore().containerExists(container)) { System.err.printf("deleting container %s at %s%n", container, context .getProviderSpecificContext().getEndpoint()); @@ -120,14 +118,50 @@ public class TweetStoreLiveTest { System.err.println("sleeping 60 seconds to allow containers to clear"); Thread.sleep(60000); } - for (BlobStoreContext context : contexts) { + for (BlobStoreContext context : contexts.values()) { System.err.printf("creating container %s at %s%n", container, context .getProviderSpecificContext().getEndpoint()); context.getBlobStore().createContainerInLocation(null, container); } + if (deleted) { System.err.println("sleeping 5 seconds to allow containers to create"); - Thread.sleep(30000); + Thread.sleep(5000); + } + + for (Entry entry : contexts.entrySet()) { + System.err.printf("filling container %s at %s%n", container, entry.getKey()); + controller.addMyTweets(entry.getKey(), statuses); + } + } + + @BeforeTest(dependsOnMethods = "clearAndCreateContainers") + @Parameters( { "warfile", "devappserver.address", "devappserver.port" }) + public void startDevAppServer(final String warfile, final String address, final String port) + throws Exception { + url = new URL(String.format("http://%s:%s", address, port)); + + server = new GoogleDevServer(); + server.writePropertiesAndStartServer(address, port, warfile, props); + } + + private void addConfigurationForTwitter(Properties props) { + String twitterIdentity = checkNotNull(System.getProperty("twitter.identity"), + "twitter.identity"); + String twitterCredential = checkNotNull(System.getProperty("twitter.credential"), + "twitter.credential"); + + props.putAll(RestContextFactory.toProperties(contextSpec("twitter", "http://twitter.com", + "1", twitterIdentity, twitterCredential, TwitterClient.class, + TwitterAsyncClient.class))); + } + + private void addCredentialsForBlobStores(Properties props) { + for (String provider : blobstores) { + props.setProperty(provider + ".identity", checkNotNull(System.getProperty(provider + + ".identity"), provider + ".identity")); + props.setProperty(provider + ".credential", checkNotNull(System.getProperty(provider + + ".credential"), provider + ".credential")); } } @@ -147,8 +181,7 @@ public class TweetStoreLiveTest { public void testPrimeContainers() throws IOException, InterruptedException { URL gurl = new URL(url, "/store/do"); - // WATCH THIS, you need to add a context each time - for (String context : new String[] { "cloudfiles", "s3", "azureblob" }) { + for (String context : blobstores) { System.out.println("storing at context: " + context); HttpURLConnection connection = (HttpURLConnection) gurl.openConnection(); connection.addRequestProperty("X-AppEngine-QueueName", "twitter"); @@ -161,7 +194,7 @@ public class TweetStoreLiveTest { System.err.println("sleeping 20 seconds to allow for eventual consistency delay"); Thread.sleep(20000); - for (BlobStoreContext context : contexts) { + for (BlobStoreContext context : contexts.values()) { assert context.createInputStreamMap(container).size() > 0 : context .getProviderSpecificContext().getEndpoint(); }