Issue 318: updated to gae 1.3.5

This commit is contained in:
Adrian Cole 2010-07-21 11:51:08 -07:00
parent 318e9b9071
commit 9bffee1135
18 changed files with 408 additions and 389 deletions

View File

@ -16,7 +16,7 @@
limitations under the License. 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 This samples uses the Google App Engine for Java SDK located at http://googleappengine.googlecode.com/files/appengine-java-sdk-1.3.5.zip
Please unzip the above file and modify your maven settings.xml like below before attempting to run 'mvn -Plive install' Please unzip the above file and modify your maven settings.xml like below before attempting to run 'mvn -Plive install'
@ -26,7 +26,7 @@ Please unzip the above file and modify your maven settings.xml like below before
<activeByDefault>true</activeByDefault> <activeByDefault>true</activeByDefault>
</activation> </activation>
<properties> <properties>
<appengine.home>/path/to/appengine-java-sdk-1.2.5</appengine.home> <appengine.home>/path/to/appengine-java-sdk-1.3.5</appengine.home>
</properties> </properties>
</profile> </profile>

View File

@ -101,7 +101,7 @@
<dependency> <dependency>
<groupId>com.google.appengine</groupId> <groupId>com.google.appengine</groupId>
<artifactId>appengine-tools-api</artifactId> <artifactId>appengine-tools-api</artifactId>
<version>1.3.2</version> <version>1.3.5</version>
<scope>system</scope> <scope>system</scope>
<systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath> <systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath>
</dependency> </dependency>

View File

@ -54,7 +54,7 @@ public class GoogleDevServer {
}); });
server.start(); server.start();
Thread.sleep(15 * 1000); Thread.sleep(30 * 1000);
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")

View File

@ -36,7 +36,7 @@ attempting to run 'mvn -Plive install'
<activeByDefault>true</activeByDefault> <activeByDefault>true</activeByDefault>
</activation> </activation>
<properties> <properties>
<appengine.home>/path/to/appengine-java-sdk-1.2.5</appengine.home> <appengine.home>/path/to/appengine-java-sdk-1.3.5</appengine.home>
<appengine.applicationid>yourappid</appengine.applicationid> <appengine.applicationid>yourappid</appengine.applicationid>
</properties> </properties>
</profile> </profile>

View File

@ -41,6 +41,7 @@
<appengine.applicationid>jclouds-tweetstore-spring</appengine.applicationid> <appengine.applicationid>jclouds-tweetstore-spring</appengine.applicationid>
<devappserver.address>localhost</devappserver.address> <devappserver.address>localhost</devappserver.address>
<devappserver.port>8088</devappserver.port> <devappserver.port>8088</devappserver.port>
<jclouds.tweetstore.blobstores>googlestorage,s3,azureblob</jclouds.tweetstore.blobstores>
<jclouds.tweetstore.container>jclouds-tweetstore-spring</jclouds.tweetstore.container> <jclouds.tweetstore.container>jclouds-tweetstore-spring</jclouds.tweetstore.container>
</properties> </properties>
@ -168,12 +169,12 @@
<dependency> <dependency>
<groupId>com.google.appengine</groupId> <groupId>com.google.appengine</groupId>
<artifactId>appengine-api-labs</artifactId> <artifactId>appengine-api-labs</artifactId>
<version>1.3.2</version> <version>1.3.5</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.appengine</groupId> <groupId>com.google.appengine</groupId>
<artifactId>appengine-tools-api</artifactId> <artifactId>appengine-tools-api</artifactId>
<version>1.3.2</version> <version>1.3.5</version>
<scope>system</scope> <scope>system</scope>
<systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath> <systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath>
</dependency> </dependency>
@ -305,6 +306,10 @@
<name>devappserver.port</name> <name>devappserver.port</name>
<value>${devappserver.port}</value> <value>${devappserver.port}</value>
</property> </property>
<property>
<name>jclouds.tweetstore.blobstores</name>
<value>${jclouds.tweetstore.blobstores}</value>
</property>
<property> <property>
<name>jclouds.tweetstore.container</name> <name>jclouds.tweetstore.container</name>
<value>${jclouds.tweetstore.container}</value> <value>${jclouds.tweetstore.container}</value>

View File

