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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,17 +24,17 @@
package org.jclouds.samples.googleappengine;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
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.aws.AWSResponseException;
import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.logging.Logger;
@ -69,32 +69,24 @@ public class JCloudsServlet extends HttpServlet {
protected Logger logger = Logger.NULL;
@Override
protected void doGet(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws ServletException, IOException {
httpServletResponse.setContentType("text/plain");
Writer writer = httpServletResponse.getWriter();
writer.write(className + "\n");
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
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);
writer.write("List:\n");
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");
}
myBuckets.add(bucket);
}
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) {
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
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
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.
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">
@ -45,4 +43,9 @@
<listener>
<listener-class>org.jclouds.samples.googleappengine.config.GuiceServletConfig</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

View File

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

View File

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