updated google app engine sample

git-svn-id: http://jclouds.googlecode.com/svn/trunk@1089 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-06-08 00:49:23 +00:00
parent bf3ba3e855
commit 9cec8159d4
10 changed files with 401 additions and 354 deletions

View File

@ -30,33 +30,27 @@ import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
/** /**
* A container that provides namespace, access control and aggregation of * A container that provides namespace, access control and aggregation of {@link S3Object}s
* {@link S3Object}s
* <p/> * <p/>
* <p/> * <p/>
* Every object stored in Amazon S3 is contained in a bucket. Buckets partition * Every object stored in Amazon S3 is contained in a bucket. Buckets partition the namespace of
* the namespace of objects stored in Amazon S3 at the top level. Within a * objects stored in Amazon S3 at the top level. Within a bucket, you can use any names for your
* bucket, you can use any names for your objects, but bucket names must be * objects, but bucket names must be unique across all of Amazon S3.
* unique across all of Amazon S3.
* <p/> * <p/>
* Buckets are similar to Internet domain names. Just as Amazon is the only * Buckets are similar to Internet domain names. Just as Amazon is the only owner of the domain name
* owner of the domain name Amazon.com, only one person or organization can own * Amazon.com, only one person or organization can own a bucket within Amazon S3. Once you create a
* a bucket within Amazon S3. Once you create a uniquely named bucket in Amazon * uniquely named bucket in Amazon S3, you can organize and name the objects within the bucket in
* S3, you can organize and name the objects within the bucket in any way you * any way you like and the bucket will remain yours for as long as you like and as long as you have
* like and the bucket will remain yours for as long as you like and as long as * the Amazon S3 account.
* you have the Amazon S3 account.
* <p/> * <p/>
* The similarities between buckets and domain names is not a coincidenceÑthere * The similarities between buckets and domain names is not a coincidenceÑthere is a direct mapping
* is a direct mapping between Amazon S3 buckets and subdomains of * between Amazon S3 buckets and subdomains of s3.amazonaws.com. Objects stored in Amazon S3 are
* s3.amazonaws.com. Objects stored in Amazon S3 are addressable using the REST * addressable using the REST API under the domain bucketname.s3.amazonaws.com. For example, if the
* API under the domain bucketname.s3.amazonaws.com. For example, if the object * object homepage.html?is stored in the Amazon S3 bucket mybucket its address would be
* homepage.html?is stored in the Amazon S3 bucket mybucket its address would be
* http://mybucket.s3.amazonaws.com/homepage.html? * http://mybucket.s3.amazonaws.com/homepage.html?
* *
* @author Adrian Cole * @author Adrian Cole
* @see <a * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html" />
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html"
* />
*/ */
public class S3Bucket { public class S3Bucket {
@Override @Override
@ -82,8 +76,7 @@ public class S3Bucket {
return false; return false;
if (!metadata.equals(s3Bucket.metadata)) if (!metadata.equals(s3Bucket.metadata))
return false; return false;
if (objects != null ? !objects.equals(s3Bucket.objects) if (objects != null ? !objects.equals(s3Bucket.objects) : s3Bucket.objects != null)
: s3Bucket.objects != null)
return false; return false;
return true; return true;
@ -122,8 +115,7 @@ public class S3Bucket {
return false; return false;
Metadata metadata = (Metadata) o; Metadata metadata = (Metadata) o;
if (canonicalUser != null ? !canonicalUser if (canonicalUser != null ? !canonicalUser.equals(metadata.canonicalUser)
.equals(metadata.canonicalUser)
: metadata.canonicalUser != null) : metadata.canonicalUser != null)
return false; return false;
if (!name.equals(metadata.name)) if (!name.equals(metadata.name))
@ -135,8 +127,7 @@ public class S3Bucket {
@Override @Override
public int hashCode() { public int hashCode() {
int result = name.hashCode(); int result = name.hashCode();
result = 31 * result result = 31 * result + (canonicalUser != null ? canonicalUser.hashCode() : 0);
+ (canonicalUser != null ? canonicalUser.hashCode() : 0);
return result; return result;
} }
@ -145,8 +136,7 @@ public class S3Bucket {
* *
* @author Adrian Cole * @author Adrian Cole
* @see <a href= * @see <a href=
* "http://docs.amazonwebservices.com/AmazonS3/latest/RESTBucketLocationGET.html" * "http://docs.amazonwebservices.com/AmazonS3/latest/RESTBucketLocationGET.html" />
* />
*/ */
public static enum LocationConstraint { public static enum LocationConstraint {
EU EU
@ -166,8 +156,7 @@ public class S3Bucket {
/** /**
* To comply with Amazon S3 requirements, bucket names must: * To comply with Amazon S3 requirements, bucket names must:
* <p/> * <p/>
* Contain lowercase letters, numbers, periods (.), underscores (_), and * Contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)
* dashes (-)
* <p/> * <p/>
* Start with a number or letter * Start with a number or letter
* <p/> * <p/>
@ -188,10 +177,9 @@ public class S3Bucket {
} }
/** /**
* Every bucket and object in Amazon S3 has an owner, the user that * Every bucket and object in Amazon S3 has an owner, the user that created the bucket or
* created the bucket or object. The owner of a bucket or object cannot * object. The owner of a bucket or object cannot be changed. However, if the object is
* be changed. However, if the object is overwritten by another user * overwritten by another user (deleted and rewritten), the new object will have a new owner.
* (deleted and rewritten), the new object will have a new owner.
*/ */
public CanonicalUser getOwner() { public CanonicalUser getOwner() {
return canonicalUser; return canonicalUser;
@ -234,6 +222,10 @@ public class S3Bucket {
return objects; return objects;
} }
public long getSize() {
return objects.size();
}
public void setContents(SortedSet<S3Object.Metadata> objects) { public void setContents(SortedSet<S3Object.Metadata> objects) {
this.objects = objects; this.objects = objects;
} }
@ -267,8 +259,8 @@ public class S3Bucket {
* a/2/a<br/> * a/2/a<br/>
* a/2/b<br/> * a/2/b<br/>
* <p/> * <p/>
* and prefix is set to <code>a/</code> and delimiter is set to * and prefix is set to <code>a/</code> and delimiter is set to <code>/</code> then
* <code>/</code> then commonprefixes would return 1,2 * commonprefixes would return 1,2
* *
* @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getPrefix() * @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getPrefix()
*/ */
@ -306,8 +298,7 @@ public class S3Bucket {
} }
/** /**
* when set, bucket contains results whose keys are lexigraphically after * when set, bucket contains results whose keys are lexigraphically after marker.
* marker.
* *
* @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getMarker() * @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getMarker()
*/ */
@ -320,12 +311,10 @@ public class S3Bucket {
} }
/** /**
* when set, bucket results will not contain keys that have text following * when set, bucket results will not contain keys that have text following this delimiter.
* this delimiter.
* <p/> * <p/>
* note that delimiter has no effect on prefix. prefix can contain the * note that delimiter has no effect on prefix. prefix can contain the delimiter many times, or
* delimiter many times, or not at all. delimiter only restricts after the * not at all. delimiter only restricts after the prefix.
* prefix.
* *
* @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getMarker() * @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getMarker()
*/ */

View File

@ -163,16 +163,13 @@ public class S3IntegrationTest {
} }
protected void createStubS3Context() { protected void createStubS3Context() {
context = S3ContextFactory.createContext("stub", "stub") context = S3ContextFactory.createContext("stub", "stub").withHttpAddress("stub").withModule(
.withHttpAddress("stub") new StubS3ConnectionModule()).build();
.withModule(new StubS3ConnectionModule())
.build();
} }
protected void createLiveS3Context(String AWSAccessKeyId, String AWSSecretAccessKey) { protected void createLiveS3Context(String AWSAccessKeyId, String AWSSecretAccessKey) {
context = buildS3ContextFactory(AWSAccessKeyId, AWSSecretAccessKey) context = buildS3ContextFactory(AWSAccessKeyId, AWSSecretAccessKey).withModule(
.withModule(createHttpModule()) createHttpModule()).build();
.build();
} }
@BeforeMethod(dependsOnMethods = "deleteBucket", groups = { "integration", "live" }) @BeforeMethod(dependsOnMethods = "deleteBucket", groups = { "integration", "live" })
@ -194,9 +191,8 @@ public class S3IntegrationTest {
} }
protected S3ContextFactory buildS3ContextFactory(String AWSAccessKeyId, String AWSSecretAccessKey) { protected S3ContextFactory buildS3ContextFactory(String AWSAccessKeyId, String AWSSecretAccessKey) {
return S3ContextFactory.createContext(AWSAccessKeyId, AWSSecretAccessKey) return S3ContextFactory.createContext(AWSAccessKeyId, AWSSecretAccessKey).withHttpSecure(
.withHttpSecure(false) false).withHttpPort(80);
.withHttpPort(80);
} }
protected Module createHttpModule() { protected Module createHttpModule() {
@ -226,8 +222,7 @@ public class S3IntegrationTest {
* @throws TimeoutException * @throws TimeoutException
*/ */
protected void emptyBucket(String name) throws InterruptedException, ExecutionException, protected void emptyBucket(String name) throws InterruptedException, ExecutionException,
TimeoutException TimeoutException {
{
if (client.bucketExists(name).get(10, TimeUnit.SECONDS)) { if (client.bucketExists(name).get(10, TimeUnit.SECONDS)) {
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>(); List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
@ -251,9 +246,8 @@ public class S3IntegrationTest {
* @throws ExecutionException * @throws ExecutionException
* @throws TimeoutException * @throws TimeoutException
*/ */
private void deleteBucket(String name) throws InterruptedException, ExecutionException, protected void deleteBucket(String name) throws InterruptedException, ExecutionException,
TimeoutException TimeoutException {
{
if (client.bucketExists(name).get(10, TimeUnit.SECONDS)) { if (client.bucketExists(name).get(10, TimeUnit.SECONDS)) {
emptyBucket(name); emptyBucket(name);
client.deleteBucketIfEmpty(name).get(10, TimeUnit.SECONDS); client.deleteBucketIfEmpty(name).get(10, TimeUnit.SECONDS);

View File

@ -23,29 +23,26 @@
*/ */
package org.jclouds.aws.s3.xml; package org.jclouds.aws.s3.xml;
import org.jclouds.aws.s3.xml.config.S3ParserModule;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import org.jclouds.aws.s3.xml.config.S3ParserModule;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
public class BaseHandlerTest { public class BaseHandlerTest {
protected S3ParserFactory parserFactory = null; protected S3ParserFactory parserFactory = null;
private Injector injector; private Injector injector;
public BaseHandlerTest() { @BeforeTest
super();
}
@BeforeMethod
protected void setUpInjector() { protected void setUpInjector() {
injector = Guice.createInjector(new S3ParserModule()); injector = Guice.createInjector(new S3ParserModule());
parserFactory = injector.getInstance(S3ParserFactory.class); parserFactory = injector.getInstance(S3ParserFactory.class);
assert parserFactory != null; assert parserFactory != null;
} }
@AfterMethod @AfterTest
protected void tearDownInjector() { protected void tearDownInjector() {
parserFactory = null; parserFactory = null;
injector = null; injector = null;

View File

@ -23,6 +23,8 @@
*/ */
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.createIn;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
@ -36,7 +38,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import org.jclouds.aws.s3.S3IntegrationTest; import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.testng.annotations.AfterTest; import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -61,19 +63,39 @@ public abstract class BasePerformance extends S3IntegrationTest {
protected ExecutorService exec; protected ExecutorService exec;
protected CompletionService<Boolean> completer; protected CompletionService<Boolean> completer;
protected String bucketNameEU;
@BeforeTest @BeforeTest
protected void setUpCallables() { protected void setUpCallables() throws InterruptedException, ExecutionException,
TimeoutException {
exec = Executors.newCachedThreadPool(); exec = Executors.newCachedThreadPool();
completer = new ExecutorCompletionService<Boolean>(exec); completer = new ExecutorCompletionService<Boolean>(exec);
bucketNameEU = (bucketPrefix).toLowerCase() + ".eu";
} }
@AfterTest @AfterTest
protected void tearDownExecutor() throws Exception { protected void tearDownExecutor() throws Exception {
if (bucketNameEU != null)
deleteBucket(bucketNameEU);
exec.shutdownNow(); exec.shutdownNow();
exec = null; exec = null;
} }
@Test(enabled = true)
public void testPutBytesSerialEU() throws Exception {
client.putBucketIfNotExists(bucketNameEU, createIn(LocationConstraint.EU)).get(10,
TimeUnit.SECONDS);
doSerial(new PutBytesCallable(this.bucketNameEU), loopCount / 10);
}
@Test(enabled = true)
public void testPutBytesParallelEU() throws InterruptedException, ExecutionException,
TimeoutException {
client.putBucketIfNotExists(bucketNameEU, createIn(LocationConstraint.EU)).get(10,
TimeUnit.SECONDS);
doParallel(new PutBytesCallable(this.bucketNameEU), loopCount);
}
@Test(enabled = true) @Test(enabled = true)
public void testPutBytesSerial() throws Exception { public void testPutBytesSerial() throws Exception {
doSerial(new PutBytesCallable(this.bucketName), loopCount / 10); doSerial(new PutBytesCallable(this.bucketName), loopCount / 10);

View File

@ -56,6 +56,11 @@
<artifactId>guice-servlet</artifactId> <artifactId>guice-servlet</artifactId>
<version>2.0</version> <version>2.0</version>
</dependency> </dependency>
<dependency>
<groupId>displaytag</groupId>
<artifactId>displaytag</artifactId>
<version>1.2</version>
</dependency>
<dependency> <dependency>
<artifactId>standard</artifactId> <artifactId>standard</artifactId>
<groupId>taglibs</groupId> <groupId>taglibs</groupId>

View File

@ -24,17 +24,17 @@
package org.jclouds.samples.googleappengine; package org.jclouds.samples.googleappengine;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.s3.S3Context; import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -69,32 +69,24 @@ public class JCloudsServlet extends HttpServlet {
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@Override @Override
protected void doGet(HttpServletRequest httpServletRequest, protected void doGet(HttpServletRequest request, HttpServletResponse response)
HttpServletResponse httpServletResponse) throws ServletException, IOException { throws ServletException, IOException {
httpServletResponse.setContentType("text/plain");
Writer writer = httpServletResponse.getWriter();
writer.write(className + "\n");
try { try {
List<S3Bucket.Metadata> myBuckets = context.getConnection().listOwnedBuckets().get(10, List<S3Bucket.Metadata> myBucketMetadata = context.getConnection().listOwnedBuckets().get(
25, TimeUnit.SECONDS);
List<S3Bucket> myBuckets = new ArrayList<S3Bucket>();
for (S3Bucket.Metadata metadata : myBucketMetadata) {
S3Bucket bucket = context.getConnection().listBucket(metadata.getName()).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
writer.write("List:\n"); myBuckets.add(bucket);
for (S3Bucket.Metadata bucket : myBuckets) {
writer.write(String.format(" %1$s", bucket));
try {
writer.write(String.format(": %1$s entries%n", context.createInputStreamMap(
bucket.getName()).size()));
} catch (AWSResponseException e) {
String message = String.format(": unable to list entries due to: %1$s%n", e
.getError().getCode());
writer.write(message);
logger.warn(e, "message");
}
} }
request.setAttribute("buckets", myBuckets);
request.setAttribute("className", className);
String nextJSP = "/WEB-INF/jsp/buckets.jsp";
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(nextJSP);
dispatcher.forward(request, response);
} catch (Exception e) { } catch (Exception e) {
throw new ServletException(e); throw new ServletException(e);
} }
writer.flush();
writer.close();
} }
} }

View File

@ -0,0 +1,39 @@
<%--
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.
====================================================================
--%>
<%@ page buffer="20kb"%>
<%@ taglib uri="http://displaytag.sf.net" prefix="display"%>
<html>
<head>
<title>jclouds: anyweight cloudware for java</title>
</head>
<body>
<h2>Bucket List</h2>
<display:table name="buckets">
<display:column property="name" title="Bucket" />
<display:column property="size" title="Size" />
</display:table>
</body>
</html>

View File

@ -1,28 +1,26 @@
<!--
<!--
Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> Copyright (C) 2009 Global Cloud Specialists, Inc.
<info@globalcloudspecialists.com>
==================================================================== ====================================================================
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one or more
or more contributor license agreements. See the NOTICE file contributor license agreements. See the NOTICE file distributed with
distributed with this work for additional information this work for additional information regarding copyright ownership.
regarding copyright ownership. The ASF licenses this file The ASF licenses this file to you under the Apache License, Version
to you under the Apache License, Version 2.0 (the 2.0 (the "License"); you may not use this file except in compliance
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0 Unless required by
applicable law or agreed to in writing, software distributed under the
Unless required by applicable law or agreed to in writing, License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
software distributed under the License is distributed on an CONDITIONS OF ANY KIND, either express or implied. See the License for
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY the specific language governing permissions and limitations under the
KIND, either express or implied. See the License for the License.
specific language governing permissions and limitations
under the License.
==================================================================== ====================================================================
-->
-->
<!DOCTYPE web-app PUBLIC <!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd"> "http://java.sun.com/dtd/web-app_2_3.dtd">
@ -45,4 +43,9 @@
<listener> <listener>
<listener-class>org.jclouds.samples.googleappengine.config.GuiceServletConfig</listener-class> <listener-class>org.jclouds.samples.googleappengine.config.GuiceServletConfig</listener-class>
</listener> </listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app> </web-app>

View File

@ -24,7 +24,13 @@
--%> --%>
<html> <html>
<head>
<title>jclouds: anyweight cloudware for java</title>
</head>
<body> <body>
<h2>Hello World!</h2> <h2>Welcome!</h2>
Click
<a href="/guice/listbuckets.s3">here</a>
to list my buckets.
</body> </body>
</html> </html>

View File

@ -81,7 +81,7 @@ public class GoogleAppEngineLiveTest {
public void shouldPass() throws InterruptedException, IOException { public void shouldPass() throws InterruptedException, IOException {
InputStream i = url.openStream(); InputStream i = url.openStream();
String string = IOUtils.toString(i); String string = IOUtils.toString(i);
assert string.indexOf("Hello World!") >= 0 : string; assert string.indexOf("Welcome") >= 0 : string;
} }
@Test(invocationCount = 5, enabled = true) @Test(invocationCount = 5, enabled = true)