From 67683084ff63145b91a04f3e690cc39e8dde656f Mon Sep 17 00:00:00 2001 From: "adrian.f.cole" Date: Sun, 10 May 2009 19:52:55 +0000 Subject: [PATCH] finished creating integration tests for all functionality needed for beta. fixed bad logging formats, added javadoc git-svn-id: http://jclouds.googlecode.com/svn/trunk@643 3d8758e0-26b5-11de-8745-db77d3ebf521 --- .../pool/FutureCommandConnectionHandle.java | 4 +- .../pool/FutureCommandConnectionPool.java | 14 +- .../FutureCommandConnectionPoolClient.java | 6 +- .../http/BaseHttpFutureCommandClient.java | 2 +- .../CloseContentAndSetExceptionHandler.java | 14 +- .../java/org/jclouds/http/HttpHeaders.java | 7 + .../java/org/jclouds/http/HttpRequest.java | 2 +- .../jclouds/http/HttpResponseException.java | 88 ++++++++ .../http/JavaUrlHttpFutureCommandClient.java | 6 +- .../commands/callables/ReturnStringIf200.java | 4 +- .../org/jclouds/lifecycle/BaseLifeCycle.java | 8 +- .../http/BaseHttpFutureCommandClientTest.java | 6 +- .../HttpNioFutureCommandConnectionHandle.java | 2 +- .../HttpNioFutureCommandConnectionPool.java | 30 +-- .../HttpNioFutureCommandExecutionHandler.java | 10 +- .../aws/s3/jets3t/JCloudsS3Service.java | 11 +- .../aws/s3/jets3t/JCloudsS3ServiceTest.java | 6 +- .../com/amazon/s3/AmazonPerformanceTest.java | 3 +- .../com/amazon/s3/BaseJCloudsPerformance.java | 10 +- .../java/com/amazon/s3/BasePerformance.java | 5 +- .../java/com/amazon/s3/DateServiceTest.java | 2 +- .../test/java/com/amazon/s3/S3ParserTest.java | 2 +- .../java/org/jclouds/aws/s3/S3Connection.java | 118 +++++++--- .../java/org/jclouds/aws/s3/S3Context.java | 16 +- .../org/jclouds/aws/s3/S3ContextFactory.java | 14 +- .../org/jclouds/aws/s3/S3InputStreamMap.java | 15 +- .../main/java/org/jclouds/aws/s3/S3Map.java | 15 +- .../java/org/jclouds/aws/s3/S3ObjectMap.java | 15 +- .../jclouds/aws/s3/S3ResponseException.java | 55 +++-- .../jclouds/aws/s3/commands/BucketExists.java | 13 +- .../jclouds/aws/s3/commands/CopyObject.java | 25 ++- .../jclouds/aws/s3/commands/DeleteBucket.java | 15 +- .../jclouds/aws/s3/commands/DeleteObject.java | 8 + .../jclouds/aws/s3/commands/GetObject.java | 22 +- .../{HeadMetaData.java => HeadObject.java} | 23 +- .../jclouds/aws/s3/commands/ListBucket.java | 19 +- ...wnedBuckets.java => ListOwnedBuckets.java} | 7 +- .../jclouds/aws/s3/commands/PutBucket.java | 11 +- .../jclouds/aws/s3/commands/PutObject.java | 50 +++-- .../aws/s3/commands/S3CommandFactory.java | 14 +- .../callables/ParseMd5FromETagHeader.java | 5 +- .../callables/ParseMetadataFromHeaders.java | 68 +++--- .../ParseObjectFromHeadersAndHttpContent.java | 37 ++-- .../s3/commands/config/S3CommandsModule.java | 8 +- .../commands/options/CopyObjectOptions.java | 42 +++- .../s3/commands/options/GetObjectOptions.java | 107 ++++++--- .../s3/commands/options/PutBucketOptions.java | 7 +- .../s3/commands/options/PutObjectOptions.java | 3 +- .../aws/s3/config/S3ContextModule.java | 6 +- .../{S3Owner.java => CanonicalUser.java} | 60 ++++-- .../org/jclouds/aws/s3/domain/S3Bucket.java | 49 +++-- .../org/jclouds/aws/s3/domain/S3Error.java | 125 ++++++----- .../org/jclouds/aws/s3/domain/S3Object.java | 97 ++++++--- .../filters/ParseS3ErrorFromXmlContent.java | 42 ++-- .../s3/filters/RequestAuthorizeSignature.java | 7 +- .../jclouds/aws/s3/internal/BaseS3Map.java | 19 +- .../aws/s3/internal/LiveS3Connection.java | 20 +- .../aws/s3/internal/LiveS3InputStreamMap.java | 6 +- .../aws/s3/internal/LiveS3ObjectMap.java | 6 +- .../java/org/jclouds/aws/s3/package-info.java | 7 + .../aws/s3/{ => reference}/S3Constants.java | 2 +- .../aws/s3/{ => reference}/S3Headers.java | 14 +- .../aws/s3/{ => util}/DateService.java | 2 +- .../jclouds/aws/s3/{ => util}/S3Utils.java | 4 +- .../jclouds/aws/s3/xml/CopyObjectHandler.java | 14 +- .../org/jclouds/aws/s3/xml/ErrorHandler.java | 17 +- .../aws/s3/xml/ListAllMyBucketsHandler.java | 26 +-- .../jclouds/aws/s3/xml/ListBucketHandler.java | 65 +++--- .../jclouds/aws/s3/xml/S3ParserFactory.java | 20 +- .../aws/s3/xml/config/S3ParserModule.java | 59 ++--- .../org/jclouds/aws/s3/S3ConnectionTest.java | 2 +- .../org/jclouds/aws/s3/S3IntegrationTest.java | 18 +- .../org/jclouds/aws/s3/S3ObjectMapTest.java | 3 +- .../java/org/jclouds/aws/s3/S3UtilsTest.java | 1 + .../org/jclouds/aws/s3/StubS3Connection.java | 10 +- .../commands/CopyObjectIntegrationTest.java | 45 ++-- .../commands/DeleteBucketIntegrationTest.java | 64 ++++++ .../commands/DeleteObjectIntegrationTest.java | 78 +++++++ .../s3/commands/GetObjectIntegrationTest.java | 204 +++++++++++++++--- .../ListOwnedBucketsIntegrationTest.java | 66 ++++++ .../s3/commands/PutBucketIntegrationTest.java | 8 +- .../s3/commands/PutObjectIntegrationTest.java | 45 ++-- .../aws/s3/commands/S3CommandFactoryTest.java | 28 +-- .../jclouds/aws/s3/commands/S3ParserTest.java | 24 +-- .../callables/DeleteBucketCallableTest.java | 92 -------- ...seObjectFromHeadersAndHttpContentTest.java | 77 +++++++ .../options/CopyObjectOptionsTest.java | 29 ++- .../options/GetObjectOptionsTest.java | 80 +++++-- .../options/PutBucketOptionsTest.java | 3 +- .../options/PutObjectOptionsTest.java | 3 +- .../aws/s3/config/S3ContextModuleTest.java | 6 +- .../jclouds/aws/s3/domain/S3ObjectTest.java | 2 +- .../RequestAuthorizeSignatureTest.java | 6 +- .../jclouds/aws/s3/xml/ErrorHandlerTest.java | 7 +- samples/googleappengine/README.txt | 54 ----- samples/googleappengine/pom.xml | 194 ----------------- .../functest/BaseGoogleAppEngineTest.java | 75 ------- .../functest/GoogleAppEngineTest.java | 100 --------- .../googleappengine/JCloudsServlet.java | 75 ------- .../config/GuiceServletConfig.java | 99 --------- .../src/main/webapp/WEB-INF/appengine-web.xml | 30 --- .../src/main/webapp/WEB-INF/web.xml | 48 ----- .../googleappengine/src/main/webapp/index.jsp | 30 --- 103 files changed, 1758 insertions(+), 1489 deletions(-) create mode 100644 core/src/main/java/org/jclouds/http/HttpResponseException.java rename s3/src/main/java/org/jclouds/aws/s3/commands/{HeadMetaData.java => HeadObject.java} (76%) rename s3/src/main/java/org/jclouds/aws/s3/commands/{GetMetaDataForOwnedBuckets.java => ListOwnedBuckets.java} (84%) rename s3/src/main/java/org/jclouds/aws/s3/domain/{S3Owner.java => CanonicalUser.java} (51%) create mode 100644 s3/src/main/java/org/jclouds/aws/s3/package-info.java rename s3/src/main/java/org/jclouds/aws/s3/{ => reference}/S3Constants.java (97%) rename s3/src/main/java/org/jclouds/aws/s3/{ => reference}/S3Headers.java (79%) rename s3/src/main/java/org/jclouds/aws/s3/{ => util}/DateService.java (98%) rename s3/src/main/java/org/jclouds/aws/s3/{ => util}/S3Utils.java (98%) create mode 100644 s3/src/test/java/org/jclouds/aws/s3/commands/DeleteBucketIntegrationTest.java create mode 100644 s3/src/test/java/org/jclouds/aws/s3/commands/DeleteObjectIntegrationTest.java create mode 100644 s3/src/test/java/org/jclouds/aws/s3/commands/ListOwnedBucketsIntegrationTest.java delete mode 100644 s3/src/test/java/org/jclouds/aws/s3/commands/callables/DeleteBucketCallableTest.java create mode 100644 s3/src/test/java/org/jclouds/aws/s3/commands/callables/ParseObjectFromHeadersAndHttpContentTest.java delete mode 100644 samples/googleappengine/README.txt delete mode 100644 samples/googleappengine/pom.xml delete mode 100644 samples/googleappengine/src/it/java/org/jclouds/samples/googleappengine/functest/BaseGoogleAppEngineTest.java delete mode 100644 samples/googleappengine/src/it/java/org/jclouds/samples/googleappengine/functest/GoogleAppEngineTest.java delete mode 100644 samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/JCloudsServlet.java delete mode 100644 samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/config/GuiceServletConfig.java delete mode 100644 samples/googleappengine/src/main/webapp/WEB-INF/appengine-web.xml delete mode 100644 samples/googleappengine/src/main/webapp/WEB-INF/web.xml delete mode 100644 samples/googleappengine/src/main/webapp/index.jsp diff --git a/core/src/main/java/org/jclouds/command/pool/FutureCommandConnectionHandle.java b/core/src/main/java/org/jclouds/command/pool/FutureCommandConnectionHandle.java index e0d023abf8..035cc77d74 100644 --- a/core/src/main/java/org/jclouds/command/pool/FutureCommandConnectionHandle.java +++ b/core/src/main/java/org/jclouds/command/pool/FutureCommandConnectionHandle.java @@ -73,7 +73,7 @@ public abstract class FutureCommandConnectionHandle command = getCommandFromConnection(connection); if (command != null) { - logger.warn(e, "exception in command: %1s", command); + logger.warn(e, "exception in command: %1$s", command); command.setException(e); } } diff --git a/core/src/main/java/org/jclouds/command/pool/FutureCommandConnectionPoolClient.java b/core/src/main/java/org/jclouds/command/pool/FutureCommandConnectionPoolClient.java index 1fe4fc4cf2..272e8c2356 100644 --- a/core/src/main/java/org/jclouds/command/pool/FutureCommandConnectionPoolClient.java +++ b/core/src/main/java/org/jclouds/command/pool/FutureCommandConnectionPoolClient.java @@ -104,13 +104,13 @@ public class FutureCommandConnectionPoolClient= 500) { - logger.info("resubmitting command: %1s", command); + logger.info("resubmitting command: %1$s", command); return true; } return false; diff --git a/core/src/main/java/org/jclouds/http/CloseContentAndSetExceptionHandler.java b/core/src/main/java/org/jclouds/http/CloseContentAndSetExceptionHandler.java index 59a741167e..5ac044fce5 100644 --- a/core/src/main/java/org/jclouds/http/CloseContentAndSetExceptionHandler.java +++ b/core/src/main/java/org/jclouds/http/CloseContentAndSetExceptionHandler.java @@ -25,7 +25,7 @@ package org.jclouds.http; import java.io.IOException; -import org.apache.commons.io.IOUtils; +import org.jclouds.Utils; /** * @@ -34,9 +34,13 @@ import org.apache.commons.io.IOUtils; public class CloseContentAndSetExceptionHandler implements HttpResponseHandler { public void handle(HttpFutureCommand command, HttpResponse response) { - String message = String.format("Command: %2s failed; response: %1s", - response, command); - command.setException(new IOException(message)); - IOUtils.closeQuietly(response.getContent()); + String content; + try { + content = Utils.toStringAndClose(response.getContent()); + command.setException(new HttpResponseException(command, response, + content)); + } catch (IOException e) { + command.setException(new HttpResponseException(command, response)); + } } } diff --git a/core/src/main/java/org/jclouds/http/HttpHeaders.java b/core/src/main/java/org/jclouds/http/HttpHeaders.java index d1b201f3c7..9c3fe96556 100644 --- a/core/src/main/java/org/jclouds/http/HttpHeaders.java +++ b/core/src/main/java/org/jclouds/http/HttpHeaders.java @@ -78,5 +78,12 @@ public interface HttpHeaders { public static final String TRANSFER_ENCODING = "Transfer-Encoding"; public static final String LAST_MODIFIED = "Last-Modified"; public static final String SERVER = "Server"; + public static final String ETAG = "ETag"; + public static final String RANGE = "Range"; + public static final String IF_MODIFIED_SINCE = "If-Modified-Since"; + public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since"; + public static final String IF_MATCH = "If-Match"; + public static final String IF_NONE_MATCH = "If-None-Match"; + public static final String CONTENT_RANGE = "Content-Range"; } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/HttpRequest.java b/core/src/main/java/org/jclouds/http/HttpRequest.java index c4bbccac78..2a03bb7c99 100644 --- a/core/src/main/java/org/jclouds/http/HttpRequest.java +++ b/core/src/main/java/org/jclouds/http/HttpRequest.java @@ -74,7 +74,7 @@ public class HttpRequest extends HttpMessage { public boolean isReplayable() { Object content = getPayload(); if (content != null && content instanceof InputStream) { - logger.warn("%1s: InputStreams are not replayable", toString()); + logger.warn("%1$s: InputStreams are not replayable", toString()); return false; } return true; diff --git a/core/src/main/java/org/jclouds/http/HttpResponseException.java b/core/src/main/java/org/jclouds/http/HttpResponseException.java new file mode 100644 index 0000000000..16da164761 --- /dev/null +++ b/core/src/main/java/org/jclouds/http/HttpResponseException.java @@ -0,0 +1,88 @@ +package org.jclouds.http; + +/** + * Represents an error obtained from an HttpResponse. + * + * @author Adrian Cole + * + */ +public class HttpResponseException extends RuntimeException { + + private static final long serialVersionUID = 1L; + protected final HttpFutureCommand command; + protected final HttpResponse response; + private String content; + + public HttpResponseException(String message, HttpFutureCommand command, + HttpResponse response, Throwable cause) { + super(message, cause); + this.command = command; + this.response = response; + } + + public HttpResponseException(String message, HttpFutureCommand command, + HttpResponse response, String content, Throwable cause) { + super(message, cause); + this.command = command; + this.response = response; + this.content = content; + } + + public HttpResponseException(HttpFutureCommand command, + HttpResponse response, Throwable cause) { + this(String.format("command: %1$s failed with response: %2$s", command, + response), command, response, cause); + } + + public HttpResponseException(HttpFutureCommand command, + HttpResponse response, String content, Throwable cause) { + this(String.format( + "command: %1$s failed with response: %2$s; content: [%3$s]", + command, response), command, response, content, cause); + } + + public HttpResponseException(String message, HttpFutureCommand command, + HttpResponse response) { + super(message); + this.command = command; + this.response = response; + } + + public HttpResponseException(String message, HttpFutureCommand command, + HttpResponse response, String content) { + super(message); + this.command = command; + this.response = response; + this.content = content; + } + + public HttpResponseException(HttpFutureCommand command, + HttpResponse response) { + this(String.format("command: %1$s failed with response: %2$s", command, + response), command, response); + } + + public HttpResponseException(HttpFutureCommand command, + HttpResponse response, String content) { + this(String.format( + "command: %1$s failed with response: %2$s; content: [%3$s]", + command, response, content), command, response, content); + } + + public HttpFutureCommand getCommand() { + return command; + } + + public HttpResponse getResponse() { + return response; + } + + public void setContent(String content) { + this.content = content; + } + + public String getContent() { + return content; + } + +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/JavaUrlHttpFutureCommandClient.java b/core/src/main/java/org/jclouds/http/JavaUrlHttpFutureCommandClient.java index 9c2ac6264c..f083d59bd5 100644 --- a/core/src/main/java/org/jclouds/http/JavaUrlHttpFutureCommandClient.java +++ b/core/src/main/java/org/jclouds/http/JavaUrlHttpFutureCommandClient.java @@ -59,13 +59,13 @@ public class JavaUrlHttpFutureCommandClient extends BaseHttpFutureCommandClient for (HttpRequestFilter filter : requestFilters) { filter.filter(request); } - logger.trace("%1s - converting request %2s", target, request); + logger.trace("%1$s - converting request %2$s", target, request); connection = openJavaConnection(request); logger - .trace("%1s - submitting request %2s", target, + .trace("%1$s - submitting request %2$s", target, connection); response = getResponse(connection); - logger.trace("%1s - received response %2s", target, response); + logger.trace("%1$s - received response %2$s", target, response); if (isRetryable(command, response)) continue; break; diff --git a/core/src/main/java/org/jclouds/http/commands/callables/ReturnStringIf200.java b/core/src/main/java/org/jclouds/http/commands/callables/ReturnStringIf200.java index 504642c626..32297e8e95 100644 --- a/core/src/main/java/org/jclouds/http/commands/callables/ReturnStringIf200.java +++ b/core/src/main/java/org/jclouds/http/commands/callables/ReturnStringIf200.java @@ -56,13 +56,13 @@ public class ReturnStringIf200 extends toReturn = Utils.toStringAndClose(entity); } catch (IOException e) { throw new HttpException(String.format( - "Couldn't receive response %1s, entity: %2s ", + "Couldn't receive response %1$s, entity: %2$s ", getResponse(), toReturn), e); } return toReturn; } else { throw new HttpException(String.format( - "Unhandled status code - %1s", getResponse())); + "Unhandled status code - %1$s", getResponse())); } } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/lifecycle/BaseLifeCycle.java b/core/src/main/java/org/jclouds/lifecycle/BaseLifeCycle.java index 9cbf949862..573bbb6d03 100644 --- a/core/src/main/java/org/jclouds/lifecycle/BaseLifeCycle.java +++ b/core/src/main/java/org/jclouds/lifecycle/BaseLifeCycle.java @@ -70,7 +70,7 @@ public abstract class BaseLifeCycle implements Runnable, LifeCycle { this.status = Status.SHUTTING_DOWN; doShutdown(); this.status = Status.SHUT_DOWN; - logger.info("%1s", this); + logger.info("%1$s", this); } protected abstract void doWork() throws Exception; @@ -88,7 +88,7 @@ public abstract class BaseLifeCycle implements Runnable, LifeCycle { @PostConstruct public void start() { - logger.info("starting %1s", this); + logger.info("starting %1$s", this); synchronized (this.statusLock) { if (this.status.compareTo(Status.SHUTDOWN_REQUEST) >= 0) { doShutdown(); @@ -116,7 +116,7 @@ public abstract class BaseLifeCycle implements Runnable, LifeCycle { for (BaseLifeCycle dependency : dependencies) { if (dependency.status.compareTo(Status.ACTIVE) != 0) { throw new IllegalStateException(String.format( - "Illegal state: %1s for component: %2s", + "Illegal state: %1$s for component: %2$s", dependency.status, dependency)); } } @@ -167,7 +167,7 @@ public abstract class BaseLifeCycle implements Runnable, LifeCycle { protected void exceptionIfNotActive() { if (!status.equals(Status.ACTIVE)) - throw new IllegalStateException(String.format("not active: %1s", + throw new IllegalStateException(String.format("not active: %1$s", this)); } diff --git a/core/src/test/java/org/jclouds/http/BaseHttpFutureCommandClientTest.java b/core/src/test/java/org/jclouds/http/BaseHttpFutureCommandClientTest.java index 043bd0806f..957763333a 100644 --- a/core/src/test/java/org/jclouds/http/BaseHttpFutureCommandClientTest.java +++ b/core/src/test/java/org/jclouds/http/BaseHttpFutureCommandClientTest.java @@ -165,7 +165,7 @@ public abstract class BaseHttpFutureCommandClientTest { get.getRequest().getHeaders().put("filterme", "filterme"); client.submit(get); assert get.get(10, TimeUnit.SECONDS).trim().equals("test") : String - .format("expected: [%1s], but got [%2s]", "test", get.get(10, + .format("expected: [%1$s], but got [%2$s]", "test", get.get(10, TimeUnit.SECONDS)); } @@ -176,7 +176,7 @@ public abstract class BaseHttpFutureCommandClientTest { get.getRequest().getHeaders().put("test", "test"); client.submit(get); assert get.get(10, TimeUnit.SECONDS).trim().equals("test") : String - .format("expected: [%1s], but got [%2s]", "test", get.get(10, + .format("expected: [%1$s], but got [%2$s]", "test", get.get(10, TimeUnit.SECONDS)); } @@ -187,7 +187,7 @@ public abstract class BaseHttpFutureCommandClientTest { assert get != null; client.submit(get); assert get.get(10, TimeUnit.SECONDS).trim().equals(XML) : String - .format("expected: [%1s], but got [%2s]", XML, get.get(10, + .format("expected: [%1$s], but got [%2$s]", XML, get.get(10, TimeUnit.SECONDS)); } diff --git a/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/pool/HttpNioFutureCommandConnectionHandle.java b/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/pool/HttpNioFutureCommandConnectionHandle.java index 13332e1a57..c690762cd2 100644 --- a/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/pool/HttpNioFutureCommandConnectionHandle.java +++ b/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/pool/HttpNioFutureCommandConnectionHandle.java @@ -53,7 +53,7 @@ public class HttpNioFutureCommandConnectionHandle extends public void startConnection() { conn.getContext().setAttribute("command", command); - logger.trace("invoking %1s on connection %2s", command, conn); + logger.trace("invoking %1$s on connection %2$s", command, conn); conn.requestOutput(); } diff --git a/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/pool/HttpNioFutureCommandConnectionPool.java b/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/pool/HttpNioFutureCommandConnectionPool.java index aa43386a6e..fe17dd43fc 100644 --- a/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/pool/HttpNioFutureCommandConnectionPool.java +++ b/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/pool/HttpNioFutureCommandConnectionPool.java @@ -97,7 +97,7 @@ public class HttpNioFutureCommandConnectionPool extends ioReactor.execute(dispatch); } catch (IOException e) { exception.set(e); - logger.error(e, "Error dispatching %1s", dispatch); + logger.error(e, "Error dispatching %1$s", dispatch); status = Status.SHUTDOWN_REQUEST; } } @@ -125,7 +125,7 @@ public class HttpNioFutureCommandConnectionPool extends public void shutdownConnection(NHttpConnection conn) { if (conn.getMetrics().getRequestCount() >= maxConnectionReuse) logger.debug( - "%1s - %2d - closing connection due to overuse %1s/%2s", + "%1$s - %2$d - closing connection due to overuse %1$s/%2$s", conn, conn.hashCode(), conn.getMetrics().getRequestCount(), maxConnectionReuse); if (conn.getStatus() == NHttpConnection.ACTIVE) { @@ -155,7 +155,7 @@ public class HttpNioFutureCommandConnectionPool extends boolean acquired = allConnections.tryAcquire(1, TimeUnit.SECONDS); if (acquired) { if (shouldDoWork()) { - logger.debug("%1s - opening new connection", target); + logger.debug("%1$s - opening new connection", target); ioReactor.connect(target, null, null, sessionCallback); } else { allConnections.release(); @@ -181,13 +181,13 @@ public class HttpNioFutureCommandConnectionPool extends SessionRequestCallback { public void completed(SessionRequest request) { - logger.trace("%1s->%2s[%3s] - SessionRequest complete", request + logger.trace("%1$s->%2$s[%3$s] - SessionRequest complete", request .getLocalAddress(), request.getRemoteAddress(), request .getAttachment()); } public void cancelled(SessionRequest request) { - logger.trace("%1s->%2s[%3s] - SessionRequest cancelled", request + logger.trace("%1$s->%2$s[%3$s] - SessionRequest cancelled", request .getLocalAddress(), request.getRemoteAddress(), request .getAttachment()); releaseConnectionAndCancelResponse(request); @@ -198,7 +198,7 @@ public class HttpNioFutureCommandConnectionPool extends FutureCommand frequest = (FutureCommand) request .getAttachment(); if (frequest != null) { - logger.error("%1s->%2s[%3s] - Cancelling FutureCommand", + logger.error("%1$s->%2$s[%3$s] - Cancelling FutureCommand", request.getLocalAddress(), request.getRemoteAddress(), frequest); frequest.cancel(true); @@ -212,7 +212,7 @@ public class HttpNioFutureCommandConnectionPool extends .getAttachment(); if (frequest != null) { logger.error(e, - "%1s->%2s[%3s] - Setting Exception on FutureCommand", + "%1$s->%2$s[%3$s] - Setting Exception on FutureCommand", request.getLocalAddress(), request.getRemoteAddress(), frequest); frequest.setException(e); @@ -221,7 +221,7 @@ public class HttpNioFutureCommandConnectionPool extends public void failed(SessionRequest request) { int count = currentSessionFailures.getAndIncrement(); - logger.warn("%1s->%2s[%3s] - SessionRequest failed", request + logger.warn("%1$s->%2$s[%3$s] - SessionRequest failed", request .getLocalAddress(), request.getRemoteAddress(), request .getAttachment()); releaseConnectionAndSetResponseException(request, request @@ -230,7 +230,7 @@ public class HttpNioFutureCommandConnectionPool extends logger .error( request.getException(), - "%1s->%2s[%3s] - SessionRequest failures: %4s, Disabling pool for %5s", + "%1$s->%2$s[%3$s] - SessionRequest failures: %4$s, Disabling pool for %5$s", request.getLocalAddress(), request .getRemoteAddress(), maxSessionFailures, target); @@ -240,7 +240,7 @@ public class HttpNioFutureCommandConnectionPool extends } public void timeout(SessionRequest request) { - logger.warn("%1s->%2s[%3s] - SessionRequest timeout", request + logger.warn("%1$s->%2$s[%3$s] - SessionRequest timeout", request .getLocalAddress(), request.getRemoteAddress(), request .getAttachment()); releaseConnectionAndCancelResponse(request); @@ -251,28 +251,28 @@ public class HttpNioFutureCommandConnectionPool extends public void connectionOpen(NHttpConnection conn) { conn.setSocketTimeout(0); available.offer(conn); - logger.trace("%1s - %2d - open", conn, conn.hashCode()); + logger.trace("%1$s - %2$d - open", conn, conn.hashCode()); } public void connectionTimeout(NHttpConnection conn) { - String message = String.format("%1s - %2d - timeout %2d", conn, conn + String message = String.format("%1$s - %2$d - timeout %2$d", conn, conn .hashCode(), conn.getSocketTimeout()); logger.warn(message); resubmitIfRequestIsReplayable(conn, new TimeoutException(message)); } public void connectionClosed(NHttpConnection conn) { - logger.trace("%1s - %2d - closed", conn, conn.hashCode()); + logger.trace("%1$s - %2$d - closed", conn, conn.hashCode()); } public void fatalIOException(IOException ex, NHttpConnection conn) { - logger.error(ex, "%3s-%1d{%2s} - io error", conn, conn.hashCode(), + logger.error(ex, "%3$s-%1$d{%2$s} - io error", conn, conn.hashCode(), target); resubmitIfRequestIsReplayable(conn, ex); } public void fatalProtocolException(HttpException ex, NHttpConnection conn) { - logger.error(ex, "%3s-%1d{%2s} - http error", conn, conn.hashCode(), + logger.error(ex, "%3$s-%1$d{%2$s} - http error", conn, conn.hashCode(), target); setExceptionOnCommand(conn, ex); } diff --git a/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/pool/HttpNioFutureCommandExecutionHandler.java b/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/pool/HttpNioFutureCommandExecutionHandler.java index 194c4c6e9d..6e8baf4621 100644 --- a/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/pool/HttpNioFutureCommandExecutionHandler.java +++ b/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/pool/HttpNioFutureCommandExecutionHandler.java @@ -134,13 +134,13 @@ public class HttpNioFutureCommandExecutionHandler implements } } else { throw new IllegalStateException(String.format( - "No command-handle associated with command %1s", context)); + "No command-handle associated with command %1$s", context)); } } protected boolean isRetryable(HttpFutureCommand command) { if (command.getRequest().isReplayable()) { - logger.info("resubmitting command: %1s", command); + logger.info("resubmitting command: %1$s", command); return true; } return false; @@ -151,14 +151,14 @@ public class HttpNioFutureCommandExecutionHandler implements try { handle.release(); } catch (InterruptedException e) { - logger.error(e, "Interrupted releasing handle %1s", handle); + logger.error(e, "Interrupted releasing handle %1$s", handle); } } protected void processResponse(org.jclouds.http.HttpResponse response, HttpFutureCommand command) throws IOException { command.getResponseFuture().setResponse(response); - logger.trace("submitting response task %1s", command + logger.trace("submitting response task %1$s", command .getResponseFuture()); executor.submit(command.getResponseFuture()); } @@ -170,7 +170,7 @@ public class HttpNioFutureCommandExecutionHandler implements try { handle.cancel(); } catch (Exception e) { - logger.error(e, "Error cancelling handle %1s", handle); + logger.error(e, "Error cancelling handle %1$s", handle); } } } diff --git a/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java b/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java index f5c0e139e9..860f4347c1 100644 --- a/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java +++ b/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java @@ -140,7 +140,8 @@ public class JCloudsS3Service extends S3Service { } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3ServiceException(String.format( - "error deleting object: %1s:%2s", bucketName, objectKey), e); + "error deleting object: %1$s:%2$s", bucketName, objectKey), + e); } } @@ -208,16 +209,16 @@ public class JCloudsS3Service extends S3Service { protected S3Bucket[] listAllBucketsImpl() throws S3ServiceException { try { List jcBucketList = connection - .getOwnedBuckets().get( - requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); + .listOwnedBuckets().get(requestTimeoutMilliseconds, + TimeUnit.MILLISECONDS); ArrayList jsBucketList = new ArrayList(); for (org.jclouds.aws.s3.domain.S3Bucket.Metadata jcBucket : jcBucketList) { org.jets3t.service.model.S3Bucket jsBucket = new org.jets3t.service.model.S3Bucket( jcBucket.getName()); jsBucket.setOwner(new org.jets3t.service.model.S3Owner(jcBucket - .getCanonicalUser().getId(), jcBucket - .getCanonicalUser().getDisplayName())); + .getOwner().getId(), jcBucket.getOwner() + .getDisplayName())); jsBucketList.add(jsBucket); } return (org.jets3t.service.model.S3Bucket[]) jsBucketList diff --git a/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceTest.java b/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceTest.java index 5bbc97f663..0418f4b471 100644 --- a/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceTest.java +++ b/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceTest.java @@ -184,7 +184,7 @@ public class JCloudsS3ServiceTest extends S3IntegrationTest { S3Bucket[] jsBuckets = service.listAllBuckets(); List jcBuckets = client - .getOwnedBuckets().get(10, TimeUnit.SECONDS); + .listOwnedBuckets().get(10, TimeUnit.SECONDS); assert jsBuckets.length == jcBuckets.size(); @@ -197,9 +197,9 @@ public class JCloudsS3ServiceTest extends S3IntegrationTest { .next(); assert jsBucket.getName().equals(jcBucket.getName()); assert jsBucket.getOwner().getId().equals( - jcBucket.getCanonicalUser().getId()); + jcBucket.getOwner().getId()); assert jsBucket.getOwner().getDisplayName().equals( - jcBucket.getCanonicalUser().getDisplayName()); + jcBucket.getOwner().getDisplayName()); } client.deleteBucketIfEmpty(bucketName); diff --git a/s3/perftest/src/test/java/com/amazon/s3/AmazonPerformanceTest.java b/s3/perftest/src/test/java/com/amazon/s3/AmazonPerformanceTest.java index 71b5387fc8..45be6ec032 100644 --- a/s3/perftest/src/test/java/com/amazon/s3/AmazonPerformanceTest.java +++ b/s3/perftest/src/test/java/com/amazon/s3/AmazonPerformanceTest.java @@ -31,12 +31,13 @@ import java.util.Map; import java.util.TreeMap; import java.util.concurrent.ExecutionException; -import org.jclouds.aws.s3.S3Constants; +import org.jclouds.aws.s3.reference.S3Constants; import org.testng.annotations.BeforeTest; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; + /** * Runs operations that amazon s3 sample code is capable of performing. * diff --git a/s3/perftest/src/test/java/com/amazon/s3/BaseJCloudsPerformance.java b/s3/perftest/src/test/java/com/amazon/s3/BaseJCloudsPerformance.java index 306acefd98..ad6412005b 100644 --- a/s3/perftest/src/test/java/com/amazon/s3/BaseJCloudsPerformance.java +++ b/s3/perftest/src/test/java/com/amazon/s3/BaseJCloudsPerformance.java @@ -56,7 +56,7 @@ public abstract class BaseJCloudsPerformance extends BasePerformance { String contentType) throws Exception { org.jclouds.aws.s3.domain.S3Object object = new org.jclouds.aws.s3.domain.S3Object( key); - object.getMetaData().setContentType(contentType); + object.getMetadata().setContentType(contentType); object.setData(data); return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null; } @@ -66,7 +66,7 @@ public abstract class BaseJCloudsPerformance extends BasePerformance { String contentType) throws Exception { org.jclouds.aws.s3.domain.S3Object object = new org.jclouds.aws.s3.domain.S3Object( key); - object.getMetaData().setContentType(contentType); + object.getMetadata().setContentType(contentType); object.setData(data); return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null; } @@ -76,9 +76,9 @@ public abstract class BaseJCloudsPerformance extends BasePerformance { InputStream data, String contentType) throws Exception { org.jclouds.aws.s3.domain.S3Object object = new org.jclouds.aws.s3.domain.S3Object( key); - object.getMetaData().setContentType(contentType); + object.getMetadata().setContentType(contentType); object.setData(data); - object.getMetaData().setSize(data.available()); + object.getMetadata().setSize(data.available()); return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null; } @@ -87,7 +87,7 @@ public abstract class BaseJCloudsPerformance extends BasePerformance { String contentType) throws Exception { org.jclouds.aws.s3.domain.S3Object object = new org.jclouds.aws.s3.domain.S3Object( key); - object.getMetaData().setContentType(contentType); + object.getMetadata().setContentType(contentType); object.setData(data); return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null; } diff --git a/s3/perftest/src/test/java/com/amazon/s3/BasePerformance.java b/s3/perftest/src/test/java/com/amazon/s3/BasePerformance.java index 653aae956e..f0128e8560 100644 --- a/s3/perftest/src/test/java/com/amazon/s3/BasePerformance.java +++ b/s3/perftest/src/test/java/com/amazon/s3/BasePerformance.java @@ -36,14 +36,15 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; -import org.jclouds.aws.s3.S3Constants; import org.jclouds.aws.s3.S3IntegrationTest; +import org.jclouds.aws.s3.reference.S3Constants; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; + import com.google.inject.Provider; /** @@ -256,7 +257,7 @@ public abstract class BasePerformance extends S3IntegrationTest { // } // for (Future isdeleted : deletes) // assert isdeleted.get(10,TimeUnit.SECONDS) : - // String.format("failed to delete %1s", + // String.format("failed to delete %1$ss", // isdeleted); // return // clientProvider.get(10,TimeUnit.SECONDS).deleteBucket(bucket).get(10,TimeUnit.SECONDS); diff --git a/s3/perftest/src/test/java/com/amazon/s3/DateServiceTest.java b/s3/perftest/src/test/java/com/amazon/s3/DateServiceTest.java index 8b764e6bd2..e0fb57a9d3 100644 --- a/s3/perftest/src/test/java/com/amazon/s3/DateServiceTest.java +++ b/s3/perftest/src/test/java/com/amazon/s3/DateServiceTest.java @@ -26,7 +26,7 @@ package com.amazon.s3; import com.google.inject.Guice; import com.google.inject.Injector; import org.jclouds.aws.PerformanceTest; -import org.jclouds.aws.s3.DateService; +import org.jclouds.aws.s3.util.DateService; import org.joda.time.DateTime; import org.testng.annotations.Test; diff --git a/s3/perftest/src/test/java/com/amazon/s3/S3ParserTest.java b/s3/perftest/src/test/java/com/amazon/s3/S3ParserTest.java index 22810d64e2..49dbf71cde 100644 --- a/s3/perftest/src/test/java/com/amazon/s3/S3ParserTest.java +++ b/s3/perftest/src/test/java/com/amazon/s3/S3ParserTest.java @@ -98,7 +98,7 @@ public class S3ParserTest extends org.jclouds.aws.s3.commands.S3ParserTest { } @SuppressWarnings("unchecked") - @Test + @Test(enabled = false) public void testAmazonCanParseListAllMyBuckets() throws IOException { ListAllMyBucketsResponse response = runAmazonParseListAllMyBuckets(); List buckets = response.entries; diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3Connection.java b/s3/src/main/java/org/jclouds/aws/s3/S3Connection.java index e3f8b562b4..3c2243d713 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3Connection.java +++ b/s3/src/main/java/org/jclouds/aws/s3/S3Connection.java @@ -42,63 +42,79 @@ import org.jclouds.aws.s3.domain.S3Object; * during processing will be wrapped in an {@link ExecutionException} as * documented in {@link Future#get()}. * + * @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAPI.html + * * @author Adrian Cole */ public interface S3Connection { /** - * Retrieves the object and metadata associated with the key. + * Retrieve a complete S3Object. * + * @see GetObject * @param bucketName * namespace of the object you are retrieving * * @param key * unique key in the s3Bucket identifying the object - * @return fully populated S3Object containing data stored in S3 + * @return Future reference to a fully populated S3Object including data + * stored in S3 or {@link S3Object#NOT_FOUND} if not present. */ Future getObject(String bucketName, String key); /** - * Retrieves the object and metadata associated with the key. + * Like {@link #getObject(String, String)} except you can use + * {@link GetObjectOptions} to control delivery. * - * @param bucketName - * namespace of the object you are retrieving + * @see #getObject(String, String) + * @see GetObjectOptions + * @return S3Object containing data relevant to the + * options specified or {@link S3Object#NOT_FOUND} if not present. * - * @param key - * unique key in the s3Bucket identifying the object - * @param options - * options for retrieving the object - * @return fully populated S3Object containing data stored in S3 + * @throws HttpResponseException + * if the conditions requested set were not satisfied by the + * object on the server. */ Future getObject(String bucketName, String key, GetObjectOptions options); /** - * Retrieves the metadata of the object associated with the key. + * Retrieves the {@link S3Object.Metadata metadata} of the object associated + * with the key. * + * @see HeadObject * @param bucketName * namespace of the metadata you are retrieving * * @param key * unique key in the s3Bucket identifying the object - * @return metadata associated with the key + * @return metadata associated with the key or + * {@link S3Object.Metadata#NOT_FOUND} if not present; */ Future headObject(String bucketName, String key); /** * Removes the object and metadata associated with the key. * + * @see DeleteObject * @param bucketName * namespace of the object you are deleting * @param key * unique key in the s3Bucket identifying the object * @return true if deleted + * @throws HttpResponseException + * if the bucket is not available */ Future deleteObject(String bucketName, String key); /** * Store data by creating or overwriting an object. + *

+ * This method will store the object with the default private + * acl. * + * @see CannedAccessPolicy#PRIVATE + * @see PutObject * @param bucketName * namespace of the object you are storing * @param object @@ -108,15 +124,19 @@ public interface S3Connection { Future putObject(String bucketName, S3Object object); /** - * Store data by creating or overwriting an object. + * Like {@link #putObject(String, S3Object)} except you can use + * {@link CopyObjectOptions} to specify an alternate + * {@link CannedAccessPolicy acl}, override + * {@link S3Object.Metadata#getUserMetadata() userMetadata}, or specify + * conditions for copying the object. * - * @param bucketName - * namespace of the object you are storing - * @param object - * contains the data and metadata to create or overwrite + * @see S3Connection#putObject(String, S3Object) + * @see PutObjectOptions * @param options * options for creating the object - * @return MD5 hash of the content uploaded + * @throws HttpResponseException + * if the conditions requested set are not satisfied by the + * object on the server. */ Future putObject(String bucketName, S3Object object, PutObjectOptions options); @@ -124,23 +144,25 @@ public interface S3Connection { /** * Create and name your own bucket in which to store your objects. * - * @return true, if the bucket was created + * @see PutBucket + * @return true, if the bucket was created or already exists */ Future putBucketIfNotExists(String name); /** - * Create and name your own bucket in which to store your objects. + * Like {@link #putBucketIfNotExists(String)} except that you can use + * {@link PutBucketOptions} to create the bucket in EU. Create and name your * + * @see PutBucketOptions * @param options * for creating your bucket - * @return true, if the bucket was created - * @see PutBucketOptions */ Future putBucketIfNotExists(String name, PutBucketOptions options); /** * Deletes the bucket, if it is empty. * + * @see DeleteBucket * @param s3Bucket * what to delete * @return false, if the bucket was not empty and therefore not deleted @@ -148,34 +170,68 @@ public interface S3Connection { Future deleteBucketIfEmpty(String s3Bucket); /** - * Copies one object to another bucket + * Copies one object to another bucket, retaining UserMetadata from the + * source. The destination will have a private acl. * - * @return metaData populated with lastModified and etag of the new object + * @see CopyObject + * @return metadata populated with lastModified and md5 of the new object */ Future copyObject(String sourceBucket, String sourceObject, String destinationBucket, String destinationObject); /** - * Copies one object to another bucket using the specifid options + * Like {@link #putObject(String, S3Object)} except you can use + * {@link PutObjectOptions} to specify an alternate + * {@link CannedAccessPolicy acl}. * - * @return metaData populated with lastModified and etag of the new object - * @see CopyObjectOptions + * @see S3Connection#putObject(String, S3Object) + * @see PutObjectOptions + * @param options + * options for creating the object + * @throws HttpResponseException + * if the conditions requested set are not satisfied by the + * object on the server. */ Future copyObject(String sourceBucket, String sourceObject, String destinationBucket, String destinationObject, CopyObjectOptions options); + /** + * @see HeadBucket + */ Future bucketExists(String name); /** + * Retrieve a complete S3Bucket listing. * - * @param s3Bucket - * @return + * @see ListBucket + * @param bucketName + * namespace of the objects you wish to list + * + * @return Future reference to a fully populated S3Bucket including metadata + * of the S3Objects it contains or {@link S3Bucket#NOT_FOUND} if not + * present. */ - Future listBucket(String name); + Future listBucket(String bucketName); + /** + * Like {@link #listBucket(String)} except you can use + * {@link ListObjectOptions} to control the amount of S3Objects to return. + * + * @see #listBucket(String) + * @see ListBucketOptions + * @return S3Bucket containing a subset of {@link S3Object.Metadata} + * depending on + * options specified or {@link S3Bucket#NOT_FOUND} if not present. + * + */ Future listBucket(String name, ListBucketOptions options); - Future> getOwnedBuckets(); + /** + * @see ListOwnedBuckets + * @return list of all of the buckets owned by the authenticated sender of + * the request. + */ + Future> listOwnedBuckets(); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3Context.java b/s3/src/main/java/org/jclouds/aws/s3/S3Context.java index 6288c4e545..ae33a07cfd 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3Context.java +++ b/s3/src/main/java/org/jclouds/aws/s3/S3Context.java @@ -23,10 +23,24 @@ */ package org.jclouds.aws.s3; - +/** + * Represents an authenticated context to S3. + * + *

Note

