mirror of https://github.com/apache/jclouds.git
Issue 114: new demo of twitter
git-svn-id: http://jclouds.googlecode.com/svn/trunk@2035 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
19e315042f
commit
483c144d38
|
@ -38,7 +38,11 @@ import com.google.inject.ImplementedBy;
|
||||||
*/
|
*/
|
||||||
@ImplementedBy(BlobMapImpl.class)
|
@ImplementedBy(BlobMapImpl.class)
|
||||||
public interface BlobMap extends ListableMap<String, Blob> {
|
public interface BlobMap extends ListableMap<String, Blob> {
|
||||||
|
|
||||||
|
Blob newBlob();
|
||||||
|
|
||||||
public static interface Factory {
|
public static interface Factory {
|
||||||
BlobMap create(String containerName, ListOptions listOptions);
|
BlobMap create(String containerName, ListOptions listOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -218,4 +218,8 @@ public class BlobMapImpl extends BaseBlobMap<Blob> implements BlobMap {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Blob newBlob() {
|
||||||
|
return connection.newBlob();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
====
|
||||||
|
|
||||||
|
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
====================================================================
|
||||||
|
====
|
||||||
|
This samples uses the Google App Engine for Java SDK located at http://googleappengine.googlecode.com/files/appengine-java-sdk-1.2.5.zip
|
||||||
|
|
||||||
|
Please unzip the above file and modify your maven settings.xml like below before attempting to run 'mvn -Plive install'
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>appengine</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<appengine.home>/path/to/appengine-java-sdk-1.2.5</appengine.home>
|
||||||
|
<appengine.applicationid>yourappid</appengine.applicationid>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>keys</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<jclouds.aws.accesskeyid>YOUR_ACCESS_KEY_ID</jclouds.aws.accesskeyid>
|
||||||
|
<jclouds.aws.secretaccesskey>YOUR_SECRET_KEY</jclouds.aws.secretaccesskey>
|
||||||
|
<jclouds.rackspace.user>YOUR_USER</jclouds.rackspace.user>
|
||||||
|
<jclouds.rackspace.key>YOUR_HEX_KEY</jclouds.rackspace.key>
|
||||||
|
<jclouds.azure.storage.account>YOUR_ACCOUNT</jclouds.azure.storage.account>
|
||||||
|
<jclouds.azure.storage.key>YOUR_BASE64_ENCODED_KEY</jclouds.azure.storage.key>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>jclouds</id>
|
||||||
|
<url>http://jclouds.googlecode.com/svn/trunk/repo</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
|
@ -0,0 +1,285 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright (C) 2009 Global Cloud Specialists, Inc.
|
||||||
|
<info@globalcloudspecialists.com>
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to you under the Apache License, Version
|
||||||
|
2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0.html 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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>jclouds-demos-project</artifactId>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>jclouds-gae-tweetstore</artifactId>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
<name>JClouds TweetStore for Google App Engine</name>
|
||||||
|
<description>JClouds TweetStore for Google App Engine</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<!--
|
||||||
|
note you must set the property ${appengine.home} to a valid
|
||||||
|
extraction of appengine-java-sdk
|
||||||
|
-->
|
||||||
|
<appengine.home>/Users/adriancole/Desktop/appengine-java-sdk-1.2.5</appengine.home>
|
||||||
|
<appengine.applicationid>jclouds-tweetstore</appengine.applicationid>
|
||||||
|
<devappserver.address>localhost</devappserver.address>
|
||||||
|
<devappserver.port>8088</devappserver.port>
|
||||||
|
<jclouds.tweetstore.container>jclouds-tweetstore</jclouds.tweetstore.container>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-blobstore-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-twitter</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-s3</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-azureblob</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-cloudfiles</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-gae</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.guice</groupId>
|
||||||
|
<artifactId>guice-servlet</artifactId>
|
||||||
|
<version>2.1-r1089</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>displaytag</groupId>
|
||||||
|
<artifactId>displaytag</artifactId>
|
||||||
|
<version>1.2</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-log4j12</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-jdk14</artifactId>
|
||||||
|
<version>1.5.6</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<artifactId>standard</artifactId>
|
||||||
|
<groupId>taglibs</groupId>
|
||||||
|
<version>1.1.2</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<artifactId>jstl</artifactId>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<version>1.1.2</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.geronimo.specs</groupId>
|
||||||
|
<artifactId>geronimo-el_1.0_spec</artifactId>
|
||||||
|
<version>1.0.1</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.geronimo.specs</groupId>
|
||||||
|
<artifactId>geronimo-jsp_2.1_spec</artifactId>
|
||||||
|
<version>1.0.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.geronimo.specs</groupId>
|
||||||
|
<artifactId>geronimo-servlet_2.5_spec</artifactId>
|
||||||
|
<version>1.2</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.appengine</groupId>
|
||||||
|
<artifactId>appengine-tools-api</artifactId>
|
||||||
|
<version>1.2.5</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<finalName>${project.artifactId}</finalName>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<webResources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/appengine</directory>
|
||||||
|
<targetPath>WEB-INF/</targetPath>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</webResources>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>integration</id>
|
||||||
|
<phase>integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>test</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<systemProperties>
|
||||||
|
<property>
|
||||||
|
<name>appengine.home</name>
|
||||||
|
<value>${appengine.home}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>devappserver.address</name>
|
||||||
|
<value>${devappserver.address}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>devappserver.port</name>
|
||||||
|
<value>${devappserver.port}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>warfile</name>
|
||||||
|
<value>${project.build.directory}/${project.artifactId}</value>
|
||||||
|
</property>
|
||||||
|
</systemProperties>
|
||||||
|
<additionalClasspathElements>
|
||||||
|
<additionalClasspathElement>${appengine.home}/lib/appengine-tools-api.jar
|
||||||
|
</additionalClasspathElement>
|
||||||
|
</additionalClasspathElements>
|
||||||
|
<environmentVariables>
|
||||||
|
<DEBUG>true</DEBUG>
|
||||||
|
<SDK_BIN>${appengine.home}/bin</SDK_BIN>
|
||||||
|
<SDK_LIB>${appengine.home}/lib</SDK_LIB>
|
||||||
|
<SDK_CONFIG>${appengine.home}/config/sdk</SDK_CONFIG>
|
||||||
|
</environmentVariables>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>live</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>integration</id>
|
||||||
|
<phase>integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>test</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<systemProperties>
|
||||||
|
<property>
|
||||||
|
<name>jclouds.twitter.user</name>
|
||||||
|
<value>${jclouds.twitter.user}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>jclouds.twitter.password</name>
|
||||||
|
<value>${jclouds.twitter.password}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>jclouds.azure.storage.account</name>
|
||||||
|
<value>${jclouds.azure.storage.account}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>jclouds.azure.storage.key</name>
|
||||||
|
<value>${jclouds.azure.storage.key}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>jclouds.rackspace.user</name>
|
||||||
|
<value>${jclouds.rackspace.user}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>jclouds.rackspace.key</name>
|
||||||
|
<value>${jclouds.rackspace.key}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>jclouds.aws.accesskeyid</name>
|
||||||
|
<value>${jclouds.aws.accesskeyid}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>jclouds.aws.secretaccesskey</name>
|
||||||
|
<value>${jclouds.aws.secretaccesskey}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>appengine.home</name>
|
||||||
|
<value>${appengine.home}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>devappserver.address</name>
|
||||||
|
<value>${devappserver.address}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>devappserver.port</name>
|
||||||
|
<value>${devappserver.port}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>jclouds.tweetstore.container</name>
|
||||||
|
<value>${jclouds.tweetstore.container}</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>warfile</name>
|
||||||
|
<value>${project.build.directory}/${project.artifactId}</value>
|
||||||
|
</property>
|
||||||
|
</systemProperties>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
====================================================================
|
||||||
|
|
||||||
|
-->
|
||||||
|
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
|
||||||
|
<application>${appengine.applicationid}</application>
|
||||||
|
<version>1</version>
|
||||||
|
<system-properties>
|
||||||
|
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties" />
|
||||||
|
</system-properties>
|
||||||
|
</appengine-web-app>
|
|
@ -0,0 +1,75 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
#
|
||||||
|
# ====================================================================
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
# ====================================================================
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||||
|
#
|
||||||
|
# ====================================================================
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
# ====================================================================
|
||||||
|
#
|
||||||
|
# A default java.util.logging configuration.
|
||||||
|
# (All App Engine logging is through java.util.logging by default).
|
||||||
|
#
|
||||||
|
# To use this configuration, copy it into your application's WEB-INF
|
||||||
|
# folder and add the following to your appengine-web.xml:
|
||||||
|
#
|
||||||
|
# <system-properties>
|
||||||
|
# <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
|
||||||
|
# </system-properties>
|
||||||
|
#
|
||||||
|
|
||||||
|
# Set the default logging level for all loggers to WARNING
|
||||||
|
.level = INFO
|
||||||
|
|
||||||
|
# Set the default logging level for ORM, specifically, to WARNING
|
||||||
|
org.jclouds.level=INFO
|
||||||
|
DataNucleus.JDO.level=WARNING
|
||||||
|
DataNucleus.Persistence.level=WARNING
|
||||||
|
DataNucleus.Cache.level=WARNING
|
||||||
|
DataNucleus.MetaData.level=WARNING
|
||||||
|
DataNucleus.General.level=WARNING
|
||||||
|
DataNucleus.Utility.level=WARNING
|
||||||
|
DataNucleus.Transaction.level=WARNING
|
||||||
|
DataNucleus.Datastore.level=WARNING
|
||||||
|
DataNucleus.ClassLoading.level=WARNING
|
||||||
|
DataNucleus.Plugin.level=WARNING
|
||||||
|
DataNucleus.ValueGeneration.level=WARNING
|
||||||
|
DataNucleus.Enhancer.level=WARNING
|
||||||
|
DataNucleus.SchemaTool.level=WARNING
|
|
@ -0,0 +1,138 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.demo.tweetstore.config;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_BLOBSTORE_CONTEXTBUILDERS;
|
||||||
|
import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
|
import org.jclouds.blobstore.BlobStoreContextBuilder;
|
||||||
|
import org.jclouds.demo.tweetstore.controller.AddTweetsController;
|
||||||
|
import org.jclouds.demo.tweetstore.controller.StoreTweetsController;
|
||||||
|
import org.jclouds.gae.config.GaeHttpCommandExecutorServiceModule;
|
||||||
|
import org.jclouds.twitter.TwitterClient;
|
||||||
|
import org.jclouds.twitter.TwitterContextFactory;
|
||||||
|
|
||||||
|
import com.google.appengine.repackaged.com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import com.google.inject.servlet.GuiceServletContextListener;
|
||||||
|
import com.google.inject.servlet.ServletModule;
|
||||||
|
import com.google.inject.util.Jsr330;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup Logging and create Injector for use in testing S3.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class GuiceServletConfig extends GuiceServletContextListener {
|
||||||
|
|
||||||
|
private Map<String, BlobStoreContext<?>> contexts;
|
||||||
|
private TwitterClient client;
|
||||||
|
private String container;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent servletContextEvent) {
|
||||||
|
Properties props = loadJCloudsProperties(servletContextEvent);
|
||||||
|
container = checkNotNull(props.getProperty(PROPERTY_TWEETSTORE_CONTAINER),
|
||||||
|
PROPERTY_TWEETSTORE_CONTAINER);
|
||||||
|
ImmutableList<String> list = ImmutableList.<String> of(checkNotNull(
|
||||||
|
props.getProperty(PROPERTY_BLOBSTORE_CONTEXTBUILDERS),
|
||||||
|
PROPERTY_BLOBSTORE_CONTEXTBUILDERS).split(","));
|
||||||
|
contexts = Maps.newHashMap();
|
||||||
|
client = TwitterContextFactory
|
||||||
|
.createContext(props, new GaeHttpCommandExecutorServiceModule()).getApi();
|
||||||
|
for (String className : list) {
|
||||||
|
Class<BlobStoreContextBuilder<?>> builderClass;
|
||||||
|
Constructor<BlobStoreContextBuilder<?>> constructor;
|
||||||
|
String name;
|
||||||
|
BlobStoreContext<?> context;
|
||||||
|
try {
|
||||||
|
builderClass = (Class<BlobStoreContextBuilder<?>>) Class.forName(className);
|
||||||
|
name = builderClass.getSimpleName().replaceAll("BlobStoreContextBuilder", "");
|
||||||
|
constructor = builderClass.getConstructor(Properties.class);
|
||||||
|
context = constructor.newInstance(props).withModules(
|
||||||
|
new GaeHttpCommandExecutorServiceModule()).buildContext();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("error instantiating " + className, e);
|
||||||
|
}
|
||||||
|
contexts.put(name, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.contextInitialized(servletContextEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Properties loadJCloudsProperties(ServletContextEvent servletContextEvent) {
|
||||||
|
InputStream input = servletContextEvent.getServletContext().getResourceAsStream(
|
||||||
|
"/WEB-INF/jclouds.properties");
|
||||||
|
Properties props = new Properties();
|
||||||
|
try {
|
||||||
|
props.load(input);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(input);
|
||||||
|
}
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Injector getInjector() {
|
||||||
|
return Guice.createInjector(new ServletModule() {
|
||||||
|
@Override
|
||||||
|
protected void configureServlets() {
|
||||||
|
bind(new TypeLiteral<Map<String, BlobStoreContext<?>>>() {
|
||||||
|
}).toInstance(GuiceServletConfig.this.contexts);
|
||||||
|
bind(TwitterClient.class).toInstance(client);
|
||||||
|
bindConstant().annotatedWith(Jsr330.named(PROPERTY_TWEETSTORE_CONTAINER)).to(container);
|
||||||
|
serve("/cron/*").with(StoreTweetsController.class);
|
||||||
|
serve("/tweets/*").with(AddTweetsController.class);
|
||||||
|
requestInjection(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextDestroyed(ServletContextEvent servletContextEvent) {
|
||||||
|
for (BlobStoreContext<?> context : contexts.values()) {
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
super.contextDestroyed(servletContextEvent);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.demo.tweetstore.controller;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.servlet.RequestDispatcher;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
|
import org.jclouds.demo.tweetstore.domain.StoredTweetStatus;
|
||||||
|
import org.jclouds.demo.tweetstore.functions.ServiceToStoredTweetStatuses;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.appengine.repackaged.com.google.common.collect.Lists;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows an example of how to use @{link BlobStoreContext} injected with Guice.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class AddTweetsController extends HttpServlet implements
|
||||||
|
Function<Set<String>, List<StoredTweetStatus>> {
|
||||||
|
|
||||||
|
/** The serialVersionUID */
|
||||||
|
private static final long serialVersionUID = 3888348023150822683L;
|
||||||
|
private final Map<String, BlobStoreContext<?>> contexts;
|
||||||
|
private final ServiceToStoredTweetStatuses blobStoreContextToContainerResult;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AddTweetsController(Map<String, BlobStoreContext<?>> contexts,
|
||||||
|
ServiceToStoredTweetStatuses blobStoreContextToContainerResult) {
|
||||||
|
this.contexts = contexts;
|
||||||
|
this.blobStoreContextToContainerResult = blobStoreContextToContainerResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
try {
|
||||||
|
addMyTweetsToRequest(request);
|
||||||
|
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/tweets.jsp");
|
||||||
|
dispatcher.forward(request, response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e, "Error listing containers");
|
||||||
|
throw new ServletException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addMyTweetsToRequest(HttpServletRequest request) throws InterruptedException,
|
||||||
|
ExecutionException, TimeoutException {
|
||||||
|
request.setAttribute("tweets", apply(contexts.keySet()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<StoredTweetStatus> apply(Set<String> in) {
|
||||||
|
List<StoredTweetStatus> statuses = Lists.newArrayList();
|
||||||
|
for (Iterable<StoredTweetStatus> list : Iterables.transform(in,
|
||||||
|
blobStoreContextToContainerResult)) {
|
||||||
|
Iterables.addAll(statuses, list);
|
||||||
|
}
|
||||||
|
return statuses;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.demo.tweetstore.controller;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.BlobMap;
|
||||||
|
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.twitter.TwitterClient;
|
||||||
|
import org.jclouds.twitter.domain.Status;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grab tweets related to me and store them into blobstores
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class StoreTweetsController extends HttpServlet {
|
||||||
|
|
||||||
|
private static final class StatusToBlob implements Function<Status, Blob> {
|
||||||
|
private final BlobMap map;
|
||||||
|
|
||||||
|
private StatusToBlob(BlobMap map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Blob apply(Status from) {
|
||||||
|
Blob to = map.newBlob();
|
||||||
|
to.getMetadata().setContentType(MediaType.TEXT_PLAIN);
|
||||||
|
to.getMetadata().setName(from.getId() + "");
|
||||||
|
to.setData(from.getText());
|
||||||
|
to.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME,
|
||||||
|
from.getUser().getScreenName());
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The serialVersionUID */
|
||||||
|
private static final long serialVersionUID = 7215420527854203714L;
|
||||||
|
|
||||||
|
private final Set<BlobMap> maps;
|
||||||
|
private final TwitterClient client;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
StoreTweetsController(Map<String, BlobStoreContext<?>> contexts,
|
||||||
|
@Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) final String container,
|
||||||
|
TwitterClient client) {
|
||||||
|
this(Sets.newHashSet(Iterables.transform(contexts.values(),
|
||||||
|
new Function<BlobStoreContext<?>, BlobMap>() {
|
||||||
|
public BlobMap apply(BlobStoreContext<?> from) {
|
||||||
|
return from.createBlobMap(container);
|
||||||
|
}
|
||||||
|
})), client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
StoreTweetsController(Set<BlobMap> maps, TwitterClient client) {
|
||||||
|
this.maps = maps;
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void addMyTweets(SortedSet<Status> allAboutMe) {
|
||||||
|
for (BlobMap map : maps) {
|
||||||
|
for (Status status : allAboutMe) {
|
||||||
|
map.put(status.getId() + "", new StatusToBlob(map).apply(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
if (request.getHeader("X-AppEngine-Cron") != null
|
||||||
|
&& request.getHeader("X-AppEngine-Cron").equals("true")) {
|
||||||
|
try {
|
||||||
|
logger.info("retrieving tweets");
|
||||||
|
addMyTweets(client.getMyMentions().get(1, TimeUnit.SECONDS));
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,154 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.demo.tweetstore.domain;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class StoredTweetStatus implements Comparable<StoredTweetStatus>, Serializable {
|
||||||
|
|
||||||
|
/** The serialVersionUID */
|
||||||
|
private static final long serialVersionUID = -3257496189689220018L;
|
||||||
|
private final String service;
|
||||||
|
private final String host;
|
||||||
|
private final String container;
|
||||||
|
private final String id;
|
||||||
|
private final String from;
|
||||||
|
private final String tweet;
|
||||||
|
private final String status;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "StoredTweetStatus [container=" + container + ", from=" + from + ", host=" + host
|
||||||
|
+ ", id=" + id + ", service=" + service + ", status=" + status + ", tweet=" + tweet
|
||||||
|
+ "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public StoredTweetStatus(String service, String host, String container, String id, String from,
|
||||||
|
String tweet, String status) {
|
||||||
|
this.service = service;
|
||||||
|
this.host = host;
|
||||||
|
this.container = container;
|
||||||
|
this.id = id;
|
||||||
|
this.from = from;
|
||||||
|
this.tweet = tweet;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((container == null) ? 0 : container.hashCode());
|
||||||
|
result = prime * result + ((from == null) ? 0 : from.hashCode());
|
||||||
|
result = prime * result + ((host == null) ? 0 : host.hashCode());
|
||||||
|
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||||
|
result = prime * result + ((service == null) ? 0 : service.hashCode());
|
||||||
|
result = prime * result + ((tweet == null) ? 0 : tweet.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
StoredTweetStatus other = (StoredTweetStatus) obj;
|
||||||
|
if (container == null) {
|
||||||
|
if (other.container != null)
|
||||||
|
return false;
|
||||||
|
} else if (!container.equals(other.container))
|
||||||
|
return false;
|
||||||
|
if (from == null) {
|
||||||
|
if (other.from != null)
|
||||||
|
return false;
|
||||||
|
} else if (!from.equals(other.from))
|
||||||
|
return false;
|
||||||
|
if (host == null) {
|
||||||
|
if (other.host != null)
|
||||||
|
return false;
|
||||||
|
} else if (!host.equals(other.host))
|
||||||
|
return false;
|
||||||
|
if (id == null) {
|
||||||
|
if (other.id != null)
|
||||||
|
return false;
|
||||||
|
} else if (!id.equals(other.id))
|
||||||
|
return false;
|
||||||
|
if (service == null) {
|
||||||
|
if (other.service != null)
|
||||||
|
return false;
|
||||||
|
} else if (!service.equals(other.service))
|
||||||
|
return false;
|
||||||
|
if (tweet == null) {
|
||||||
|
if (other.tweet != null)
|
||||||
|
return false;
|
||||||
|
} else if (!tweet.equals(other.tweet))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getService() {
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContainer() {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFrom() {
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTweet() {
|
||||||
|
return tweet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compareTo(StoredTweetStatus o) {
|
||||||
|
if (id == null)
|
||||||
|
return -1;
|
||||||
|
return (int) ((this == o) ? 0 : id.compareTo(o.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.demo.tweetstore.functions;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.BlobMap;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.demo.tweetstore.domain.StoredTweetStatus;
|
||||||
|
import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.util.Utils;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class KeyToStoredTweetStatus implements Function<String, StoredTweetStatus> {
|
||||||
|
private final String host;
|
||||||
|
private final BlobMap map;
|
||||||
|
private final String service;
|
||||||
|
private final String container;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
KeyToStoredTweetStatus(BlobMap map, String service, String host, String container) {
|
||||||
|
this.host = host;
|
||||||
|
this.map = map;
|
||||||
|
this.service = service;
|
||||||
|
this.container = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StoredTweetStatus apply(String id) {
|
||||||
|
String status;
|
||||||
|
String from;
|
||||||
|
String tweet;
|
||||||
|
try {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
Blob blob = map.get(id);
|
||||||
|
status = ((System.currentTimeMillis() - start) + "ms");
|
||||||
|
from = blob.getMetadata().getUserMetadata().get(TweetStoreConstants.SENDER_NAME);
|
||||||
|
tweet = Utils.toStringAndClose((InputStream) blob.getData());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e, "Error listing container %s//%s/$s", service, container, id);
|
||||||
|
status = (e.getMessage());
|
||||||
|
tweet = "";
|
||||||
|
from = "";
|
||||||
|
}
|
||||||
|
return new StoredTweetStatus(service, host, container, id, from, tweet, status);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.demo.tweetstore.functions;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.BlobMap;
|
||||||
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
|
import org.jclouds.demo.tweetstore.domain.StoredTweetStatus;
|
||||||
|
import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ServiceToStoredTweetStatuses implements Function<String, Iterable<StoredTweetStatus>> {
|
||||||
|
|
||||||
|
private final Map<String, BlobStoreContext<?>> contexts;
|
||||||
|
private final String container;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ServiceToStoredTweetStatuses(Map<String, BlobStoreContext<?>> contexts,
|
||||||
|
@Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container) {
|
||||||
|
this.contexts = contexts;
|
||||||
|
this.container = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
public Iterable<StoredTweetStatus> apply(String service) {
|
||||||
|
BlobStoreContext<?> context = contexts.get(service);
|
||||||
|
String host = context.getEndPoint().getHost();
|
||||||
|
try {
|
||||||
|
BlobMap blobMap = context.createBlobMap(container);
|
||||||
|
Set<String> blobs = blobMap.keySet();
|
||||||
|
return Iterables.transform(blobs, new KeyToStoredTweetStatus(blobMap, service, host,
|
||||||
|
container));
|
||||||
|
} catch (Exception e) {
|
||||||
|
StoredTweetStatus result = new StoredTweetStatus(service, host, container, null, null,
|
||||||
|
null, e.getMessage());
|
||||||
|
logger.error(e, "Error listing service %s", service);
|
||||||
|
return Collections.singletonList(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.demo.tweetstore.reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration properties and constants used in TweetStore connections.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public interface TweetStoreConstants {
|
||||||
|
public static final String PROPERTY_TWEETSTORE_CONTAINER = "jclouds.tweetstore.container";
|
||||||
|
public static final String SENDER_NAME = "jclouds.tweetstore.sendername";
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<cronentries>
|
||||||
|
<cron>
|
||||||
|
<url>/cron/do</url>
|
||||||
|
<description>store twitter messages into cache stores
|
||||||
|
</description>
|
||||||
|
<schedule>every 2 minutes</schedule>
|
||||||
|
</cron>
|
||||||
|
</cronentries>
|
|
@ -0,0 +1,52 @@
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (C) 2009 Cloud Conscious, LLC.
|
||||||
|
<info@cloudconscious.com>
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or
|
||||||
|
more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information regarding
|
||||||
|
copyright ownership. The ASF licenses this file to you under the
|
||||||
|
Apache License, Version 2.0 (the "License"); you may not use
|
||||||
|
this file except in compliance with the License. You may obtain
|
||||||
|
a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0 Unless required by
|
||||||
|
applicable law or agreed to in writing, software distributed
|
||||||
|
under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions
|
||||||
|
and limitations under the License.
|
||||||
|
====================================================================
|
||||||
|
-->
|
||||||
|
<!DOCTYPE web-app PUBLIC
|
||||||
|
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
|
||||||
|
"http://java.sun.com/dtd/web-app_2_3.dtd">
|
||||||
|
|
||||||
|
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
|
||||||
|
<display-name>jclouds-blobstore-example</display-name>
|
||||||
|
|
||||||
|
<!-- Servlets -->
|
||||||
|
<filter>
|
||||||
|
<filter-name>guiceFilter</filter-name>
|
||||||
|
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>guiceFilter</filter-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
|
|
||||||
|
|
||||||
|
<listener>
|
||||||
|
<listener-class>org.jclouds.demo.tweetstore.config.GuiceServletConfig</listener-class>
|
||||||
|
</listener>
|
||||||
|
|
||||||
|
<welcome-file-list>
|
||||||
|
<welcome-file>index.jsp</welcome-file>
|
||||||
|
</welcome-file-list>
|
||||||
|
|
||||||
|
</web-app>
|
|
@ -0,0 +1,36 @@
|
||||||
|
<%--
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
====================================================================
|
||||||
|
|
||||||
|
--%>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>jclouds: anyweight cloudware for java</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Welcome!</h2>
|
||||||
|
Click
|
||||||
|
<a href="/tweets/get">here</a>
|
||||||
|
to see tweets about jclouds.
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,113 @@
|
||||||
|
<%--
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
====================================================================
|
||||||
|
|
||||||
|
--%>
|
||||||
|
<%@ page buffer="20kb"%>
|
||||||
|
<%@ taglib uri="http://displaytag.sf.net" prefix="display"%>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>jclouds: anyweight cloudware for java</title>
|
||||||
|
<style type="text/css">
|
||||||
|
<!--
|
||||||
|
table.staticheader {
|
||||||
|
text-decoration: none;
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
width: 98%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.staticheader th {
|
||||||
|
padding: 3px 3px 3px 3px !important;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.staticheader td {
|
||||||
|
padding: 3px 3px 3px 3px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.staticheader thead tr {
|
||||||
|
position: relative;
|
||||||
|
height: 10px;
|
||||||
|
background-color: #D7E5F3;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.staticheader tbody {
|
||||||
|
height:800px;
|
||||||
|
overflow-x:hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow:scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.staticheader tbody tr {
|
||||||
|
height: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.staticheader tbody tr.odd {
|
||||||
|
background-color: #eee
|
||||||
|
}
|
||||||
|
|
||||||
|
table.staticheader tbody tr.tableRowEven,tr.even {
|
||||||
|
background-color: #ddd
|
||||||
|
}
|
||||||
|
|
||||||
|
table.staticheader tbody tr td:last-child {
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.staticheader tbody td {
|
||||||
|
padding: 2px 4px 2px 4px !important;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
div.TableContainer {
|
||||||
|
height: 800px;
|
||||||
|
overflow-x:hidden;
|
||||||
|
overflow-y:auto;
|
||||||
|
}
|
||||||
|
-->
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Tweets in Clouds</h2>
|
||||||
|
<table width="100%" border="0">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
<div class="TableContainer">
|
||||||
|
|
||||||
|
<display:table name="tweets" defaultsort="1" cellpadding="5" cellspacing="1" class="staticheader">
|
||||||
|
<display:column property="id" title="Tweet ID" />
|
||||||
|
<display:column property="from" title="Who Said it" />
|
||||||
|
<display:column property="tweet" title="Tweet" />
|
||||||
|
<display:column property="service" title="Cloud" />
|
||||||
|
<display:column property="host" title="Host" />
|
||||||
|
<display:column property="status" title="Status" />
|
||||||
|
</display:table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.jclouds.demo.tweetstore.controller;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.BlobStore;
|
||||||
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.integration.StubBlobStoreContextBuilder;
|
||||||
|
import org.jclouds.demo.tweetstore.domain.StoredTweetStatus;
|
||||||
|
import org.jclouds.demo.tweetstore.functions.ServiceToStoredTweetStatuses;
|
||||||
|
import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
import org.testng.collections.Maps;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code AddTweetsController}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "tweetstore.AddTweetsControllerTest")
|
||||||
|
public class AddTweetsControllerTest {
|
||||||
|
|
||||||
|
Map<String, BlobStoreContext<?>> createServices(String container) throws InterruptedException,
|
||||||
|
ExecutionException {
|
||||||
|
Map<String, BlobStoreContext<?>> services = Maps.newHashMap();
|
||||||
|
for (String name : new String[] { "1", "2" }) {
|
||||||
|
BlobStoreContext<BlobStore> context = new StubBlobStoreContextBuilder().buildContext();
|
||||||
|
context.getBlobStore().createContainer(container).get();
|
||||||
|
Blob blob = context.getBlobStore().newBlob();
|
||||||
|
blob.getMetadata().setName("1");
|
||||||
|
blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank");
|
||||||
|
blob.setData("I love beans!");
|
||||||
|
context.getBlobStore().putBlob(container, blob).get();
|
||||||
|
services.put(name, context);
|
||||||
|
}
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStoreTweets() throws IOException, InterruptedException, ExecutionException {
|
||||||
|
String container = "container";
|
||||||
|
Map<String, BlobStoreContext<?>> contexts = createServices(container);
|
||||||
|
|
||||||
|
ServiceToStoredTweetStatuses function = new ServiceToStoredTweetStatuses(contexts, container);
|
||||||
|
AddTweetsController controller = new AddTweetsController(contexts, function);
|
||||||
|
List<StoredTweetStatus> list = controller.apply(ImmutableSet.of("1", "2"));
|
||||||
|
assertEquals(list.size(), 2);
|
||||||
|
assertEquals(list, ImmutableList.of(new StoredTweetStatus("1", "localhost", container, "1",
|
||||||
|
"frank", "I love beans!", null), new StoredTweetStatus("2", "localhost", container,
|
||||||
|
"1", "frank", "I love beans!", null)));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
package org.jclouds.demo.tweetstore.controller;
|
||||||
|
|
||||||
|
import static org.easymock.classextension.EasyMock.createMock;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.jclouds.blobstore.BlobMap;
|
||||||
|
import org.jclouds.blobstore.BlobStore;
|
||||||
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.integration.StubBlobStoreContextBuilder;
|
||||||
|
import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
|
||||||
|
import org.jclouds.twitter.TwitterClient;
|
||||||
|
import org.jclouds.twitter.domain.Status;
|
||||||
|
import org.jclouds.twitter.domain.User;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code StoreTweetsController}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "tweetstore.StoreTweetsControllerTest")
|
||||||
|
public class StoreTweetsControllerTest {
|
||||||
|
|
||||||
|
|
||||||
|
TwitterClient createTwitterClient() {
|
||||||
|
return createMock(TwitterClient.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<BlobMap> createMaps() throws InterruptedException, ExecutionException {
|
||||||
|
BlobStoreContext<BlobStore> context = new StubBlobStoreContextBuilder().buildContext();
|
||||||
|
context.getBlobStore().createContainer("test1").get();
|
||||||
|
context.getBlobStore().createContainer("test2").get();
|
||||||
|
return ImmutableSet.of(context.createBlobMap("test1"), context.createBlobMap("test2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStoreTweets() throws IOException, InterruptedException, ExecutionException {
|
||||||
|
Set<BlobMap> maps = createMaps();
|
||||||
|
StoreTweetsController function = new StoreTweetsController(maps, 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 jimmy = new User();
|
||||||
|
jimmy.setScreenName("jimmy");
|
||||||
|
Status jimmyStatus = new Status();
|
||||||
|
jimmyStatus.setId(2);
|
||||||
|
jimmyStatus.setUser(jimmy);
|
||||||
|
jimmyStatus.setText("cloud is king");
|
||||||
|
|
||||||
|
allAboutMe.add(frankStatus);
|
||||||
|
allAboutMe.add(jimmyStatus);
|
||||||
|
|
||||||
|
function.addMyTweets(allAboutMe);
|
||||||
|
|
||||||
|
for (BlobMap map : maps) {
|
||||||
|
Blob frankBlob = map.get("1");
|
||||||
|
assertEquals(frankBlob.getMetadata().getName(), "1");
|
||||||
|
assertEquals(frankBlob.getMetadata().getUserMetadata()
|
||||||
|
.get(TweetStoreConstants.SENDER_NAME), "frank");
|
||||||
|
assertEquals(frankBlob.getMetadata().getContentType(), "text/plain");
|
||||||
|
assertEquals(IOUtils.toString((InputStream) frankBlob.getData()), "I love beans!");
|
||||||
|
|
||||||
|
Blob jimmyBlob = map.get("2");
|
||||||
|
assertEquals(jimmyBlob.getMetadata().getName(), "2");
|
||||||
|
assertEquals(jimmyBlob.getMetadata().getUserMetadata()
|
||||||
|
.get(TweetStoreConstants.SENDER_NAME), "jimmy");
|
||||||
|
assertEquals(jimmyBlob.getMetadata().getContentType(), "text/plain");
|
||||||
|
assertEquals(IOUtils.toString((InputStream) jimmyBlob.getData()), "cloud is king");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.jclouds.demo.tweetstore.functions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.BlobMap;
|
||||||
|
import org.jclouds.blobstore.BlobStore;
|
||||||
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.integration.StubBlobStoreContextBuilder;
|
||||||
|
import org.jclouds.demo.tweetstore.domain.StoredTweetStatus;
|
||||||
|
import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code KeyToStoredTweetStatus}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "tweetstore.KeyToStoredTweetStatusTest")
|
||||||
|
public class KeyToStoredTweetStatusTest {
|
||||||
|
|
||||||
|
BlobMap createMap() throws InterruptedException, ExecutionException {
|
||||||
|
BlobStoreContext<BlobStore> context = new StubBlobStoreContextBuilder().buildContext();
|
||||||
|
context.getBlobStore().createContainer("test1").get();
|
||||||
|
return context.createBlobMap("test1");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStoreTweets() throws IOException, InterruptedException, ExecutionException {
|
||||||
|
BlobMap map = createMap();
|
||||||
|
Blob blob = map.newBlob();
|
||||||
|
blob.getMetadata().setName("1");
|
||||||
|
blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank");
|
||||||
|
blob.setData("I love beans!");
|
||||||
|
map.put("1", blob);
|
||||||
|
String host = "localhost";
|
||||||
|
String service = "stub";
|
||||||
|
String container = "tweetstore";
|
||||||
|
|
||||||
|
KeyToStoredTweetStatus function = new KeyToStoredTweetStatus(map, service, host, container);
|
||||||
|
StoredTweetStatus result = function.apply("1");
|
||||||
|
|
||||||
|
StoredTweetStatus expected = new StoredTweetStatus(service, host, container, "1", "frank",
|
||||||
|
"I love beans!", null);
|
||||||
|
|
||||||
|
assertEquals(result, expected);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package org.jclouds.demo.tweetstore.functions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.BlobStore;
|
||||||
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.integration.StubBlobStoreContextBuilder;
|
||||||
|
import org.jclouds.demo.tweetstore.domain.StoredTweetStatus;
|
||||||
|
import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
import org.testng.collections.Maps;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code ServiceToStoredTweetStatuses}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "tweetstore.ServiceToStoredTweetStatuses")
|
||||||
|
public class ServiceToStoredTweetStatusesTest {
|
||||||
|
|
||||||
|
Map<String, BlobStoreContext<?>> createServices(String container) throws InterruptedException,
|
||||||
|
ExecutionException {
|
||||||
|
Map<String, BlobStoreContext<?>> services = Maps.newHashMap();
|
||||||
|
for (String name : new String[] { "1", "2" }) {
|
||||||
|
BlobStoreContext<BlobStore> context = new StubBlobStoreContextBuilder().buildContext();
|
||||||
|
context.getBlobStore().createContainer(container).get();
|
||||||
|
Blob blob = context.getBlobStore().newBlob();
|
||||||
|
blob.getMetadata().setName("1");
|
||||||
|
blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank");
|
||||||
|
blob.setData("I love beans!");
|
||||||
|
context.getBlobStore().putBlob(container, blob).get();
|
||||||
|
services.put(name, context);
|
||||||
|
}
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStoreTweets() throws IOException, InterruptedException, ExecutionException {
|
||||||
|
String container = "container";
|
||||||
|
Map<String, BlobStoreContext<?>> contexts = createServices(container);
|
||||||
|
|
||||||
|
ServiceToStoredTweetStatuses function = new ServiceToStoredTweetStatuses(contexts, container);
|
||||||
|
|
||||||
|
assertEquals(Iterables.getLast(function.apply("1")), new StoredTweetStatus("1", "localhost",
|
||||||
|
container, "1", "frank", "I love beans!", null));
|
||||||
|
|
||||||
|
assertEquals(Iterables.getLast(function.apply("2")), new StoredTweetStatus("2", "localhost",
|
||||||
|
container, "1", "frank", "I love beans!", null));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.demo.tweetstore.integration;
|
||||||
|
|
||||||
|
import com.google.appengine.tools.KickStart;
|
||||||
|
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic functionality to start a local google app engine instance.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class GoogleDevServer {
|
||||||
|
|
||||||
|
Thread server;
|
||||||
|
|
||||||
|
public void writePropertiesAndStartServer(final String address,
|
||||||
|
final String port, final String warfile, Properties props)
|
||||||
|
throws IOException, InterruptedException {
|
||||||
|
String filename = String.format(
|
||||||
|
"%1$s/WEB-INF/jclouds.properties", warfile);
|
||||||
|
System.err.println("file: " + filename);
|
||||||
|
props.store(new FileOutputStream(filename), "test");
|
||||||
|
assert new File(filename).exists();
|
||||||
|
this.server = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
KickStart
|
||||||
|
.main(new String[]{
|
||||||
|
"com.google.appengine.tools.development.DevAppServerMain",
|
||||||
|
"--disable_update_check", "-a", address, "-p",
|
||||||
|
port, warfile});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
server.start();
|
||||||
|
Thread.sleep(10 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public void stop() throws Exception {
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,190 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.demo.tweetstore.integration;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
|
||||||
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
|
||||||
|
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT;
|
||||||
|
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY;
|
||||||
|
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_BLOBSTORE_CONTEXTBUILDERS;
|
||||||
|
import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER;
|
||||||
|
import static org.jclouds.rackspace.reference.RackspaceConstants.PROPERTY_RACKSPACE_KEY;
|
||||||
|
import static org.jclouds.rackspace.reference.RackspaceConstants.PROPERTY_RACKSPACE_USER;
|
||||||
|
import static org.jclouds.twitter.reference.TwitterConstants.PROPERTY_TWITTER_PASSWORD;
|
||||||
|
import static org.jclouds.twitter.reference.TwitterConstants.PROPERTY_TWITTER_USER;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.jclouds.aws.s3.S3PropertiesBuilder;
|
||||||
|
import org.jclouds.aws.s3.blobstore.S3BlobStoreContextBuilder;
|
||||||
|
import org.jclouds.aws.s3.blobstore.S3BlobStoreContextFactory;
|
||||||
|
import org.jclouds.azure.storage.blob.AzureBlobPropertiesBuilder;
|
||||||
|
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStoreContextBuilder;
|
||||||
|
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStoreContextFactory;
|
||||||
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
|
import org.jclouds.rackspace.cloudfiles.CloudFilesPropertiesBuilder;
|
||||||
|
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextBuilder;
|
||||||
|
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextFactory;
|
||||||
|
import org.jclouds.twitter.TwitterPropertiesBuilder;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.BeforeTest;
|
||||||
|
import org.testng.annotations.Parameters;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts up the Google App Engine for Java Development environment and deploys an application which
|
||||||
|
* tests accesses twitter and blobstores.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", sequential = true, testName = "functionalTests")
|
||||||
|
public class TweetStoreLiveTest {
|
||||||
|
|
||||||
|
GoogleDevServer server;
|
||||||
|
private URL url;
|
||||||
|
private ImmutableSet<BlobStoreContext<? extends Object>> contexts;
|
||||||
|
private String container;
|
||||||
|
|
||||||
|
@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)));
|
||||||
|
props.setProperty(PROPERTY_BLOBSTORE_CONTEXTBUILDERS, String.format("%s,%s,%s",
|
||||||
|
S3BlobStoreContextBuilder.class.getName(), CloudFilesBlobStoreContextBuilder.class
|
||||||
|
.getName(), AzureBlobStoreContextBuilder.class.getName()));
|
||||||
|
|
||||||
|
props = new TwitterPropertiesBuilder(props).withCredentials(
|
||||||
|
checkNotNull(System.getProperty(PROPERTY_TWITTER_USER), PROPERTY_TWITTER_USER),
|
||||||
|
System.getProperty(PROPERTY_TWITTER_PASSWORD, PROPERTY_TWITTER_PASSWORD)).build();
|
||||||
|
|
||||||
|
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 {
|
||||||
|
container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER));
|
||||||
|
BlobStoreContext<?> s3Context = S3BlobStoreContextFactory.createContext(checkNotNull(System
|
||||||
|
.getProperty(PROPERTY_AWS_ACCESSKEYID), PROPERTY_AWS_ACCESSKEYID), System
|
||||||
|
.getProperty(PROPERTY_AWS_SECRETACCESSKEY, PROPERTY_AWS_SECRETACCESSKEY));
|
||||||
|
|
||||||
|
BlobStoreContext<?> cfContext = CloudFilesBlobStoreContextFactory.createContext(checkNotNull(
|
||||||
|
System.getProperty(PROPERTY_RACKSPACE_USER), PROPERTY_RACKSPACE_USER), System
|
||||||
|
.getProperty(PROPERTY_RACKSPACE_KEY, PROPERTY_RACKSPACE_KEY));
|
||||||
|
|
||||||
|
BlobStoreContext<?> azContext = AzureBlobStoreContextFactory.createContext(checkNotNull(
|
||||||
|
System.getProperty(PROPERTY_AZURESTORAGE_ACCOUNT), PROPERTY_AZURESTORAGE_ACCOUNT),
|
||||||
|
System.getProperty(PROPERTY_AZURESTORAGE_KEY, PROPERTY_AZURESTORAGE_KEY));
|
||||||
|
this.contexts = ImmutableSet.of(s3Context, cfContext, azContext);
|
||||||
|
boolean deleted = false;
|
||||||
|
for (BlobStoreContext<?> context : contexts) {
|
||||||
|
if (context.getBlobStore().exists(container)) {
|
||||||
|
System.err.printf("deleting container %s at %s%n", container, context.getEndPoint());
|
||||||
|
context.getBlobStore().deleteContainer(container).get(30, TimeUnit.SECONDS);
|
||||||
|
deleted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (deleted) {
|
||||||
|
System.err.println("sleeping 30 seconds to allow containers to clear");
|
||||||
|
Thread.sleep(30000);
|
||||||
|
}
|
||||||
|
for (BlobStoreContext<?> context : contexts) {
|
||||||
|
System.err.printf("creating container %s at %s%n", container, context.getEndPoint());
|
||||||
|
context.getBlobStore().createContainer(container).get(30, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldPass() throws InterruptedException, IOException {
|
||||||
|
InputStream i = url.openStream();
|
||||||
|
String string = IOUtils.toString(i);
|
||||||
|
assert string.indexOf("Welcome") >= 0 : string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "shouldPass", expectedExceptions = IOException.class)
|
||||||
|
public void shouldFail() throws InterruptedException, IOException {
|
||||||
|
new URL(url, "/cron/do").openStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "shouldFail")
|
||||||
|
public void testPrimeContainers() throws IOException {
|
||||||
|
URL gurl = new URL(url, "/cron/do");
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) gurl.openConnection();
|
||||||
|
connection.addRequestProperty("X-AppEngine-Cron", "true");
|
||||||
|
InputStream i = connection.getInputStream();
|
||||||
|
String string = IOUtils.toString(i);
|
||||||
|
assert string.indexOf("Done!") >= 0 : string;
|
||||||
|
for (BlobStoreContext<?> context : contexts) {
|
||||||
|
assert context.createInputStreamMap(container).size() > 0 : context.getEndPoint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(invocationCount = 5, dependsOnMethods = "testPrimeContainers")
|
||||||
|
public void testSerial() throws InterruptedException, IOException {
|
||||||
|
URL gurl = new URL(url, "/tweets/get");
|
||||||
|
InputStream i = gurl.openStream();
|
||||||
|
String string = IOUtils.toString(i);
|
||||||
|
assert string.indexOf("Tweets in Clouds") >= 0 : string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(invocationCount = 10, dependsOnMethods = "testPrimeContainers", threadPoolSize = 3)
|
||||||
|
public void testParallel() throws InterruptedException, IOException {
|
||||||
|
URL gurl = new URL(url, "/tweets/get");
|
||||||
|
InputStream i = gurl.openStream();
|
||||||
|
String string = IOUtils.toString(i);
|
||||||
|
assert string.indexOf("Tweets in Clouds") >= 0 : string;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
$HeadURL$
|
||||||
|
$Revision$
|
||||||
|
$Date$
|
||||||
|
|
||||||
|
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
|
||||||
|
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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>jclouds-project</artifactId>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../project/pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>jclouds-demos-project</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>jclouds demos project</name>
|
||||||
|
<modules>
|
||||||
|
<module>gae-tweetstore</module>
|
||||||
|
</modules>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<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-log4j</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
|
@ -53,8 +53,8 @@ public class Status implements Comparable<Status> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Status(DateTime createdAt, boolean favorited, String geo, long id,
|
public Status(DateTime createdAt, boolean favorited, String geo, long id,
|
||||||
String inReplyToScreenName, Integer inReplyToStatusId, Integer inReplyToUserId, String source,
|
String inReplyToScreenName, Integer inReplyToStatusId, Integer inReplyToUserId,
|
||||||
String text, boolean truncated, User user) {
|
String source, String text, boolean truncated, User user) {
|
||||||
this.createdAt = createdAt;
|
this.createdAt = createdAt;
|
||||||
this.favorited = favorited;
|
this.favorited = favorited;
|
||||||
this.geo = geo;
|
this.geo = geo;
|
||||||
|
@ -72,7 +72,9 @@ public class Status implements Comparable<Status> {
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
|
result = prime * result + ((createdAt == null) ? 0 : createdAt.hashCode());
|
||||||
result = prime * result + (int) (id ^ (id >>> 32));
|
result = prime * result + (int) (id ^ (id >>> 32));
|
||||||
|
result = prime * result + ((text == null) ? 0 : text.hashCode());
|
||||||
result = prime * result + ((user == null) ? 0 : user.hashCode());
|
result = prime * result + ((user == null) ? 0 : user.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -86,8 +88,18 @@ public class Status implements Comparable<Status> {
|
||||||
if (getClass() != obj.getClass())
|
if (getClass() != obj.getClass())
|
||||||
return false;
|
return false;
|
||||||
Status other = (Status) obj;
|
Status other = (Status) obj;
|
||||||
|
if (createdAt == null) {
|
||||||
|
if (other.createdAt != null)
|
||||||
|
return false;
|
||||||
|
} else if (!createdAt.equals(other.createdAt))
|
||||||
|
return false;
|
||||||
if (id != other.id)
|
if (id != other.id)
|
||||||
return false;
|
return false;
|
||||||
|
if (text == null) {
|
||||||
|
if (other.text != null)
|
||||||
|
return false;
|
||||||
|
} else if (!text.equals(other.text))
|
||||||
|
return false;
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
if (other.user != null)
|
if (other.user != null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -177,7 +189,7 @@ public class Status implements Comparable<Status> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(Status o) {
|
public int compareTo(Status o) {
|
||||||
return (int) ((this == o) ? 0 : id - id);
|
return (int) ((this == o) ? 0 : id + "".compareTo(o.id + ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeo(String geo) {
|
public void setGeo(String geo) {
|
||||||
|
|
|
@ -126,6 +126,7 @@ public class User implements Comparable<User> {
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + (int) (id ^ (id >>> 32));
|
result = prime * result + (int) (id ^ (id >>> 32));
|
||||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
result = prime * result + ((screenName == null) ? 0 : screenName.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +146,11 @@ public class User implements Comparable<User> {
|
||||||
return false;
|
return false;
|
||||||
} else if (!name.equals(other.name))
|
} else if (!name.equals(other.name))
|
||||||
return false;
|
return false;
|
||||||
|
if (screenName == null) {
|
||||||
|
if (other.screenName != null)
|
||||||
|
return false;
|
||||||
|
} else if (!screenName.equals(other.screenName))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,39 @@ public class ParseStatusesFromJsonResponseTest {
|
||||||
SortedSet<Status> expects = ImmutableSortedSet
|
SortedSet<Status> expects = ImmutableSortedSet
|
||||||
.of(
|
.of(
|
||||||
|
|
||||||
|
new Status(
|
||||||
|
dateService.cDateParse("Sat Oct 31 01:45:14 +0000 2009"),
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
5303839785l,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"<a href=\"http://www.tweetdeck.com/\" rel=\"nofollow\">TweetDeck</a>",
|
||||||
|
"RT @jclouds: come find out about #cloud storage and how to access it from #java in palo alto this Tuesday: http://is.gd/4IFA9",
|
||||||
|
false,
|
||||||
|
new User(
|
||||||
|
dateService.cDateParse("Sat Apr 26 06:13:08 +0000 2008"),
|
||||||
|
"Jack of All Trades: Dad to anZel and Arden, VMware, vCloud, Security, Compliance, Former Developer",
|
||||||
|
0,
|
||||||
|
474,
|
||||||
|
false,
|
||||||
|
199,
|
||||||
|
false,
|
||||||
|
14540593,
|
||||||
|
"Bay Area, CA",
|
||||||
|
"Jian Zhen",
|
||||||
|
false,
|
||||||
|
"C6E2EE",
|
||||||
|
URI
|
||||||
|
.create("http://s.twimg.com/a/1256778767/images/themes/theme2/bg.gif"),
|
||||||
|
false,
|
||||||
|
URI
|
||||||
|
.create("http://a3.twimg.com/profile_images/64445411/30b8b19_bigger_normal.jpg"),
|
||||||
|
"1F98C7", "C6E2EE", "DAECF4", "663B12", false, "zhenjl",
|
||||||
|
1981, "Pacific Time (US & Canada)", URI
|
||||||
|
.create("http://zhen.org"), -28800, false)),
|
||||||
|
|
||||||
new Status(
|
new Status(
|
||||||
dateService.cDateParse("Sat Oct 31 09:35:27 +0000 2009"),
|
dateService.cDateParse("Sat Oct 31 09:35:27 +0000 2009"),
|
||||||
false,
|
false,
|
||||||
|
@ -80,39 +113,7 @@ public class ParseStatusesFromJsonResponseTest {
|
||||||
"Pacific Time (US & Canada)",
|
"Pacific Time (US & Canada)",
|
||||||
URI
|
URI
|
||||||
.create("http://siliconangle.net/ver2/author/jwatters/"),
|
.create("http://siliconangle.net/ver2/author/jwatters/"),
|
||||||
-28800, false)),
|
-28800, false))
|
||||||
new Status(
|
|
||||||
dateService.cDateParse("Sat Oct 31 01:45:14 +0000 2009"),
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
5303839785l,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
"<a href=\"http://www.tweetdeck.com/\" rel=\"nofollow\">TweetDeck</a>",
|
|
||||||
"RT @jclouds: come find out about #cloud storage and how to access it from #java in palo alto this Tuesday: http://is.gd/4IFA9",
|
|
||||||
false,
|
|
||||||
new User(
|
|
||||||
dateService.cDateParse("Sat Apr 26 06:13:08 +0000 2008"),
|
|
||||||
"Jack of All Trades: Dad to anZel and Arden, VMware, vCloud, Security, Compliance, Former Developer",
|
|
||||||
0,
|
|
||||||
474,
|
|
||||||
false,
|
|
||||||
199,
|
|
||||||
false,
|
|
||||||
14540593,
|
|
||||||
"Bay Area, CA",
|
|
||||||
"Jian Zhen",
|
|
||||||
false,
|
|
||||||
"C6E2EE",
|
|
||||||
URI
|
|
||||||
.create("http://s.twimg.com/a/1256778767/images/themes/theme2/bg.gif"),
|
|
||||||
false,
|
|
||||||
URI
|
|
||||||
.create("http://a3.twimg.com/profile_images/64445411/30b8b19_bigger_normal.jpg"),
|
|
||||||
"1F98C7", "C6E2EE", "DAECF4", "663B12", false, "zhenjl",
|
|
||||||
1981, "Pacific Time (US & Canada)", URI
|
|
||||||
.create("http://zhen.org"), -28800, false))
|
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -121,5 +122,4 @@ public class ParseStatusesFromJsonResponseTest {
|
||||||
SortedSet<Status> response = parser.apply(is);
|
SortedSet<Status> response = parser.apply(is);
|
||||||
assertEquals(response, expects);
|
assertEquals(response, expects);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue