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
This commit is contained in:
adrian.f.cole 2009-05-10 19:52:55 +00:00
parent 589c37ec04
commit 67683084ff
103 changed files with 1758 additions and 1489 deletions

View File

@ -73,7 +73,7 @@ public abstract class FutureCommandConnectionHandle<C, O extends FutureCommand<?
if (isCompleted()) {
return;
}
logger.trace("%1s - %2d - releasing to pool", conn, conn.hashCode());
logger.trace("%1$s - %2$d - releasing to pool", conn, conn.hashCode());
available.put(conn);
conn = null;
command = null;
@ -85,7 +85,7 @@ public abstract class FutureCommandConnectionHandle<C, O extends FutureCommand<?
return;
}
if (conn != null) {
logger.trace("%1s - %2d - cancelled; shutting down connection",
logger.trace("%1$s - %2$d - cancelled; shutting down connection",
conn, conn.hashCode());
try {
shutdownConnection();

View File

@ -83,23 +83,23 @@ public abstract class FutureCommandConnectionPool<C, O extends FutureCommand<?,
hitBottom = available.size() == 0
&& allConnections.availablePermits() == 0;
if (hitBottom)
logger.warn("%1s - saturated connection pool", this);
logger.warn("%1$s - saturated connection pool", this);
}
logger
.debug(
"%1s - attempting to acquire connection; %d currently available",
"%1$s - attempting to acquire connection; %d currently available",
this, available.size());
C conn = available.poll(5, TimeUnit.SECONDS);
if (conn == null)
throw new TimeoutException(
"could not obtain a pooled connection within 5 seconds");
logger.trace("%1s - %2d - aquired", conn, conn.hashCode());
logger.trace("%1$s - %2$d - aquired", conn, conn.hashCode());
if (connectionValid(conn)) {
logger.debug("%1s - %2d - reusing", conn, conn.hashCode());
logger.debug("%1$s - %2$d - reusing", conn, conn.hashCode());
return conn;
} else {
logger.debug("%1s - %2d - unusable", conn, conn.hashCode());
logger.debug("%1$s - %2$d - unusable", conn, conn.hashCode());
shutdownConnection(conn);
allConnections.release();
return getConnection();
@ -130,7 +130,7 @@ public abstract class FutureCommandConnectionPool<C, O extends FutureCommand<?,
O command = getCommandFromConnection(connection);
if (command != null) {
if (isReplayable(command)) {
logger.info("resubmitting command: %1s", command);
logger.info("resubmitting command: %1$s", command);
commandQueue.add(command);
} else {
command.setException(e);
@ -151,7 +151,7 @@ public abstract class FutureCommandConnectionPool<C, O extends FutureCommand<?,
protected void setExceptionOnCommand(C connection, Exception e) {
FutureCommand<?, ?, ?> 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);
}
}

View File

@ -104,13 +104,13 @@ public class FutureCommandConnectionPoolClient<C, O extends FutureCommand<?, ?,
logger
.warn(
e,
"Interrupted getting a connection for command %1s; retrying",
"Interrupted getting a connection for command %1$s; retrying",
command);
commandQueue.add(command);
return;
} catch (TimeoutException e) {
logger.warn(e,
"Timeout getting a connection for command %1s; retrying",
"Timeout getting a connection for command %1$s; retrying",
command);
commandQueue.add(command);
return;
@ -118,7 +118,7 @@ public class FutureCommandConnectionPoolClient<C, O extends FutureCommand<?, ?,
if (connectionHandle == null) {
logger.error(
"Failed to obtain connection for command %1s; retrying",
"Failed to obtain connection for command %1$s; retrying",
command);
commandQueue.add(command);
return;

View File

@ -64,7 +64,7 @@ public abstract class BaseHttpFutureCommandClient implements HttpFutureCommandC
HttpResponse response) {
int code = response.getStatusCode();
if (command.getRequest().isReplayable() && code >= 500) {
logger.info("resubmitting command: %1s", command);
logger.info("resubmitting command: %1$s", command);
return true;
}
return false;

View File

@ -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));
}
}
}

View File

@ -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";
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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()));
}
}
}

View File

@ -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));
}

View File

@ -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));
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -140,7 +140,8 @@ public class JCloudsS3Service extends S3Service {
} catch (Exception e) {
Utils.<S3ServiceException> 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<org.jclouds.aws.s3.domain.S3Bucket.Metadata> jcBucketList = connection
.getOwnedBuckets().get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
.listOwnedBuckets().get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS);
ArrayList<org.jets3t.service.model.S3Bucket> jsBucketList = new ArrayList<org.jets3t.service.model.S3Bucket>();
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

View File

@ -184,7 +184,7 @@ public class JCloudsS3ServiceTest extends S3IntegrationTest {
S3Bucket[] jsBuckets = service.listAllBuckets();
List<org.jclouds.aws.s3.domain.S3Bucket.Metadata> 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);

View File

@ -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.
*

View File

@ -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;
}

View File

@ -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<Boolean> 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);

View File

@ -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;

View File

@ -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<Bucket> buckets = response.entries;

View File

@ -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 <code>S3Object</code>.
*
* @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<S3Object> 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
* <code>options</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<S3Object> 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<S3Object.Metadata> 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<Boolean> deleteObject(String bucketName, String key);
/**
* Store data by creating or overwriting an object.
* <p/>
* This method will store the object with the default <code>private</code>
* 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<byte[]> 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<byte[]> 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<Boolean> 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<Boolean> 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<Boolean> 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<S3Object.Metadata> 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<S3Object.Metadata> copyObject(String sourceBucket,
String sourceObject, String destinationBucket,
String destinationObject, CopyObjectOptions options);
/**
* @see HeadBucket
*/
Future<Boolean> bucketExists(String name);
/**
* Retrieve a complete <code>S3Bucket</code> 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<S3Bucket> listBucket(String name);
Future<S3Bucket> 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
* <code>options</options> specified or {@link S3Bucket#NOT_FOUND} if not present.
*
*/
Future<S3Bucket> listBucket(String name, ListBucketOptions options);
Future<List<S3Bucket.Metadata>> getOwnedBuckets();
/**
* @see ListOwnedBuckets
* @return list of all of the buckets owned by the authenticated sender of
* the request.
*/
Future<List<S3Bucket.Metadata>> listOwnedBuckets();
}

View File

@ -23,10 +23,24 @@
*/
package org.jclouds.aws.s3;
/**
* Represents an authenticated context to S3.
*
* <h2>Note</h2> 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();

View File

@ -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.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or
* Context provided.
*
* <p/>
* If no <code>Module</code>s are specified, the default
* {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpFutureCommandClientModule http transports} will be
* installed.
*
* @see S3Context
* @author Adrian Cole
*/
public class S3ContextFactory {

View File

@ -27,7 +27,20 @@ import java.io.File;
import java.io.InputStream;
import java.util.Map;
public interface S3InputStreamMap extends Map<String, InputStream>, S3Map {
/**
* Map view of an {@link S3Bucket}. Provides additional methods for inserting
* common object types.
*
* <h2>Note</h2> All <code>put</code> 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<String, InputStream> {
InputStream putString(String key, String value);
InputStream putFile(String key, File value);

View File

@ -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<K, V> extends Map<K, V> {
/**
*
* @return s3 bucket listing that this map represents
*/
S3Bucket getBucket();
}

View File

@ -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<String, S3Object>, S3Map {
/**
* Map view of an {@link S3Bucket}.
*
* <p/>
* 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<String, S3Object> {
}

View File

@ -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;
}
}

View File

@ -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<Boolean> {
@Inject
@ -57,8 +63,9 @@ public class BucketExists extends S3FutureCommand<Boolean> {
@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;

View File

@ -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.
* <p/>
* 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<S3Object.Metadata> {
@Inject
@ -51,9 +70,9 @@ public class CopyObject extends S3FutureCommand<S3Object.Metadata> {
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());
}
}

View File

@ -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.
* <p />
* 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<Boolean> {
@Inject
@ -54,7 +66,8 @@ public class DeleteBucket extends S3FutureCommand<Boolean> {
@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) {

View File

@ -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<Boolean> {
@Inject

View File

@ -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
* <p/>
* 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.
* <p />
* <p/>
* This command allows you to specify {@link GetObjectOptions} to control
* delivery of content.
*
* <h2>Note</h2> If you specify any of the below options, you will receive
* partial content:
* <ul>
* <li>{@link GetObjectOptions#range}</li>
* <li>{@link GetObjectOptions#startAt}</li>
* <li>{@link GetObjectOptions#tail}</li>
* </ul>
*
* @see GetObjectOptions
* @see http
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectGET
* .html
* @author Adrian Cole
*/
public class GetObject extends S3FutureCommand<S3Object> {

View File

@ -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.
*
* <p/>
* 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<S3Object.Metadata> {
public class HeadObject extends S3FutureCommand<S3Object.Metadata> {
@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<S3Object.Metadata> {
@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;

View File

@ -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.
* <p />
* To list the keys of a bucket, you must have READ access to the bucket.
* <p/>
* 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<S3Bucket> {
@Inject
@ -62,7 +78,8 @@ public class ListBucket extends S3FutureCommand<S3Bucket> {
@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())) {

View File

@ -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<List<S3Bucket.Metadata>> {
public class ListOwnedBuckets extends S3FutureCommand<List<S3Bucket.Metadata>> {
@Inject
public GetMetaDataForOwnedBuckets(@Named("jclouds.http.address") String amazonHost,
public ListOwnedBuckets(@Named("jclouds.http.address") String amazonHost,
ParseSax<List<S3Bucket.Metadata>> callable) {
super("GET", "/", callable, amazonHost);
}

View File

@ -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.
* <p/>
* 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
*
*/

View File

@ -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.
*
* <p/>
* This returns a byte[] of the md5 hash of what Amazon S3 received
* <p />
* <p/>
* 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<byte[]> {
@Inject
@ -43,38 +61,38 @@ public class PutObject extends S3FutureCommand<byte[]> {
@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());
}

View File

@ -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());
}

View File

@ -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}.
*

View File

@ -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);
S3Object.Metadata metadata = new S3Object.Metadata(key);
addAllHeadersTo(metadata);
extractUserMetadata(metaData);
addMd5(metaData);
addUserMetadataTo(metadata);
addMd5To(metadata);
parseLastModifiedOrThrowException(metaData);
setContentTypeOrThrowException(metaData);
parseLastModifiedOrThrowException(metadata);
setContentTypeOrThrowException(metadata);
setContentLengthOrThrowException(metadata);
metaData.setCacheControl(getResponse().getFirstHeaderOrNull(
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<String, String> 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());
}
}

View File

@ -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<S3Object> {
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);
}
}

View File

@ -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));
}

View File

@ -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<S3Object.MetaData> object = connection.copyObject("sourceBucket", "objectName",
* Future<S3Object.Metadata> 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<String, String> 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
* <p />
@ -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,6 +280,13 @@ 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()

View File

@ -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. <h2>
* Usage</h2> 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<String> ranges = new ArrayList<String>();
@Override
public Multimap<String, String> buildRequestHeaders() {
Multimap<String, String> 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 <code>start</code>
*/
public GetObjectOptions startAt(long start) {
checkArgument(start >= 0, "start must be >= 0");
ranges.add(String.format("%d-", start));
return this;
}
/**
* download the last <code>count</code> 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 {
@ -220,6 +251,22 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
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()
*/

View File

@ -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.*;
* <p/>
* <code>
* 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(
"<CreateBucketConfiguration><LocationConstraint>%1s</LocationConstraint></CreateBucketConfiguration>",
"<CreateBucketConfiguration><LocationConstraint>%1$s</LocationConstraint></CreateBucketConfiguration>",
constraint.toString());
return this;
}

View File

@ -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.*;
/**

View File

@ -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);
}

View File

@ -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.
* <p/>
*
* @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;
}
}

View File

@ -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<S3Object.Metadata> getContents() {
@ -195,8 +194,8 @@ public class S3Bucket {
isComplete = complete;
}
public Metadata getMetaData() {
return metaData;
public Metadata getMetadata() {
return metadata;
}
public void setCommonPrefixes(Set<String> commonPrefixes) {

View File

@ -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<String, String> details = new HashMap<String, String>();
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<String, String> context) {
this.details = context;
}
/**
* @return additional details surrounding the error.
*/
public Map<String, String> getDetails() {
return details;
}
public void setRequestToken(String requestToken) {
this.requestToken = requestToken;
}
public String getRequestToken() {
return requestToken;
}
}

View File

@ -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<String, String> allHeaders = HashMultimap.create();
private Multimap<String, String> 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<String, String> allHeaders) {
this.allHeaders = allHeaders;
}
public Multimap<String, String> 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;
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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<T> implements Map<String, T>, S3Map {
public abstract class BaseS3Map<V> implements S3Map<String, V> {
protected final S3Connection connection;
protected final String bucket;
@ -88,8 +87,8 @@ public abstract class BaseS3Map<T> implements Map<String, T>, 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<T> implements Map<String, T>, 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<S3Object> getAllObjects() {
@ -123,7 +122,7 @@ public abstract class BaseS3Map<T> implements Map<String, T>, S3Map {
} catch (Exception e) {
Utils.<S3RuntimeException> 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<T> implements Map<String, T>, S3Map {
} catch (Exception e) {
Utils.<S3RuntimeException> 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<T> implements Map<String, T>, S3Map {
} catch (Exception e) {
Utils.<S3RuntimeException> 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);
}
}

View File

@ -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<S3Object.Metadata> 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<List<Metadata>> getOwnedBuckets() {
GetMetaDataForOwnedBuckets listRequest = factory
.createGetMetaDataForOwnedBuckets();
public Future<List<Metadata>> listOwnedBuckets() {
ListOwnedBuckets listRequest = factory
.createGetMetadataForOwnedBuckets();
client.submit(listRequest);
return listRequest;
}

View File

@ -69,7 +69,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
} catch (Exception e) {
Utils.<S3RuntimeException> 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<InputStream> implements
} catch (Exception e) {
Utils.<S3RuntimeException> 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<InputStream> implements
} catch (Exception e) {
Utils.<S3RuntimeException> 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);
}
}

View File

@ -92,7 +92,7 @@ public class LiveS3ObjectMap extends BaseS3Map<S3Object> implements S3ObjectMap
} catch (Exception e) {
Utils.<S3RuntimeException> 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<S3Object> implements S3ObjectMap
} catch (Exception e) {
Utils.<S3RuntimeException> 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<S3Object> implements S3ObjectMap
} catch (Exception e) {
Utils.<S3RuntimeException> 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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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";
}

View File

@ -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;

View File

@ -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;

View File

@ -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<S3Object.Metadata> {
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();

View File

@ -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<S3Error> {
@ -46,20 +49,10 @@ public class ErrorHandler extends ParseSax.HandlerWithResult<S3Error> {
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();
}

View File

@ -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:
* <p/>
* 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<S3Bucket.Metadata> buckets = new ArrayList<S3Bucket.Metadata>();
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());

View File

@ -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:
* <p/>
* 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<S3Bucket> {
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();

View File

@ -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<List<S3Bucket.Metadata>> parseListAllMyBucketsFactory;
@VisibleForTesting
public static interface GenericParseFactory<T> {
ParseSax<T> create(ParseSax.HandlerWithResult<T> handler);
}
@ -51,7 +54,9 @@ public class S3ParserFactory {
@Inject
Provider<ListAllMyBucketsHandler> ListAllMyBucketsHandlerprovider;
@VisibleForTesting
/**
* @return a parser used to handle {@link ListOwnedBuckets} responses
*/
public ParseSax<List<S3Bucket.Metadata>> createListBucketsParser() {
return parseListAllMyBucketsFactory
.create(ListAllMyBucketsHandlerprovider.get());
@ -63,7 +68,9 @@ public class S3ParserFactory {
@Inject
Provider<ListBucketHandler> ListBucketHandlerprovider;
@VisibleForTesting
/**
* @return a parser used to handle {@link ListBucket} responses
*/
public ParseSax<S3Bucket> createListBucketParser() {
return parseListBucketFactory.create(ListBucketHandlerprovider.get());
}
@ -74,7 +81,9 @@ public class S3ParserFactory {
@Inject
Provider<CopyObjectHandler> copyObjectHandlerProvider;
@VisibleForTesting
/**
* @return a parser used to handle {@link CopyObject} responses
*/
public ParseSax<S3Object.Metadata> createCopyObjectParser() {
return parseCopyObjectFactory.create(copyObjectHandlerProvider.get());
}
@ -85,6 +94,9 @@ public class S3ParserFactory {
@Inject
Provider<ErrorHandler> errorHandlerProvider;
/**
* @return a parser used to handle error conditions.
*/
public ParseSax<S3Error> createErrorParser() {
return parseErrorFactory.create(errorHandlerProvider.get());
}

View File

@ -46,37 +46,23 @@ import com.google.inject.assistedinject.FactoryProvider;
* @author Adrian Cole
*/
public class S3ParserModule extends AbstractModule {
private final TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.Metadata>>> listBucketsTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.Metadata>>>() {
};
private final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Bucket>> bucketTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Bucket>>() {
};
private final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.Metadata>> objectMetadataTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.Metadata>>() {
};
private final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Error>> errorTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Error>>() {
};
@Override
protected void configure() {
install(new SaxModule());
bindCallablesThatReturnParseResults();
bindParserImplementationsToReturnTypes();
}
final TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.Metadata>>> listBucketsTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.Metadata>>>() {
};
final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Bucket>> bucketTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Bucket>>() {
};
final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.Metadata>> objectMetaDataTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.Metadata>>() {
};
final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Error>> errorTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Error>>() {
};
bind(listBucketsTypeLiteral).toProvider(
FactoryProvider.newFactory(listBucketsTypeLiteral,
new TypeLiteral<ParseSax<List<S3Bucket.Metadata>>>() {
}));
bind(bucketTypeLiteral).toProvider(
FactoryProvider.newFactory(bucketTypeLiteral,
new TypeLiteral<ParseSax<S3Bucket>>() {
}));
bind(objectMetaDataTypeLiteral).toProvider(
FactoryProvider.newFactory(objectMetaDataTypeLiteral,
new TypeLiteral<ParseSax<S3Object.Metadata>>() {
}));
bind(errorTypeLiteral).toProvider(
FactoryProvider.newFactory(errorTypeLiteral,
new TypeLiteral<ParseSax<S3Error>>() {
}));
// Bind the implementations of handlers to the interfaces they implement
private void bindParserImplementationsToReturnTypes() {
bind(
new TypeLiteral<ParseSax.HandlerWithResult<List<S3Bucket.Metadata>>>() {
}).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<ParseSax<List<S3Bucket.Metadata>>>() {
}));
bind(bucketTypeLiteral).toProvider(
FactoryProvider.newFactory(bucketTypeLiteral,
new TypeLiteral<ParseSax<S3Bucket>>() {
}));
bind(objectMetadataTypeLiteral).toProvider(
FactoryProvider.newFactory(objectMetadataTypeLiteral,
new TypeLiteral<ParseSax<S3Object.Metadata>>() {
}));
bind(errorTypeLiteral).toProvider(
FactoryProvider.newFactory(errorTypeLiteral,
new TypeLiteral<ParseSax<S3Error>>() {
}));
}
}

View File

@ -40,7 +40,7 @@ public class S3ConnectionTest extends S3IntegrationTest {
@Test
void testListBuckets() throws Exception {
List<S3Bucket.Metadata> myBuckets = client.getOwnedBuckets().get(10,
List<S3Bucket.Metadata> myBuckets = client.listOwnedBuckets().get(10,
TimeUnit.SECONDS);
for (S3Bucket.Metadata bucket : myBuckets) {
context.createInputStreamMap(bucket.getName()).size();

View File

@ -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 = "<apples><apple name=\"fuji\" /></apples>";
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 = "<apples><apple name=\"fuji\" /></apples>";
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<S3Bucket.Metadata> metaData = client.getOwnedBuckets().get(10,
List<S3Bucket.Metadata> metadata = client.listOwnedBuckets().get(10,
TimeUnit.SECONDS);
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
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);

View File

@ -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<S3Object> {
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);

View File

@ -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;

View File

@ -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<List<Metadata>> getOwnedBuckets() {
public Future<List<Metadata>> listOwnedBuckets() {
return new FutureBase<List<S3Bucket.Metadata>>() {
public List<S3Bucket.Metadata> get() throws InterruptedException,
ExecutionException {

View File

@ -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);
}
}

View File

@ -0,0 +1,64 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
* <p/>
* 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);
}
}

View File

@ -0,0 +1,78 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
* <p/>
* 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;
}
}

View File

@ -1,6 +1,6 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
* Getright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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
}
}

View File

@ -0,0 +1,66 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
* <p/>
* 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<S3Bucket.Metadata> 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<S3Bucket.Metadata> 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);
}
}