Please issue {@link #close()} when you are finished with this + * context in order to release resources. + * + * + * @see S3Connection + * @see S3InputStreamMap + * @see S3ObjectMap + * @author Adrian Cole + * + */ public interface S3Context { /** + * low-level api to S3. Threadsafe implementations will return a singleton. + * * @return a connection to S3 */ S3Connection getConnection(); diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3ContextFactory.java b/s3/src/main/java/org/jclouds/aws/s3/S3ContextFactory.java index 3327bbf779..b1b1de8c04 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3ContextFactory.java +++ b/s3/src/main/java/org/jclouds/aws/s3/S3ContextFactory.java @@ -24,8 +24,8 @@ package org.jclouds.aws.s3; import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.aws.s3.S3Constants.PROPERTY_AWS_ACCESSKEYID; -import static org.jclouds.aws.s3.S3Constants.PROPERTY_AWS_SECRETACCESSKEY; +import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_AWS_ACCESSKEYID; +import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_AWS_SECRETACCESSKEY; import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_IO_WORKER_THREADS; import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS; import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE; @@ -58,7 +58,17 @@ import com.google.inject.name.Names; /** * Creates {@link S3Context} or {@link Injector} instances based on the most * commonly requested arguments. + *

+ * Note that Threadsafe objects will be bound as singletons to the Injector or + * Context provided. * + *

+ * If no Modules are specified, the default + * {@link JDKLoggingModule logging} and + * {@link JavaUrlHttpFutureCommandClientModule http transports} will be + * installed. + * + * @see S3Context * @author Adrian Cole */ public class S3ContextFactory { diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3InputStreamMap.java b/s3/src/main/java/org/jclouds/aws/s3/S3InputStreamMap.java index 550cb23584..a1cb486c52 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3InputStreamMap.java +++ b/s3/src/main/java/org/jclouds/aws/s3/S3InputStreamMap.java @@ -27,7 +27,20 @@ import java.io.File; import java.io.InputStream; import java.util.Map; -public interface S3InputStreamMap extends Map, S3Map { +/** + * Map view of an {@link S3Bucket}. Provides additional methods for inserting + * common object types. + * + *

Note

All put operations will invoke + * {@link S3Object#generateMd5}. By extension, {@link #put(String, InputStream)} + * will result in the InputStream being converted to a byte array. For this + * reason, do not use {@link #put(String, InputStream)} to store files. Use + * {@link #putFile(String, File)} or {@link S3ObjectMap} instead. + * + * @author Adrian Cole + * + */ +public interface S3InputStreamMap extends S3Map { InputStream putString(String key, String value); InputStream putFile(String key, File value); diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3Map.java b/s3/src/main/java/org/jclouds/aws/s3/S3Map.java index 1b8036f930..b1ffd03970 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3Map.java +++ b/s3/src/main/java/org/jclouds/aws/s3/S3Map.java @@ -23,10 +23,23 @@ */ package org.jclouds.aws.s3; +import java.util.Map; + import org.jclouds.aws.s3.domain.S3Bucket; -public interface S3Map { +/** + * All Map views of {@link S3Bucket}s provide means to access the underlying S3 + * object. + * + * @author Adrian Cole + * + */ +public interface S3Map extends Map { + /** + * + * @return s3 bucket listing that this map represents + */ S3Bucket getBucket(); } \ No newline at end of file diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3ObjectMap.java b/s3/src/main/java/org/jclouds/aws/s3/S3ObjectMap.java index 4406b0c69c..2eda5a170d 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3ObjectMap.java +++ b/s3/src/main/java/org/jclouds/aws/s3/S3ObjectMap.java @@ -23,10 +23,19 @@ */ package org.jclouds.aws.s3; -import java.util.Map; - +import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Object; -public interface S3ObjectMap extends Map, S3Map { +/** + * Map view of an {@link S3Bucket}. + * + *

+ * This allows you to acces the underlying {@link S3Object} so that you can + * manually set metadata such as length, content-type, or md5 hash. + * + * @author Adrian Cole + * + */ +public interface S3ObjectMap extends S3Map { } \ No newline at end of file diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3ResponseException.java b/s3/src/main/java/org/jclouds/aws/s3/S3ResponseException.java index 5d49621293..78eb3ae15e 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3ResponseException.java +++ b/s3/src/main/java/org/jclouds/aws/s3/S3ResponseException.java @@ -26,31 +26,50 @@ package org.jclouds.aws.s3; import org.jclouds.aws.s3.domain.S3Error; import org.jclouds.http.HttpFutureCommand; import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; + +/** + * Encapsulates an S3 Error from Amazon. + * + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingRESTError.html + * @see S3Error + * @see ParseS3ErrorFromXmlContent + * @author Adrian Cole + * + */ +public class S3ResponseException extends HttpResponseException { -public class S3ResponseException extends RuntimeException { private static final long serialVersionUID = 1L; - private final HttpFutureCommand command; - private final HttpResponse response; - private S3Error error; + private S3Error error = new S3Error(); public S3ResponseException(HttpFutureCommand command, HttpResponse response, S3Error error) { - super(String.format( - "command: %1s failed with response: %2s; error from s3: %3s", - command, response, error)); - this.command = command; - this.response = response; + super(error.toString(), command, response); this.setError(error); } public S3ResponseException(HttpFutureCommand command, - HttpResponse response) { - super(String.format("command: %1s failed with response: %2s", command, - response)); - this.command = command; - this.response = response; + HttpResponse response, S3Error error, Throwable cause) { + super(error.toString(), command, response, cause); + this.setError(error); + + } + + public S3ResponseException(String message, HttpFutureCommand command, + HttpResponse response, S3Error error) { + super(message, command, response); + this.setError(error); + + } + + public S3ResponseException(String message, HttpFutureCommand command, + HttpResponse response, S3Error error, Throwable cause) { + super(message, command, response, cause); + this.setError(error); + } public void setError(S3Error error) { @@ -61,12 +80,4 @@ public class S3ResponseException extends RuntimeException { return error; } - public HttpFutureCommand getCommand() { - return command; - } - - public HttpResponse getResponse() { - return response; - } - } diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/BucketExists.java b/s3/src/main/java/org/jclouds/aws/s3/commands/BucketExists.java index 9b3dd64a33..ae77b641b2 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/BucketExists.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/BucketExists.java @@ -29,7 +29,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.jclouds.aws.s3.S3ResponseException; +import org.jclouds.http.HttpResponseException; import org.jclouds.http.commands.callables.ReturnTrueIf2xx; import com.google.common.annotations.VisibleForTesting; @@ -37,6 +37,12 @@ import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.inject.name.Named; +/** + * Issues a HEAD command to determine if the bucket exists or not. + * + * @author Adrian Cole + * + */ public class BucketExists extends S3FutureCommand { @Inject @@ -57,8 +63,9 @@ public class BucketExists extends S3FutureCommand { @VisibleForTesting Boolean attemptNotFound(ExecutionException e) throws ExecutionException { - if (e.getCause() != null && e.getCause() instanceof S3ResponseException) { - S3ResponseException responseException = (S3ResponseException) e + if (e.getCause() != null + && e.getCause() instanceof HttpResponseException) { + HttpResponseException responseException = (HttpResponseException) e .getCause(); if (responseException.getResponse().getStatusCode() == 404) { return false; diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/CopyObject.java b/s3/src/main/java/org/jclouds/aws/s3/commands/CopyObject.java index 7860a98d23..cea901ea39 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/CopyObject.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/CopyObject.java @@ -34,6 +34,25 @@ import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.inject.name.Named; +/** + * The copy operation creates a copy of an object that is already storedin + * Amazon S3. + *

+ * When copying an object, you can preserve all metadata (default) or + * {@link CopyObjectOptions#overrideMetadataWith(com.google.common.collect.Multimap) + * specify new metadata}. However, the ACL is not preserved and is set to + * private for the user making the request. To override the default ACL setting, + * {@link CopyObjectOptions#overrideAcl(org.jclouds.aws.s3.domain.acl.CannedAccessPolicy) + * specify a new ACL} when generating a copy request. + * + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectCOPY + * .html + * @see CopyObjectOptions + * @see CannedAccessPolicy + * @author Adrian Cole + * + */ public class CopyObject extends S3FutureCommand { @Inject @@ -51,9 +70,9 @@ public class CopyObject extends S3FutureCommand { handler.setKey(destinationObject); getRequest().getHeaders().put( "x-amz-copy-source", - String.format("/%1s/%2s", checkNotNull(sourceBucket, - "sourceBucket"), checkNotNull( - sourceObject, "sourceObject"))); + String.format("/%1$s/%2$s", checkNotNull(sourceBucket, + "sourceBucket"), checkNotNull(sourceObject, + "sourceObject"))); getRequest().getHeaders().putAll(options.buildRequestHeaders()); } } \ No newline at end of file diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/DeleteBucket.java b/s3/src/main/java/org/jclouds/aws/s3/commands/DeleteBucket.java index 0028edc246..ca335b6d79 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/DeleteBucket.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/DeleteBucket.java @@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.jclouds.aws.s3.S3ResponseException; +import org.jclouds.http.HttpResponseException; import org.jclouds.http.commands.callables.ReturnTrueIf2xx; import com.google.common.annotations.VisibleForTesting; @@ -35,6 +36,17 @@ import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.inject.name.Named; +/** + * The DELETE request operation deletes the bucket named in the URI. All objects + * in the bucket must be deleted before the bucket itself can be deleted. + *

+ * Only the owner of a bucket can delete it, regardless of the bucket's access + * control policy. + * + * @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html? + * RESTBucketDELETE.html + * @author Adrian Cole + */ public class DeleteBucket extends S3FutureCommand { @Inject @@ -54,7 +66,8 @@ public class DeleteBucket extends S3FutureCommand { @VisibleForTesting Boolean attemptNotFound(ExecutionException e) throws ExecutionException { - if (e.getCause() != null && e.getCause() instanceof S3ResponseException) { + if (e.getCause() != null + && e.getCause() instanceof HttpResponseException) { S3ResponseException responseException = (S3ResponseException) e .getCause(); if (responseException.getResponse().getStatusCode() == 404) { diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/DeleteObject.java b/s3/src/main/java/org/jclouds/aws/s3/commands/DeleteObject.java index 05bb3e3e93..88dbd63438 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/DeleteObject.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/DeleteObject.java @@ -31,6 +31,14 @@ import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.inject.name.Named; +/** + * The DELETE request operation removes the specified object from Amazon S3. + * Once deleted, there is no method to restore or undelete an object. + * + * @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html? + * RESTObjectDELETE.html + * @author Adrian Cole + */ public class DeleteObject extends S3FutureCommand { @Inject diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/GetObject.java b/s3/src/main/java/org/jclouds/aws/s3/commands/GetObject.java index cedd683ceb..f052cccfba 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/GetObject.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/GetObject.java @@ -43,8 +43,28 @@ import com.google.inject.name.Named; * Retrieves the S3Object associated with the Key or {@link S3Object#NOT_FOUND} * if not available; * - * @author Adrian Cole + *

+ * To use GET, you must have READ access to the object. If READ access is + * granted to the anonymous user, you can request the object without an + * authorization header. + *

+ *

+ * This command allows you to specify {@link GetObjectOptions} to control + * delivery of content. * + *

Note

If you specify any of the below options, you will receive + * partial content: + *
    + *
  • {@link GetObjectOptions#range}
  • + *
  • {@link GetObjectOptions#startAt}
  • + *
  • {@link GetObjectOptions#tail}
  • + *
+ * + * @see GetObjectOptions + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectGET + * .html + * @author Adrian Cole */ public class GetObject extends S3FutureCommand { diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/HeadMetaData.java b/s3/src/main/java/org/jclouds/aws/s3/commands/HeadObject.java similarity index 76% rename from s3/src/main/java/org/jclouds/aws/s3/commands/HeadMetaData.java rename to s3/src/main/java/org/jclouds/aws/s3/commands/HeadObject.java index 0a26a5c887..ba215a9606 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/HeadMetaData.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/HeadObject.java @@ -29,9 +29,9 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.jclouds.aws.s3.S3ResponseException; import org.jclouds.aws.s3.commands.callables.ParseMetadataFromHeaders; import org.jclouds.aws.s3.domain.S3Object; +import org.jclouds.http.HttpResponseException; import com.google.common.annotations.VisibleForTesting; import com.google.inject.Inject; @@ -40,15 +40,25 @@ import com.google.inject.name.Named; /** * Retrieves the metadata associated with the Key or - * {@link S3Object.Metadata#NOT_FOUND} if not available; + * {@link S3Object.Metadata#NOT_FOUND} if not available. * + *

+ * The HEAD operation is used to retrieve information about a specific object or + * object size, without actually fetching the object itself. This is useful if + * you're only interested in the object metadata, and don't want to waste + * bandwidth on the object data. + * + * @see GetObject + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectHEAD + * .html * @author Adrian Cole * */ -public class HeadMetaData extends S3FutureCommand { +public class HeadObject extends S3FutureCommand { @Inject - public HeadMetaData(@Named("jclouds.http.address") String amazonHost, + public HeadObject(@Named("jclouds.http.address") String amazonHost, ParseMetadataFromHeaders callable, @Assisted("bucketName") String bucket, @Assisted("key") String key) { super("HEAD", "/" + checkNotNull(key), callable, amazonHost, bucket); @@ -68,8 +78,9 @@ public class HeadMetaData extends S3FutureCommand { @VisibleForTesting S3Object.Metadata attemptNotFound(ExecutionException e) throws ExecutionException { - if (e.getCause() != null && e.getCause() instanceof S3ResponseException) { - S3ResponseException responseException = (S3ResponseException) e + if (e.getCause() != null + && e.getCause() instanceof HttpResponseException) { + HttpResponseException responseException = (HttpResponseException) e .getCause(); if (responseException.getResponse().getStatusCode() == 404) { return S3Object.Metadata.NOT_FOUND; diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/ListBucket.java b/s3/src/main/java/org/jclouds/aws/s3/commands/ListBucket.java index b18552dab6..c81a84bfcf 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/ListBucket.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/ListBucket.java @@ -31,6 +31,7 @@ import org.jclouds.aws.s3.S3ResponseException; import org.jclouds.aws.s3.commands.options.ListBucketOptions; import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.xml.ListBucketHandler; +import org.jclouds.http.HttpResponseException; import org.jclouds.http.commands.callables.xml.ParseSax; import com.google.common.annotations.VisibleForTesting; @@ -38,6 +39,21 @@ import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.inject.name.Named; +/** + * A GET request operation using a bucket URI lists information about the + * objects in the bucket. + *

+ * To list the keys of a bucket, you must have READ access to the bucket. + *

+ * List output is controllable via {@link ListBucketOptions} + * + * @see ListBucketOptions + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET + * .html + * @author Adrian Cole + * + */ public class ListBucket extends S3FutureCommand { @Inject @@ -62,7 +78,8 @@ public class ListBucket extends S3FutureCommand { @VisibleForTesting S3Bucket attemptNotFound(ExecutionException e) throws ExecutionException { - if (e.getCause() != null && e.getCause() instanceof S3ResponseException) { + if (e.getCause() != null + && e.getCause() instanceof HttpResponseException) { S3ResponseException responseException = (S3ResponseException) e .getCause(); if ("NoSuchBucket".equals(responseException.getError().getCode())) { diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/GetMetaDataForOwnedBuckets.java b/s3/src/main/java/org/jclouds/aws/s3/commands/ListOwnedBuckets.java similarity index 84% rename from s3/src/main/java/org/jclouds/aws/s3/commands/GetMetaDataForOwnedBuckets.java rename to s3/src/main/java/org/jclouds/aws/s3/commands/ListOwnedBuckets.java index 1595989c4c..1af41a5651 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/GetMetaDataForOwnedBuckets.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/ListOwnedBuckets.java @@ -35,13 +35,16 @@ import com.google.inject.name.Named; * Returns a list of all of the buckets owned by the authenticated sender of the * request. * + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTServiceGET + * .html * @author Adrian Cole * */ -public class GetMetaDataForOwnedBuckets extends S3FutureCommand> { +public class ListOwnedBuckets extends S3FutureCommand> { @Inject - public GetMetaDataForOwnedBuckets(@Named("jclouds.http.address") String amazonHost, + public ListOwnedBuckets(@Named("jclouds.http.address") String amazonHost, ParseSax> callable) { super("GET", "/", callable, amazonHost); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/PutBucket.java b/s3/src/main/java/org/jclouds/aws/s3/commands/PutBucket.java index a61998ecdc..95f0adb443 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/PutBucket.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/PutBucket.java @@ -23,8 +23,8 @@ */ package org.jclouds.aws.s3.commands; -import org.jclouds.aws.s3.S3Utils; import org.jclouds.aws.s3.commands.options.PutBucketOptions; +import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.http.HttpHeaders; import org.jclouds.http.commands.callables.ReturnTrueIf2xx; @@ -34,7 +34,16 @@ import com.google.inject.name.Named; /** * Create and name your own bucket in which to store your objects. + *

+ * The PUT request operation with a bucket URI creates a new bucket. Depending + * on your latency and legal requirements, you can specify a location constraint + * that will affect where your data physically resides. You can currently + * specify a Europe (EU) location constraint via {@link PutBucketOptions}. * + * @see PutBucketOptions + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT + * .html * @author Adrian Cole * */ diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/PutObject.java b/s3/src/main/java/org/jclouds/aws/s3/commands/PutObject.java index 5b1f464c95..56c612333b 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/PutObject.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/PutObject.java @@ -23,18 +23,36 @@ */ package org.jclouds.aws.s3.commands; -import static com.google.common.base.Preconditions.*; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; -import org.jclouds.aws.s3.S3Utils; import org.jclouds.aws.s3.commands.callables.ParseMd5FromETagHeader; import org.jclouds.aws.s3.commands.options.PutObjectOptions; import org.jclouds.aws.s3.domain.S3Object; +import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.http.HttpHeaders; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.inject.name.Named; +/** + * Store data by creating or overwriting an object. + * + *

+ * This returns a byte[] of the md5 hash of what Amazon S3 received + *

+ *

+ * This command allows you to specify {@link PutObjectOptions} to control + * delivery of content. + * + * + * @see PutObjectOptions + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT + * .html + * @author Adrian Cole + */ public class PutObject extends S3FutureCommand { @Inject @@ -43,38 +61,38 @@ public class PutObject extends S3FutureCommand { @Assisted S3Object object, @Assisted PutObjectOptions options) { super("PUT", "/" + checkNotNull(object.getKey()), callable, amazonHost, s3Bucket); - checkArgument(object.getMetaData().getSize() >=0,"size must be set"); - + checkArgument(object.getMetadata().getSize() >= 0, "size must be set"); + getRequest().setPayload( checkNotNull(object.getData(), "object.getContent()")); getRequest().getHeaders().put( HttpHeaders.CONTENT_TYPE, - checkNotNull(object.getMetaData().getContentType(), - "object.metaData.contentType()")); + checkNotNull(object.getMetadata().getContentType(), + "object.metadata.contentType()")); getRequest().getHeaders().put(HttpHeaders.CONTENT_LENGTH, - object.getMetaData().getSize() + ""); + object.getMetadata().getSize() + ""); - if (object.getMetaData().getCacheControl() != null) { + if (object.getMetadata().getCacheControl() != null) { getRequest().getHeaders().put(HttpHeaders.CACHE_CONTROL, - object.getMetaData().getCacheControl()); + object.getMetadata().getCacheControl()); } - if (object.getMetaData().getContentDisposition() != null) { + if (object.getMetadata().getContentDisposition() != null) { getRequest().getHeaders().put(HttpHeaders.CONTENT_DISPOSITION, - object.getMetaData().getContentDisposition()); + object.getMetadata().getContentDisposition()); } - if (object.getMetaData().getContentEncoding() != null) { + if (object.getMetadata().getContentEncoding() != null) { getRequest().getHeaders().put(HttpHeaders.CONTENT_ENCODING, - object.getMetaData().getContentEncoding()); + object.getMetadata().getContentEncoding()); } - if (object.getMetaData().getMd5() != null) + if (object.getMetadata().getMd5() != null) getRequest().getHeaders().put(HttpHeaders.CONTENT_MD5, - S3Utils.toBase64String(object.getMetaData().getMd5())); + S3Utils.toBase64String(object.getMetadata().getMd5())); getRequest().getHeaders() - .putAll(object.getMetaData().getUserMetadata()); + .putAll(object.getMetadata().getUserMetadata()); getRequest().getHeaders().putAll(options.buildRequestHeaders()); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/S3CommandFactory.java b/s3/src/main/java/org/jclouds/aws/s3/commands/S3CommandFactory.java index 517885ac34..7a39b25f4f 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/S3CommandFactory.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/S3CommandFactory.java @@ -116,23 +116,23 @@ public class S3CommandFactory { } @Inject - private HeadMetaDataFactory headMetaDataFactory; + private HeadMetadataFactory headMetadataFactory; - public static interface HeadMetaDataFactory { - HeadMetaData create(@Assisted("bucketName") String bucket, + public static interface HeadMetadataFactory { + HeadObject create(@Assisted("bucketName") String bucket, @Assisted("key") String key); } - public HeadMetaData createHeadMetaData(String bucket, String key) { - return headMetaDataFactory.create(bucket, key); + public HeadObject createHeadMetadata(String bucket, String key) { + return headMetadataFactory.create(bucket, key); } @Inject @Named("jclouds.http.address") String amazonHost; - public GetMetaDataForOwnedBuckets createGetMetaDataForOwnedBuckets() { - return new GetMetaDataForOwnedBuckets(amazonHost, parserFactory + public ListOwnedBuckets createGetMetadataForOwnedBuckets() { + return new ListOwnedBuckets(amazonHost, parserFactory .createListBucketsParser()); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/callables/ParseMd5FromETagHeader.java b/s3/src/main/java/org/jclouds/aws/s3/commands/callables/ParseMd5FromETagHeader.java index 3590dd8085..6d17882cef 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/callables/ParseMd5FromETagHeader.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/callables/ParseMd5FromETagHeader.java @@ -24,11 +24,12 @@ package org.jclouds.aws.s3.commands.callables; import org.apache.commons.io.IOUtils; -import org.jclouds.aws.s3.S3Headers; -import org.jclouds.aws.s3.S3Utils; +import org.jclouds.aws.s3.reference.S3Headers; +import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.http.HttpException; import org.jclouds.http.HttpFutureCommand; + /** * Parses an MD5 checksum from the header {@link S3Headers#ETAG}. * diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/callables/ParseMetadataFromHeaders.java b/s3/src/main/java/org/jclouds/aws/s3/commands/callables/ParseMetadataFromHeaders.java index 2b3f2eadce..c973b736e4 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/callables/ParseMetadataFromHeaders.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/callables/ParseMetadataFromHeaders.java @@ -25,10 +25,11 @@ package org.jclouds.aws.s3.commands.callables; import java.util.Map.Entry; -import org.jclouds.aws.s3.DateService; -import org.jclouds.aws.s3.S3Headers; -import org.jclouds.aws.s3.S3Utils; import org.jclouds.aws.s3.domain.S3Object; +import org.jclouds.aws.s3.domain.S3Object.Metadata; +import org.jclouds.aws.s3.reference.S3Headers; +import org.jclouds.aws.s3.util.DateService; +import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.http.HttpException; import org.jclouds.http.HttpFutureCommand; import org.jclouds.http.HttpHeaders; @@ -52,30 +53,36 @@ public class ParseMetadataFromHeaders extends /** * parses the http response headers to create a new - * {@link S3Object.MetaData} object. + * {@link S3Object.Metadata} object. */ public S3Object.Metadata call() throws HttpException { checkCode(); - - S3Object.Metadata metaData = new S3Object.Metadata(key); - extractUserMetadata(metaData); - addMd5(metaData); + S3Object.Metadata metadata = new S3Object.Metadata(key); + addAllHeadersTo(metadata); - parseLastModifiedOrThrowException(metaData); - setContentTypeOrThrowException(metaData); + addUserMetadataTo(metadata); + addMd5To(metadata); - metaData.setCacheControl(getResponse().getFirstHeaderOrNull( + parseLastModifiedOrThrowException(metadata); + setContentTypeOrThrowException(metadata); + setContentLengthOrThrowException(metadata); + + metadata.setCacheControl(getResponse().getFirstHeaderOrNull( HttpHeaders.CACHE_CONTROL)); - metaData.setContentDisposition(getResponse().getFirstHeaderOrNull( + metadata.setContentDisposition(getResponse().getFirstHeaderOrNull( HttpHeaders.CONTENT_DISPOSITION)); - metaData.setContentEncoding(getResponse().getFirstHeaderOrNull( + metadata.setContentEncoding(getResponse().getFirstHeaderOrNull( HttpHeaders.CONTENT_ENCODING)); - return metaData; + return metadata; } - private void setContentTypeOrThrowException(S3Object.Metadata metaData) + private void addAllHeadersTo(Metadata metadata) { + metadata.getAllHeaders().putAll(getResponse().getHeaders()); + } + + private void setContentTypeOrThrowException(S3Object.Metadata metadata) throws HttpException { String contentType = getResponse().getFirstHeaderOrNull( HttpHeaders.CONTENT_TYPE); @@ -83,39 +90,50 @@ public class ParseMetadataFromHeaders extends throw new HttpException(HttpHeaders.CONTENT_TYPE + " not found in headers"); else - metaData.setContentType(contentType); + metadata.setContentType(contentType); } - private void parseLastModifiedOrThrowException(S3Object.Metadata metaData) + private void setContentLengthOrThrowException(S3Object.Metadata metadata) + throws HttpException { + String contentLength = getResponse().getFirstHeaderOrNull( + HttpHeaders.CONTENT_LENGTH); + if (contentLength == null) + throw new HttpException(HttpHeaders.CONTENT_LENGTH + + " not found in headers"); + else + metadata.setSize(Long.parseLong(contentLength)); + } + + private void parseLastModifiedOrThrowException(S3Object.Metadata metadata) throws HttpException { String lastModified = getResponse().getFirstHeaderOrNull( HttpHeaders.LAST_MODIFIED); - metaData.setLastModified(dateParser + metadata.setLastModified(dateParser .dateTimeFromHeaderFormat(lastModified)); - if (metaData.getLastModified() == null) + if (metadata.getLastModified() == null) throw new HttpException("could not parse: " + HttpHeaders.LAST_MODIFIED + ": " + lastModified); } - private void addMd5(S3Object.Metadata metaData) { + private void addMd5To(S3Object.Metadata metadata) { String md5Header = getResponse() .getFirstHeaderOrNull(S3Headers.AMZ_MD5); if (md5Header != null) { - metaData.setMd5(S3Utils.fromHexString(md5Header)); + metadata.setMd5(S3Utils.fromHexString(md5Header)); } String eTag = getResponse().getFirstHeaderOrNull(S3Headers.ETAG); - if (metaData.getMd5() == null && eTag != null) { - metaData.setMd5(S3Utils.fromHexString(eTag.replaceAll("\"", ""))); + if (metadata.getMd5() == null && eTag != null) { + metadata.setMd5(S3Utils.fromHexString(eTag.replaceAll("\"", ""))); } } - private void extractUserMetadata(S3Object.Metadata metaData) { + private void addUserMetadataTo(S3Object.Metadata metadata) { for (Entry header : getResponse().getHeaders() .entries()) { if (header.getKey() != null && header.getKey().startsWith( S3Headers.USER_METADATA_PREFIX)) - metaData.getUserMetadata().put(header.getKey(), + metadata.getUserMetadata().put(header.getKey(), header.getValue()); } } diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/callables/ParseObjectFromHeadersAndHttpContent.java b/s3/src/main/java/org/jclouds/aws/s3/commands/callables/ParseObjectFromHeadersAndHttpContent.java index 59ed37ab69..4ac62a1cf2 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/callables/ParseObjectFromHeadersAndHttpContent.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/callables/ParseObjectFromHeadersAndHttpContent.java @@ -24,11 +24,11 @@ package org.jclouds.aws.s3.commands.callables; import org.jclouds.aws.s3.domain.S3Object; -import org.jclouds.aws.s3.domain.S3Object.Metadata; import org.jclouds.http.HttpException; import org.jclouds.http.HttpFutureCommand; import org.jclouds.http.HttpHeaders; +import com.google.common.annotations.VisibleForTesting; import com.google.inject.Inject; /** @@ -39,11 +39,12 @@ import com.google.inject.Inject; */ public class ParseObjectFromHeadersAndHttpContent extends HttpFutureCommand.ResponseCallable { - private final ParseMetadataFromHeaders metaDataParser; + private final ParseMetadataFromHeaders metadataParser; @Inject - public ParseObjectFromHeadersAndHttpContent(ParseMetadataFromHeaders metaDataParser) { - this.metaDataParser = metaDataParser; + public ParseObjectFromHeadersAndHttpContent( + ParseMetadataFromHeaders metadataParser) { + this.metadataParser = metadataParser; } /** @@ -56,26 +57,38 @@ public class ParseObjectFromHeadersAndHttpContent extends */ public S3Object call() throws HttpException { checkCode(); - metaDataParser.setResponse(getResponse()); - S3Object.Metadata metaData = metaDataParser.call(); - - parseContentLengthOrThrowException(metaData); - return new S3Object(metaData, getResponse().getContent()); + metadataParser.setResponse(getResponse()); + S3Object.Metadata metadata = metadataParser.call(); + S3Object object = new S3Object(metadata, getResponse().getContent()); + parseContentLengthOrThrowException(object); + return object; } - private void parseContentLengthOrThrowException(Metadata metaData) + @VisibleForTesting + void parseContentLengthOrThrowException(S3Object object) throws HttpException { String contentLength = getResponse().getFirstHeaderOrNull( HttpHeaders.CONTENT_LENGTH); + String contentRange = getResponse().getFirstHeaderOrNull( + HttpHeaders.CONTENT_RANGE); if (contentLength == null) throw new HttpException(HttpHeaders.CONTENT_LENGTH + " header not present in headers: " + getResponse().getHeaders()); - metaData.setSize(Long.parseLong(contentLength)); + object.setContentLength(Long.parseLong(contentLength)); + + if (contentRange == null) { + object.getMetadata().setSize(object.getContentLength()); + } else { + object.setContentRange(contentRange); + object.getMetadata().setSize( + Long.parseLong(contentRange.substring(contentRange + .lastIndexOf('/')+1))); + } } public void setKey(String key) { - this.metaDataParser.setKey(key); + this.metadataParser.setKey(key); } } \ No newline at end of file diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/config/S3CommandsModule.java b/s3/src/main/java/org/jclouds/aws/s3/commands/config/S3CommandsModule.java index ce1d882cbd..ca8895b54c 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/config/S3CommandsModule.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/config/S3CommandsModule.java @@ -27,7 +27,7 @@ import org.jclouds.aws.s3.commands.BucketExists; import org.jclouds.aws.s3.commands.DeleteBucket; import org.jclouds.aws.s3.commands.DeleteObject; import org.jclouds.aws.s3.commands.GetObject; -import org.jclouds.aws.s3.commands.HeadMetaData; +import org.jclouds.aws.s3.commands.HeadObject; import org.jclouds.aws.s3.commands.PutBucket; import org.jclouds.aws.s3.commands.PutObject; import org.jclouds.aws.s3.commands.S3CommandFactory; @@ -76,10 +76,10 @@ public class S3CommandsModule extends AbstractModule { S3CommandFactory.GetObjectFactory.class, GetObject.class)); - bind(S3CommandFactory.HeadMetaDataFactory.class).toProvider( + bind(S3CommandFactory.HeadMetadataFactory.class).toProvider( FactoryProvider.newFactory( - S3CommandFactory.HeadMetaDataFactory.class, - HeadMetaData.class)); + S3CommandFactory.HeadMetadataFactory.class, + HeadObject.class)); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/options/CopyObjectOptions.java b/s3/src/main/java/org/jclouds/aws/s3/commands/options/CopyObjectOptions.java index 1ed06347e3..2cdbfccbcb 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/options/CopyObjectOptions.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/options/CopyObjectOptions.java @@ -29,8 +29,10 @@ import static com.google.common.base.Preconditions.checkState; import java.io.UnsupportedEncodingException; -import org.jclouds.aws.s3.DateService; -import org.jclouds.aws.s3.S3Utils; +import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.jclouds.aws.s3.reference.S3Headers; +import org.jclouds.aws.s3.util.DateService; +import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.http.options.BaseHttpRequestOptions; import org.joda.time.DateTime; @@ -55,7 +57,7 @@ import com.google.common.collect.Multimap; * * // this will copy the object, provided it wasn't modified since yesterday. * // it will not use metadata from the source, and instead use what we pass in. - * Future object = connection.copyObject("sourceBucket", "objectName", + * Future object = connection.copyObject("sourceBucket", "objectName", * "destinationBucket", "destinationName", * overrideMetadataWith(meta). * ifSourceModifiedSince(new DateTime().minusDays(1)) @@ -75,6 +77,27 @@ public class CopyObjectOptions extends BaseHttpRequestOptions { private Multimap metadata; + private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE; + + /** + * Override the default ACL (private) with the specified one. + * + * @see CannedAccessPolicy + */ + public CopyObjectOptions overrideAcl(CannedAccessPolicy acl) { + this.acl = checkNotNull(acl, "acl"); + if (!acl.equals(CannedAccessPolicy.PRIVATE)) + this.replaceHeader(S3Headers.CANNED_ACL, acl.toString()); + return this; + } + + /** + * @see CopyObjectOptions#overrideAcl(CannedAccessPolicy) + */ + public CannedAccessPolicy getAcl() { + return acl; + } + /** * For use in the header x-amz-copy-source-if-unmodified-since *

@@ -201,7 +224,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions { "ifMd5DoesntMatch() is not compatible with ifMd5Matches()"); checkState(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifMd5Matches()"); - replaceHeader("x-amz-copy-source-if-match", String.format("\"%1s\"", + replaceHeader("x-amz-copy-source-if-match", String.format("\"%1$s\"", S3Utils.toHexString(checkNotNull(md5, "md5")))); return this; } @@ -226,7 +249,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions { .checkState(getIfUnmodifiedSince() == null, "ifUnmodifiedSince() is not compatible with ifMd5DoesntMatch()"); replaceHeader("x-amz-copy-source-if-none-match", String.format( - "\"%1s\"", S3Utils.toHexString(checkNotNull(md5, + "\"%1$s\"", S3Utils.toHexString(checkNotNull(md5, "ifMd5DoesntMatch")))); return this; } @@ -257,7 +280,14 @@ public class CopyObjectOptions extends BaseHttpRequestOptions { } public static class Builder { - + /** + * @see CopyObjectOptions#overrideAcl(CannedAccessPolicy) + */ + public static CopyObjectOptions overrideAcl(CannedAccessPolicy acl) { + CopyObjectOptions options = new CopyObjectOptions(); + return options.overrideAcl(acl); + } + /** * @see CopyObjectOptions#getIfModifiedSince() */ diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/options/GetObjectOptions.java b/s3/src/main/java/org/jclouds/aws/s3/commands/options/GetObjectOptions.java index da471e7931..59af678eea 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/options/GetObjectOptions.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/options/GetObjectOptions.java @@ -24,16 +24,20 @@ package org.jclouds.aws.s3.commands.options; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - +import static com.google.common.base.Preconditions.checkArgument; import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; -import org.jclouds.aws.s3.DateService; -import org.jclouds.aws.s3.S3Headers; -import org.jclouds.aws.s3.S3Utils; +import org.jclouds.aws.s3.util.DateService; +import org.jclouds.aws.s3.util.S3Utils; +import org.jclouds.http.HttpHeaders; import org.jclouds.http.options.BaseHttpRequestOptions; import org.joda.time.DateTime; +import com.google.common.base.Joiner; +import com.google.common.collect.Multimap; + /** * Contains options supported in the REST API for the GET object operation.

* Usage

The recommended way to instantiate a GetObjectOptions object is to @@ -58,16 +62,42 @@ import org.joda.time.DateTime; public class GetObjectOptions extends BaseHttpRequestOptions { private final static DateService dateService = new DateService(); public static final GetObjectOptions NONE = new GetObjectOptions(); + private final List ranges = new ArrayList(); + + @Override + public Multimap buildRequestHeaders() { + Multimap headers = super.buildRequestHeaders(); + String range = getRange(); + if (range != null) + headers.put(HttpHeaders.RANGE, this.getRange()); + return headers; + } /** - * Only download the specified range of the object. + * download the specified range of the object. */ public GetObjectOptions range(long start, long end) { - checkState(start >= 0, "start must be >= 0"); - checkState(end >= 0, "end must be >= 0"); - headers - .put(S3Headers.RANGE, String - .format("bytes=%1d-%2d", start, end)); + checkArgument(start >= 0, "start must be >= 0"); + checkArgument(end >= 0, "end must be >= 0"); + ranges.add(String.format("%d-%d", start, end)); + return this; + } + + /** + * download the object offset at start + */ + public GetObjectOptions startAt(long start) { + checkArgument(start >= 0, "start must be >= 0"); + ranges.add(String.format("%d-", start)); + return this; + } + + /** + * download the last count bytes of the object + */ + public GetObjectOptions tail(long count) { + checkArgument(count > 0, "count must be > 0"); + ranges.add(String.format("-%d", count)); return this; } @@ -78,7 +108,8 @@ public class GetObjectOptions extends BaseHttpRequestOptions { * @see GetObjectOptions#range(long, long) */ public String getRange() { - return this.getFirstHeaderOrNull(S3Headers.RANGE); + return (ranges.size() > 0) ? String.format("bytes=%s", Joiner.on(",") + .join(ranges)) : null; } /** @@ -88,11 +119,11 @@ public class GetObjectOptions extends BaseHttpRequestOptions { * {@link #ifUnmodifiedSince(DateTime)} */ public GetObjectOptions ifModifiedSince(DateTime ifModifiedSince) { - checkState(getIfMatch() == null, + checkArgument(getIfMatch() == null, "ifMd5Matches() is not compatible with ifModifiedSince()"); - checkState(getIfUnmodifiedSince() == null, + checkArgument(getIfUnmodifiedSince() == null, "ifUnmodifiedSince() is not compatible with ifModifiedSince()"); - this.headers.put(S3Headers.OBJECT_IF_MODIFIED_SINCE, + this.headers.put(HttpHeaders.IF_MODIFIED_SINCE, dateService.toHeaderString(checkNotNull(ifModifiedSince, "ifModifiedSince"))); return this; @@ -107,7 +138,7 @@ public class GetObjectOptions extends BaseHttpRequestOptions { * @see GetObjectOptions#ifModifiedSince(DateTime) */ public String getIfModifiedSince() { - return this.getFirstHeaderOrNull(S3Headers.OBJECT_IF_MODIFIED_SINCE); + return this.getFirstHeaderOrNull(HttpHeaders.IF_MODIFIED_SINCE); } /** @@ -117,11 +148,11 @@ public class GetObjectOptions extends BaseHttpRequestOptions { * {@link #ifModifiedSince(DateTime)} */ public GetObjectOptions ifUnmodifiedSince(DateTime ifUnmodifiedSince) { - checkState(getIfNoneMatch() == null, + checkArgument(getIfNoneMatch() == null, "ifMd5DoesntMatch() is not compatible with ifUnmodifiedSince()"); - checkState(getIfModifiedSince() == null, + checkArgument(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifUnmodifiedSince()"); - this.headers.put(S3Headers.OBJECT_IF_UNMODIFIED_SINCE, dateService + this.headers.put(HttpHeaders.IF_UNMODIFIED_SINCE, dateService .toHeaderString(checkNotNull(ifUnmodifiedSince, "ifUnmodifiedSince"))); return this; @@ -136,7 +167,7 @@ public class GetObjectOptions extends BaseHttpRequestOptions { * @see GetObjectOptions#ifUnmodifiedSince(DateTime) */ public String getIfUnmodifiedSince() { - return this.getFirstHeaderOrNull(S3Headers.OBJECT_IF_UNMODIFIED_SINCE); + return this.getFirstHeaderOrNull(HttpHeaders.IF_UNMODIFIED_SINCE); } /** @@ -153,11 +184,11 @@ public class GetObjectOptions extends BaseHttpRequestOptions { */ public GetObjectOptions ifMd5Matches(byte[] md5) throws UnsupportedEncodingException { - checkState(getIfNoneMatch() == null, + checkArgument(getIfNoneMatch() == null, "ifMd5DoesntMatch() is not compatible with ifMd5Matches()"); - checkState(getIfModifiedSince() == null, + checkArgument(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifMd5Matches()"); - this.headers.put(S3Headers.OBJECT_IF_MATCH, String.format("\"%1s\"", + this.headers.put(HttpHeaders.IF_MATCH, String.format("\"%1$s\"", S3Utils.toHexString(checkNotNull(md5, "md5")))); return this; } @@ -171,7 +202,7 @@ public class GetObjectOptions extends BaseHttpRequestOptions { * @see GetObjectOptions#ifMd5Matches(String) */ public String getIfMatch() { - return this.getFirstHeaderOrNull(S3Headers.OBJECT_IF_MATCH); + return this.getFirstHeaderOrNull(HttpHeaders.IF_MATCH); } /** @@ -188,13 +219,12 @@ public class GetObjectOptions extends BaseHttpRequestOptions { */ public GetObjectOptions ifMd5DoesntMatch(byte[] md5) throws UnsupportedEncodingException { - checkState(getIfMatch() == null, + checkArgument(getIfMatch() == null, "ifMd5Matches() is not compatible with ifMd5DoesntMatch()"); - checkState(getIfUnmodifiedSince() == null, + checkArgument(getIfUnmodifiedSince() == null, "ifUnmodifiedSince() is not compatible with ifMd5DoesntMatch()"); - this.headers.put(S3Headers.OBJECT_IF_NONE_MATCH, String.format( - "\"%1s\"", S3Utils.toHexString(checkNotNull(md5, - "ifMd5DoesntMatch")))); + this.headers.put(HttpHeaders.IF_NONE_MATCH, String.format("\"%1$s\"", + S3Utils.toHexString(checkNotNull(md5, "ifMd5DoesntMatch")))); return this; } @@ -207,7 +237,8 @@ public class GetObjectOptions extends BaseHttpRequestOptions { * @see GetObjectOptions#ifMd5DoesntMatch(String) */ public String getIfNoneMatch() { - return this.getFirstHeaderOrNull(S3Headers.OBJECT_IF_NONE_MATCH); + return this + .getFirstHeaderOrNull(org.jclouds.http.HttpHeaders.IF_NONE_MATCH); } public static class Builder { @@ -219,7 +250,23 @@ public class GetObjectOptions extends BaseHttpRequestOptions { GetObjectOptions options = new GetObjectOptions(); return options.range(start, end); } + + /** + * @see GetObjectOptions#startAt(long) + */ + public static GetObjectOptions startAt(long start) { + GetObjectOptions options = new GetObjectOptions(); + return options.startAt(start); + } + /** + * @see GetObjectOptions#tail(long) + */ + public static GetObjectOptions tail(long count) { + GetObjectOptions options = new GetObjectOptions(); + return options.tail(count); + } + /** * @see GetObjectOptions#getIfModifiedSince() */ diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutBucketOptions.java b/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutBucketOptions.java index f198978d01..9f5d540f12 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutBucketOptions.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutBucketOptions.java @@ -23,11 +23,12 @@ */ package org.jclouds.aws.s3.commands.options; -import org.jclouds.aws.s3.S3Headers; import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.http.options.BaseHttpRequestOptions; + import static com.google.common.base.Preconditions.*; /** @@ -38,7 +39,7 @@ import static com.google.common.base.Preconditions.*; *

* * import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.* - * import static org.jclouds.aws.s3.domain.S3Bucket.MetaData.LocationConstraint.*; + * import static org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint.*; * import org.jclouds.aws.s3.S3Connection; * * S3Connection connection = // get connection @@ -64,7 +65,7 @@ public class PutBucketOptions extends BaseHttpRequestOptions { this.constraint = checkNotNull(constraint, "constraint"); this.payload = String .format( - "%1s", + "%1$s", constraint.toString()); return this; } diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutObjectOptions.java b/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutObjectOptions.java index eb627719d8..615faca8af 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutObjectOptions.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutObjectOptions.java @@ -23,10 +23,11 @@ */ package org.jclouds.aws.s3.commands.options; -import org.jclouds.aws.s3.S3Headers; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.http.options.BaseHttpRequestOptions; + import static com.google.common.base.Preconditions.*; /** diff --git a/s3/src/main/java/org/jclouds/aws/s3/config/S3ContextModule.java b/s3/src/main/java/org/jclouds/aws/s3/config/S3ContextModule.java index ebffe43428..6185d800e9 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/config/S3ContextModule.java +++ b/s3/src/main/java/org/jclouds/aws/s3/config/S3ContextModule.java @@ -38,6 +38,7 @@ import org.jclouds.aws.s3.internal.GuiceS3Context; import org.jclouds.aws.s3.internal.LiveS3Connection; import org.jclouds.aws.s3.internal.LiveS3InputStreamMap; import org.jclouds.aws.s3.internal.LiveS3ObjectMap; +import org.jclouds.http.CloseContentAndSetExceptionHandler; import org.jclouds.http.HttpConstants; import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpResponseHandler; @@ -88,13 +89,14 @@ public class S3ContextModule extends AbstractModule { LiveS3InputStreamMap.class)); bind(S3Context.class).to(GuiceS3Context.class); bind(HttpResponseHandler.class).annotatedWith(RedirectHandler.class) - .to(ParseS3ErrorFromXmlContent.class).in(Scopes.SINGLETON); + .to(CloseContentAndSetExceptionHandler.class).in( + Scopes.SINGLETON); bind(HttpResponseHandler.class).annotatedWith(ClientErrorHandler.class) .to(ParseS3ErrorFromXmlContent.class).in(Scopes.SINGLETON); bind(HttpResponseHandler.class).annotatedWith(ServerErrorHandler.class) .to(ParseS3ErrorFromXmlContent.class).in(Scopes.SINGLETON); requestInjection(this); - logger.info("S3 Context = %1s://%2s:%3s", + logger.info("S3 Context = %1$s://%2$s:%3$s", (isSecure ? "https" : "http"), address, port); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/domain/S3Owner.java b/s3/src/main/java/org/jclouds/aws/s3/domain/CanonicalUser.java similarity index 51% rename from s3/src/main/java/org/jclouds/aws/s3/domain/S3Owner.java rename to s3/src/main/java/org/jclouds/aws/s3/domain/CanonicalUser.java index 1930f317da..fb100ca548 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/domain/S3Owner.java +++ b/s3/src/main/java/org/jclouds/aws/s3/domain/CanonicalUser.java @@ -24,47 +24,69 @@ package org.jclouds.aws.s3.domain; /** - * // TODO: Adrian: Document this! - * + * 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. + *

+ * + * @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html? + * RESTAccessPolicy.html * @author Adrian Cole */ -public class S3Owner { - private String id; +public class CanonicalUser { + private final String id; private String displayName; - public String getId() { - return id; + public CanonicalUser(String id) { + this.id = id; } - public void setId(String id) { - this.id = id; + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("S3Owner"); + sb.append("{id='").append(id).append('\''); + sb.append(", displayName='").append(displayName).append('\''); + sb.append('}'); + return sb.toString(); + } + + public String getId() { + return id; } public String getDisplayName() { - return displayName; + return displayName; } public void setDisplayName(String displayName) { - this.displayName = displayName; + this.displayName = displayName; } @Override public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof S3Owner)) return false; + if (this == o) + return true; + if (!(o instanceof CanonicalUser)) + return false; - S3Owner s3Owner = (S3Owner) o; + CanonicalUser s3Owner = (CanonicalUser) o; - if (displayName != null ? !displayName.equals(s3Owner.displayName) : s3Owner.displayName != null) return false; - if (!id.equals(s3Owner.id)) return false; + if (displayName != null ? !displayName.equals(s3Owner.displayName) + : s3Owner.displayName != null) + return false; + if (!id.equals(s3Owner.id)) + return false; - return true; + return true; } @Override public int hashCode() { - int result = id.hashCode(); - result = 31 * result + (displayName != null ? displayName.hashCode() : 0); - return result; + int result = id.hashCode(); + result = 31 * result + + (displayName != null ? displayName.hashCode() : 0); + return result; } } diff --git a/s3/src/main/java/org/jclouds/aws/s3/domain/S3Bucket.java b/s3/src/main/java/org/jclouds/aws/s3/domain/S3Bucket.java index db18f5e476..4469759a3a 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/domain/S3Bucket.java +++ b/s3/src/main/java/org/jclouds/aws/s3/domain/S3Bucket.java @@ -42,7 +42,7 @@ public class S3Bucket { public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("S3Bucket"); - sb.append("{metaData=").append(metaData); + sb.append("{metadata=").append(metadata); sb.append(", isComplete=").append(isComplete); sb.append('}'); return sb.toString(); @@ -59,7 +59,7 @@ public class S3Bucket { if (isComplete != s3Bucket.isComplete) return false; - if (!metaData.equals(s3Bucket.metaData)) + if (!metadata.equals(s3Bucket.metadata)) return false; if (objects != null ? !objects.equals(s3Bucket.objects) : s3Bucket.objects != null) @@ -71,7 +71,7 @@ public class S3Bucket { @Override public int hashCode() { int result = objects != null ? objects.hashCode() : 0; - result = 31 * result + metaData.hashCode(); + result = 31 * result + metadata.hashCode(); result = 31 * result + (isComplete ? 1 : 0); return result; } @@ -80,7 +80,7 @@ public class S3Bucket { @Override public String toString() { final StringBuilder sb = new StringBuilder(); - sb.append("MetaData"); + sb.append("Metadata"); sb.append("{name='").append(name).append('\''); sb.append(", creationDate=").append(creationDate); sb.append(", canonicalUser=").append(canonicalUser); @@ -95,17 +95,12 @@ public class S3Bucket { if (!(o instanceof Metadata)) return false; - Metadata metaData = (Metadata) o; - + Metadata metadata = (Metadata) o; if (canonicalUser != null ? !canonicalUser - .equals(metaData.canonicalUser) - : metaData.canonicalUser != null) + .equals(metadata.canonicalUser) + : metadata.canonicalUser != null) return false; - if (creationDate != null ? !creationDate - .equals(metaData.creationDate) - : metaData.creationDate != null) - return false; - if (!name.equals(metaData.name)) + if (!name.equals(metadata.name)) return false; return true; @@ -114,8 +109,6 @@ public class S3Bucket { @Override public int hashCode() { int result = name.hashCode(); - result = 31 * result - + (creationDate != null ? creationDate.hashCode() : 0); result = 31 * result + (canonicalUser != null ? canonicalUser.hashCode() : 0); return result; @@ -127,7 +120,7 @@ public class S3Bucket { private final String name; private DateTime creationDate; - private S3Owner canonicalUser; + private CanonicalUser canonicalUser; public Metadata(String name) { this.name = checkNotNull(name, "name"); @@ -145,11 +138,17 @@ public class S3Bucket { this.creationDate = creationDate; } - public S3Owner getCanonicalUser() { + /** + * 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; } - public void setCanonicalUser(S3Owner canonicalUser) { + public void setOwner(CanonicalUser canonicalUser) { this.canonicalUser = canonicalUser; } @@ -163,20 +162,20 @@ public class S3Bucket { private String marker; private String delimiter; private long maxKeys; - private final Metadata metaData; + private final Metadata metadata; private boolean isComplete; public S3Bucket(String name) { - this.metaData = new Metadata(name); + this.metadata = new Metadata(name); } public String getName() { - return this.metaData.getName(); + return this.metadata.getName(); } - public S3Bucket(Metadata metaData) { - this.metaData = checkNotNull(metaData, "metaData"); + public S3Bucket(Metadata metadata) { + this.metadata = checkNotNull(metadata, "metadata"); } public Set getContents() { @@ -195,8 +194,8 @@ public class S3Bucket { isComplete = complete; } - public Metadata getMetaData() { - return metaData; + public Metadata getMetadata() { + return metadata; } public void setCommonPrefixes(Set commonPrefixes) { diff --git a/s3/src/main/java/org/jclouds/aws/s3/domain/S3Error.java b/s3/src/main/java/org/jclouds/aws/s3/domain/S3Error.java index 737c1880a0..da333802cc 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/domain/S3Error.java +++ b/s3/src/main/java/org/jclouds/aws/s3/domain/S3Error.java @@ -23,17 +23,25 @@ */ package org.jclouds.aws.s3.domain; +import java.util.HashMap; +import java.util.Map; + +/** + * When an Amazon S3 request is in error, the client receives an error response. + * + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?ErrorResponse + * .html + * @author Adrian Cole + * + */ public class S3Error { private String code; private String message; - private String resource; private String requestId; - private String hostId; - private String header; - private String signatureProvided; - private String stringToSign; + private String requestToken; + private Map details = new HashMap(); private String stringSigned; - private String stringToSignBytes; @Override public String toString() { @@ -41,17 +49,12 @@ public class S3Error { sb.append("S3Error"); sb.append("{code='").append(code).append('\''); sb.append(", message='").append(message).append('\''); - sb.append(", resource='").append(resource).append('\''); sb.append(", requestId='").append(requestId).append('\''); - sb.append(", hostId='").append(hostId).append('\''); - sb.append(", header='").append(header).append('\''); - sb.append(", signatureProvided='").append(signatureProvided).append( - '\''); - sb.append(", stringToSign='").append(stringToSign).append('\''); - sb.append(", stringSigned='").append(getStringSigned()).append('\''); - sb.append(", stringToSignBytes='").append(stringToSignBytes).append( - '\''); - sb.append('}'); + sb.append(", requestToken='").append(requestToken).append('\''); + if (stringSigned != null) + sb.append(", stringSigned='").append(stringSigned).append('\''); + sb.append(", context='").append(details.toString()).append('\'') + .append('}'); return sb.toString(); } @@ -59,6 +62,13 @@ public class S3Error { this.code = code; } + /** + * The error code is a string that uniquely identifies an error condition. + * It is meant to be read and understood by programs that detect and handle + * errors by type + * + * @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/ErrorCode.html + */ public String getCode() { return code; } @@ -67,71 +77,58 @@ public class S3Error { this.message = message; } + /** + * The error message contains a generic description of the error condition + * in English. + * + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/ErrorMessage.html + */ public String getMessage() { return message; } - public void setResource(String resource) { - this.resource = resource; - } - - public String getResource() { - return resource; - } - public void setRequestId(String requestId) { this.requestId = requestId; } + /** + * * A unique ID assigned to each request by the system. In the unlikely + * event that you have problems with Amazon S3, Amazon can use this to help + * troubleshoot the problem. + * + */ public String getRequestId() { return requestId; } - public void setHostId(String hostId) { - this.hostId = hostId; - } - - public String getHostId() { - return hostId; - } - - public void setSignatureProvided(String signatureProvided) { - this.signatureProvided = signatureProvided; - } - - public String getSignatureProvided() { - return signatureProvided; - } - - public void setStringToSign(String stringToSign) { - this.stringToSign = stringToSign; - } - - public String getStringToSign() { - return stringToSign; - } - - public void setStringToSignBytes(String stringToSignBytes) { - this.stringToSignBytes = stringToSignBytes; - } - - public String getStringToSignBytes() { - return stringToSignBytes; - } - - public void setHeader(String header) { - this.header = header; - } - - public String getHeader() { - return header; - } - public void setStringSigned(String stringSigned) { this.stringSigned = stringSigned; } + /** + * @return what jclouds signed before sending the request. + */ public String getStringSigned() { return stringSigned; } + + public void setDetails(Map context) { + this.details = context; + } + + /** + * @return additional details surrounding the error. + */ + public Map getDetails() { + return details; + } + + public void setRequestToken(String requestToken) { + this.requestToken = requestToken; + } + + public String getRequestToken() { + return requestToken; + } } diff --git a/s3/src/main/java/org/jclouds/aws/s3/domain/S3Object.java b/s3/src/main/java/org/jclouds/aws/s3/domain/S3Object.java index 1e3c2e238e..373bbc3806 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/domain/S3Object.java +++ b/s3/src/main/java/org/jclouds/aws/s3/domain/S3Object.java @@ -31,8 +31,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.Arrays; -import org.jclouds.aws.s3.S3Utils; -import org.jclouds.aws.s3.S3Utils.Md5InputStreamResult; +import org.jclouds.aws.s3.util.S3Utils; +import org.jclouds.aws.s3.util.S3Utils.Md5InputStreamResult; import org.jclouds.http.ContentTypes; import org.joda.time.DateTime; @@ -48,18 +48,20 @@ public class S3Object { public static final S3Object NOT_FOUND = new S3Object(Metadata.NOT_FOUND); private Object data; - private Metadata metaData; + private Metadata metadata; + private long contentLength = -1; + private String contentRange; public S3Object(String key) { this(new Metadata(key)); } - public S3Object(Metadata metaData) { - this.metaData = metaData; + public S3Object(Metadata metadata) { + this.metadata = metadata; } - public S3Object(Metadata metaData, Object data) { - this(metaData); + public S3Object(Metadata metadata, Object data) { + this(metadata); setData(data); } @@ -77,6 +79,7 @@ public class S3Object { private volatile long size = -1; // only parsed during head or get + private Multimap allHeaders = HashMultimap.create(); private Multimap userMetadata = HashMultimap.create(); private DateTime lastModified; private String dataType = ContentTypes.UNKNOWN_MIME_TYPE; @@ -85,7 +88,7 @@ public class S3Object { private String dataEncoding; // only parsed on list - private S3Owner owner = null; + private CanonicalUser owner = null; private String storageClass = null; public Metadata(String key) { @@ -97,7 +100,7 @@ public class S3Object { @Override public String toString() { final StringBuilder sb = new StringBuilder(); - sb.append("MetaData"); + sb.append("Metadata"); sb.append("{key='").append(key).append('\''); sb.append(", lastModified=").append(lastModified); sb.append(", md5=").append( @@ -116,20 +119,20 @@ public class S3Object { if (!(o instanceof Metadata)) return false; - Metadata metaData = (Metadata) o; + Metadata metadata = (Metadata) o; - if (size != metaData.size) + if (size != metadata.size) return false; - if (dataType != null ? !dataType.equals(metaData.dataType) - : metaData.dataType != null) + if (dataType != null ? !dataType.equals(metadata.dataType) + : metadata.dataType != null) return false; - if (!key.equals(metaData.key)) + if (!key.equals(metadata.key)) return false; if (lastModified != null ? !lastModified - .equals(metaData.lastModified) - : metaData.lastModified != null) + .equals(metadata.lastModified) + : metadata.lastModified != null) return false; - if (!Arrays.equals(getMd5(), metaData.getMd5())) + if (!Arrays.equals(getMd5(), metadata.getMd5())) return false; return true; } @@ -190,11 +193,17 @@ public class S3Object { return userMetadata; } - public void setOwner(S3Owner owner) { + public void setOwner(CanonicalUser owner) { this.owner = owner; } - public S3Owner getOwner() { + /** + * 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 owner; } @@ -229,16 +238,24 @@ public class S3Object { public String getContentEncoding() { return dataEncoding; } + + public void setAllHeaders(Multimap allHeaders) { + this.allHeaders = allHeaders; + } + + public Multimap getAllHeaders() { + return allHeaders; + } } public String getKey() { - return metaData.getKey(); + return metadata.getKey(); } public void setData(Object data) { this.data = checkNotNull(data, "data"); - if (getMetaData().getSize() == -1) - this.getMetaData().setSize(S3Utils.calculateSize(data)); + if (getMetadata().getSize() == -1) + this.getMetadata().setSize(S3Utils.calculateSize(data)); } public void generateMd5() throws IOException { @@ -246,11 +263,11 @@ public class S3Object { if (data instanceof InputStream) { Md5InputStreamResult result = S3Utils .generateMd5Result((InputStream) data); - getMetaData().setSize(result.length); - getMetaData().setMd5(result.md5); + getMetadata().setSize(result.length); + getMetadata().setMd5(result.md5); setData(result.data); } else { - getMetaData().setMd5(S3Utils.md5(data)); + getMetadata().setMd5(S3Utils.md5(data)); } } @@ -258,19 +275,19 @@ public class S3Object { return data; } - public void setMetaData(Metadata metaData) { - this.metaData = metaData; + public void setMetadata(Metadata metadata) { + this.metadata = metadata; } - public Metadata getMetaData() { - return metaData; + public Metadata getMetadata() { + return metadata; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("S3Object"); - sb.append("{metaData=").append(metaData); + sb.append("{metadata=").append(metadata); sb.append('}'); return sb.toString(); } @@ -286,7 +303,7 @@ public class S3Object { if (data != null ? !data.equals(s3Object.data) : s3Object.data != null) return false; - if (!metaData.equals(s3Object.metaData)) + if (!metadata.equals(s3Object.metadata)) return false; return true; @@ -295,8 +312,24 @@ public class S3Object { @Override public int hashCode() { int result = data != null ? data.hashCode() : 0; - result = 31 * result + metaData.hashCode(); + result = 31 * result + metadata.hashCode(); return result; } + public void setContentLength(long contentLength) { + this.contentLength = contentLength; + } + + public long getContentLength() { + return contentLength; + } + + public void setContentRange(String contentRange) { + this.contentRange = contentRange; + } + + public String getContentRange() { + return contentRange; + } + } diff --git a/s3/src/main/java/org/jclouds/aws/s3/filters/ParseS3ErrorFromXmlContent.java b/s3/src/main/java/org/jclouds/aws/s3/filters/ParseS3ErrorFromXmlContent.java index 3259ce77ad..0fbf54076f 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/filters/ParseS3ErrorFromXmlContent.java +++ b/s3/src/main/java/org/jclouds/aws/s3/filters/ParseS3ErrorFromXmlContent.java @@ -30,13 +30,14 @@ import javax.annotation.Resource; import org.apache.commons.io.IOUtils; import org.jclouds.aws.s3.S3ResponseException; import org.jclouds.aws.s3.domain.S3Error; +import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.xml.S3ParserFactory; -import org.jclouds.http.HttpException; import org.jclouds.http.HttpFutureCommand; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponseHandler; import org.jclouds.logging.Logger; + import com.google.inject.Inject; /** @@ -57,29 +58,26 @@ public class ParseS3ErrorFromXmlContent implements HttpResponseHandler { } public void handle(HttpFutureCommand command, HttpResponse response) { - int code = response.getStatusCode(); - if (code >= 300) { - InputStream errorStream = response.getContent(); + S3Error error = new S3Error(); + error.setRequestId(response.getFirstHeaderOrNull(S3Headers.REQUEST_ID)); + error.setRequestToken(response + .getFirstHeaderOrNull(S3Headers.REQUEST_TOKEN)); + InputStream errorStream = response.getContent(); + try { if (errorStream != null) { - try { - S3Error error = parserFactory.createErrorParser().parse( - errorStream); - if ("SignatureDoesNotMatch".equals(error.getCode())) - error.setStringSigned(RequestAuthorizeSignature - .createStringToSign(command.getRequest())); - logger.trace("received the following error from s3: %1s", - error); - command.setException(new S3ResponseException(command, - response, error)); - } catch (HttpException he) { - logger.error(he, "error parsing response %1s", response); - } finally { - IOUtils.closeQuietly(errorStream); - } - } else { - command - .setException(new S3ResponseException(command, response)); + error = parserFactory.createErrorParser().parse(errorStream); + if ("SignatureDoesNotMatch".equals(error.getCode())) + error.setStringSigned(RequestAuthorizeSignature + .createStringToSign(command.getRequest())); + error.setRequestToken(response + .getFirstHeaderOrNull(S3Headers.REQUEST_TOKEN)); } + } catch (Exception e) { + logger.warn(e, "error parsing XML reponse: %1$s", response); + } finally { + command.setException(new S3ResponseException(command, response, + error)); + IOUtils.closeQuietly(errorStream); } } diff --git a/s3/src/main/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignature.java b/s3/src/main/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignature.java index cff0889998..281c827638 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignature.java +++ b/s3/src/main/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignature.java @@ -29,14 +29,15 @@ import java.util.TreeSet; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import org.jclouds.aws.s3.DateService; -import org.jclouds.aws.s3.S3Constants; -import org.jclouds.aws.s3.S3Utils; +import org.jclouds.aws.s3.reference.S3Constants; +import org.jclouds.aws.s3.util.DateService; +import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.http.HttpException; import org.jclouds.http.HttpHeaders; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequestFilter; + import com.google.inject.Inject; import com.google.inject.name.Named; diff --git a/s3/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java b/s3/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java index a307eb80d7..c749796a7a 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java +++ b/s3/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java @@ -31,7 +31,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -40,16 +39,16 @@ import java.util.concurrent.TimeoutException; import org.jclouds.Utils; import org.jclouds.aws.s3.S3Connection; -import org.jclouds.aws.s3.S3Constants; import org.jclouds.aws.s3.S3Map; import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Object; +import org.jclouds.aws.s3.reference.S3Constants; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.inject.name.Named; -public abstract class BaseS3Map implements Map, S3Map { +public abstract class BaseS3Map implements S3Map { protected final S3Connection connection; protected final String bucket; @@ -88,8 +87,8 @@ public abstract class BaseS3Map implements Map, S3Map { protected boolean containsMd5(byte[] md5) throws InterruptedException, ExecutionException, TimeoutException { - for (S3Object.Metadata metaData : refreshBucket().getContents()) { - if (Arrays.equals(md5, metaData.getMd5())) + for (S3Object.Metadata metadata : refreshBucket().getContents()) { + if (Arrays.equals(md5, metadata.getMd5())) return true; } return false; @@ -104,9 +103,9 @@ public abstract class BaseS3Map implements Map, S3Map { } else { object = new S3Object("dummy", value); } - if (object.getMetaData().getMd5() == null) + if (object.getMetadata().getMd5() == null) object.generateMd5(); - return object.getMetaData().getMd5(); + return object.getMetadata().getMd5(); } protected Set getAllObjects() { @@ -123,7 +122,7 @@ public abstract class BaseS3Map implements Map, S3Map { } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3RuntimeException(String.format( - "Error getting value from bucket %1s:%2s", bucket, + "Error getting value from bucket %1$s:%2$s", bucket, object != null ? object.getKey() : "unknown"), e); } if (object != S3Object.NOT_FOUND) @@ -146,7 +145,7 @@ public abstract class BaseS3Map implements Map, S3Map { } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3RuntimeException(String.format( - "Error searching for ETAG of value: [%2s] in bucket:%1s", + "Error searching for ETAG of value: [%2$s] in bucket:%1$s", bucket, value), e); } } @@ -210,7 +209,7 @@ public abstract class BaseS3Map implements Map, S3Map { } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3RuntimeException(String.format( - "Error searching for %1s:%2s", bucket, key), e); + "Error searching for %1$s:%2$s", bucket, key), e); } } diff --git a/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3Connection.java b/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3Connection.java index 246cc3cad1..70b2bbaa62 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3Connection.java +++ b/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3Connection.java @@ -31,9 +31,9 @@ import org.jclouds.aws.s3.commands.BucketExists; import org.jclouds.aws.s3.commands.CopyObject; import org.jclouds.aws.s3.commands.DeleteBucket; import org.jclouds.aws.s3.commands.DeleteObject; -import org.jclouds.aws.s3.commands.GetMetaDataForOwnedBuckets; +import org.jclouds.aws.s3.commands.ListOwnedBuckets; import org.jclouds.aws.s3.commands.GetObject; -import org.jclouds.aws.s3.commands.HeadMetaData; +import org.jclouds.aws.s3.commands.HeadObject; import org.jclouds.aws.s3.commands.ListBucket; import org.jclouds.aws.s3.commands.PutBucket; import org.jclouds.aws.s3.commands.PutObject; @@ -96,12 +96,12 @@ public class LiveS3Connection implements S3Connection { /** * {@inheritDoc} * - * @see HeadMetaData + * @see HeadObject */ public Future headObject(String s3Bucket, String key) { - HeadMetaData headMetaData = factory.createHeadMetaData(s3Bucket, key); - client.submit(headMetaData); - return headMetaData; + HeadObject headMetadata = factory.createHeadMetadata(s3Bucket, key); + client.submit(headMetadata); + return headMetadata; } /** @@ -230,11 +230,11 @@ public class LiveS3Connection implements S3Connection { /** * {@inheritDoc} * - * @see GetMetaDataForOwnedBuckets + * @see ListOwnedBuckets */ - public Future> getOwnedBuckets() { - GetMetaDataForOwnedBuckets listRequest = factory - .createGetMetaDataForOwnedBuckets(); + public Future> listOwnedBuckets() { + ListOwnedBuckets listRequest = factory + .createGetMetadataForOwnedBuckets(); client.submit(listRequest); return listRequest; } diff --git a/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3InputStreamMap.java b/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3InputStreamMap.java index b904a25925..9b3de25473 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3InputStreamMap.java +++ b/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3InputStreamMap.java @@ -69,7 +69,7 @@ public class LiveS3InputStreamMap extends BaseS3Map implements } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3RuntimeException(String.format( - "Error geting object %1s:%2s", bucket, o), e); + "Error geting object %1$s:%2$s", bucket, o), e); } } @@ -86,7 +86,7 @@ public class LiveS3InputStreamMap extends BaseS3Map implements } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3RuntimeException(String.format( - "Error removing object %1s:%2s", bucket, o), e); + "Error removing object %1$s:%2$s", bucket, o), e); } return old; } @@ -155,7 +155,7 @@ public class LiveS3InputStreamMap extends BaseS3Map implements } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3RuntimeException(String.format( - "Error adding object %1s:%2s", bucket, object), e); + "Error adding object %1$s:%2$s", bucket, object), e); } } diff --git a/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3ObjectMap.java b/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3ObjectMap.java index 894340130c..a34533e8ad 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3ObjectMap.java +++ b/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3ObjectMap.java @@ -92,7 +92,7 @@ public class LiveS3ObjectMap extends BaseS3Map implements S3ObjectMap } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3RuntimeException(String.format( - "Error geting object %1s:%2s", bucket, key), e); + "Error geting object %1$s:%2$s", bucket, key), e); } } @@ -104,7 +104,7 @@ public class LiveS3ObjectMap extends BaseS3Map implements S3ObjectMap } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3RuntimeException(String.format( - "Error putting object %1s:%2s%n%1s", bucket, key, value), e); + "Error putting object %1$s:%2$s%n%1$s", bucket, key, value), e); } return returnVal; } @@ -133,7 +133,7 @@ public class LiveS3ObjectMap extends BaseS3Map implements S3ObjectMap } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3RuntimeException(String.format( - "Error removing object %1s:%2s", bucket, key), e); + "Error removing object %1$s:%2$s", bucket, key), e); } return old; } diff --git a/s3/src/main/java/org/jclouds/aws/s3/package-info.java b/s3/src/main/java/org/jclouds/aws/s3/package-info.java new file mode 100644 index 0000000000..3da7692279 --- /dev/null +++ b/s3/src/main/java/org/jclouds/aws/s3/package-info.java @@ -0,0 +1,7 @@ +/** + * This package contains an Amazon S3 client implemented by {@link HttpFutureCommand} commands. + * + * @see http://aws.amazon.com/s3/ + * @author Adrian Cole + */ +package org.jclouds.aws.s3; \ No newline at end of file diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3Constants.java b/s3/src/main/java/org/jclouds/aws/s3/reference/S3Constants.java similarity index 97% rename from s3/src/main/java/org/jclouds/aws/s3/S3Constants.java rename to s3/src/main/java/org/jclouds/aws/s3/reference/S3Constants.java index 692fac62e2..e44b2c70d6 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3Constants.java +++ b/s3/src/main/java/org/jclouds/aws/s3/reference/S3Constants.java @@ -21,7 +21,7 @@ * under the License. * ==================================================================== */ -package org.jclouds.aws.s3; +package org.jclouds.aws.s3.reference; import org.jclouds.command.pool.PoolConstants; import org.jclouds.http.HttpConstants; diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3Headers.java b/s3/src/main/java/org/jclouds/aws/s3/reference/S3Headers.java similarity index 79% rename from s3/src/main/java/org/jclouds/aws/s3/S3Headers.java rename to s3/src/main/java/org/jclouds/aws/s3/reference/S3Headers.java index dbb8df0bb6..990dedec8f 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3Headers.java +++ b/s3/src/main/java/org/jclouds/aws/s3/reference/S3Headers.java @@ -21,9 +21,11 @@ * under the License. * ==================================================================== */ -package org.jclouds.aws.s3; +package org.jclouds.aws.s3.reference; -public interface S3Headers { +import org.jclouds.http.HttpHeaders; + +public interface S3Headers extends HttpHeaders{ /** * The canned ACL to apply to the object. Options include private, @@ -38,12 +40,8 @@ public interface S3Headers { * 8 KB. */ public static final String USER_METADATA_PREFIX = "x-amz-meta-"; - public static final String ETAG = "ETag"; public static final String AMZ_MD5 = "x-amz-meta-object-md5"; - public static final String RANGE = "Range"; - public static final String OBJECT_IF_MODIFIED_SINCE = "If-Modified-Since"; - public static final String OBJECT_IF_UNMODIFIED_SINCE = "If-Unmodified-Since"; - public static final String OBJECT_IF_MATCH = "If-Match"; - public static final String OBJECT_IF_NONE_MATCH = "If-None-Match"; + public static final String REQUEST_ID = "x-amz-request-id"; + public static final String REQUEST_TOKEN = "x-amz-id-2"; } \ No newline at end of file diff --git a/s3/src/main/java/org/jclouds/aws/s3/DateService.java b/s3/src/main/java/org/jclouds/aws/s3/util/DateService.java similarity index 98% rename from s3/src/main/java/org/jclouds/aws/s3/DateService.java rename to s3/src/main/java/org/jclouds/aws/s3/util/DateService.java index b949d86466..f0a7bf13bd 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/DateService.java +++ b/s3/src/main/java/org/jclouds/aws/s3/util/DateService.java @@ -21,7 +21,7 @@ * under the License. * ==================================================================== */ -package org.jclouds.aws.s3; +package org.jclouds.aws.s3.util; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3Utils.java b/s3/src/main/java/org/jclouds/aws/s3/util/S3Utils.java similarity index 98% rename from s3/src/main/java/org/jclouds/aws/s3/S3Utils.java rename to s3/src/main/java/org/jclouds/aws/s3/util/S3Utils.java index 2d94cbeee7..7855d7513c 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3Utils.java +++ b/s3/src/main/java/org/jclouds/aws/s3/util/S3Utils.java @@ -21,7 +21,7 @@ * under the License. * ==================================================================== */ -package org.jclouds.aws.s3; +package org.jclouds.aws.s3.util; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @@ -231,7 +231,7 @@ public class S3Utils extends Utils { if (o instanceof InputStream) { String returnVal = toStringAndClose((InputStream) o); - if (object.getMetaData().getContentType().indexOf("xml") >= 0) { + if (object.getMetadata().getContentType().indexOf("xml") >= 0) { } return returnVal; diff --git a/s3/src/main/java/org/jclouds/aws/s3/xml/CopyObjectHandler.java b/s3/src/main/java/org/jclouds/aws/s3/xml/CopyObjectHandler.java index 11891aa84a..40e9f2e531 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/xml/CopyObjectHandler.java +++ b/s3/src/main/java/org/jclouds/aws/s3/xml/CopyObjectHandler.java @@ -23,9 +23,9 @@ */ package org.jclouds.aws.s3.xml; -import org.jclouds.aws.s3.DateService; -import org.jclouds.aws.s3.S3Utils; import org.jclouds.aws.s3.domain.S3Object; +import org.jclouds.aws.s3.util.DateService; +import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.http.commands.callables.xml.ParseSax; import com.google.inject.Inject; @@ -38,25 +38,25 @@ import com.google.inject.Inject; public class CopyObjectHandler extends ParseSax.HandlerWithResult { - private S3Object.Metadata metaData; + private S3Object.Metadata metadata; private StringBuilder currentText = new StringBuilder(); @Inject private DateService dateParser; public void setKey(String key) { - metaData = new S3Object.Metadata(key); + metadata = new S3Object.Metadata(key); } public S3Object.Metadata getResult() { - return metaData; + return metadata; } public void endElement(String uri, String name, String qName) { if (qName.equals("ETag")) { - metaData.setMd5(S3Utils.fromHexString(currentText.toString() + metadata.setMd5(S3Utils.fromHexString(currentText.toString() .replaceAll("\"", ""))); } else if (qName.equals("LastModified")) { - metaData.setLastModified(dateParser + metadata.setLastModified(dateParser .dateTimeFromXMLFormat(currentText.toString())); } currentText = new StringBuilder(); diff --git a/s3/src/main/java/org/jclouds/aws/s3/xml/ErrorHandler.java b/s3/src/main/java/org/jclouds/aws/s3/xml/ErrorHandler.java index 99b421322c..61cbc22a73 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/xml/ErrorHandler.java +++ b/s3/src/main/java/org/jclouds/aws/s3/xml/ErrorHandler.java @@ -29,6 +29,9 @@ import org.jclouds.http.commands.callables.xml.ParseSax; /** * Parses the error from the Amazon S3 REST API. * + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingRESTError + * .html * @author Adrian Cole */ public class ErrorHandler extends ParseSax.HandlerWithResult { @@ -46,20 +49,10 @@ public class ErrorHandler extends ParseSax.HandlerWithResult { error.setCode(currentText.toString()); } else if (qName.equals("Message")) { error.setMessage(currentText.toString()); - } else if (qName.equals("Resource")) { - error.setResource(currentText.toString()); } else if (qName.equals("RequestId")) { error.setRequestId(currentText.toString()); - } else if (qName.equals("HostId")) { - error.setHostId(currentText.toString()); - } else if (qName.equals("Header")) { - error.setHeader(currentText.toString()); - } else if (qName.equals("SignatureProvided")) { - error.setSignatureProvided(currentText.toString()); - } else if (qName.equals("StringToSign")) { - error.setStringToSign(currentText.toString()); - } else if (qName.equals("StringToSignBytes")) { - error.setStringToSignBytes(currentText.toString()); + } else if (!qName.equals("Error")) { + error.getDetails().put(qName, currentText.toString()); } currentText = new StringBuilder(); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/xml/ListAllMyBucketsHandler.java b/s3/src/main/java/org/jclouds/aws/s3/xml/ListAllMyBucketsHandler.java index a6fa09fcbd..592ea39e91 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/xml/ListAllMyBucketsHandler.java +++ b/s3/src/main/java/org/jclouds/aws/s3/xml/ListAllMyBucketsHandler.java @@ -26,17 +26,21 @@ package org.jclouds.aws.s3.xml; import java.util.ArrayList; import java.util.List; -import org.jclouds.aws.s3.DateService; +import org.jclouds.aws.s3.domain.CanonicalUser; import org.jclouds.aws.s3.domain.S3Bucket; -import org.jclouds.aws.s3.domain.S3Owner; +import org.jclouds.aws.s3.util.DateService; import org.jclouds.http.commands.callables.xml.ParseSax; -import org.xml.sax.Attributes; import com.google.inject.Inject; /** - * Parses the response from Amazon S3 GET Service command. + * Parses the following XML document: + *

+ * ListAllMyBucketsResult xmlns="http://doc.s3.amazonaws.com/2006-03-01" * + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTServiceGET + * .html * @author Adrian Cole */ public class ListAllMyBucketsHandler extends @@ -44,7 +48,7 @@ public class ListAllMyBucketsHandler extends private List buckets = new ArrayList(); private S3Bucket.Metadata currentS3Bucket; - private S3Owner currentOwner; + private CanonicalUser currentOwner; private StringBuilder currentText = new StringBuilder(); private final DateService dateParser; @@ -58,21 +62,13 @@ public class ListAllMyBucketsHandler extends return buckets; } - public void startElement(String uri, String name, String qName, - Attributes attrs) { - if (qName.equals("Bucket")) { - } else if (qName.equals("Owner")) { - currentOwner = new S3Owner(); - } - } - public void endElement(String uri, String name, String qName) { if (qName.equals("ID")) { // owner stuff - currentOwner.setId(currentText.toString()); + currentOwner = new CanonicalUser(currentText.toString()); } else if (qName.equals("DisplayName")) { currentOwner.setDisplayName(currentText.toString()); } else if (qName.equals("Bucket")) { - currentS3Bucket.setCanonicalUser(currentOwner); + currentS3Bucket.setOwner(currentOwner); buckets.add(currentS3Bucket); } else if (qName.equals("Name")) { currentS3Bucket = new S3Bucket.Metadata(currentText.toString()); diff --git a/s3/src/main/java/org/jclouds/aws/s3/xml/ListBucketHandler.java b/s3/src/main/java/org/jclouds/aws/s3/xml/ListBucketHandler.java index d0ccf4cbd0..aaed56537f 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/xml/ListBucketHandler.java +++ b/s3/src/main/java/org/jclouds/aws/s3/xml/ListBucketHandler.java @@ -25,82 +25,79 @@ package org.jclouds.aws.s3.xml; import static com.google.common.base.Preconditions.checkNotNull; -import org.jclouds.aws.s3.DateService; -import org.jclouds.aws.s3.S3Utils; +import org.jclouds.aws.s3.domain.CanonicalUser; import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Object; -import org.jclouds.aws.s3.domain.S3Owner; +import org.jclouds.aws.s3.util.DateService; +import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.http.commands.callables.xml.ParseSax; import org.xml.sax.Attributes; -import org.xml.sax.SAXException; import com.google.inject.Inject; /** - * // TODO: Adrian: Document this! + * Parses the following XML document: + *

+ * ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01" * + * @see http + * ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET + * .html * @author Adrian Cole */ public class ListBucketHandler extends ParseSax.HandlerWithResult { + private S3Bucket s3Bucket; + private S3Object.Metadata currentObjectMetadata; + private CanonicalUser currentOwner; + private StringBuilder currentText = new StringBuilder(); + + private final DateService dateParser; + + @Inject + public ListBucketHandler(DateService dateParser) { + this.dateParser = dateParser; + } public S3Bucket getResult() { return s3Bucket; } public void setBucketName(String bucketName) { - this.s3Bucket = new S3Bucket(bucketName); + this.s3Bucket = new S3Bucket(checkNotNull(bucketName, "bucketName")); } - private S3Bucket s3Bucket; - private S3Object.Metadata currentObjectMetaData; - private S3Owner currentOwner; - private StringBuilder currentText = new StringBuilder(); - @Inject - private DateService dateParser; private boolean inCommonPrefixes; - @Override - public void startDocument() throws SAXException { - checkNotNull(s3Bucket, "s3Bucket"); - s3Bucket.getContents().clear(); - s3Bucket.getCommonPrefixes().clear(); - super.startDocument(); - } - public void startElement(String uri, String name, String qName, Attributes attrs) { - if (qName.equals("Contents")) { - } else if (qName.equals("Owner")) { - currentOwner = new S3Owner(); - } else if (qName.equals("CommonPrefixes")) { + if (qName.equals("CommonPrefixes")) { inCommonPrefixes = true; } } public void endElement(String uri, String name, String qName) { - - if (qName.equals("ID")) { // owner stuff - currentOwner.setId(currentText.toString()); + if (qName.equals("ID")) { + currentOwner = new CanonicalUser(currentText.toString()); } else if (qName.equals("DisplayName")) { currentOwner.setDisplayName(currentText.toString()); } else if (qName.equals("Key")) { // content stuff - currentObjectMetaData = new S3Object.Metadata(currentText + currentObjectMetadata = new S3Object.Metadata(currentText .toString()); } else if (qName.equals("LastModified")) { - currentObjectMetaData.setLastModified(dateParser + currentObjectMetadata.setLastModified(dateParser .dateTimeFromXMLFormat(currentText.toString())); } else if (qName.equals("ETag")) { - currentObjectMetaData.setMd5(S3Utils.fromHexString(currentText + currentObjectMetadata.setMd5(S3Utils.fromHexString(currentText .toString().replaceAll("\"", ""))); } else if (qName.equals("Size")) { - currentObjectMetaData.setSize(Long + currentObjectMetadata.setSize(Long .parseLong(currentText.toString())); } else if (qName.equals("Owner")) { - currentObjectMetaData.setOwner(currentOwner); + currentObjectMetadata.setOwner(currentOwner); } else if (qName.equals("StorageClass")) { - currentObjectMetaData.setStorageClass(currentText.toString()); + currentObjectMetadata.setStorageClass(currentText.toString()); } else if (qName.equals("Contents")) { - s3Bucket.getContents().add(currentObjectMetaData); + s3Bucket.getContents().add(currentObjectMetadata); } else if (qName.equals("Name")) {// bucket stuff last, as least likely } else if (qName.equals("Prefix")) { String prefix = currentText.toString().trim(); diff --git a/s3/src/main/java/org/jclouds/aws/s3/xml/S3ParserFactory.java b/s3/src/main/java/org/jclouds/aws/s3/xml/S3ParserFactory.java index a0c2556cd1..1b9e98015c 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/xml/S3ParserFactory.java +++ b/s3/src/main/java/org/jclouds/aws/s3/xml/S3ParserFactory.java @@ -35,7 +35,9 @@ import com.google.inject.Inject; import com.google.inject.Provider; /** - * Creates Parsers needed to interpret S3 Server responses + * Creates Parsers needed to interpret S3 Server messages. This class uses guice + * assisted inject, which mandates the creation of many single-method + * interfaces. These interfaces are not intended for public api. * * @author Adrian Cole */ @@ -44,6 +46,7 @@ public class S3ParserFactory { @Inject private GenericParseFactory> parseListAllMyBucketsFactory; + @VisibleForTesting public static interface GenericParseFactory { ParseSax create(ParseSax.HandlerWithResult handler); } @@ -51,7 +54,9 @@ public class S3ParserFactory { @Inject Provider ListAllMyBucketsHandlerprovider; - @VisibleForTesting + /** + * @return a parser used to handle {@link ListOwnedBuckets} responses + */ public ParseSax> createListBucketsParser() { return parseListAllMyBucketsFactory .create(ListAllMyBucketsHandlerprovider.get()); @@ -63,7 +68,9 @@ public class S3ParserFactory { @Inject Provider ListBucketHandlerprovider; - @VisibleForTesting + /** + * @return a parser used to handle {@link ListBucket} responses + */ public ParseSax createListBucketParser() { return parseListBucketFactory.create(ListBucketHandlerprovider.get()); } @@ -74,7 +81,9 @@ public class S3ParserFactory { @Inject Provider copyObjectHandlerProvider; - @VisibleForTesting + /** + * @return a parser used to handle {@link CopyObject} responses + */ public ParseSax createCopyObjectParser() { return parseCopyObjectFactory.create(copyObjectHandlerProvider.get()); } @@ -85,6 +94,9 @@ public class S3ParserFactory { @Inject Provider errorHandlerProvider; + /** + * @return a parser used to handle error conditions. + */ public ParseSax createErrorParser() { return parseErrorFactory.create(errorHandlerProvider.get()); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java b/s3/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java index aa62aa2301..11ab8fca59 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java +++ b/s3/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java @@ -46,37 +46,23 @@ import com.google.inject.assistedinject.FactoryProvider; * @author Adrian Cole */ public class S3ParserModule extends AbstractModule { + private final TypeLiteral>> listBucketsTypeLiteral = new TypeLiteral>>() { + }; + private final TypeLiteral> bucketTypeLiteral = new TypeLiteral>() { + }; + private final TypeLiteral> objectMetadataTypeLiteral = new TypeLiteral>() { + }; + private final TypeLiteral> errorTypeLiteral = new TypeLiteral>() { + }; + @Override protected void configure() { install(new SaxModule()); + bindCallablesThatReturnParseResults(); + bindParserImplementationsToReturnTypes(); + } - final TypeLiteral>> listBucketsTypeLiteral = new TypeLiteral>>() { - }; - final TypeLiteral> bucketTypeLiteral = new TypeLiteral>() { - }; - final TypeLiteral> objectMetaDataTypeLiteral = new TypeLiteral>() { - }; - final TypeLiteral> errorTypeLiteral = new TypeLiteral>() { - }; - - bind(listBucketsTypeLiteral).toProvider( - FactoryProvider.newFactory(listBucketsTypeLiteral, - new TypeLiteral>>() { - })); - bind(bucketTypeLiteral).toProvider( - FactoryProvider.newFactory(bucketTypeLiteral, - new TypeLiteral>() { - })); - bind(objectMetaDataTypeLiteral).toProvider( - FactoryProvider.newFactory(objectMetaDataTypeLiteral, - new TypeLiteral>() { - })); - bind(errorTypeLiteral).toProvider( - FactoryProvider.newFactory(errorTypeLiteral, - new TypeLiteral>() { - })); - - // Bind the implementations of handlers to the interfaces they implement + private void bindParserImplementationsToReturnTypes() { bind( new TypeLiteral>>() { }).to(ListAllMyBucketsHandler.class); @@ -88,4 +74,23 @@ public class S3ParserModule extends AbstractModule { }).to(ErrorHandler.class); } + private void bindCallablesThatReturnParseResults() { + bind(listBucketsTypeLiteral).toProvider( + FactoryProvider.newFactory(listBucketsTypeLiteral, + new TypeLiteral>>() { + })); + bind(bucketTypeLiteral).toProvider( + FactoryProvider.newFactory(bucketTypeLiteral, + new TypeLiteral>() { + })); + bind(objectMetadataTypeLiteral).toProvider( + FactoryProvider.newFactory(objectMetadataTypeLiteral, + new TypeLiteral>() { + })); + bind(errorTypeLiteral).toProvider( + FactoryProvider.newFactory(errorTypeLiteral, + new TypeLiteral>() { + })); + } + } \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/S3ConnectionTest.java b/s3/src/test/java/org/jclouds/aws/s3/S3ConnectionTest.java index 34c8e391c7..424d045774 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/S3ConnectionTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/S3ConnectionTest.java @@ -40,7 +40,7 @@ public class S3ConnectionTest extends S3IntegrationTest { @Test void testListBuckets() throws Exception { - List myBuckets = client.getOwnedBuckets().get(10, + List myBuckets = client.listOwnedBuckets().get(10, TimeUnit.SECONDS); for (S3Bucket.Metadata bucket : myBuckets) { context.createInputStreamMap(bucket.getName()).size(); diff --git a/s3/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java index a5c5f6de01..99812c9157 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java @@ -46,6 +46,8 @@ import java.util.logging.Logger; import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Object; +import org.jclouds.aws.s3.reference.S3Constants; +import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.http.HttpConstants; import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule; import org.testng.annotations.AfterTest; @@ -54,10 +56,15 @@ import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; + import com.google.inject.Module; @Test public class S3IntegrationTest { + protected static final String TEST_STRING = ""; + + protected byte[] goodMd5; + protected byte[] badMd5; protected void createBucketAndEnsureEmpty(String sourceBucket) throws InterruptedException, ExecutionException, TimeoutException { @@ -66,13 +73,11 @@ public class S3IntegrationTest { .getContents().size(), 0); } - protected static final String TEST_STRING = ""; - protected void addObjectToBucket(String sourceBucket, String key) throws InterruptedException, ExecutionException, TimeoutException, IOException { S3Object sourceObject = new S3Object(key); - sourceObject.getMetaData().setContentType("text/xml"); + sourceObject.getMetadata().setContentType("text/xml"); sourceObject.setData(TEST_STRING); addObjectToBucket(sourceBucket, sourceObject); } @@ -146,6 +151,8 @@ public class S3IntegrationTest { : sysAWSSecretAccessKey); client = context.getConnection(); deleteEverything(); + goodMd5 = S3Utils.md5(TEST_STRING); + badMd5 = S3Utils.md5("alf"); } protected boolean debugEnabled() { @@ -168,7 +175,6 @@ public class S3IntegrationTest { checkNotNull(AWSSecretAccessKey, "AWSSecretAccessKey")); properties.setProperty(HttpConstants.PROPERTY_HTTP_SECURE, "false"); properties.setProperty(HttpConstants.PROPERTY_HTTP_PORT, "80"); - // properties.setProperty("jclouds.http.sax.debug", "true"); return properties; } @@ -178,10 +184,10 @@ public class S3IntegrationTest { protected void deleteEverything() throws Exception { try { - List metaData = client.getOwnedBuckets().get(10, + List metadata = client.listOwnedBuckets().get(10, TimeUnit.SECONDS); List> results = new ArrayList>(); - for (S3Bucket.Metadata metaDatum : metaData) { + for (S3Bucket.Metadata metaDatum : metadata) { if (metaDatum.getName().startsWith(bucketPrefix.toLowerCase())) { S3Bucket bucket = client.listBucket(metaDatum.getName()) .get(10, TimeUnit.SECONDS); diff --git a/s3/src/test/java/org/jclouds/aws/s3/S3ObjectMapTest.java b/s3/src/test/java/org/jclouds/aws/s3/S3ObjectMapTest.java index 84608d29d6..ac1602b42a 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/S3ObjectMapTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/S3ObjectMapTest.java @@ -37,6 +37,7 @@ import java.util.Map.Entry; import org.apache.commons.io.IOUtils; import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.internal.BaseS3Map; +import org.jclouds.aws.s3.util.S3Utils; import org.testng.annotations.Test; /** @@ -141,7 +142,7 @@ public class S3ObjectMapTest extends BaseS3MapTest { for (String key : fiveInputs.keySet()) { S3Object object = new S3Object(key); object.setData(fiveInputs.get(key)); - object.getMetaData().setSize(fiveBytes.get(key).length); + object.getMetadata().setSize(fiveBytes.get(key).length); newMap.put(key, object); } map.putAll(newMap); diff --git a/s3/src/test/java/org/jclouds/aws/s3/S3UtilsTest.java b/s3/src/test/java/org/jclouds/aws/s3/S3UtilsTest.java index 5837cd34ad..ddc63f7416 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/S3UtilsTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/S3UtilsTest.java @@ -25,6 +25,7 @@ package org.jclouds.aws.s3; import org.bouncycastle.util.encoders.Base64; import org.jclouds.aws.PerformanceTest; +import org.jclouds.aws.s3.util.S3Utils; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; diff --git a/s3/src/test/java/org/jclouds/aws/s3/StubS3Connection.java b/s3/src/test/java/org/jclouds/aws/s3/StubS3Connection.java index ca0b8f35b2..a02339acda 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/StubS3Connection.java +++ b/s3/src/test/java/org/jclouds/aws/s3/StubS3Connection.java @@ -79,8 +79,8 @@ public class StubS3Connection implements S3Connection { .get(s3Bucket); if (!realContents.containsKey(key)) return S3Object.Metadata.NOT_FOUND; - S3Object.Metadata metaData = new S3Object.Metadata(key); - return metaData; + S3Object.Metadata metadata = new S3Object.Metadata(key); + return metadata; } }; } @@ -173,8 +173,8 @@ public class StubS3Connection implements S3Connection { .get(s3Bucket); if (realContents != null) { for (String key : realContents.keySet()) { - S3Object.Metadata metaData = new S3Object.Metadata(key); - contents.add(metaData); + S3Object.Metadata metadata = new S3Object.Metadata(key); + contents.add(metadata); } } S3Bucket returnVal = new S3Bucket(s3Bucket); @@ -205,7 +205,7 @@ public class StubS3Connection implements S3Connection { } } - public Future> getOwnedBuckets() { + public Future> listOwnedBuckets() { return new FutureBase>() { public List get() throws InterruptedException, ExecutionException { diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/CopyObjectIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/CopyObjectIntegrationTest.java index aca83a3820..ea731638ea 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/CopyObjectIntegrationTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/CopyObjectIntegrationTest.java @@ -27,22 +27,26 @@ import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSo import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5Matches; import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceModifiedSince; import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceUnmodifiedSince; +import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideAcl; import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideMetadataWith; import static org.testng.Assert.assertEquals; import java.io.IOException; +import java.net.URL; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.jclouds.aws.s3.S3Headers; import org.jclouds.aws.s3.S3IntegrationTest; -import org.jclouds.aws.s3.S3ResponseException; -import org.jclouds.aws.s3.S3Utils; import org.jclouds.aws.s3.domain.S3Object; +import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.jclouds.aws.s3.reference.S3Headers; +import org.jclouds.aws.s3.util.S3Utils; +import org.jclouds.http.HttpResponseException; import org.joda.time.DateTime; import org.testng.annotations.Test; + import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; @@ -60,6 +64,25 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest { String sourceKey = "apples"; String destinationKey = "pears"; + + @Test() + void testCannedAccessPolicyPublic() throws Exception { + String sourceBucket = bucketPrefix + "tcapp"; + String destinationBucket = sourceBucket + "dest"; + + setupSourceBucket(sourceBucket, sourceKey); + + createBucketAndEnsureEmpty(destinationBucket); + client.copyObject(sourceBucket, sourceKey, destinationBucket, + destinationKey,overrideAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS); + + validateContent(destinationBucket, destinationKey); + + URL url = new URL(String.format("http://%1$s.s3.amazonaws.com/%2$s", + destinationBucket, destinationKey)); + S3Utils.toStringAndClose(url.openStream()); + + } @Test() void testCopyObject() throws Exception { String sourceBucket = bucketPrefix + "testcopyobject"; @@ -110,7 +133,7 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest { destinationKey, ifSourceModifiedSince(after)).get(10, TimeUnit.SECONDS); } catch (ExecutionException e) { - S3ResponseException ex = (S3ResponseException) e.getCause(); + HttpResponseException ex = (HttpResponseException) e.getCause(); assertEquals(ex.getResponse().getStatusCode(), 412); } } @@ -136,7 +159,7 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest { destinationKey, ifSourceModifiedSince(before)).get(10, TimeUnit.SECONDS); } catch (ExecutionException e) { - S3ResponseException ex = (S3ResponseException) e.getCause(); + HttpResponseException ex = (HttpResponseException) e.getCause(); assertEquals(ex.getResponse().getStatusCode(), 412); } } @@ -145,8 +168,6 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest { void testCopyIfMatch() throws InterruptedException, ExecutionException, TimeoutException, IOException { String sourceBucket = bucketPrefix + "tcim"; - byte[] realMd5 = S3Utils.md5(TEST_STRING); - byte[] badMd5 = S3Utils.md5("alf"); String destinationBucket = sourceBucket + "dest"; @@ -154,7 +175,7 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest { createBucketAndEnsureEmpty(destinationBucket); client.copyObject(sourceBucket, sourceKey, destinationBucket, - destinationKey, ifSourceMd5Matches(realMd5)).get(10, + destinationKey, ifSourceMd5Matches(goodMd5)).get(10, TimeUnit.SECONDS); validateContent(destinationBucket, destinationKey); @@ -163,7 +184,7 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest { destinationKey, ifSourceMd5Matches(badMd5)).get(10, TimeUnit.SECONDS); } catch (ExecutionException e) { - S3ResponseException ex = (S3ResponseException) e.getCause(); + HttpResponseException ex = (HttpResponseException) e.getCause(); assertEquals(ex.getResponse().getStatusCode(), 412); } } @@ -172,8 +193,6 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest { void testCopyIfNoneMatch() throws IOException, InterruptedException, ExecutionException, TimeoutException { String sourceBucket = bucketPrefix + "tcinm"; - byte[] realMd5 = S3Utils.md5(TEST_STRING); - byte[] badMd5 = S3Utils.md5("alf"); String destinationBucket = sourceBucket + "dest"; @@ -187,10 +206,10 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest { try { client.copyObject(sourceBucket, sourceKey, destinationBucket, - destinationKey, ifSourceMd5DoesntMatch(realMd5)).get(10, + destinationKey, ifSourceMd5DoesntMatch(goodMd5)).get(10, TimeUnit.SECONDS); } catch (ExecutionException e) { - S3ResponseException ex = (S3ResponseException) e.getCause(); + HttpResponseException ex = (HttpResponseException) e.getCause(); assertEquals(ex.getResponse().getStatusCode(), 412); } } diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/DeleteBucketIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/DeleteBucketIntegrationTest.java new file mode 100644 index 0000000000..c4ad980e60 --- /dev/null +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/DeleteBucketIntegrationTest.java @@ -0,0 +1,64 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ +package org.jclouds.aws.s3.commands; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.aws.s3.S3IntegrationTest; +import org.testng.annotations.Test; + +/** + * Tests integrated functionality of all deleteBucket commands. + *

+ * Each test uses a different bucket name, so it should be perfectly fine to run + * in parallel. + * + * @author Adrian Cole + * + */ +@Test(groups = "integration", testName = "s3.DeleteBucketIntegrationTest") +public class DeleteBucketIntegrationTest extends S3IntegrationTest { + + @Test() + void deleteBucketIfEmptyNotFound() throws Exception { + String bucketName = bucketPrefix + "dbienf"; + assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS); + } + + @Test() + void deleteBucketIfEmptyButHasContents() throws Exception { + String bucketName = bucketPrefix + "dbiebhc"; + createBucketAndEnsureEmpty(bucketName); + addObjectToBucket(bucketName,"test"); + assert !client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS); + } + + @Test() + void deleteBucketIfEmpty() throws Exception { + String bucketName = bucketPrefix + "dbie"; + createBucketAndEnsureEmpty(bucketName); + assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS); + assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS); + } +} \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/DeleteObjectIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/DeleteObjectIntegrationTest.java new file mode 100644 index 0000000000..fd90677212 --- /dev/null +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/DeleteObjectIntegrationTest.java @@ -0,0 +1,78 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ +package org.jclouds.aws.s3.commands; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +import org.jclouds.aws.s3.S3IntegrationTest; +import org.jclouds.aws.s3.S3ResponseException; +import org.jclouds.aws.s3.domain.S3Object; +import org.testng.annotations.Test; +import static org.testng.Assert.assertEquals; + +/** + * Tests integrated functionality of all deleteObject commands. + *

+ * Each test uses a different bucket name, so it should be perfectly fine to run + * in parallel. + * + * @author Adrian Cole + * + */ +@Test(groups = "integration", testName = "s3.DeleteObjectIntegrationTest") +public class DeleteObjectIntegrationTest extends S3IntegrationTest { + + @Test() + void deleteObjectNotFound() throws Exception { + String bucketName = bucketPrefix + "donf"; + createBucketAndEnsureEmpty(bucketName); + addObjectToBucket(bucketName, "test"); + assert client.deleteObject(bucketName, "test") + .get(10, TimeUnit.SECONDS); + } + + @Test + void deleteObjectNoBucket() throws Exception { + String bucketName = bucketPrefix + "donb"; + try { + client.deleteObject(bucketName, "test").get(10, TimeUnit.SECONDS); + } catch (ExecutionException e) { + assert e.getCause() instanceof S3ResponseException; + assertEquals(((S3ResponseException) e.getCause()).getResponse() + .getStatusCode(), 404); + } + } + + @Test() + void deleteObject() throws Exception { + String bucketName = bucketPrefix + "do"; + createBucketAndEnsureEmpty(bucketName); + addObjectToBucket(bucketName, "test"); + assert client.deleteObject(bucketName, "test") + .get(10, TimeUnit.SECONDS); + assert client.headObject(bucketName, "test").get(10, TimeUnit.SECONDS) == S3Object.Metadata.NOT_FOUND; + + } +} \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/GetObjectIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/GetObjectIntegrationTest.java index 29ea328104..04e94ecf2f 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/GetObjectIntegrationTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/GetObjectIntegrationTest.java @@ -1,6 +1,6 @@ /** * - * Copyright (C) 2009 Adrian Cole + * Getright (C) 2009 Adrian Cole * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -23,11 +23,17 @@ */ package org.jclouds.aws.s3.commands; +import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.*; +import static org.testng.Assert.assertEquals; + import java.io.IOException; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.jclouds.aws.s3.S3IntegrationTest; +import org.jclouds.aws.s3.domain.S3Object; +import org.jclouds.aws.s3.util.S3Utils; import org.testng.annotations.Test; /** @@ -41,14 +47,181 @@ import org.testng.annotations.Test; */ @Test(groups = "integration", testName = "s3.GetObjectIntegrationTest") public class GetObjectIntegrationTest extends S3IntegrationTest { + // + // @Test + // void testGetIfModifiedSince() throws InterruptedException, + // ExecutionException, TimeoutException, IOException { + // String bucket = bucketPrefix + "testGetIfModifiedSince".toLowerCase(); + // String key = "apples"; + // + // DateTime before = new DateTime(); + // setUpBucket(bucket, key); + // DateTime after = new DateTime().plusSeconds(1); + // + // client.getObject(bucket, key, ifModifiedSince(before)).get(10, + // TimeUnit.SECONDS); + // validateContent(bucket, key); + // + // try { + // client.getObject(bucket, key, ifModifiedSince(after)).get(10, + // TimeUnit.SECONDS); + // validateContent(bucket, key); + // } catch (ExecutionException e) { + // if (e.getCause() instanceof HttpResponseException) { + // HttpResponseException ex = (HttpResponseException) e.getCause(); + // assertEquals(ex.getResponse().getStatusCode(), 304); + // } else { + // throw e; + // } + // } + // + // } + // + + // + // @Test + // void testGetIfUnmodifiedSince() throws InterruptedException, + // ExecutionException, TimeoutException, IOException { + // String bucket = bucketPrefix + "testGetIfUnmodifiedSince".toLowerCase(); + // String key = "apples"; + // + // DateTime before = new DateTime(); + // setUpBucket(bucket, key); + // DateTime after = new DateTime().plusSeconds(1); + // + // client.getObject(bucket, key, ifUnmodifiedSince(after)).get(10, + // TimeUnit.SECONDS); + // validateContent(bucket, key); + // + // try { + // client.getObject(bucket, key, ifUnmodifiedSince(before)).get(10, + // TimeUnit.SECONDS); + // validateContent(bucket, key); + // } catch (ExecutionException e) { + // if (e.getCause() instanceof S3ResponseException) { + // S3ResponseException ex = (S3ResponseException) e.getCause(); + // assertEquals(ex.getResponse().getStatusCode(), 412); + // } else { + // throw e; + // } + // } + // + // } + // + // @Test + // void testGetIfMatch() throws InterruptedException, ExecutionException, + // TimeoutException, IOException { + // String bucket = bucketPrefix + "testGetIfMatch".toLowerCase(); + // String key = "apples"; + // + // setUpBucket(bucket, key); + // + // client.getObject(bucket, key, ifMd5Matches(goodMd5)).get(10, + // TimeUnit.SECONDS); + // validateContent(bucket, key); + // + // try { + // client.getObject(bucket, key, ifMd5Matches(badMd5)).get(10, + // TimeUnit.SECONDS); + // validateContent(bucket, key); + // } catch (ExecutionException e) { + // if (e.getCause() instanceof S3ResponseException) { + // S3ResponseException ex = (S3ResponseException) e.getCause(); + // assertEquals(ex.getResponse().getStatusCode(), 412); + // } else { + // throw e; + // } + // } + // } + // + // @Test + // void testGetIfNoneMatch() throws InterruptedException, + // ExecutionException, + // TimeoutException, IOException { + // String bucket = bucketPrefix + "testGetIfNoneMatch".toLowerCase(); + // String key = "apples"; + // + // setUpBucket(bucket, key); + // + // client.getObject(bucket, key, ifMd5DoesntMatch(badMd5)).get(10, + // TimeUnit.SECONDS); + // validateContent(bucket, key); + // + // try { + // client.getObject(bucket, key, ifMd5DoesntMatch(goodMd5)).get(10, + // TimeUnit.SECONDS); + // validateContent(bucket, key); + // } catch (ExecutionException e) { + // if (e.getCause() instanceof HttpResponseException) { + // HttpResponseException ex = (HttpResponseException) e.getCause(); + // assertEquals(ex.getResponse().getStatusCode(), 304); + // } else { + // throw e; + // } + // } + // } @Test - void testGetIfModifiedSince() throws InterruptedException, ExecutionException, TimeoutException, IOException { - String bucket = bucketPrefix + "testGetIfModifiedSince".toLowerCase(); + void testGetRange() throws InterruptedException, ExecutionException, + TimeoutException, IOException { + String bucket = bucketPrefix + "testGetRange".toLowerCase(); String key = "apples"; setUpBucket(bucket, key); + S3Object object1 = client.getObject(bucket, key, range(0, 5)).get(10, + TimeUnit.SECONDS); + assertEquals(S3Utils.getContentAsStringAndClose(object1), TEST_STRING + .substring(0, 6)); + S3Object object2 = client.getObject(bucket, key, + range(5, TEST_STRING.length())).get(10, TimeUnit.SECONDS); + assertEquals(S3Utils.getContentAsStringAndClose(object2), TEST_STRING + .substring(5, TEST_STRING.length())); + } + + @Test + void testGetTwoRanges() throws InterruptedException, ExecutionException, + TimeoutException, IOException { + String bucket = bucketPrefix + "testGetTwoRanges".toLowerCase(); + String key = "apples"; + + setUpBucket(bucket, key); + S3Object object = client.getObject(bucket, key, + range(0, 5).range(5, TEST_STRING.length())).get(10, + TimeUnit.SECONDS); + + assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING); + } + + @Test + void testGetTail() throws InterruptedException, ExecutionException, + TimeoutException, IOException { + String bucket = bucketPrefix + "testGetTail".toLowerCase(); + String key = "apples"; + + setUpBucket(bucket, key); + S3Object object = client.getObject(bucket, key, tail(5)).get(10, + TimeUnit.SECONDS); + assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING + .substring(TEST_STRING.length() - 5)); + assertEquals(object.getContentLength(), 5); + assertEquals(object.getMetadata().getSize(), TEST_STRING.length()); + + } + + @Test + void testGetStartAt() throws InterruptedException, ExecutionException, + TimeoutException, IOException { + String bucket = bucketPrefix + "testGetStartAt".toLowerCase(); + String key = "apples"; + + setUpBucket(bucket, key); + S3Object object = client.getObject(bucket, key, startAt(5)).get(10, + TimeUnit.SECONDS); + assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING + .substring(5, TEST_STRING.length())); + assertEquals(object.getContentLength(), TEST_STRING.length() - 5); + assertEquals(object.getMetadata().getSize(), TEST_STRING.length()); } private void setUpBucket(String sourceBucket, String sourceKey) @@ -58,29 +231,4 @@ public class GetObjectIntegrationTest extends S3IntegrationTest { addObjectToBucket(sourceBucket, sourceKey); validateContent(sourceBucket, sourceKey); } - - @Test - void testGetIfUnmodifiedSince() { - // TODO - } - - @Test - void testGetIfMatch() { - // TODO - } - - @Test - void testGetIfNoneMatch() { - // TODO - } - - @Test - void testGetWithMetadata() { - // TODO - } - - @Test - void testGetRange() { - // TODO - } } \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/ListOwnedBucketsIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/ListOwnedBucketsIntegrationTest.java new file mode 100644 index 0000000000..a880f6860d --- /dev/null +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/ListOwnedBucketsIntegrationTest.java @@ -0,0 +1,66 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ +package org.jclouds.aws.s3.commands; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.jclouds.aws.s3.S3IntegrationTest; +import org.jclouds.aws.s3.domain.S3Bucket; +import org.testng.annotations.Test; + +/** + * Tests integrated functionality of all listOwnedBucket commands. + *

+ * Each test uses a different bucket name, so it should be perfectly fine to run + * in parallel. + * + * @author Adrian Cole + * + */ +@Test(groups = "integration", testName = "s3.ListOwnedBucketsIntegrationTest") +public class ListOwnedBucketsIntegrationTest extends S3IntegrationTest { + + @Test() + void bucketDoesntExist() throws Exception { + String bucketName = bucketPrefix + "shouldntexist"; + List list = client.listOwnedBuckets().get(10, + TimeUnit.SECONDS); + assert !list.contains(new S3Bucket(bucketName)); + } + + @Test() + void bucketExists() throws Exception { + String bucketName = bucketPrefix + "needstoexist"; + assert client.putBucketIfNotExists(bucketName) + .get(10, TimeUnit.SECONDS); + List list = client.listOwnedBuckets().get(10, + TimeUnit.SECONDS); + S3Bucket.Metadata firstBucket = list.get(0); + S3Bucket.Metadata toMatch = new S3Bucket.Metadata(bucketName); + toMatch.setOwner(firstBucket.getOwner()); + + assert list.contains(toMatch); + } +} \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/PutBucketIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/PutBucketIntegrationTest.java index b58a6372ab..a9f6ac8af4 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/PutBucketIntegrationTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/PutBucketIntegrationTest.java @@ -31,9 +31,9 @@ import java.net.URL; import java.util.concurrent.TimeUnit; import org.jclouds.aws.s3.S3IntegrationTest; -import org.jclouds.aws.s3.S3Utils; import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.jclouds.aws.s3.util.S3Utils; import org.testng.annotations.Test; /** @@ -55,7 +55,7 @@ public class PutBucketIntegrationTest extends S3IntegrationTest { client.putBucketIfNotExists(bucketName, withBucketAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS); - URL url = new URL(String.format("http://%1s.s3.amazonaws.com", + URL url = new URL(String.format("http://%1$s.s3.amazonaws.com", bucketName)); S3Utils.toStringAndClose(url.openStream()); } @@ -65,7 +65,7 @@ public class PutBucketIntegrationTest extends S3IntegrationTest { String bucketName = bucketPrefix + "private"; client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS); - URL url = new URL(String.format("http://%1s.s3.amazonaws.com", + URL url = new URL(String.format("http://%1$s.s3.amazonaws.com", bucketName)); S3Utils.toStringAndClose(url.openStream()); } @@ -79,7 +79,7 @@ public class PutBucketIntegrationTest extends S3IntegrationTest { CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS); - URL url = new URL(String.format("http://%1s.s3.amazonaws.com", + URL url = new URL(String.format("http://%1$s.s3.amazonaws.com", bucketName)); S3Utils.toStringAndClose(url.openStream()); } diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/PutObjectIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/PutObjectIntegrationTest.java index 2a6f23e529..4012513fce 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/PutObjectIntegrationTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/PutObjectIntegrationTest.java @@ -35,15 +35,16 @@ import java.net.URL; import java.util.concurrent.TimeUnit; import org.apache.commons.io.IOUtils; -import org.jclouds.aws.s3.S3Headers; import org.jclouds.aws.s3.S3IntegrationTest; -import org.jclouds.aws.s3.S3Utils; import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.*; import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.jclouds.aws.s3.reference.S3Headers; +import org.jclouds.aws.s3.util.S3Utils; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; + /** * Tests integrated functionality of all PutObject commands. *

@@ -70,13 +71,13 @@ public class PutObjectIntegrationTest extends S3IntegrationTest { @Test(dataProvider = "putTests") void testPutObject(String key, String type, Object content, Object realObject) throws Exception { - String bucketName = bucketPrefix + "filetestsforadrian"; + String bucketName = bucketPrefix + "tpo"; client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS); context.createS3ObjectMap(bucketName).clear(); assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS) .getContents().size(), 0); S3Object object = new S3Object(key); - object.getMetaData().setContentType(type); + object.getMetadata().setContentType(type); object.setData(content); if (content instanceof InputStream) { object.generateMd5(); @@ -92,42 +93,42 @@ public class PutObjectIntegrationTest extends S3IntegrationTest { } @Test - void testMetaData() throws Exception { - String bucketName = bucketPrefix + "header"; + void testMetadata() throws Exception { + String bucketName = bucketPrefix + "tmd"; createBucketAndEnsureEmpty(bucketName); String key = "hello"; S3Object object = new S3Object(key, TEST_STRING); - object.getMetaData().setCacheControl("no-cache"); - object.getMetaData().setContentType("text/plain"); - object.getMetaData().setContentEncoding("x-compress"); - object.getMetaData().setSize(TEST_STRING.length()); - object.getMetaData().setContentDisposition( + object.getMetadata().setCacheControl("no-cache"); + object.getMetadata().setContentType("text/plain"); + object.getMetadata().setContentEncoding("x-compress"); + object.getMetadata().setSize(TEST_STRING.length()); + object.getMetadata().setContentDisposition( "attachment; filename=hello.txt"); - object.getMetaData().getUserMetadata().put( + object.getMetadata().getUserMetadata().put( S3Headers.USER_METADATA_PREFIX + "adrian", "powderpuff"); - object.getMetaData().setMd5(S3Utils.md5(TEST_STRING.getBytes())); + object.getMetadata().setMd5(S3Utils.md5(TEST_STRING.getBytes())); addObjectToBucket(bucketName, object); S3Object newObject = validateContent(bucketName, key); // TODO.. why does this come back as binary/octetstring - assertEquals(newObject.getMetaData().getContentType(), + assertEquals(newObject.getMetadata().getContentType(), "binary/octet-stream"); - assertEquals(newObject.getMetaData().getContentEncoding(), "x-compress"); - assertEquals(newObject.getMetaData().getContentDisposition(), + assertEquals(newObject.getMetadata().getContentEncoding(), "x-compress"); + assertEquals(newObject.getMetadata().getContentDisposition(), "attachment; filename=hello.txt"); - assertEquals(newObject.getMetaData().getCacheControl(), "no-cache"); - assertEquals(newObject.getMetaData().getSize(), TEST_STRING.length()); - assertEquals(newObject.getMetaData().getUserMetadata().values() + assertEquals(newObject.getMetadata().getCacheControl(), "no-cache"); + assertEquals(newObject.getMetadata().getSize(), TEST_STRING.length()); + assertEquals(newObject.getMetadata().getUserMetadata().values() .iterator().next(), "powderpuff"); - assertEquals(newObject.getMetaData().getMd5(), S3Utils.md5(TEST_STRING + assertEquals(newObject.getMetadata().getMd5(), S3Utils.md5(TEST_STRING .getBytes())); } @Test() void testCannedAccessPolicyPublic() throws Exception { - String bucketName = bucketPrefix + "aclpublic"; + String bucketName = bucketPrefix + "tcapp"; createBucketAndEnsureEmpty(bucketName); String key = "hello"; @@ -138,7 +139,7 @@ public class PutObjectIntegrationTest extends S3IntegrationTest { withAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS); - URL url = new URL(String.format("http://%1s.s3.amazonaws.com/%1s", + URL url = new URL(String.format("http://%1$s.s3.amazonaws.com/%2$s", bucketName, key)); S3Utils.toStringAndClose(url.openStream()); diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/S3CommandFactoryTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/S3CommandFactoryTest.java index 09eb79e079..e4950a9be3 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/S3CommandFactoryTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/S3CommandFactoryTest.java @@ -116,22 +116,22 @@ public class S3CommandFactoryTest { @Test void testCreatePutObject() { - S3Object.Metadata metaData = createMock(S3Object.Metadata.class); - S3Object object = new S3Object(metaData); - expect(metaData.getSize()).andReturn(4L).atLeastOnce(); - expect(metaData.getKey()).andReturn("rawr"); - expect(metaData.getContentType()).andReturn("text/xml").atLeastOnce(); - expect(metaData.getCacheControl()).andReturn("no-cache").atLeastOnce(); - expect(metaData.getContentDisposition()).andReturn("disposition") + S3Object.Metadata metadata = createMock(S3Object.Metadata.class); + S3Object object = new S3Object(metadata); + expect(metadata.getSize()).andReturn(4L).atLeastOnce(); + expect(metadata.getKey()).andReturn("rawr"); + expect(metadata.getContentType()).andReturn("text/xml").atLeastOnce(); + expect(metadata.getCacheControl()).andReturn("no-cache").atLeastOnce(); + expect(metadata.getContentDisposition()).andReturn("disposition") .atLeastOnce(); - expect(metaData.getContentEncoding()).andReturn("encoding") + expect(metadata.getContentEncoding()).andReturn("encoding") .atLeastOnce(); - expect(metaData.getMd5()).andReturn("encoding".getBytes()) + expect(metadata.getMd5()).andReturn("encoding".getBytes()) .atLeastOnce(); Multimap userMdata = HashMultimap.create(); - expect(metaData.getUserMetadata()).andReturn(userMdata).atLeastOnce(); + expect(metadata.getUserMetadata()).andReturn(userMdata).atLeastOnce(); - replay(metaData); + replay(metadata); object.setData(""); assert commandFactory.createPutObject("test", object, @@ -145,13 +145,13 @@ public class S3CommandFactoryTest { } @Test - void testCreateHeadMetaData() { - assert commandFactory.createHeadMetaData("test", "blah") != null; + void testCreateHeadMetadata() { + assert commandFactory.createHeadMetadata("test", "blah") != null; } @Test void testCreateListAllMyBuckets() { - assert commandFactory.createGetMetaDataForOwnedBuckets() != null; + assert commandFactory.createGetMetadataForOwnedBuckets() != null; } @Test diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/S3ParserTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/S3ParserTest.java index 1aefebc661..e4597b3d86 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/S3ParserTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/S3ParserTest.java @@ -35,10 +35,10 @@ import java.util.concurrent.ExecutorCompletionService; import org.apache.commons.io.IOUtils; import org.jclouds.aws.PerformanceTest; -import org.jclouds.aws.s3.S3Utils; +import org.jclouds.aws.s3.domain.CanonicalUser; import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Object; -import org.jclouds.aws.s3.domain.S3Owner; +import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.xml.CopyObjectHandler; import org.jclouds.aws.s3.xml.ListBucketHandler; import org.jclouds.aws.s3.xml.S3ParserFactory; @@ -64,7 +64,7 @@ public class S3ParserTest extends PerformanceTest { Injector injector = null; public static final String listAllMyBucketsResultOn200 = "e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0adrianjbosstest2009-03-12T02:00:07.000Zadrianjbosstest22009-03-12T02:00:09.000Z"; - + S3ParserFactory parserFactory = null; @BeforeMethod @@ -122,11 +122,10 @@ public class S3ParserTest extends PerformanceTest { DateTime date2 = bucket2.getCreationDate(); assert date2.equals(expectedDate2); assert s3Buckets.size() == 2; - S3Owner owner = new S3Owner(); - owner - .setId("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0"); - assert bucket1.getCanonicalUser().equals(owner); - assert bucket2.getCanonicalUser().equals(owner); + CanonicalUser owner = new CanonicalUser( + "e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0"); + assert bucket1.getOwner().equals(owner); + assert bucket2.getOwner().equals(owner); } public static final String listBucketResult = "adrianjbosstest1000false33662009-03-12T02:00:13.000Z"9d7bb64e8e18ee34eec06dd2cf37b766"136e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0ferncamSTANDARD"; @@ -140,15 +139,14 @@ public class S3ParserTest extends PerformanceTest { S3Object.Metadata object = bucket.getContents().iterator().next(); assert object.getKey().equals("3366"); DateTime expected = new DateTime("2009-03-12T02:00:13.000Z"); - assert object.getLastModified().equals(expected) : String - .format("expected %1s, but got %1s", expected, object + assert object.getLastModified().equals(expected) : String.format( + "expected %1$s, but got %1$s", expected, object .getLastModified()); assertEquals(S3Utils.toHexString(object.getMd5()), "9d7bb64e8e18ee34eec06dd2cf37b766"); assert object.getSize() == 136; - S3Owner owner = new S3Owner(); - owner - .setId("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0"); + CanonicalUser owner = new CanonicalUser( + "e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0"); owner.setDisplayName("ferncam"); assert object.getOwner().equals(owner); assert object.getStorageClass().equals("STANDARD"); diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/callables/DeleteBucketCallableTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/callables/DeleteBucketCallableTest.java deleted file mode 100644 index e95b3c56a8..0000000000 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/callables/DeleteBucketCallableTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * - * Copyright (C) 2009 Adrian Cole - * - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - */ -package org.jclouds.aws.s3.commands.callables; - -import org.testng.annotations.Test; - -@Test -public class DeleteBucketCallableTest { - - // private HttpFutureCommand.ResponseCallable callable = null; - // - // @BeforeMethod - // void setUp() { - // callable = new DeleteBucketCallable(); - // } - // - // @AfterMethod - // void tearDown() { - // callable = null; - // } - // - // @Test(expectedExceptions = HttpException.class) - // public void testExceptionWhenNoContentOn409() throws Exception { - // HttpResponse response = createMock(HttpResponse.class); - // expect(response.getStatusCode()).andReturn(409).atLeastOnce(); - // expect(response.getContent()).andReturn(null); - // replay(response); - // callable.setResponse(response); - // callable.call(); - // } - // - // @Test - // public void testExceptionWhenIOExceptionOn409() throws - // ExecutionException, - // InterruptedException, TimeoutException, IOException { - // HttpResponse response = createMock(HttpResponse.class); - // expect(response.getStatusCode()).andReturn(409).atLeastOnce(); - // RuntimeException exception = new RuntimeException("bad"); - // expect(response.getContent()).andThrow(exception); - // replay(response); - // callable.setResponse(response); - // try { - // callable.call(); - // } catch (Exception e) { - // assert e.equals(exception); - // } - // verify(response); - // } - // - // @Test - // public void testFalseWhenBucketNotEmptyOn409() throws Exception { - // HttpResponse response = createMock(HttpResponse.class); - // expect(response.getStatusCode()).andReturn(409).atLeastOnce(); - // expect(response.getContent()).andReturn( - // IOUtils.toInputStream("BucketNotEmpty")).atLeastOnce(); - // replay(response); - // callable.setResponse(response); - // assert !callable.call().booleanValue(); - // verify(response); - // } - // - // @Test - // public void testResponseOk() throws Exception { - // HttpResponse response = createMock(HttpResponse.class); - // expect(response.getStatusCode()).andReturn(204).atLeastOnce(); - // replay(response); - // callable.setResponse(response); - // assertEquals(callable.call(), new Boolean(true)); - // verify(response); - // } -} \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/callables/ParseObjectFromHeadersAndHttpContentTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/callables/ParseObjectFromHeadersAndHttpContentTest.java new file mode 100644 index 0000000000..19e2079b3c --- /dev/null +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/callables/ParseObjectFromHeadersAndHttpContentTest.java @@ -0,0 +1,77 @@ +package org.jclouds.aws.s3.commands.callables; + +import static org.testng.Assert.*; +import static org.easymock.classextension.EasyMock.*; + +import org.apache.commons.io.IOUtils; +import org.jclouds.aws.s3.domain.S3Object; +import org.jclouds.aws.s3.domain.S3Object.Metadata; +import org.jclouds.http.HttpException; +import org.jclouds.http.HttpHeaders; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * + * @author Adrian Cole + * + */ +@Test +public class ParseObjectFromHeadersAndHttpContentTest { + ParseObjectFromHeadersAndHttpContent callable; + ParseMetadataFromHeaders metadataParser; + + @BeforeMethod + void setUp() { + metadataParser = createMock(ParseMetadataFromHeaders.class); + callable = new ParseObjectFromHeadersAndHttpContent(metadataParser); + } + + @AfterMethod + void tearDown() { + callable = null; + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testCall() throws HttpException { + HttpResponse response = createMock(HttpResponse.class); + expect(response.getStatusCode()).andReturn(409).atLeastOnce(); + expect(response.getContent()).andReturn(null); + replay(response); + callable.setResponse(response); + callable.call(); + } + + @Test + public void testParseContentLengthWhenContentRangeSet() + throws HttpException { + HttpResponse response = createMock(HttpResponse.class); + metadataParser.setResponse(response); + Metadata meta = createMock(Metadata.class); + expect(metadataParser.call()).andReturn(meta); + expect(meta.getSize()).andReturn(-1l); + meta.setSize(-1l); + expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH)) + .andReturn("10485760").atLeastOnce(); + expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_RANGE)) + .andReturn("0-10485759/20232760").atLeastOnce(); + meta.setSize(20232760l); + expect(meta.getSize()).andReturn(20232760l); + + expect(response.getStatusCode()).andReturn(200).atLeastOnce(); + expect(response.getContent()).andReturn(IOUtils.toInputStream("test")); + replay(response); + replay(metadataParser); + replay(meta); + + callable.setResponse(response); + S3Object object = callable.call(); + assertEquals(object.getContentLength(), 10485760); + assertEquals(object.getMetadata().getSize(), 20232760); + assertEquals(object.getContentRange(), "0-10485759/20232760"); + + } + +} diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/options/CopyObjectOptionsTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/options/CopyObjectOptionsTest.java index 207e6494b1..b3a07d5b43 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/options/CopyObjectOptionsTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/options/CopyObjectOptionsTest.java @@ -27,6 +27,7 @@ import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSo import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5Matches; import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceModifiedSince; import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceUnmodifiedSince; +import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideAcl; import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideMetadataWith; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; @@ -34,8 +35,10 @@ import static org.testng.Assert.assertTrue; import java.io.UnsupportedEncodingException; -import org.jclouds.aws.s3.DateService; -import org.jclouds.aws.s3.S3Utils; +import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.jclouds.aws.s3.reference.S3Headers; +import org.jclouds.aws.s3.util.DateService; +import org.jclouds.aws.s3.util.S3Utils; import org.joda.time.DateTime; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -311,4 +314,26 @@ public class CopyObjectOptionsTest { assertTrue(headers.containsValue(value)); } + + + @Test + public void testAclDefault() { + CopyObjectOptions options = new CopyObjectOptions(); + assertEquals(options.getAcl(), CannedAccessPolicy.PRIVATE); + } + + @Test + public void testAclStatic() { + CopyObjectOptions options = overrideAcl(CannedAccessPolicy.AUTHENTICATED_READ); + assertEquals(options.getAcl(), CannedAccessPolicy.AUTHENTICATED_READ); + } + + @Test + void testBuildRequestHeadersACL() throws UnsupportedEncodingException { + + Multimap headers = overrideAcl( + CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders(); + assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(), + CannedAccessPolicy.AUTHENTICATED_READ.toString()); + } } diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/options/GetObjectOptionsTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/options/GetObjectOptionsTest.java index 8b97136534..770c7c4342 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/options/GetObjectOptionsTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/options/GetObjectOptionsTest.java @@ -23,6 +23,8 @@ */ package org.jclouds.aws.s3.commands.options; +import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.startAt; +import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.tail; import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.ifMd5DoesntMatch; import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.ifMd5Matches; import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.ifModifiedSince; @@ -33,8 +35,8 @@ import static org.testng.Assert.assertNull; import java.io.UnsupportedEncodingException; -import org.jclouds.aws.s3.DateService; -import org.jclouds.aws.s3.S3Utils; +import org.jclouds.aws.s3.util.DateService; +import org.jclouds.aws.s3.util.S3Utils; import org.joda.time.DateTime; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; @@ -128,6 +130,58 @@ public class GetObjectOptionsTest { assertEquals(options.getRange(), "bytes=0-1024"); } + @Test + public void testRangeZeroToFive() { + GetObjectOptions options = new GetObjectOptions(); + options.range(0, 5); + assertEquals(options.getRange(), "bytes=0-5"); + } + + @Test + public void testTail() { + GetObjectOptions options = new GetObjectOptions(); + options.tail(100); + assertEquals(options.getRange(), "bytes=-100"); + } + + @Test + public void testTailStatic() { + GetObjectOptions options = tail(100); + assertEquals(options.getRange(), "bytes=-100"); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testTailFail() { + GetObjectOptions options = new GetObjectOptions(); + options.tail(0); + } + + @Test + public void testStartAt() { + GetObjectOptions options = new GetObjectOptions(); + options.startAt(100); + assertEquals(options.getRange(), "bytes=100-"); + } + + @Test + public void testStartAtStatic() { + GetObjectOptions options = startAt(100); + assertEquals(options.getRange(), "bytes=100-"); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testStartAtFail() { + GetObjectOptions options = new GetObjectOptions(); + options.startAt(-1); + } + + @Test + public void testRangeZeroToFiveAnd10through100() { + GetObjectOptions options = new GetObjectOptions(); + options.range(0, 5).range(10, 100); + assertEquals(options.getRange(), "bytes=0-5,10-100"); + } + @Test public void testNullRange() { GetObjectOptions options = new GetObjectOptions(); @@ -140,17 +194,17 @@ public class GetObjectOptionsTest { bytes1to1024(options); } - @Test(expectedExceptions = IllegalStateException.class) + @Test(expectedExceptions = IllegalArgumentException.class) public void testRangeNegative1() { range(-1, 0); } - @Test(expectedExceptions = IllegalStateException.class) + @Test(expectedExceptions = IllegalArgumentException.class) public void testRangeNegative2() { range(0, -1); } - @Test(expectedExceptions = IllegalStateException.class) + @Test(expectedExceptions = IllegalArgumentException.class) public void testRangeNegative() { range(-1, -1); } @@ -209,7 +263,7 @@ public class GetObjectOptionsTest { assertEquals(match, expected); } - @Test(expectedExceptions = IllegalStateException.class) + @Test(expectedExceptions = IllegalArgumentException.class) public void testIfUnmodifiedAfterModified() { ifModifiedSince(now).ifUnmodifiedSince(now); @@ -221,19 +275,19 @@ public class GetObjectOptionsTest { } - @Test(expectedExceptions = IllegalStateException.class) + @Test(expectedExceptions = IllegalArgumentException.class) public void testIfUnmodifiedAfterMd5DoesntMatch() throws UnsupportedEncodingException { ifMd5DoesntMatch(testBytes).ifUnmodifiedSince(now); } - @Test(expectedExceptions = IllegalStateException.class) + @Test(expectedExceptions = IllegalArgumentException.class) public void testIfModifiedAfterUnmodified() { ifUnmodifiedSince(now).ifModifiedSince(now); } - @Test(expectedExceptions = IllegalStateException.class) + @Test(expectedExceptions = IllegalArgumentException.class) public void testIfModifiedAfterMd5Matches() throws UnsupportedEncodingException { ifMd5Matches(testBytes).ifModifiedSince(now); @@ -245,7 +299,7 @@ public class GetObjectOptionsTest { ifMd5DoesntMatch(testBytes).ifModifiedSince(now); } - @Test(expectedExceptions = IllegalStateException.class) + @Test(expectedExceptions = IllegalArgumentException.class) public void testMd5MatchesAfterIfModified() throws UnsupportedEncodingException { ifModifiedSince(now).ifMd5Matches(testBytes); @@ -258,7 +312,7 @@ public class GetObjectOptionsTest { } - @Test(expectedExceptions = IllegalStateException.class) + @Test(expectedExceptions = IllegalArgumentException.class) public void testMd5MatchesAfterMd5DoesntMatch() throws UnsupportedEncodingException { ifMd5DoesntMatch(testBytes).ifMd5Matches(testBytes); @@ -270,14 +324,14 @@ public class GetObjectOptionsTest { } - @Test(expectedExceptions = IllegalStateException.class) + @Test(expectedExceptions = IllegalArgumentException.class) public void testMd5DoesntMatchAfterIfUnmodified() throws UnsupportedEncodingException { ifUnmodifiedSince(now).ifMd5DoesntMatch(testBytes); } - @Test(expectedExceptions = IllegalStateException.class) + @Test(expectedExceptions = IllegalArgumentException.class) public void testMd5DoesntMatchAfterMd5Matches() throws UnsupportedEncodingException { ifMd5Matches(testBytes).ifMd5DoesntMatch(testBytes); diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutBucketOptionsTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutBucketOptionsTest.java index f92aadac8c..687600884c 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutBucketOptionsTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutBucketOptionsTest.java @@ -30,11 +30,12 @@ import static org.testng.Assert.assertNull; import java.io.UnsupportedEncodingException; -import org.jclouds.aws.s3.S3Headers; import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.jclouds.aws.s3.reference.S3Headers; import org.testng.annotations.Test; + import com.google.common.collect.Multimap; /** diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutObjectOptionsTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutObjectOptionsTest.java index 2a5e323e8a..37fcf4e0bb 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutObjectOptionsTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutObjectOptionsTest.java @@ -28,10 +28,11 @@ import static org.testng.Assert.assertEquals; import java.io.UnsupportedEncodingException; -import org.jclouds.aws.s3.S3Headers; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.jclouds.aws.s3.reference.S3Headers; import org.testng.annotations.Test; + import com.google.common.collect.Multimap; /** diff --git a/s3/src/test/java/org/jclouds/aws/s3/config/S3ContextModuleTest.java b/s3/src/test/java/org/jclouds/aws/s3/config/S3ContextModuleTest.java index de723ee5af..d86900b2fe 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/config/S3ContextModuleTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/config/S3ContextModuleTest.java @@ -25,8 +25,9 @@ package org.jclouds.aws.s3.config; import static org.testng.Assert.assertEquals; -import org.jclouds.aws.s3.S3Constants; import org.jclouds.aws.s3.filters.ParseS3ErrorFromXmlContent; +import org.jclouds.aws.s3.reference.S3Constants; +import org.jclouds.http.CloseContentAndSetExceptionHandler; import org.jclouds.http.HttpResponseHandler; import org.jclouds.http.annotation.ClientErrorHandler; import org.jclouds.http.annotation.RedirectHandler; @@ -36,6 +37,7 @@ import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; + import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; @@ -118,7 +120,7 @@ public class S3ContextModuleTest { RedirectHandlerTest error = injector .getInstance(RedirectHandlerTest.class); assertEquals(error.errorHandler.getClass(), - ParseS3ErrorFromXmlContent.class); + CloseContentAndSetExceptionHandler.class); } } \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/domain/S3ObjectTest.java b/s3/src/test/java/org/jclouds/aws/s3/domain/S3ObjectTest.java index 015e4e4d3d..258f08efbd 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/domain/S3ObjectTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/domain/S3ObjectTest.java @@ -39,7 +39,7 @@ public class S3ObjectTest { S3Object object = new S3Object("test"); File file = new File("hello.txt"); object.setData(file); - assertEquals(object.getMetaData().getContentType(), + assertEquals(object.getMetadata().getContentType(), ContentTypes.UNKNOWN_MIME_TYPE); } } diff --git a/s3/src/test/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignatureTest.java b/s3/src/test/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignatureTest.java index 37da341c9e..b042215717 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignatureTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignatureTest.java @@ -26,11 +26,13 @@ package org.jclouds.aws.s3.filters; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.name.Names; -import org.jclouds.aws.s3.DateService; -import org.jclouds.aws.s3.S3Constants; + +import org.jclouds.aws.s3.reference.S3Constants; +import org.jclouds.aws.s3.util.DateService; import org.testng.annotations.Test; + @Test(groups = "unit", sequential = true, testName = "s3.RequestAuthorizeSignatureTest") public class RequestAuthorizeSignatureTest { diff --git a/s3/src/test/java/org/jclouds/aws/s3/xml/ErrorHandlerTest.java b/s3/src/test/java/org/jclouds/aws/s3/xml/ErrorHandlerTest.java index da5bf64ea9..f6d383f20c 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/xml/ErrorHandlerTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/xml/ErrorHandlerTest.java @@ -23,7 +23,7 @@ */ package org.jclouds.aws.s3.xml; -import static org.testng.Assert.*; +import static org.testng.Assert.assertEquals; import org.apache.commons.io.IOUtils; import org.jclouds.aws.s3.domain.S3Error; @@ -31,7 +31,6 @@ import org.jclouds.http.HttpException; import org.jclouds.http.commands.callables.xml.ParseSax; import org.testng.annotations.Test; - @Test public class ErrorHandlerTest extends BaseHandlerTest { public static final String errorFromAmazonIfYouDontRemoveTransferEncodingHeader = "NotImplementedA header you provided implies functionality that is not implemented

Transfer-Encoding
7C59925D75D15561fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb"; @@ -46,9 +45,9 @@ public class ErrorHandlerTest extends BaseHandlerTest { assertEquals(error.getCode(), "NotImplemented"); assertEquals(error.getMessage(), "A header you provided implies functionality that is not implemented"); - assertEquals(error.getHeader(), "Transfer-Encoding"); + assertEquals(error.getDetails().get("Header"), "Transfer-Encoding"); assertEquals(error.getRequestId(), "7C59925D75D15561"); - assertEquals(error.getHostId(), + assertEquals(error.getDetails().get("HostId"), "fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb"); } diff --git a/samples/googleappengine/README.txt b/samples/googleappengine/README.txt deleted file mode 100644 index 6221dd9b45..0000000000 --- a/samples/googleappengine/README.txt +++ /dev/null @@ -1,54 +0,0 @@ -==== - - Copyright (C) 2009 Adrian Cole - - ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - ==================================================================== -==== -This samples uses the Google App Engine for Java SDK located at http://googleappengine.googlecode.com/files/appengine-java-sdk-1.2.0.zip - -Please unzip the above file and modify your maven settings.xml like below before attempting to run 'mvn install' - - - appengine - - true - - - /path/to/appengine-java-sdk-1.2.0 - - - - - aws - - true - - - YOUR_ACCESS_KEY_ID - YOUR_SECRET_KEY - - - - - - jclouds - http://jclouds.googlecode.com/svn/trunk/repo - - diff --git a/samples/googleappengine/pom.xml b/samples/googleappengine/pom.xml deleted file mode 100644 index 7ab8d1726b..0000000000 --- a/samples/googleappengine/pom.xml +++ /dev/null @@ -1,194 +0,0 @@ - - - - - jclouds-project - org.jclouds - 1.0-SNAPSHOT - ../../project/pom.xml - - 4.0.0 - jclouds-gae-s3-example - war - JClouds Sample for Google App Engine - JClouds Sample for Google App Engine - - - - /Users/adriancole/Desktop/appengine-java-sdk-1.2.0 - localhost - 8088 - - - - - - - guice-snapshot - http://guice-maven.googlecode.com/svn/trunk - - - - - - Main Maven Repo - http://repo1.maven.org/maven2/ - - - - - - ${project.groupId} - jclouds-gae - ${project.version} - - - ${project.groupId} - jclouds-s3 - ${project.version} - - - ${project.groupId} - jclouds-s3 - ${project.version} - test - test-jar - - - com.google.code.guice - guice-servlet - 2.0-r943 - - - standard - taglibs - 1.1.2 - jar - runtime - - - jstl - javax.servlet - 1.1.2 - jar - compile - - - org.apache.geronimo.specs - geronimo-el_1.0_spec - 1.0.1 - compile - - - org.apache.geronimo.specs - geronimo-jsp_2.1_spec - 1.0.1 - provided - - - org.apache.geronimo.specs - geronimo-servlet_2.5_spec - 1.2 - provided - - - - com.google.appengine - appengine-tools-api - 1.2.0 - system - ${appengine.home}/lib/appengine-tools-api.jar - - - - - ${project.artifactId} - src/it/java - - - org.apache.maven.plugins - maven-surefire-plugin - 2.4.3 - - - integration - integration-test - - test - - - target/test-classes - - - jclouds.aws.accesskeyid - ${jclouds.aws.accesskeyid} - - - jclouds.aws.secretaccesskey - ${jclouds.aws.secretaccesskey} - - - appengine.home - ${appengine.home} - - - devappserver.address - ${devappserver.address} - - - devappserver.port - ${devappserver.port} - - - warfile - ${project.build.directory}/${project.artifactId} - - - - ${appengine.home}/lib/appengine-tools-api.jar - - - - true - ${appengine.home}/bin - ${appengine.home}/lib - ${appengine.home}/config/sdk - - - - - - - target/classes - - - - - - diff --git a/samples/googleappengine/src/it/java/org/jclouds/samples/googleappengine/functest/BaseGoogleAppEngineTest.java b/samples/googleappengine/src/it/java/org/jclouds/samples/googleappengine/functest/BaseGoogleAppEngineTest.java deleted file mode 100644 index 27daf85e80..0000000000 --- a/samples/googleappengine/src/it/java/org/jclouds/samples/googleappengine/functest/BaseGoogleAppEngineTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * - * Copyright (C) 2009 Adrian Cole - * - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - */ -package org.jclouds.samples.googleappengine.functest; - -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.util.Properties; - -import org.testng.annotations.AfterTest; - -import com.google.appengine.tools.KickStart; - -/** - * Basic functionality to start a local google app engine instance. - * - * @author Adrian Cole - * - */ -public abstract class BaseGoogleAppEngineTest { - - Thread server; - URL url; - - protected void writePropertiesAndStartServer(final String address, - final String port, final String warfile, Properties props) - throws IOException, FileNotFoundException, InterruptedException { - url = new URL(String.format("http://%1s:%2s", address, port)); - - props.store(new FileOutputStream(String.format( - "%1s/WEB-INF/jclouds.properties", warfile)), "test"); - this.server = new Thread(new Runnable() { - public void run() { - KickStart - .main(new String[] { - "com.google.appengine.tools.development.DevAppServerMain", - "--disable_update_check", "-a", address, "-p", - port, warfile }); - - } - - }); - server.start(); - Thread.sleep(7 * 1000); - } - - @SuppressWarnings("deprecation") - @AfterTest - public void stopDevAppServer() throws Exception { - server.stop(); - } - -} \ No newline at end of file diff --git a/samples/googleappengine/src/it/java/org/jclouds/samples/googleappengine/functest/GoogleAppEngineTest.java b/samples/googleappengine/src/it/java/org/jclouds/samples/googleappengine/functest/GoogleAppEngineTest.java deleted file mode 100644 index 00cbd0a577..0000000000 --- a/samples/googleappengine/src/it/java/org/jclouds/samples/googleappengine/functest/GoogleAppEngineTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * - * Copyright (C) 2009 Adrian Cole - * - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - */ -package org.jclouds.samples.googleappengine.functest; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Properties; - -import org.apache.commons.io.IOUtils; -import org.jclouds.aws.s3.S3Constants; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Optional; -import org.testng.annotations.Parameters; -import org.testng.annotations.Test; - -/** - * Starts up the Google App Engine for Java Development environment and deploys - * an application which tests S3. - * - * @author Adrian Cole - * - */ -@Test(groups = "integration", enabled = true, sequential = true, testName = "functionalTests") -public class GoogleAppEngineTest extends BaseGoogleAppEngineTest { - - private static final String sysAWSAccessKeyId = System - .getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID); - private static final String sysAWSSecretAccessKey = System - .getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY); - - @BeforeTest - @Parameters( { "warfile", "devappserver.address", "devappserver.port", - S3Constants.PROPERTY_AWS_ACCESSKEYID, - S3Constants.PROPERTY_AWS_SECRETACCESSKEY }) - public void startDevAppServer(final String warfile, final String address, - final String port, @Optional String AWSAccessKeyId, - @Optional String AWSSecretAccessKey) throws Exception { - AWSAccessKeyId = AWSAccessKeyId != null ? AWSAccessKeyId - : sysAWSAccessKeyId; - AWSSecretAccessKey = AWSSecretAccessKey != null ? AWSSecretAccessKey - : sysAWSSecretAccessKey; - - checkNotNull(AWSAccessKeyId, "AWSAccessKeyId"); - checkNotNull(AWSSecretAccessKey, "AWSSecretAccessKey"); - - Properties props = new Properties(); - props.put(S3Constants.PROPERTY_AWS_ACCESSKEYID, AWSAccessKeyId); - props.put(S3Constants.PROPERTY_AWS_SECRETACCESSKEY, AWSSecretAccessKey); - writePropertiesAndStartServer(address, port, warfile, props); - } - - @Test - public void shouldPass() throws InterruptedException, IOException { - InputStream i = url.openStream(); - String string = IOUtils.toString(i); - assert string.indexOf("Hello World!") >= 0 : string; - } - - @Test(invocationCount = 5, enabled = true) - public void testGuiceJCloudsSerial() throws InterruptedException, - IOException { - URL gurl = new URL(url, "/guice/listbuckets.s3"); - InputStream i = gurl.openStream(); - String string = IOUtils.toString(i); - assert string.indexOf("List") >= 0 : string; - } - - @Test(invocationCount = 50, enabled = false, threadPoolSize = 10) - public void testGuiceJCloudsParallel() throws InterruptedException, - IOException { - URL gurl = new URL(url, "/guice/listbuckets.s3"); - InputStream i = gurl.openStream(); - String string = IOUtils.toString(i); - assert string.indexOf("List") >= 0 : string; - } -} diff --git a/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/JCloudsServlet.java b/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/JCloudsServlet.java deleted file mode 100644 index 66b36ec2fa..0000000000 --- a/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/JCloudsServlet.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * - * Copyright (C) 2009 Adrian Cole - * - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - */ -package org.jclouds.samples.googleappengine; - -import java.io.IOException; -import java.io.Writer; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.jclouds.aws.s3.S3Context; -import org.jclouds.aws.s3.domain.S3Bucket; - -import com.google.inject.Inject; -import com.google.inject.Singleton; - -/** - * Shows an example of how to use @{link S3Connection} injected with Guice. - * - * @author Adrian Cole - */ -@Singleton -public class JCloudsServlet extends HttpServlet { - private static final long serialVersionUID = 1L; - - @Inject - S3Context context; - - @Override - protected void doGet(HttpServletRequest httpServletRequest, - HttpServletResponse httpServletResponse) throws ServletException, - IOException { - httpServletResponse.setContentType("text/plain"); - Writer writer = httpServletResponse.getWriter(); - try { - List myBuckets = context.getConnection() - .getOwnedBuckets().get(10, TimeUnit.SECONDS); - writer.write("List:\n"); - for (S3Bucket.Metadata bucket : myBuckets) { - writer.write(String.format(" %1s: %2s entries%n", bucket - .getName(), context.createInputStreamMap( - bucket.getName()).size())); - } - } catch (Exception e) { - throw new ServletException(e); - } - writer.flush(); - writer.close(); - } -} \ No newline at end of file diff --git a/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/config/GuiceServletConfig.java b/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/config/GuiceServletConfig.java deleted file mode 100644 index b3f0afdf85..0000000000 --- a/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/config/GuiceServletConfig.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * - * Copyright (C) 2009 Adrian Cole - * - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - */ -package org.jclouds.samples.googleappengine.config; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -import javax.servlet.ServletContextEvent; - -import org.apache.commons.io.IOUtils; -import org.jclouds.aws.s3.S3Constants; -import org.jclouds.aws.s3.S3Context; -import org.jclouds.aws.s3.S3ContextFactory; -import org.jclouds.gae.config.URLFetchServiceClientModule; -import org.jclouds.samples.googleappengine.JCloudsServlet; - -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.servlet.GuiceServletContextListener; -import com.google.inject.servlet.ServletModule; - -/** - * Setup Logging and create Injector for use in testing S3. - * - * @author Adrian Cole - * - */ -public class GuiceServletConfig extends GuiceServletContextListener { - @Inject - S3Context context; - String accessKeyId; - String secretAccessKey; - - @Override - public void contextInitialized(ServletContextEvent servletContextEvent) { - Properties props = loadJCloudsProperties(servletContextEvent); - this.accessKeyId = props - .getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID); - this.secretAccessKey = props - .getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY); - super.contextInitialized(servletContextEvent); - } - - private Properties loadJCloudsProperties( - ServletContextEvent servletContextEvent) { - InputStream input = servletContextEvent.getServletContext() - .getResourceAsStream("/WEB-INF/jclouds.properties"); - Properties props = new Properties(); - try { - props.load(input); - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - IOUtils.closeQuietly(input); - } - return props; - } - - @Override - protected Injector getInjector() { - return S3ContextFactory.createInjector(accessKeyId, secretAccessKey, - false, new URLFetchServiceClientModule(), - new ServletModule() { - @Override - protected void configureServlets() { - serve("*.s3").with(JCloudsServlet.class); - requestInjection(this); - } - }); - } - - @Override - public void contextDestroyed(ServletContextEvent servletContextEvent) { - context.close(); - super.contextDestroyed(servletContextEvent); - } -} \ No newline at end of file diff --git a/samples/googleappengine/src/main/webapp/WEB-INF/appengine-web.xml b/samples/googleappengine/src/main/webapp/WEB-INF/appengine-web.xml deleted file mode 100644 index 8f17694b44..0000000000 --- a/samples/googleappengine/src/main/webapp/WEB-INF/appengine-web.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - jclouds-s3-example - 1 - diff --git a/samples/googleappengine/src/main/webapp/WEB-INF/web.xml b/samples/googleappengine/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 73a4a41c95..0000000000 --- a/samples/googleappengine/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - jclouds-s3-example - - - - guiceFilter - com.google.inject.servlet.GuiceFilter - - - - guiceFilter - /guice/* - - - - - org.jclouds.samples.googleappengine.config.GuiceServletConfig - - diff --git a/samples/googleappengine/src/main/webapp/index.jsp b/samples/googleappengine/src/main/webapp/index.jsp deleted file mode 100644 index 6529d030ec..0000000000 --- a/samples/googleappengine/src/main/webapp/index.jsp +++ /dev/null @@ -1,30 +0,0 @@ -<%-- - - - Copyright (C) 2009 Adrian Cole - - ==================================================================== - 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. - ==================================================================== - ---%> - - -

Hello World!

- -