@ -63,10 +63,9 @@ public class StoreTweetsController extends HttpServlet {
public Blob apply(Status from) { public Blob apply(Status from) {
Blob to = map.newBlob(from.getId() + ""); Blob to = map.newBlob(from.getId() + "");
to.getMetadata().setContentType(MediaType.TEXT_PLAIN);
to.setPayload(from.getText()); to.setPayload(from.getText());
to.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, to.getPayload().setContentType(MediaType.TEXT_PLAIN);
from.getUser().getScreenName()); to.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, from.getUser().getScreenName());
return to; return to;
} }
} }
@ -84,8 +83,7 @@ public class StoreTweetsController extends HttpServlet {
@Inject @Inject
@VisibleForTesting @VisibleForTesting
public StoreTweetsController(Map<String, BlobStoreContext> contexts, public StoreTweetsController(Map<String, BlobStoreContext> contexts,
@Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container, @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container, TwitterClient client) {
TwitterClient client) {
this.container = container; this.container = container;
this.contexts = contexts; this.contexts = contexts;
this.client = client; this.client = client;
@ -93,8 +91,8 @@ public class StoreTweetsController extends HttpServlet {
@VisibleForTesting @VisibleForTesting
public void addMyTweets(String contextName, Set<Status> allAboutMe) { public void addMyTweets(String contextName, Set<Status> allAboutMe) {
BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in "
+ contextName + " in " + contexts.keySet()); + contexts.keySet());
BlobMap map = context.createBlobMap(container); BlobMap map = context.createBlobMap(container);
for (Status status : allAboutMe) { for (Status status : allAboutMe) {
Blob blob = null; Blob blob = null;
@ -104,20 +102,17 @@ public class StoreTweetsController extends HttpServlet {
} catch (AuthorizationException e) { } catch (AuthorizationException e) {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
logger.error(e, "Error storing tweet %s (blob[%s]) on map %s/%s", status.getId(), blob, logger.error(e, "Error storing tweet %s (blob[%s]) on map %s/%s", status.getId(), blob, context, container);
context, container);
} }
} }
} }
@Override @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
throws ServletException, IOException {
if (request.getHeader("X-AppEngine-QueueName") != null if (request.getHeader("X-AppEngine-QueueName") != null
&& request.getHeader("X-AppEngine-QueueName").equals("twitter")) { && request.getHeader("X-AppEngine-QueueName").equals("twitter")) {
try { try {
String contextName = checkNotNull(request.getHeader("context"), String contextName = checkNotNull(request.getHeader("context"), "missing header context");
"missing header context");
logger.info("retrieving tweets"); logger.info("retrieving tweets");
addMyTweets(contextName, client.getMyMentions()); addMyTweets(contextName, client.getMyMentions());
logger.debug("done storing tweets"); logger.debug("done storing tweets");

View File

@ -54,7 +54,7 @@ public class GoogleDevServer {
}); });
server.start(); server.start();
Thread.sleep(10 * 1000); Thread.sleep(30 * 1000);
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")

View File

@ -49,13 +49,14 @@ import org.testng.annotations.Parameters;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.inject.Module; import com.google.inject.Module;
/** /**
* Starts up the Google App Engine for Java Development environment and deploys an application which * Starts up the Google App Engine for Java Development environment and deploys
* tests accesses twitter and blobstores. * an application which tests accesses twitter and blobstores.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@ -67,7 +68,9 @@ public class TweetStoreLiveTest {
private Map<String, BlobStoreContext> contexts; private Map<String, BlobStoreContext> contexts;
private String container; private String container;
private static final Iterable<String> blobstores = ImmutableSet.of("cloudfiles", "googlestorage", "s3", "azureblob"); private static final String blobs = System.getProperty("jclouds.tweetstore.blobstores",
"cloudfiles,googlestorage,s3,azureblob");
private static final Iterable<String> blobstores = Splitter.on(',').split(blobs);
private static final Properties props = new Properties(); private static final Properties props = new Properties();
@BeforeTest @BeforeTest
@ -75,7 +78,7 @@ public class TweetStoreLiveTest {
container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER)); container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER));
props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER), props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER),
PROPERTY_TWEETSTORE_CONTAINER)); PROPERTY_TWEETSTORE_CONTAINER));
props.setProperty(SpringServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, Joiner.on(',').join(blobstores)); props.setProperty(SpringServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, Joiner.on(',').join(blobstores));
@ -95,7 +98,7 @@ public class TweetStoreLiveTest {
} }
RestContext<TwitterClient, TwitterAsyncClient> twitterContext = new RestContextFactory().createContext("twitter", RestContext<TwitterClient, TwitterAsyncClient> twitterContext = new RestContextFactory().createContext("twitter",
wiring, props); wiring, props);
StoreTweetsController controller = new StoreTweetsController(contexts, container, twitterContext.getApi()); StoreTweetsController controller = new StoreTweetsController(contexts, container, twitterContext.getApi());
Set<Status> statuses = twitterContext.getApi().getMyMentions(); Set<Status> statuses = twitterContext.getApi().getMyMentions();
@ -104,7 +107,7 @@ public class TweetStoreLiveTest {
for (BlobStoreContext context : contexts.values()) { for (BlobStoreContext context : contexts.values()) {
if (context.getBlobStore().containerExists(container)) { if (context.getBlobStore().containerExists(container)) {
System.err.printf("deleting container %s at %s%n", container, context.getProviderSpecificContext() System.err.printf("deleting container %s at %s%n", container, context.getProviderSpecificContext()
.getEndpoint()); .getEndpoint());
context.getBlobStore().deleteContainer(container); context.getBlobStore().deleteContainer(container);
deleted = true; deleted = true;
} }
@ -115,7 +118,7 @@ public class TweetStoreLiveTest {
} }
for (BlobStoreContext context : contexts.values()) { for (BlobStoreContext context : contexts.values()) {
System.err.printf("creating container %s at %s%n", container, context.getProviderSpecificContext() System.err.printf("creating container %s at %s%n", container, context.getProviderSpecificContext()
.getEndpoint()); .getEndpoint());
context.getBlobStore().createContainerInLocation(null, container); context.getBlobStore().createContainerInLocation(null, container);
} }
if (deleted) { if (deleted) {
@ -134,15 +137,15 @@ public class TweetStoreLiveTest {
String twitterCredential = checkNotNull(System.getProperty("twitter.credential"), "twitter.credential"); String twitterCredential = checkNotNull(System.getProperty("twitter.credential"), "twitter.credential");
props.putAll(RestContextFactory.toProperties(contextSpec("twitter", "http://twitter.com", "1", twitterIdentity, props.putAll(RestContextFactory.toProperties(contextSpec("twitter", "http://twitter.com", "1", twitterIdentity,
twitterCredential, TwitterClient.class, TwitterAsyncClient.class))); twitterCredential, TwitterClient.class, TwitterAsyncClient.class)));
} }
private void addCredentialsForBlobStores(Properties props) { private void addCredentialsForBlobStores(Properties props) {
for (String provider : blobstores) { for (String provider : blobstores) {
props.setProperty(provider + ".identity", checkNotNull(System.getProperty(provider + ".identity"), provider props.setProperty(provider + ".identity", checkNotNull(System.getProperty(provider + ".identity"), provider
+ ".identity")); + ".identity"));
props.setProperty(provider + ".credential", checkNotNull(System.getProperty(provider + ".credential"), props.setProperty(provider + ".credential", checkNotNull(System.getProperty(provider + ".credential"),
provider + ".credential")); provider + ".credential"));
} }
} }
@ -170,7 +173,7 @@ public class TweetStoreLiveTest {
public void testPrimeContainers() throws IOException, InterruptedException { public void testPrimeContainers() throws IOException, InterruptedException {
URL gurl = new URL(url, "/store/do"); URL gurl = new URL(url, "/store/do");
// WATCH THIS, you need to add a context each time // WATCH THIS, you need to add a context each time
for (String context : new String[] { "cloudfiles", "s3", "azureblob" }) { for (String context : blobstores) {
System.out.println("storing at context: " + context); System.out.println("storing at context: " + context);
HttpURLConnection connection = (HttpURLConnection) gurl.openConnection(); HttpURLConnection connection = (HttpURLConnection) gurl.openConnection();
connection.addRequestProperty("X-AppEngine-QueueName", "twitter"); connection.addRequestProperty("X-AppEngine-QueueName", "twitter");

View File

@ -28,7 +28,7 @@ attempting to run 'mvn -Plive install'
<activeByDefault>true</activeByDefault> <activeByDefault>true</activeByDefault>
</activation> </activation>
<properties> <properties>
<appengine.home>/path/to/appengine-java-sdk-1.2.5</appengine.home> <appengine.home>/path/to/appengine-java-sdk-1.3.5</appengine.home>
<appengine.applicationid>yourappid</appengine.applicationid> <appengine.applicationid>yourappid</appengine.applicationid>
</properties> </properties>
</profile> </profile>

View File

@ -1,309 +1,313 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright (C) 2009 Cloud Conscious, LLC. Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
<info@cloudconscious.com>
==================================================================== ====================================================================
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"); you
you may not use this file except in compliance with the License. may not use this file except in compliance with the License. You may
You may obtain a copy of the License at obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 Unless required by http://www.apache.org/licenses/LICENSE-2.0 Unless required by
applicable law or agreed to in writing, software distributed applicable law or agreed to in writing, software distributed under the
under the License is distributed on an "AS IS" BASIS, WITHOUT License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. CONDITIONS OF ANY KIND, either express or implied. See the License for
See the License for the specific language governing permissions the specific language governing permissions and limitations under the
and limitations under the License. License.
==================================================================== ====================================================================
--> -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <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"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>
<artifactId>jclouds-demos-project</artifactId> <artifactId>jclouds-demos-project</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>jclouds-demo-gae-tweetstore</artifactId> <artifactId>jclouds-demo-gae-tweetstore</artifactId>
<packaging>war</packaging> <packaging>war</packaging>
<name>JClouds TweetStore for Google App Engine</name> <name>JClouds TweetStore for Google App Engine</name>
<description>JClouds TweetStore for Google App Engine</description> <description>JClouds TweetStore for Google App Engine</description>
<properties> <properties>
<!-- <!--
note you must set the property ${appengine.home} to a valid note you must set the property ${appengine.home} to a valid
extraction of appengine-java-sdk extraction of appengine-java-sdk
--> -->
<appengine.home>YOUR_APPENGINE_HOME</appengine.home> <appengine.home>YOUR_APPENGINE_HOME</appengine.home>
<appengine.applicationid>jclouds-tweetstore</appengine.applicationid> <appengine.applicationid>jclouds-tweetstore</appengine.applicationid>
<devappserver.address>localhost</devappserver.address> <devappserver.address>localhost</devappserver.address>
<devappserver.port>8088</devappserver.port> <devappserver.port>8088</devappserver.port>
<jclouds.tweetstore.container>jclouds-tweetstore</jclouds.tweetstore.container> <jclouds.tweetstore.blobstores>googlestorage,s3,azureblob</jclouds.tweetstore.blobstores>
</properties> <jclouds.tweetstore.container>jclouds-tweetstore</jclouds.tweetstore.container>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>jclouds-blobstore</artifactId> <artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>jclouds-blobstore</artifactId> <artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<type>test-jar</type> <type>test-jar</type>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId> <artifactId>jclouds-core</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<type>test-jar</type> <type>test-jar</type>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>jclouds-log4j</artifactId> <artifactId>jclouds-log4j</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>log4j</groupId> <groupId>log4j</groupId>
<artifactId>log4j</artifactId> <artifactId>log4j</artifactId>
<version>1.2.14</version> <version>1.2.14</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>jclouds-twitter</artifactId> <artifactId>jclouds-twitter</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>jclouds-aws</artifactId> <artifactId>jclouds-aws</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>jclouds-azure</artifactId> <artifactId>jclouds-azure</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>jclouds-rackspace</artifactId> <artifactId>jclouds-rackspace</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>jclouds-gae</artifactId> <artifactId>jclouds-gae</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.code.guice</groupId> <groupId>com.google.code.guice</groupId>
<artifactId>guice-servlet</artifactId> <artifactId>guice-servlet</artifactId>
<version>2.1-r1172</version> <version>2.1-r1172</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>displaytag</groupId> <groupId>displaytag</groupId>
<artifactId>displaytag</artifactId> <artifactId>displaytag</artifactId>
<version>1.2</version> <version>1.2</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId> <artifactId>slf4j-log4j12</artifactId>
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId> <artifactId>slf4j-jdk14</artifactId>
<version>1.5.6</version> <version>1.5.6</version>
</dependency> </dependency>
<dependency> <dependency>
<artifactId>standard</artifactId> <artifactId>standard</artifactId>
<groupId>taglibs</groupId> <groupId>taglibs</groupId>
<version>1.1.2</version> <version>1.1.2</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency> <dependency>
<artifactId>jstl</artifactId> <artifactId>jstl</artifactId>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<version>1.1.2</version> <version>1.1.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.geronimo.specs</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-el_1.0_spec</artifactId> <artifactId>geronimo-el_1.0_spec</artifactId>
<version>1.0.1</version> <version>1.0.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.geronimo.specs</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jsp_2.1_spec</artifactId> <artifactId>geronimo-jsp_2.1_spec</artifactId>
<version>1.0.1</version> <version>1.0.1</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.geronimo.specs</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_2.5_spec</artifactId> <artifactId>geronimo-servlet_2.5_spec</artifactId>
<version>1.2</version> <version>1.2</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.appengine</groupId> <groupId>com.google.appengine</groupId>
<artifactId>appengine-api-labs</artifactId> <artifactId>appengine-api-labs</artifactId>
<version>1.3.2</version> <version>1.3.5</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.appengine</groupId> <groupId>com.google.appengine</groupId>
<artifactId>appengine-tools-api</artifactId> <artifactId>appengine-tools-api</artifactId>
<version>1.3.2</version> <version>1.3.5</version>
<scope>system</scope> <scope>system</scope>
<systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath> <systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>${project.artifactId}</finalName> <finalName>${project.artifactId}</finalName>
<plugins> <plugins>
<plugin> <plugin>
<artifactId>maven-war-plugin</artifactId> <artifactId>maven-war-plugin</artifactId>
<configuration> <configuration>
<webResources> <webResources>
<resource> <resource>
<directory>src/main/appengine</directory> <directory>src/main/appengine</directory>
<targetPath>WEB-INF/</targetPath> <targetPath>WEB-INF/</targetPath>
<filtering>true</filtering> <filtering>true</filtering>
</resource> </resource>
</webResources> </webResources>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<executions> <executions>
<execution> <execution>
<id>integration</id> <id>integration</id>
<phase>integration-test</phase> <phase>integration-test</phase>
<goals> <goals>
<goal>test</goal> <goal>test</goal>
</goals> </goals>
<configuration> <configuration>
<systemProperties> <systemProperties>
<property> <property>
<name>appengine.home</name> <name>appengine.home</name>
<value>${appengine.home}</value> <value>${appengine.home}</value>
</property> </property>
<property> <property>
<name>devappserver.address</name> <name>devappserver.address</name>
<value>${devappserver.address}</value> <value>${devappserver.address}</value>
</property> </property>
<property> <property>
<name>devappserver.port</name> <name>devappserver.port</name>
<value>${devappserver.port}</value> <value>${devappserver.port}</value>
</property> </property>
<property> <property>
<name>warfile</name> <name>warfile</name>
<value>${project.build.directory}/${project.artifactId}</value> <value>${project.build.directory}/${project.artifactId}</value>
</property> </property>
</systemProperties> </systemProperties>
<additionalClasspathElements> <additionalClasspathElements>
<additionalClasspathElement>${appengine.home}/lib/appengine-tools-api.jar</additionalClasspathElement> <additionalClasspathElement>${appengine.home}/lib/appengine-tools-api.jar</additionalClasspathElement>
</additionalClasspathElements> </additionalClasspathElements>
<environmentVariables> <environmentVariables>
<DEBUG>true</DEBUG> <DEBUG>true</DEBUG>
<SDK_BIN>${appengine.home}/bin</SDK_BIN> <SDK_BIN>${appengine.home}/bin</SDK_BIN>
<SDK_LIB>${appengine.home}/lib</SDK_LIB> <SDK_LIB>${appengine.home}/lib</SDK_LIB>
<SDK_CONFIG>${appengine.home}/config/sdk</SDK_CONFIG> <SDK_CONFIG>${appengine.home}/config/sdk</SDK_CONFIG>
</environmentVariables> </environmentVariables>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<profiles> <profiles>
<profile> <profile>
<id>live</id> <id>live</id>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<executions> <executions>
<execution> <execution>
<id>integration</id> <id>integration</id>
<phase>integration-test</phase> <phase>integration-test</phase>
<goals> <goals>
<goal>test</goal> <goal>test</goal>
</goals> </goals>
<configuration> <configuration>
<systemProperties> <systemProperties>
<property> <property>
<name>twitter.identity</name> <name>twitter.identity</name>
<value>${jclouds.twitter.user}</value> <value>${jclouds.twitter.user}</value>
</property> </property>
<property> <property>
<name>twitter.credential</name> <name>twitter.credential</name>
<value>${jclouds.twitter.password}</value> <value>${jclouds.twitter.password}</value>
</property> </property>
<property> <property>
<name>azureblob.identity</name> <name>azureblob.identity</name>
<value>${jclouds.azure.storage.account}</value> <value>${jclouds.azure.storage.account}</value>
</property> </property>
<property> <property>
<name>azureblob.credential</name> <name>azureblob.credential</name>
<value>${jclouds.azure.storage.key}</value> <value>${jclouds.azure.storage.key}</value>
</property> </property>
<property> <property>
<name>cloudfiles.identity</name> <name>cloudfiles.identity</name>
<value>${jclouds.rackspace.user}</value> <value>${jclouds.rackspace.user}</value>
</property> </property>
<property> <property>
<name>cloudfiles.credential</name> <name>cloudfiles.credential</name>
<value>${jclouds.rackspace.key}</value> <value>${jclouds.rackspace.key}</value>
</property> </property>
<property> <property>
<name>s3.identity</name> <name>s3.identity</name>
<value>${jclouds.aws.accesskeyid}</value> <value>${jclouds.aws.accesskeyid}</value>
</property> </property>
<property> <property>
<name>s3.credential</name> <name>s3.credential</name>
<value>${jclouds.aws.secretaccesskey}</value> <value>${jclouds.aws.secretaccesskey}</value>
</property> </property>
<property> <property>
<name>googlestorage.identity</name> <name>googlestorage.identity</name>
<value>${jclouds.googlestorage.accesskeyid}</value> <value>${jclouds.googlestorage.accesskeyid}</value>
</property> </property>
<property> <property>
<name>googlestorage.credential</name> <name>googlestorage.credential</name>
<value>${jclouds.googlestorage.secretaccesskey}</value> <value>${jclouds.googlestorage.secretaccesskey}</value>
</property> </property>
<property> <property>
<name>appengine.home</name> <name>appengine.home</name>
<value>${appengine.home}</value> <value>${appengine.home}</value>
</property> </property>
<property> <property>
<name>devappserver.address</name> <name>devappserver.address</name>
<value>${devappserver.address}</value> <value>${devappserver.address}</value>
</property> </property>
<property> <property>
<name>devappserver.port</name> <name>devappserver.port</name>
<value>${devappserver.port}</value> <value>${devappserver.port}</value>
</property> </property>
<property> <property>
<name>jclouds.tweetstore.container</name> <name>jclouds.tweetstore.blobstores</name>
<value>${jclouds.tweetstore.container}</value> <value>${jclouds.tweetstore.blobstores}</value>
</property> </property>
<property> <property>
<name>warfile</name> <name>jclouds.tweetstore.container</name>
<value>${project.build.directory}/${project.artifactId}</value> <value>${jclouds.tweetstore.container}</value>
</property> </property>
</systemProperties> <property>
</configuration> <name>warfile</name>
</execution> <value>${project.build.directory}/${project.artifactId}</value>
</executions> </property>
</plugin> </systemProperties>
</plugins> </configuration>
</build> </execution>
</profile> </executions>
</profiles> </plugin>
</plugins>
</build>
</profile>
</profiles>
</project> </project>

View File

@ -63,8 +63,8 @@ public class StoreTweetsController extends HttpServlet {
public Blob apply(Status from) { public Blob apply(Status from) {
Blob to = map.newBlob(from.getId() + ""); Blob to = map.newBlob(from.getId() + "");
to.getMetadata().setContentType(MediaType.TEXT_PLAIN);
to.setPayload(from.getText()); to.setPayload(from.getText());
to.getPayload().setContentType(MediaType.TEXT_PLAIN);
to.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, from.getUser().getScreenName()); to.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, from.getUser().getScreenName());
return to; return to;
} }
@ -83,7 +83,7 @@ public class StoreTweetsController extends HttpServlet {
@Inject @Inject
@VisibleForTesting @VisibleForTesting
public StoreTweetsController(Map<String, BlobStoreContext> contexts, public StoreTweetsController(Map<String, BlobStoreContext> contexts,
@Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container, TwitterClient client) { @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container, TwitterClient client) {
this.container = container; this.container = container;
this.contexts = contexts; this.contexts = contexts;
this.client = client; this.client = client;
@ -92,7 +92,7 @@ public class StoreTweetsController extends HttpServlet {
@VisibleForTesting @VisibleForTesting
public void addMyTweets(String contextName, Set<Status> allAboutMe) { public void addMyTweets(String contextName, Set<Status> allAboutMe) {
BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in " BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in "
+ contexts.keySet()); + contexts.keySet());
BlobMap map = context.createBlobMap(container); BlobMap map = context.createBlobMap(container);
for (Status status : allAboutMe) { for (Status status : allAboutMe) {
Blob blob = null; Blob blob = null;
@ -110,7 +110,7 @@ public class StoreTweetsController extends HttpServlet {
@Override @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (request.getHeader("X-AppEngine-QueueName") != null if (request.getHeader("X-AppEngine-QueueName") != null
&& request.getHeader("X-AppEngine-QueueName").equals("twitter")) { && request.getHeader("X-AppEngine-QueueName").equals("twitter")) {
try { try {
String contextName = checkNotNull(request.getHeader("context"), "missing header context"); String contextName = checkNotNull(request.getHeader("context"), "missing header context");
logger.info("retrieving tweets"); logger.info("retrieving tweets");

View File

@ -54,7 +54,7 @@ public class GoogleDevServer {
}); });
server.start(); server.start();
Thread.sleep(10 * 1000); Thread.sleep(30 * 1000);
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")

View File

@ -38,6 +38,7 @@ import org.jclouds.blobstore.BlobStoreContextFactory;
import org.jclouds.demo.tweetstore.config.GuiceServletConfig; import org.jclouds.demo.tweetstore.config.GuiceServletConfig;
import org.jclouds.demo.tweetstore.controller.StoreTweetsController; import org.jclouds.demo.tweetstore.controller.StoreTweetsController;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.RestContextFactory; import org.jclouds.rest.RestContextFactory;
import org.jclouds.twitter.TwitterAsyncClient; import org.jclouds.twitter.TwitterAsyncClient;
@ -49,13 +50,14 @@ import org.testng.annotations.Parameters;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.inject.Module; import com.google.inject.Module;
/** /**
* Starts up the Google App Engine for Java Development environment and deploys an application which * Starts up the Google App Engine for Java Development environment and deploys
* tests accesses twitter and blobstores. * an application which tests accesses twitter and blobstores.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@ -66,8 +68,9 @@ public class TweetStoreLiveTest {
private URL url; private URL url;
private Map<String, BlobStoreContext> contexts; private Map<String, BlobStoreContext> contexts;
private String container; private String container;
private static final String blobs = System.getProperty("jclouds.tweetstore.blobstores",
private static final Iterable<String> blobstores = ImmutableSet.of("cloudfiles", "googlestorage", "s3", "azureblob"); "cloudfiles,googlestorage,s3,azureblob");
private static final Iterable<String> blobstores = Splitter.on(',').split(blobs);
private static final Properties props = new Properties(); private static final Properties props = new Properties();
@BeforeTest @BeforeTest
@ -75,7 +78,7 @@ public class TweetStoreLiveTest {
container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER)); container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER));
props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER), props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER),
PROPERTY_TWEETSTORE_CONTAINER)); PROPERTY_TWEETSTORE_CONTAINER));
props.setProperty(GuiceServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, Joiner.on(',').join(blobstores)); props.setProperty(GuiceServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, Joiner.on(',').join(blobstores));
@ -95,18 +98,22 @@ public class TweetStoreLiveTest {
} }
RestContext<TwitterClient, TwitterAsyncClient> twitterContext = new RestContextFactory().createContext("twitter", RestContext<TwitterClient, TwitterAsyncClient> twitterContext = new RestContextFactory().createContext("twitter",
wiring, props); wiring, props);
StoreTweetsController controller = new StoreTweetsController(contexts, container, twitterContext.getApi()); StoreTweetsController controller = new StoreTweetsController(contexts, container, twitterContext.getApi());
Set<Status> statuses = twitterContext.getApi().getMyMentions(); Set<Status> statuses = twitterContext.getApi().getMyMentions();
boolean deleted = false; boolean deleted = false;
for (BlobStoreContext context : contexts.values()) { for (BlobStoreContext context : contexts.values()) {
if (context.getBlobStore().containerExists(container)) { try {
System.err.printf("deleting container %s at %s%n", container, context.getProviderSpecificContext() if (context.getBlobStore().containerExists(container)) {
System.err.printf("deleting container %s at %s%n", container, context.getProviderSpecificContext()
.getEndpoint()); .getEndpoint());
context.getBlobStore().deleteContainer(container); context.getBlobStore().deleteContainer(container);
deleted = true; deleted = true;
}
} catch (AuthorizationException e) {
throw new AuthorizationException("for context: " + context, e);
} }
} }
if (deleted) { if (deleted) {
@ -115,7 +122,7 @@ public class TweetStoreLiveTest {
} }
for (BlobStoreContext context : contexts.values()) { for (BlobStoreContext context : contexts.values()) {
System.err.printf("creating container %s at %s%n", container, context.getProviderSpecificContext() System.err.printf("creating container %s at %s%n", container, context.getProviderSpecificContext()
.getEndpoint()); .getEndpoint());
context.getBlobStore().createContainerInLocation(null, container); context.getBlobStore().createContainerInLocation(null, container);
} }
@ -144,15 +151,15 @@ public class TweetStoreLiveTest {
String twitterCredential = checkNotNull(System.getProperty("twitter.credential"), "twitter.credential"); String twitterCredential = checkNotNull(System.getProperty("twitter.credential"), "twitter.credential");
props.putAll(RestContextFactory.toProperties(contextSpec("twitter", "http://twitter.com", "1", twitterIdentity, props.putAll(RestContextFactory.toProperties(contextSpec("twitter", "http://twitter.com", "1", twitterIdentity,
twitterCredential, TwitterClient.class, TwitterAsyncClient.class))); twitterCredential, TwitterClient.class, TwitterAsyncClient.class)));
} }
private void addCredentialsForBlobStores(Properties props) { private void addCredentialsForBlobStores(Properties props) {
for (String provider : blobstores) { for (String provider : blobstores) {
props.setProperty(provider + ".identity", checkNotNull(System.getProperty(provider + ".identity"), provider props.setProperty(provider + ".identity", checkNotNull(System.getProperty(provider + ".identity"), provider
+ ".identity")); + ".identity"));
props.setProperty(provider + ".credential", checkNotNull(System.getProperty(provider + ".credential"), props.setProperty(provider + ".credential", checkNotNull(System.getProperty(provider + ".credential"),
provider + ".credential")); provider + ".credential"));
} }
} }

View File

@ -97,8 +97,7 @@ public class ApacheHCUtils {
} }
public static void addEntityForContent(HttpEntityEnclosingRequest apacheRequest, Payload payload) { public static void addEntityForContent(HttpEntityEnclosingRequest apacheRequest, Payload payload) {
payload = payload instanceof DelegatingPayload ? DelegatingPayload.class.cast(payload) payload = payload instanceof DelegatingPayload ? DelegatingPayload.class.cast(payload).getDelegate() : payload;
.getDelegate() : payload;
if (payload instanceof StringPayload) { if (payload instanceof StringPayload) {
StringEntity nStringEntity = null; StringEntity nStringEntity = null;
try { try {
@ -109,17 +108,15 @@ public class ApacheHCUtils {
nStringEntity.setContentType(payload.getContentType()); nStringEntity.setContentType(payload.getContentType());
apacheRequest.setEntity(nStringEntity); apacheRequest.setEntity(nStringEntity);
} else if (payload instanceof FilePayload) { } else if (payload instanceof FilePayload) {
apacheRequest.setEntity(new FileEntity((File) payload.getRawContent(), payload apacheRequest.setEntity(new FileEntity((File) payload.getRawContent(), payload.getContentType()));
.getContentType()));
} else if (payload instanceof ByteArrayPayload) { } else if (payload instanceof ByteArrayPayload) {
ByteArrayEntity Entity = new ByteArrayEntity((byte[]) payload.getRawContent()); ByteArrayEntity Entity = new ByteArrayEntity((byte[]) payload.getRawContent());
Entity.setContentType(payload.getContentType()); Entity.setContentType(payload.getContentType());
apacheRequest.setEntity(Entity); apacheRequest.setEntity(Entity);
} else { } else {
InputStream inputStream = payload.getInput(); InputStream inputStream = payload.getInput();
if (!new Long(1).equals(payload.getContentLength())) if (payload.getContentLength() == null)
throw new IllegalArgumentException( throw new IllegalArgumentException("you must specify size when content is an InputStream");
"you must specify size when content is an InputStream");
InputStreamEntity Entity = new InputStreamEntity(inputStream, payload.getContentLength()); InputStreamEntity Entity = new InputStreamEntity(inputStream, payload.getContentLength());
Entity.setContentType(payload.getContentType()); Entity.setContentType(payload.getContentType());
apacheRequest.setEntity(Entity); apacheRequest.setEntity(Entity);

View File

@ -19,4 +19,4 @@
# #
# An extension to run jclouds on Google App Engine (http://code.google.com/appengine/). # An extension to run jclouds on Google App Engine (http://code.google.com/appengine/).
# #
# TODO: Usage example. # TODO: Usage example.

View File

@ -47,24 +47,24 @@
<dependency> <dependency>
<groupId>com.google.appengine</groupId> <groupId>com.google.appengine</groupId>
<artifactId>appengine-api</artifactId> <artifactId>appengine-api</artifactId>
<version>1.3.2</version> <version>1.3.5</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.appengine</groupId> <groupId>com.google.appengine</groupId>
<artifactId>appengine-api-stubs</artifactId> <artifactId>appengine-api-stubs</artifactId>
<version>1.3.2</version> <version>1.3.5</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.appengine</groupId> <groupId>com.google.appengine</groupId>
<artifactId>appengine-testing</artifactId> <artifactId>appengine-testing</artifactId>
<version>1.3.2</version> <version>1.3.5</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.appengine</groupId> <groupId>com.google.appengine</groupId>
<artifactId>appengine-local-runtime</artifactId> <artifactId>appengine-local-runtime</artifactId>
<version>1.3.2</version> <version>1.3.5</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -34,6 +34,7 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.encryption.EncryptionService; import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.io.Payload;
import com.google.appengine.api.urlfetch.FetchOptions; import com.google.appengine.api.urlfetch.FetchOptions;
import com.google.appengine.api.urlfetch.HTTPHeader; import com.google.appengine.api.urlfetch.HTTPHeader;
@ -48,7 +49,7 @@ import com.google.common.base.Function;
*/ */
@Singleton @Singleton
public class ConvertToGaeRequest implements Function<HttpRequest, HTTPRequest> { public class ConvertToGaeRequest implements Function<HttpRequest, HTTPRequest> {
public static final String USER_AGENT = "jclouds/1.0 urlfetch/1.3.2"; public static final String USER_AGENT = "jclouds/1.0 urlfetch/1.3.5";
private final EncryptionService encryptionService; private final EncryptionService encryptionService;
@ -58,8 +59,8 @@ public class ConvertToGaeRequest implements Function<HttpRequest, HTTPRequest> {
} }
/** /**
* byte [] content is replayable and the only content type supportable by GAE. As such, we * byte [] content is replayable and the only content type supportable by
* convert the original request content to a byte array. * GAE. As such, we convert the original request content to a byte array.
*/ */
@Override @Override
public HTTPRequest apply(HttpRequest request) { public HTTPRequest apply(HttpRequest request) {
@ -73,8 +74,7 @@ public class ConvertToGaeRequest implements Function<HttpRequest, HTTPRequest> {
FetchOptions options = disallowTruncate(); FetchOptions options = disallowTruncate();
options.doNotFollowRedirects(); options.doNotFollowRedirects();
HTTPRequest gaeRequest = new HTTPRequest(url, HTTPMethod.valueOf(request.getMethod() HTTPRequest gaeRequest = new HTTPRequest(url, HTTPMethod.valueOf(request.getMethod().toString()), options);
.toString()), options);
for (String header : request.getHeaders().keySet()) { for (String header : request.getHeaders().keySet()) {
for (String value : request.getHeaders().get(header)) { for (String value : request.getHeaders().get(header)) {
@ -84,15 +84,21 @@ public class ConvertToGaeRequest implements Function<HttpRequest, HTTPRequest> {
} }
gaeRequest.addHeader(new HTTPHeader(HttpHeaders.USER_AGENT, USER_AGENT)); gaeRequest.addHeader(new HTTPHeader(HttpHeaders.USER_AGENT, USER_AGENT));
/** /**
* byte [] content is replayable and the only content type supportable by GAE. As such, we * byte [] content is replayable and the only content type supportable by
* convert the original request content to a byte array. * GAE. As such, we convert the original request content to a byte array.
*/ */
if (request.getPayload() != null) { if (request.getPayload() != null) {
InputStream input = request.getPayload().getInput(); InputStream input = request.getPayload().getInput();
try { try {
byte[] array = toByteArray(input); byte[] array = toByteArray(input);
if (!request.getPayload().isRepeatable()) if (!request.getPayload().isRepeatable()) {
Payload oldPayload = request.getPayload();
request.setPayload(array); request.setPayload(array);
if (oldPayload.getContentMD5() != null)
request.getPayload().setContentMD5(oldPayload.getContentMD5());
if (oldPayload.getContentType() != null)
request.getPayload().setContentType(oldPayload.getContentType());
}
gaeRequest.setPayload(array); gaeRequest.setPayload(array);
} catch (IOException e) { } catch (IOException e) {
Throwables.propagate(e); Throwables.propagate(e);
@ -100,16 +106,15 @@ public class ConvertToGaeRequest implements Function<HttpRequest, HTTPRequest> {
closeQuietly(input); closeQuietly(input);
} }
if (request.getPayload().getContentMD5() != null) if (request.getPayload().getContentMD5() != null)
gaeRequest.addHeader(new HTTPHeader("Content-MD5", encryptionService.base64(request gaeRequest.setHeader(new HTTPHeader("Content-MD5", encryptionService.base64(request.getPayload()
.getPayload().getContentMD5()))); .getContentMD5())));
if (request.getPayload().getContentType() != null)
Long length = checkNotNull(request.getPayload().getContentLength(), gaeRequest.setHeader(new HTTPHeader(HttpHeaders.CONTENT_TYPE, request.getPayload().getContentType()));
"payload.getContentLength"); Long length = checkNotNull(request.getPayload().getContentLength(), "payload.getContentLength");
gaeRequest.addHeader(new HTTPHeader(HttpHeaders.CONTENT_LENGTH, length.toString())); gaeRequest.setHeader(new HTTPHeader(HttpHeaders.CONTENT_LENGTH, length.toString()));
} else { } else {
gaeRequest.addHeader(new HTTPHeader(HttpHeaders.CONTENT_LENGTH, "0")); gaeRequest.setHeader(new HTTPHeader(HttpHeaders.CONTENT_LENGTH, "0"));
} }
return gaeRequest; return gaeRequest;
} }
} }

View File

@ -37,6 +37,7 @@ import org.testng.annotations.BeforeTest;
import org.testng.annotations.Parameters; import org.testng.annotations.Parameters;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPRequest; import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.repackaged.com.google.common.base.Charsets; import com.google.appengine.repackaged.com.google.common.base.Charsets;
import com.google.common.io.Files; import com.google.common.io.Files;
@ -84,9 +85,10 @@ public class ConvertToGaeRequestTest {
HttpRequest request = new HttpRequest(HttpMethod.GET, endPoint); HttpRequest request = new HttpRequest(HttpMethod.GET, endPoint);
HTTPRequest gaeRequest = req.apply(request); HTTPRequest gaeRequest = req.apply(request);
assert gaeRequest.getPayload() == null; assert gaeRequest.getPayload() == null;
assertEquals(gaeRequest.getHeaders().size(), 2);// content length, user agent assertEquals(gaeRequest.getHeaders().size(), 2);// content length, user
// agent
assertEquals(gaeRequest.getHeaders().get(0).getName(), HttpHeaders.USER_AGENT); assertEquals(gaeRequest.getHeaders().get(0).getName(), HttpHeaders.USER_AGENT);
assertEquals(gaeRequest.getHeaders().get(0).getValue(), "jclouds/1.0 urlfetch/1.3.2"); assertEquals(gaeRequest.getHeaders().get(0).getValue(), "jclouds/1.0 urlfetch/1.3.5");
} }
@Test @Test
@ -129,15 +131,16 @@ public class ConvertToGaeRequestTest {
} }
private void testHoot(HttpRequest request) throws IOException { private void testHoot(HttpRequest request) throws IOException {
request.getHeaders().put(HttpHeaders.CONTENT_TYPE, "text/plain"); request.getPayload().setContentType("text/plain");
request.getPayload().setContentMD5(new byte[] { 1, 2, 3, 4 });
HTTPRequest gaeRequest = req.apply(request); HTTPRequest gaeRequest = req.apply(request);
try {
assertEquals(gaeRequest.getHeaders().get(0).getName(), HttpHeaders.CONTENT_TYPE); StringBuilder builder = new StringBuilder();
assertEquals(gaeRequest.getHeaders().get(0).getValue(), "text/plain"); for (HTTPHeader header : gaeRequest.getHeaders()) {
} catch (AssertionError e) { builder.append(header.getName()).append(": ").append(header.getValue()).append("\n");
assertEquals(gaeRequest.getHeaders().get(1).getName(), HttpHeaders.CONTENT_TYPE);
assertEquals(gaeRequest.getHeaders().get(1).getValue(), "text/plain");
} }
assertEquals(builder.toString(),
"User-Agent: jclouds/1.0 urlfetch/1.3.5\nContent-MD5: AQIDBA==\nContent-Type: text/plain\nContent-Length: 5\n");
assertEquals(new String(gaeRequest.getPayload()), "hoot!"); assertEquals(new String(gaeRequest.getPayload()), "hoot!");
} }
} }