updated tweetstore demos to include googlestorage and latest api

This commit is contained in:
Adrian Cole 2010-07-06 13:33:07 -07:00
parent f777592a83
commit c8b3240d04
18 changed files with 396 additions and 293 deletions

View File

@ -64,6 +64,18 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-twitter</artifactId>
@ -242,43 +254,43 @@
<configuration>
<systemProperties>
<property>
<name>jclouds.twitter.user</name>
<name>twitter.identity</name>
<value>${jclouds.twitter.user}</value>
</property>
<property>
<name>jclouds.twitter.password</name>
<name>twitter.credential</name>
<value>${jclouds.twitter.password}</value>
</property>
<property>
<name>jclouds.azure.storage.account</name>
<name>azureblob.identity</name>
<value>${jclouds.azure.storage.account}</value>
</property>
<property>
<name>jclouds.azure.storage.key</name>
<name>azureblob.credential</name>
<value>${jclouds.azure.storage.key}</value>
</property>
<property>
<name>jclouds.rackspace.user</name>
<name>cloudfiles.identity</name>
<value>${jclouds.rackspace.user}</value>
</property>
<property>
<name>jclouds.rackspace.key</name>
<name>cloudfiles.credential</name>
<value>${jclouds.rackspace.key}</value>
</property>
<property>
<name>jclouds.emcsaas.uid</name>
<value>${jclouds.emcsaas.uid}</value>
<name>googlestorage.identity</name>
<value>${jclouds.googlestorage.accesskeyid}</value>
</property>
<property>
<name>jclouds.emcsaas.key</name>
<value>${jclouds.emcsaas.key}</value>
<name>googlestorage.credential</name>
<value>${jclouds.googlestorage.secretaccesskey}</value>
</property>
<property>
<name>jclouds.aws.accesskeyid</name>
<name>s3.identity</name>
<value>${jclouds.aws.accesskeyid}</value>
</property>
<property>
<name>jclouds.aws.secretaccesskey</name>
<name>s3.credential</name>
<value>${jclouds.aws.secretaccesskey}</value>
</property>
<property>

View File

@ -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<Module> modules = ImmutableSet.<Module> 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(

View File

@ -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<Status, Blob> {
private final BlobMap map;
private static final class StatusToBlob implements Function<Status, Blob> {
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<String, BlobStoreContext> contexts;
private final TwitterClient client;
private final String container;
private final Map<String, BlobStoreContext> 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<String, BlobStoreContext> contexts,
@Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) final String container,
@Inject
@VisibleForTesting
public StoreTweetsController(Map<String, BlobStoreContext> 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<Status> 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<Status> 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);
}
}
}

View File

@ -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";
}

View File

@ -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<String, BlobStoreContext> 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");

View File

@ -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<String, BlobStoreContext> createBlobStores() throws InterruptedException, ExecutionException {
Map<String, BlobStoreContext> contexts = ImmutableMap.<String, BlobStoreContext> 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<Status> 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);

View File

@ -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");
}

View File

@ -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<String, BlobStoreContext> 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");

View File

@ -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<BlobStoreContext> contexts;
private Map<String, BlobStoreContext> contexts;
private String container;
private static final Iterable<String> 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<Module> wiring = ImmutableSet.<Module> of(new Log4JLoggingModule());
this.contexts = Maps.newConcurrentMap();
for (String provider : blobstores) {
contexts.put(provider, factory.createContext(provider, wiring, props));
}
RestContext<TwitterClient, TwitterAsyncClient> twitterContext = new RestContextFactory()
.createContext("twitter", wiring, props);
StoreTweetsController controller = new StoreTweetsController(contexts, container,
twitterContext.getApi());
SortedSet<Status> 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<String, BlobStoreContext> 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();
}

View File

@ -1,29 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
<!--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
Copyright (C) 2009 Cloud Conscious, LLC.
<info@cloudconscious.com>
====================================================================
Licensed 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
====================================================================
Licensed 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.
====================================================================
-->
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.
====================================================================
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-demos-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
@ -64,6 +63,18 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-twitter</artifactId>
@ -74,11 +85,6 @@
<artifactId>jclouds-aws</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-atmos</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-azure</artifactId>
@ -232,45 +238,45 @@
<configuration>
<systemProperties>
<property>
<name>jclouds.twitter.user</name>
<name>twitter.identity</name>
<value>${jclouds.twitter.user}</value>
</property>
<property>
<name>jclouds.twitter.password</name>
<name>twitter.credential</name>
<value>${jclouds.twitter.password}</value>
</property>
<property>
<name>jclouds.azure.storage.account</name>
<name>azureblob.identity</name>
<value>${jclouds.azure.storage.account}</value>
</property>
<property>
<name>jclouds.azure.storage.key</name>
<name>azureblob.credential</name>
<value>${jclouds.azure.storage.key}</value>
</property>
<property>
<name>jclouds.rackspace.user</name>
<name>cloudfiles.identity</name>
<value>${jclouds.rackspace.user}</value>
</property>
<property>
<name>jclouds.rackspace.key</name>
<name>cloudfiles.credential</name>
<value>${jclouds.rackspace.key}</value>
</property>
<property>
<name>jclouds.emcsaas.uid</name>
<value>${jclouds.emcsaas.uid}</value>
</property>
<property>
<name>jclouds.emcsaas.key</name>
<value>${jclouds.emcsaas.key}</value>
</property>
<property>
<name>jclouds.aws.accesskeyid</name>
<name>s3.identity</name>
<value>${jclouds.aws.accesskeyid}</value>
</property>
<property>
<name>jclouds.aws.secretaccesskey</name>
<name>s3.credential</name>
<value>${jclouds.aws.secretaccesskey}</value>
</property>
<property>
<name>googlestorage.identity</name>
<value>${jclouds.googlestorage.accesskeyid}</value>
</property>
<property>
<name>googlestorage.credential</name>
<value>${jclouds.googlestorage.secretaccesskey}</value>
</property>
<property>
<name>appengine.home</name>
<value>${appengine.home}</value>

View File

@ -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<Module> modules = ImmutableSet.<Module> 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();

View File

@ -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<String, BlobStoreContext> contexts,
@Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) final String container,
public StoreTweetsController(Map<String, BlobStoreContext> 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<Status> allAboutMe) {
public void addMyTweets(String contextName, SortedSet<Status> 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);
}
}
}

View File

@ -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";
}

View File

@ -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<String, BlobStoreContext> 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");

View File

@ -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<String, BlobStoreContext> createBlobStores() throws InterruptedException, ExecutionException {
Map<String, BlobStoreContext> contexts = ImmutableMap.<String, BlobStoreContext> 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<Status> 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);

View File

@ -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");
}

View File

@ -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<String, BlobStoreContext> 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");

View File

@ -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<BlobStoreContext> contexts;
private Map<String, BlobStoreContext> contexts;
private String container;
private static final Iterable<String> 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<Module> wiring = ImmutableSet.<Module> of(new Log4JLoggingModule());
this.contexts = Maps.newConcurrentMap();
for (String provider : blobstores) {
contexts.put(provider, factory.createContext(provider, wiring, props));
}
RestContext<TwitterClient, TwitterAsyncClient> twitterContext = new RestContextFactory()
.createContext("twitter", wiring, props);
StoreTweetsController controller = new StoreTweetsController(contexts, container,
twitterContext.getApi());
SortedSet<Status> 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<String, BlobStoreContext> 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();
}