View File

@ -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());
}

View File

@ -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.
* <p/>
@ -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());

View File

@ -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<String, String> userMdata = HashMultimap.create();
expect(metaData.getUserMetadata()).andReturn(userMdata).atLeastOnce();
expect(metadata.getUserMetadata()).andReturn(userMdata).atLeastOnce();
replay(metaData);
replay(metadata);
object.setData("<a></a>");
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

View File

@ -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;
@ -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 = "<ListBucketHandler xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>adrianjbosstest</Name><Prefix></Prefix><Marker></Marker><MaxKeys>1000</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>3366</Key><LastModified>2009-03-12T02:00:13.000Z</LastModified><ETag>&quot;9d7bb64e8e18ee34eec06dd2cf37b766&quot;</ETag><Size>136</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketHandler>";
@ -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");

View File

@ -1,92 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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<Boolean> 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);
// }
}

View File

@ -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");
}
}

View File

@ -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<String, String> headers = overrideAcl(
CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders();
assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(),
CannedAccessPolicy.AUTHENTICATED_READ.toString());
}
}

View File

@ -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);

View File

@ -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;
/**

View File

@ -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;
/**

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -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 = "<Error><Code>NotImplemented</Code><Message>A header you provided implies functionality that is not implemented</Message><Header>Transfer-Encoding</Header><RequestId>7C59925D75D15561</RequestId><HostId>fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb</HostId></Error>";
@ -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");
}

View File

@ -1,54 +0,0 @@
====
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
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'
<profile>
<id>appengine</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<appengine.home>/path/to/appengine-java-sdk-1.2.0</appengine.home>
</properties>
</profile>
<profile>
<id>aws</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<jclouds.aws.accesskeyid>YOUR_ACCESS_KEY_ID</jclouds.aws.accesskeyid>
<jclouds.aws.secretaccesskey>YOUR_SECRET_KEY</jclouds.aws.secretaccesskey>
</properties>
</profile>
<repositories>
<repository>
<id>jclouds</id>
<url>http://jclouds.googlecode.com/svn/trunk/repo</url>
</repository>
</repositories>

View File

@ -1,194 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
$HeadURL$
$Revision$
$Date$
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.html
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>jclouds-project</artifactId>
<groupId>org.jclouds</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jclouds-gae-s3-example</artifactId>
<packaging>war</packaging>
<name>JClouds Sample for Google App Engine</name>
<description>JClouds Sample for Google App Engine</description>
<properties>
<!-- note you must set the property ${appengine.home} to a valid extraction of appengine-java-sdk -->
<appengine.home>/Users/adriancole/Desktop/appengine-java-sdk-1.2.0</appengine.home>
<devappserver.address>localhost</devappserver.address>
<devappserver.port>8088</devappserver.port>
<jclouds.aws.accesskeyid></jclouds.aws.accesskeyid>
<jclouds.aws.secretaccesskey></jclouds.aws.secretaccesskey>
</properties>
<repositories>
<repository>
<id>guice-snapshot</id>
<url>http://guice-maven.googlecode.com/svn/trunk</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>Main Maven Repo</id>
<url>http://repo1.maven.org/maven2/</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-gae</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-s3</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-s3</artifactId>
<version>${project.version}</version>
<scope>test</scope>
<type>test-jar</type>
</dependency>
<dependency>
<groupId>com.google.code.guice</groupId>
<artifactId>guice-servlet</artifactId>
<version>2.0-r943</version>
</dependency>
<dependency>
<artifactId>standard</artifactId>
<groupId>taglibs</groupId>
<version>1.1.2</version>
<type>jar</type>
<scope>runtime</scope>
</dependency>
<dependency>
<artifactId>jstl</artifactId>
<groupId>javax.servlet</groupId>
<version>1.1.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-el_1.0_spec</artifactId>
<version>1.0.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jsp_2.1_spec</artifactId>
<version>1.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_2.5_spec</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-tools-api</artifactId>
<version>1.2.0</version>
<scope>system</scope>
<systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<testSourceDirectory>src/it/java</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<testClassesDirectory>target/test-classes</testClassesDirectory>
<systemProperties>
<property>
<name>jclouds.aws.accesskeyid</name>
<value>${jclouds.aws.accesskeyid}</value>
</property>
<property>
<name>jclouds.aws.secretaccesskey</name>
<value>${jclouds.aws.secretaccesskey}</value>
</property>
<property>
<name>appengine.home</name>
<value>${appengine.home}</value>
</property>
<property>
<name>devappserver.address</name>
<value>${devappserver.address}</value>
</property>
<property>
<name>devappserver.port</name>
<value>${devappserver.port}</value>
</property>
<property>
<name>warfile</name>
<value>${project.build.directory}/${project.artifactId}</value>
</property>
</systemProperties>
<additionalClasspathElements>
<additionalClasspathElement>${appengine.home}/lib/appengine-tools-api.jar
</additionalClasspathElement>
</additionalClasspathElements>
<environmentVariables>
<DEBUG>true</DEBUG>
<SDK_BIN>${appengine.home}/bin</SDK_BIN>
<SDK_LIB>${appengine.home}/lib</SDK_LIB>
<SDK_CONFIG>${appengine.home}/config/sdk</SDK_CONFIG>
</environmentVariables>
</configuration>
</execution>
</executions>
<configuration>
<!-- fool default surefire execution in 'test' to not find any test classes -->
<testClassesDirectory>target/classes</testClassesDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,75 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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();
}
}

View File

@ -1,100 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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;
}
}

View File

@ -1,75 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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<S3Bucket.Metadata> 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();
}
}

View File

@ -1,99 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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);
}
}

Some files were not shown because too many files have changed in this diff Show More