separated out unit tests from integration tests and fixed javadoc

git-svn-id: http://jclouds.googlecode.com/svn/trunk@810 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-05-19 17:33:41 +00:00
parent 40067b58f0
commit 69deb933e8
89 changed files with 4960 additions and 4239 deletions

View File

@ -23,26 +23,20 @@
*/ */
package org.jclouds.http.internal; package org.jclouds.http.internal;
import java.net.URL; import com.google.inject.Inject;
import java.util.Collections; import org.jclouds.http.*;
import java.util.List;
import javax.annotation.Resource;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpFutureCommandClient;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseHandler;
import org.jclouds.http.annotation.ClientErrorHandler; import org.jclouds.http.annotation.ClientErrorHandler;
import org.jclouds.http.annotation.RedirectHandler; import org.jclouds.http.annotation.RedirectHandler;
import org.jclouds.http.annotation.ServerErrorHandler; import org.jclouds.http.annotation.ServerErrorHandler;
import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler; import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.inject.Inject; import javax.annotation.Resource;
import java.net.URL;
import java.util.Collections;
import java.util.List;
public abstract class BaseHttpFutureCommandClient implements HttpFutureCommandClient { public abstract class BaseHttpFutureCommandClient implements HttpFutureCommandClient {
protected final URL target; protected final URL target;
@ -63,30 +57,30 @@ public abstract class BaseHttpFutureCommandClient implements HttpFutureCommandC
@Inject @Inject
public BaseHttpFutureCommandClient(URL target) { public BaseHttpFutureCommandClient(URL target) {
this.target = target; this.target = target;
} }
protected boolean isRetryable(HttpFutureCommand<?> command, protected boolean isRetryable(HttpFutureCommand<?> command,
HttpResponse response) { HttpResponse response) {
int code = response.getStatusCode(); int code = response.getStatusCode();
if (command.getRequest().isReplayable() && code >= 500) { if (command.getRequest().isReplayable() && code >= 500) {
logger.info("resubmitting command: %1$s", command); logger.debug("resubmitting command: %1$s", command);
return true; return true;
} }
return false; return false;
} }
protected void handleResponse(HttpFutureCommand<?> command, HttpResponse response) { protected void handleResponse(HttpFutureCommand<?> command, HttpResponse response) {
int code = response.getStatusCode(); int code = response.getStatusCode();
if (code >= 500) { if (code >= 500) {
this.serverErrorHandler.handle(command, response); this.serverErrorHandler.handle(command, response);
} else if (code >= 400 && code < 500) { } else if (code >= 400 && code < 500) {
this.clientErrorHandler.handle(command, response); this.clientErrorHandler.handle(command, response);
} else if (code >= 300 && code < 400) { } else if (code >= 300 && code < 400) {
this.redirectHandler.handle(command, response); this.redirectHandler.handle(command, response);
} else { } else {
command.getResponseFuture().setResponse(response); command.getResponseFuture().setResponse(response);
command.getResponseFuture().run(); command.getResponseFuture().run();
} }
} }

View File

@ -23,44 +23,41 @@
*/ */
package org.jclouds.logging.config; package org.jclouds.logging.config;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Resource;
import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import static com.google.common.collect.Sets.filter;
import com.google.common.collect.Sets;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.ProvisionException; import com.google.inject.ProvisionException;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import com.google.inject.spi.InjectionListener; import com.google.inject.spi.InjectionListener;
import com.google.inject.spi.TypeEncounter; import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener; import com.google.inject.spi.TypeListener;
import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory;
import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/** /**
* TypeListener that will bind {@link org.jclouds.logging.Logger} to members annotated with * TypeListener that will bind {@link org.jclouds.logging.Logger} to members annotated with
* {@link javax.annotation.Resource} * {@link javax.annotation.Resource}
* * <p/>
* This class is a TypeListener so that it can create a logger whose category is * This class is a TypeListener so that it can create a logger whose category is
* the same as the name of the injected instance's class. * the same as the name of the injected instance's class.
* * <p/>
* Note that this occurs post-object construction through * Note that this occurs post-object construction through
* {@link com.google.inject.Binder#bindListener}. * {@link com.google.inject.Binder#bindListener}.
* * <p/>
* Here's an example usage: * Here's an example usage:
* <pre> * <pre>
* class A { * class A {
* @Resource private Logger logger = Logger.NULL; * @Resource private Logger logger = Logger.NULL;
* } * }
* * <p/>
* Injector i = Guice.createInjector(new AbstractModule() { * Injector i = Guice.createInjector(new AbstractModule() {
* @Override protected void configure() { * @Override protected void configure() {
* bindListener(any(), new * bindListener(any(), new
@ -68,79 +65,72 @@ import com.google.inject.spi.TypeListener;
* JDKLogger.JDKLoggerFactory())); * JDKLogger.JDKLoggerFactory()));
* } * }
* }); * });
* * <p/>
* A = i.getInstance(A.class); * A = i.getInstance(A.class);
* // A will now have a logger associated with it * // A will now have a logger associated with it
* </pre> * </pre>
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
public class BindLoggersAnnotatedWithResource implements TypeListener { public class BindLoggersAnnotatedWithResource implements TypeListener {
static class AssignLoggerToField<I> implements InjectionListener<I> { static class AssignLoggerToField<I> implements InjectionListener<I> {
private final Logger logger; private final Logger logger;
private final Field field; private final Field field;
AssignLoggerToField(Logger logger, Field field) { AssignLoggerToField(Logger logger, Field field) {
this.logger = logger; this.logger = logger;
this.field = field; this.field = field;
} }
public void afterInjection(I injectee) { public void afterInjection(I injectee) {
try { try {
field.setAccessible(true); field.setAccessible(true);
field.set(injectee, logger); field.set(injectee, logger);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw new ProvisionException(e.getMessage(), e); throw new ProvisionException(e.getMessage(), e);
} }
} }
} }
static class LoggerFieldsAnnotatedWithResource implements static class LoggerFieldsAnnotatedWithResource implements
Function<Field, Field> { Predicate<Field> {
public Field apply(Field from) { public boolean apply(Field from) {
Annotation inject = from.getAnnotation(Resource.class); Annotation inject = from.getAnnotation(Resource.class);
if (inject != null && from.getType().isAssignableFrom(Logger.class)) { return (inject != null && from.getType().isAssignableFrom(Logger.class));
return from; }
}
return null;
}
} }
private final LoggerFactory loggerFactory; private final LoggerFactory loggerFactory;
@Inject @Inject
public BindLoggersAnnotatedWithResource(LoggerFactory loggerFactory) { public BindLoggersAnnotatedWithResource(LoggerFactory loggerFactory) {
this.loggerFactory = loggerFactory; this.loggerFactory = loggerFactory;
} }
public <I> void hear(TypeLiteral<I> injectableType, public <I> void hear(TypeLiteral<I> injectableType,
TypeEncounter<I> encounter) { TypeEncounter<I> encounter) {
Class<? super I> type = injectableType.getRawType(); Class<? super I> type = injectableType.getRawType();
Set<Field> loggerFields = getLoggerFieldsAnnotatedWithResource(type); Set<Field> loggerFields = getLoggerFieldsAnnotatedWithResource(type);
if (loggerFields.size() == 0) if (loggerFields.size() == 0)
return; return;
Logger logger = loggerFactory.getLogger(type.getName()); Logger logger = loggerFactory.getLogger(type.getName());
for (Field field : loggerFields) { for (Field field : loggerFields) {
encounter.register(new AssignLoggerToField<I>(logger, field)); encounter.register(new AssignLoggerToField<I>(logger, field));
} }
} }
@VisibleForTesting @VisibleForTesting
Set<Field> getLoggerFieldsAnnotatedWithResource(Class<?> declaredType) { Set<Field> getLoggerFieldsAnnotatedWithResource(Class<?> declaredType) {
Set<Field> fields = new HashSet<Field>(); Set<Field> fields = new HashSet<Field>();
Class<?> type = declaredType; Class<?> type = declaredType;
while (type != null) { while (type != null) {
fields.addAll(Arrays.asList(type.getDeclaredFields())); fields.addAll(Arrays.asList(type.getDeclaredFields()));
type = type.getSuperclass(); type = type.getSuperclass();
} }
Set<Field> loggerFields = Sets.newHashSet(Iterables.transform(fields, return filter(fields, new LoggerFieldsAnnotatedWithResource());
new LoggerFieldsAnnotatedWithResource()));
loggerFields.remove(null);
return loggerFields;
} }
} }

View File

@ -37,6 +37,12 @@ import org.apache.commons.io.IOUtils;
public class Utils { public class Utils {
/**
*
* @param <E> Exception type you'd like rethrown
* @param e Exception you are inspecting
* @throws E
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <E extends Exception> void rethrowIfRuntimeOrSameType(Exception e) throws E { public static <E extends Exception> void rethrowIfRuntimeOrSameType(Exception e) throws E {
if (e instanceof ExecutionException) { if (e instanceof ExecutionException) {

View File

@ -23,129 +23,126 @@
*/ */
package org.jclouds.logging.config; package org.jclouds.logging.config;
import static com.google.inject.matcher.Matchers.any;
import static org.easymock.classextension.EasyMock.createMock;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.lang.reflect.Field;
import java.util.Set;
import javax.annotation.Resource;
import org.jclouds.logging.Logger;
import org.jclouds.logging.config.BindLoggersAnnotatedWithResource.AssignLoggerToField;
import org.jclouds.logging.config.BindLoggersAnnotatedWithResource.LoggerFieldsAnnotatedWithResource;
import org.jclouds.logging.jdk.JDKLogger;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Injector; import com.google.inject.Injector;
import static com.google.inject.matcher.Matchers.any;
import static org.easymock.classextension.EasyMock.createMock;
import org.jclouds.logging.Logger;
import org.jclouds.logging.config.BindLoggersAnnotatedWithResource.AssignLoggerToField;
import org.jclouds.logging.config.BindLoggersAnnotatedWithResource.LoggerFieldsAnnotatedWithResource;
import org.jclouds.logging.jdk.JDKLogger;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.Set;
@Test
public class BindLoggersAnnotatedWithResourceTest { public class BindLoggersAnnotatedWithResourceTest {
private BindLoggersAnnotatedWithResource blawr; private BindLoggersAnnotatedWithResource blawr;
public static class A { public static class A {
@Resource @Resource
private Logger logger = Logger.NULL; private Logger logger = Logger.NULL;
} }
public static class B { public static class B {
@Resource @Resource
private Logger logger = Logger.NULL; private Logger logger = Logger.NULL;
} }
@BeforeMethod @BeforeMethod
void createBlawr() { void createBlawr() {
blawr = new BindLoggersAnnotatedWithResource( blawr = new BindLoggersAnnotatedWithResource(
new JDKLogger.JDKLoggerFactory()); new JDKLogger.JDKLoggerFactory());
} }
@Test @Test
void testHear() { void testHear() {
Injector i = Guice.createInjector(new AbstractModule() { Injector i = Guice.createInjector(new AbstractModule() {
@Override @Override
protected void configure() { protected void configure() {
bindListener(any(), blawr); bindListener(any(), blawr);
} }
}); });
assertEquals(i.getInstance(A.class).logger.getCategory(), getClass() assertEquals(i.getInstance(A.class).logger.getCategory(), getClass()
.getName() .getName()
+ "$A"); + "$A");
assertEquals(i.getInstance(B.class).logger.getCategory(), getClass() assertEquals(i.getInstance(B.class).logger.getCategory(), getClass()
.getName() .getName()
+ "$B"); + "$B");
} }
@Test @Test
public void testAssignLoggerToField() throws SecurityException, public void testAssignLoggerToField() throws SecurityException,
NoSuchFieldException, IllegalArgumentException, NoSuchFieldException, IllegalArgumentException,
IllegalAccessException { IllegalAccessException {
Logger logger = createMock(Logger.class); Logger logger = createMock(Logger.class);
A a = new A(); A a = new A();
Field field = A.class.getDeclaredField("logger"); Field field = A.class.getDeclaredField("logger");
AssignLoggerToField<A> assigner = new AssignLoggerToField<A>(logger, AssignLoggerToField<A> assigner = new AssignLoggerToField<A>(logger,
field); field);
assigner.afterInjection(a); assigner.afterInjection(a);
assert field.get(a).equals(logger); assert field.get(a).equals(logger);
} }
@Test @Test
public void testLoggerFieldsAnnotatedWithResource() public void testLoggerFieldsAnnotatedWithResource()
throws SecurityException, NoSuchFieldException { throws SecurityException, NoSuchFieldException {
LoggerFieldsAnnotatedWithResource function = new LoggerFieldsAnnotatedWithResource(); LoggerFieldsAnnotatedWithResource predicate = new LoggerFieldsAnnotatedWithResource();
assertEquals(function.apply(A.class.getDeclaredField("logger")), assert predicate.apply(A.class.getDeclaredField("logger"));
A.class.getDeclaredField("logger"));
} }
public static class C { public static class C {
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Inject @Inject
private Logger logger = Logger.NULL; private Logger logger = Logger.NULL;
} }
@Test @Test
public void testLoggerFieldsAnnotatedWithInjectReturnsNull() public void testLoggerFieldsAnnotatedWithInjectReturnsNull()
throws SecurityException, NoSuchFieldException { throws SecurityException, NoSuchFieldException {
LoggerFieldsAnnotatedWithResource function = new LoggerFieldsAnnotatedWithResource(); LoggerFieldsAnnotatedWithResource predicate = new LoggerFieldsAnnotatedWithResource();
assertNull(function.apply(C.class.getDeclaredField("logger"))); assert ! predicate.apply(C.class.getDeclaredField("logger"));
} }
public static class D { public static class D {
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Resource @Resource
private Logger logger = Logger.NULL; private Logger logger = Logger.NULL;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Resource @Resource
private Logger blogger; private Logger blogger;
} }
@Test @Test
public void testGetLoggerFieldsAnnotatedWithResourceNoLogger() { public void testGetLoggerFieldsAnnotatedWithResourceNoLogger() {
Set<Field> fields = blawr.getLoggerFieldsAnnotatedWithResource(this Set<Field> fields = blawr.getLoggerFieldsAnnotatedWithResource(this
.getClass()); .getClass());
assertEquals(fields.size(), 0); assertEquals(fields.size(), 0);
} }
@Test @Test
public void testGetLoggerFieldsAnnotatedWithResourceOneLogger() { public void testGetLoggerFieldsAnnotatedWithResourceOneLogger() {
Set<Field> fields = blawr.getLoggerFieldsAnnotatedWithResource(A.class); Set<Field> fields = blawr.getLoggerFieldsAnnotatedWithResource(A.class);
assertEquals(fields.size(), 1); assertEquals(fields.size(), 1);
} }
@Test @Test
public void testGetLoggerFieldsAnnotatedWithResourceTwoLoggers() { public void testGetLoggerFieldsAnnotatedWithResourceTwoLoggers() {
Set<Field> fields = blawr.getLoggerFieldsAnnotatedWithResource(D.class); Set<Field> fields = blawr.getLoggerFieldsAnnotatedWithResource(D.class);
assertEquals(fields.size(), 2); assertEquals(fields.size(), 2);
} }
} }

View File

@ -24,32 +24,18 @@
package org.jclouds.gae; package org.jclouds.gae;
import static com.google.appengine.api.urlfetch.FetchOptions.Builder.disallowTruncate; import static com.google.appengine.api.urlfetch.FetchOptions.Builder.disallowTruncate;
import com.google.appengine.api.urlfetch.*;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import org.apache.commons.io.IOUtils;
import org.jclouds.http.*;
import org.jclouds.http.internal.BaseHttpFutureCommandClient;
import java.io.ByteArrayInputStream; import java.io.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import org.apache.commons.io.IOUtils;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpFutureCommandClient;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.internal.BaseHttpFutureCommandClient;
import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
/** /**
* Google App Engine version of {@link HttpFutureCommandClient} * Google App Engine version of {@link HttpFutureCommandClient}
* *
@ -60,56 +46,56 @@ public class URLFetchServiceClient extends BaseHttpFutureCommandClient {
@Inject @Inject
public URLFetchServiceClient(URL target, URLFetchService urlFetchService) public URLFetchServiceClient(URL target, URLFetchService urlFetchService)
throws MalformedURLException { throws MalformedURLException {
super(target); super(target);
this.urlFetchService = urlFetchService; this.urlFetchService = urlFetchService;
} }
public void submit(HttpFutureCommand<?> command) { public void submit(HttpFutureCommand<?> command) {
HttpRequest request = command.getRequest(); HttpRequest request = command.getRequest();
HTTPResponse gaeResponse = null; HTTPResponse gaeResponse = null;
try { try {
for (HttpRequestFilter filter : requestFilters) { for (HttpRequestFilter filter : requestFilters) {
filter.filter(request); filter.filter(request);
} }
HttpResponse response = null; HttpResponse response = null;
for (;;) { for (; ;) {
logger.trace("%1$s - converting request %2$s", target, request); logger.trace("%1$s - converting request %2$s", target, request);
HTTPRequest gaeRequest = convert(request); HTTPRequest gaeRequest = convert(request);
if (logger.isTraceEnabled()) if (logger.isTraceEnabled())
logger.trace( logger.trace(
"%1$s - submitting request %2$s, headers: %3$s", "%1$s - submitting request %2$s, headers: %3$s",
target, gaeRequest.getURL(), target, gaeRequest.getURL(),
headersAsString(gaeRequest.getHeaders())); headersAsString(gaeRequest.getHeaders()));
gaeResponse = this.urlFetchService.fetch(gaeRequest); gaeResponse = this.urlFetchService.fetch(gaeRequest);
if (logger.isTraceEnabled()) if (logger.isTraceEnabled())
logger logger
.trace( .trace(
"%1$s - received response code %2$s, headers: %3$s", "%1$s - received response code %2$s, headers: %3$s",
target, gaeResponse.getResponseCode(), target, gaeResponse.getResponseCode(),
headersAsString(gaeResponse.getHeaders())); headersAsString(gaeResponse.getHeaders()));
response = convert(gaeResponse); response = convert(gaeResponse);
if (isRetryable(command, response)) if (isRetryable(command, response))
continue; continue;
break; break;
} }
handleResponse(command, response); handleResponse(command, response);
} catch (Exception e) { } catch (Exception e) {
if (gaeResponse != null && gaeResponse.getContent() != null) { if (gaeResponse != null && gaeResponse.getContent() != null) {
logger.error(e, logger.error(e,
"error encountered during the execution: %1$s%n%2$s", "error encountered during the execution: %1$s%n%2$s",
gaeResponse, new String(gaeResponse.getContent())); gaeResponse, new String(gaeResponse.getContent()));
} }
command.setException(e); command.setException(e);
} }
} }
String headersAsString(List<HTTPHeader> headers) { String headersAsString(List<HTTPHeader> headers) {
StringBuilder builder = new StringBuilder(""); StringBuilder builder = new StringBuilder("");
for (HTTPHeader header : headers) for (HTTPHeader header : headers)
builder.append("[").append(header.getName()).append("=").append( builder.append("[").append(header.getName()).append("=").append(
header.getValue()).append("],"); header.getValue()).append("],");
return builder.toString(); return builder.toString();
} }
/** /**
@ -118,54 +104,54 @@ public class URLFetchServiceClient extends BaseHttpFutureCommandClient {
*/ */
@VisibleForTesting @VisibleForTesting
void changeRequestContentToBytes(HttpRequest request) throws IOException { void changeRequestContentToBytes(HttpRequest request) throws IOException {
Object content = request.getPayload(); Object content = request.getPayload();
if (content == null || content instanceof byte[]) { if (content == null || content instanceof byte[]) {
return; return;
} else if (content instanceof String) { } else if (content instanceof String) {
String string = (String) content; String string = (String) content;
request.setPayload(string.getBytes()); request.setPayload(string.getBytes());
} else if (content instanceof InputStream || content instanceof File) { } else if (content instanceof InputStream || content instanceof File) {
InputStream i = content instanceof InputStream ? (InputStream) content InputStream i = content instanceof InputStream ? (InputStream) content
: new FileInputStream((File) content); : new FileInputStream((File) content);
try { try {
request.setPayload(IOUtils.toByteArray(i)); request.setPayload(IOUtils.toByteArray(i));
} finally { } finally {
IOUtils.closeQuietly(i); IOUtils.closeQuietly(i);
} }
} else { } else {
throw new UnsupportedOperationException("Content not supported " throw new UnsupportedOperationException("Content not supported "
+ content.getClass()); + content.getClass());
} }
} }
@VisibleForTesting @VisibleForTesting
HttpResponse convert(HTTPResponse gaeResponse) { HttpResponse convert(HTTPResponse gaeResponse) {
HttpResponse response = new HttpResponse(); HttpResponse response = new HttpResponse();
response.setStatusCode(gaeResponse.getResponseCode()); response.setStatusCode(gaeResponse.getResponseCode());
for (HTTPHeader header : gaeResponse.getHeaders()) { for (HTTPHeader header : gaeResponse.getHeaders()) {
response.getHeaders().put(header.getName(), header.getValue()); response.getHeaders().put(header.getName(), header.getValue());
} }
if (gaeResponse.getContent() != null) { if (gaeResponse.getContent() != null) {
response.setContent(new ByteArrayInputStream(gaeResponse response.setContent(new ByteArrayInputStream(gaeResponse
.getContent())); .getContent()));
} }
return response; return response;
} }
@VisibleForTesting @VisibleForTesting
HTTPRequest convert(HttpRequest request) throws IOException { HTTPRequest convert(HttpRequest request) throws IOException {
URL url = new URL(target, request.getUri()); URL url = new URL(target, request.getUri());
HTTPRequest gaeRequest = new HTTPRequest(url, HTTPMethod HTTPRequest gaeRequest = new HTTPRequest(url, HTTPMethod
.valueOf(request.getMethod()), disallowTruncate()); .valueOf(request.getMethod()), disallowTruncate());
for (String header : request.getHeaders().keySet()) { for (String header : request.getHeaders().keySet()) {
for (String value : request.getHeaders().get(header)) for (String value : request.getHeaders().get(header))
gaeRequest.addHeader(new HTTPHeader(header, value)); gaeRequest.addHeader(new HTTPHeader(header, value));
} }
if (request.getPayload() != null) { if (request.getPayload() != null) {
changeRequestContentToBytes(request); changeRequestContentToBytes(request);
gaeRequest.setPayload((byte[]) request.getPayload()); gaeRequest.setPayload((byte[]) request.getPayload());
} }
return gaeRequest; return gaeRequest;
} }
} }

View File

@ -23,22 +23,17 @@
*/ */
package org.jclouds.http.httpnio.pool; package org.jclouds.http.httpnio.pool;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.http.nio.NHttpConnection;
import org.jclouds.command.pool.FutureCommandConnectionPoolClient;
import org.jclouds.http.*;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import org.apache.http.nio.NHttpConnection;
import org.jclouds.command.pool.FutureCommandConnectionPoolClient;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpFutureCommandClient;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/** /**
* // TODO: Adrian: Document this! * // TODO: Adrian: Document this!
* *
@ -46,41 +41,41 @@ import com.google.inject.Singleton;
*/ */
@Singleton @Singleton
public class HttpNioConnectionPoolClient public class HttpNioConnectionPoolClient
extends extends
FutureCommandConnectionPoolClient<NHttpConnection, HttpFutureCommand<?>> FutureCommandConnectionPoolClient<NHttpConnection, HttpFutureCommand<?>>
implements HttpFutureCommandClient { implements HttpFutureCommandClient {
private List<HttpRequestFilter> requestFilters = Collections.emptyList(); private List<HttpRequestFilter> requestFilters = Collections.emptyList();
public List<HttpRequestFilter> getRequestFilters() { public List<HttpRequestFilter> getRequestFilters() {
return requestFilters; return requestFilters;
} }
@Inject(optional = true) @Inject(optional = true)
public void setRequestFilters(List<HttpRequestFilter> requestFilters) { public void setRequestFilters(List<HttpRequestFilter> requestFilters) {
this.requestFilters = requestFilters; this.requestFilters = requestFilters;
} }
@Override @Override
protected void invoke(HttpFutureCommand<?> command) { protected void invoke(HttpFutureCommand<?> command) {
HttpRequest request = (HttpRequest) command.getRequest(); HttpRequest request = (HttpRequest) command.getRequest();
try { try {
for (HttpRequestFilter filter : getRequestFilters()) { for (HttpRequestFilter filter : getRequestFilters()) {
filter.filter(request); filter.filter(request);
} }
super.invoke(command); super.invoke(command);
} catch (HttpException e) { } catch (HttpException e) {
command.setException(e); command.setException(e);
} }
} }
@Inject @Inject
public HttpNioConnectionPoolClient( public HttpNioConnectionPoolClient(
ExecutorService executor, ExecutorService executor,
HttpNioFutureCommandConnectionPool httpFutureCommandConnectionHandleNHttpConnectionNioFutureCommandConnectionPool, HttpNioFutureCommandConnectionPool httpFutureCommandConnectionHandleNHttpConnectionNioFutureCommandConnectionPool,
BlockingQueue<HttpFutureCommand<?>> commandQueue) { BlockingQueue<HttpFutureCommand<?>> commandQueue) {
super( super(
executor, executor,
httpFutureCommandConnectionHandleNHttpConnectionNioFutureCommandConnectionPool, httpFutureCommandConnectionHandleNHttpConnectionNioFutureCommandConnectionPool,
commandQueue); commandQueue);
} }
} }

View File

@ -23,14 +23,8 @@
*/ */
package org.jclouds.http.httpnio.pool; package org.jclouds.http.httpnio.pool;
import java.io.IOException; import com.google.inject.Inject;
import java.net.InetSocketAddress; import com.google.inject.name.Named;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.apache.http.HttpException; import org.apache.http.HttpException;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor; import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.nio.NHttpConnection; import org.apache.http.nio.NHttpConnection;
@ -46,8 +40,9 @@ import org.jclouds.command.pool.FutureCommandConnectionPool;
import org.jclouds.command.pool.PoolConstants; import org.jclouds.command.pool.PoolConstants;
import org.jclouds.http.HttpFutureCommand; import org.jclouds.http.HttpFutureCommand;
import com.google.inject.Inject; import java.io.IOException;
import com.google.inject.name.Named; import java.net.InetSocketAddress;
import java.util.concurrent.*;
/** /**
* Connection Pool for HTTP requests that utilizes Apache HTTPNio * Connection Pool for HTTP requests that utilizes Apache HTTPNio
@ -55,8 +50,8 @@ import com.google.inject.name.Named;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class HttpNioFutureCommandConnectionPool extends public class HttpNioFutureCommandConnectionPool extends
FutureCommandConnectionPool<NHttpConnection, HttpFutureCommand<?>> FutureCommandConnectionPool<NHttpConnection, HttpFutureCommand<?>>
implements EventListener { implements EventListener {
private final NHttpClientConnectionPoolSessionRequestCallback sessionCallback; private final NHttpClientConnectionPoolSessionRequestCallback sessionCallback;
private final DefaultConnectingIOReactor ioReactor; private final DefaultConnectingIOReactor ioReactor;
@ -66,227 +61,227 @@ public class HttpNioFutureCommandConnectionPool extends
@Inject @Inject
public HttpNioFutureCommandConnectionPool( public HttpNioFutureCommandConnectionPool(
ExecutorService executor, ExecutorService executor,
Semaphore allConnections, Semaphore allConnections,
BlockingQueue<HttpFutureCommand<?>> commandQueue, BlockingQueue<HttpFutureCommand<?>> commandQueue,
BlockingQueue<NHttpConnection> available, BlockingQueue<NHttpConnection> available,
AsyncNHttpClientHandler clientHandler, AsyncNHttpClientHandler clientHandler,
DefaultConnectingIOReactor ioReactor, DefaultConnectingIOReactor ioReactor,
IOEventDispatch dispatch, IOEventDispatch dispatch,
FutureCommandConnectionHandleFactory requestHandleFactory, FutureCommandConnectionHandleFactory requestHandleFactory,
InetSocketAddress target, InetSocketAddress target,
@Named(PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE) int maxConnectionReuse, @Named(PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE) int maxConnectionReuse,
@Named(PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES) int maxSessionFailures) { @Named(PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES) int maxSessionFailures) {
super(executor, allConnections, commandQueue, requestHandleFactory, super(executor, allConnections, commandQueue, requestHandleFactory,
maxConnectionReuse, available); maxConnectionReuse, available);
this.ioReactor = ioReactor; this.ioReactor = ioReactor;
this.dispatch = dispatch; this.dispatch = dispatch;
this.target = target; this.target = target;
this.maxSessionFailures = maxSessionFailures; this.maxSessionFailures = maxSessionFailures;
this.sessionCallback = new NHttpClientConnectionPoolSessionRequestCallback(); this.sessionCallback = new NHttpClientConnectionPoolSessionRequestCallback();
clientHandler.setEventListener(this); clientHandler.setEventListener(this);
} }
@Override @Override
public void start() { public void start() {
synchronized (this.statusLock) { synchronized (this.statusLock) {
if (this.status.compareTo(Status.INACTIVE) == 0) { if (this.status.compareTo(Status.INACTIVE) == 0) {
executor.execute(new Runnable() { executor.execute(new Runnable() {
public void run() { public void run() {
try { try {
ioReactor.execute(dispatch); ioReactor.execute(dispatch);
} catch (IOException e) { } catch (IOException e) {
exception.set(e); exception.set(e);
logger.error(e, "Error dispatching %1$s", dispatch); logger.error(e, "Error dispatching %1$s", dispatch);
status = Status.SHUTDOWN_REQUEST; status = Status.SHUTDOWN_REQUEST;
} }
} }
}); });
} }
super.start(); super.start();
} }
} }
public void shutdownReactor(long waitMs) { public void shutdownReactor(long waitMs) {
try { try {
this.ioReactor.shutdown(waitMs); this.ioReactor.shutdown(waitMs);
} catch (IOException e) { } catch (IOException e) {
logger.error(e, "Error shutting down reactor"); logger.error(e, "Error shutting down reactor");
} }
} }
@Override @Override
public boolean connectionValid(NHttpConnection conn) { public boolean connectionValid(NHttpConnection conn) {
return conn.isOpen() && !conn.isStale() return conn.isOpen() && !conn.isStale()
&& conn.getMetrics().getRequestCount() < maxConnectionReuse; && conn.getMetrics().getRequestCount() < maxConnectionReuse;
} }
@Override @Override
public void shutdownConnection(NHttpConnection conn) { public void shutdownConnection(NHttpConnection conn) {
if (conn.getMetrics().getRequestCount() >= maxConnectionReuse) if (conn.getMetrics().getRequestCount() >= maxConnectionReuse)
logger.debug( logger.debug(
"%1$s - %2$d - closing connection due to overuse %1$s/%2$s", "%1$s - %2$d - closing connection due to overuse %1$s/%2$s",
conn, conn.hashCode(), conn.getMetrics().getRequestCount(), conn, conn.hashCode(), conn.getMetrics().getRequestCount(),
maxConnectionReuse); maxConnectionReuse);
if (conn.getStatus() == NHttpConnection.ACTIVE) { if (conn.getStatus() == NHttpConnection.ACTIVE) {
try { try {
conn.shutdown(); conn.shutdown();
} catch (IOException e) { } catch (IOException e) {
logger.error(e, "Error shutting down connection"); logger.error(e, "Error shutting down connection");
} }
} }
} }
@Override @Override
protected void doWork() throws Exception { protected void doWork() throws Exception {
createNewConnection(); createNewConnection();
} }
@Override @Override
protected void doShutdown() { protected void doShutdown() {
// Give the I/O reactor 1 sec to shut down // Give the I/O reactor 1 sec to shut down
shutdownReactor(1000); shutdownReactor(1000);
assert this.ioReactor.getStatus().equals(IOReactorStatus.SHUT_DOWN) : "incorrect status after io reactor shutdown :" assert this.ioReactor.getStatus().equals(IOReactorStatus.SHUT_DOWN) : "incorrect status after io reactor shutdown :"
+ this.ioReactor.getStatus(); + this.ioReactor.getStatus();
} }
@Override @Override
protected void createNewConnection() throws InterruptedException { protected void createNewConnection() throws InterruptedException {
boolean acquired = allConnections.tryAcquire(1, TimeUnit.SECONDS); boolean acquired = allConnections.tryAcquire(1, TimeUnit.SECONDS);
if (acquired) { if (acquired) {
if (shouldDoWork()) { if (shouldDoWork()) {
logger.debug("%1$s - opening new connection", target); logger.debug("%1$s - opening new connection", target);
ioReactor.connect(target, null, null, sessionCallback); ioReactor.connect(target, null, null, sessionCallback);
} else { } else {
allConnections.release(); allConnections.release();
} }
} }
} }
@Override @Override
protected void associateHandleWithConnection( protected void associateHandleWithConnection(
FutureCommandConnectionHandle<NHttpConnection, HttpFutureCommand<?>> handle, FutureCommandConnectionHandle<NHttpConnection, HttpFutureCommand<?>> handle,
NHttpConnection connection) { NHttpConnection connection) {
connection.getContext().setAttribute("command-handle", handle); connection.getContext().setAttribute("command-handle", handle);
} }
@Override @Override
protected HttpNioFutureCommandConnectionHandle getHandleFromConnection( protected HttpNioFutureCommandConnectionHandle getHandleFromConnection(
NHttpConnection connection) { NHttpConnection connection) {
return (HttpNioFutureCommandConnectionHandle) connection.getContext() return (HttpNioFutureCommandConnectionHandle) connection.getContext()
.getAttribute("command-handle"); .getAttribute("command-handle");
} }
class NHttpClientConnectionPoolSessionRequestCallback implements class NHttpClientConnectionPoolSessionRequestCallback implements
SessionRequestCallback { SessionRequestCallback {
public void completed(SessionRequest request) { public void completed(SessionRequest request) {
logger.trace("%1$s->%2$s[%3$s] - SessionRequest complete", request logger.trace("%1$s->%2$s[%3$s] - SessionRequest complete", request
.getLocalAddress(), request.getRemoteAddress(), request .getLocalAddress(), request.getRemoteAddress(), request
.getAttachment()); .getAttachment());
} }
public void cancelled(SessionRequest request) { public void cancelled(SessionRequest request) {
logger.trace("%1$s->%2$s[%3$s] - SessionRequest cancelled", request logger.trace("%1$s->%2$s[%3$s] - SessionRequest cancelled", request
.getLocalAddress(), request.getRemoteAddress(), request .getLocalAddress(), request.getRemoteAddress(), request
.getAttachment()); .getAttachment());
releaseConnectionAndCancelResponse(request); releaseConnectionAndCancelResponse(request);
} }
private void releaseConnectionAndCancelResponse(SessionRequest request) { private void releaseConnectionAndCancelResponse(SessionRequest request) {
allConnections.release(); allConnections.release();
FutureCommand<?, ?, ?> frequest = (FutureCommand<?, ?, ?>) request FutureCommand<?, ?, ?> frequest = (FutureCommand<?, ?, ?>) request
.getAttachment(); .getAttachment();
if (frequest != null) { if (frequest != null) {
logger.error("%1$s->%2$s[%3$s] - Cancelling FutureCommand", logger.error("%1$s->%2$s[%3$s] - Cancelling FutureCommand",
request.getLocalAddress(), request.getRemoteAddress(), request.getLocalAddress(), request.getRemoteAddress(),
frequest); frequest);
frequest.cancel(true); frequest.cancel(true);
} }
} }
private void releaseConnectionAndSetResponseException( private void releaseConnectionAndSetResponseException(
SessionRequest request, Exception e) { SessionRequest request, Exception e) {
allConnections.release(); allConnections.release();
HttpFutureCommand<?> frequest = (HttpFutureCommand<?>) request HttpFutureCommand<?> frequest = (HttpFutureCommand<?>) request
.getAttachment(); .getAttachment();
if (frequest != null) { if (frequest != null) {
logger.error(e, logger.error(e,
"%1$s->%2$s[%3$s] - Setting Exception on FutureCommand", "%1$s->%2$s[%3$s] - Setting Exception on FutureCommand",
request.getLocalAddress(), request.getRemoteAddress(), request.getLocalAddress(), request.getRemoteAddress(),
frequest); frequest);
frequest.setException(e); frequest.setException(e);
} }
} }
public void failed(SessionRequest request) { public void failed(SessionRequest request) {
int count = currentSessionFailures.getAndIncrement(); int count = currentSessionFailures.getAndIncrement();
logger.warn("%1$s->%2$s[%3$s] - SessionRequest failed", request logger.warn("%1$s->%2$s[%3$s] - SessionRequest failed", request
.getLocalAddress(), request.getRemoteAddress(), request .getLocalAddress(), request.getRemoteAddress(), request
.getAttachment()); .getAttachment());
releaseConnectionAndSetResponseException(request, request releaseConnectionAndSetResponseException(request, request
.getException()); .getException());
if (count >= maxSessionFailures) { if (count >= maxSessionFailures) {
logger logger
.error( .error(
request.getException(), request.getException(),
"%1$s->%2$s[%3$s] - SessionRequest failures: %4$s, Disabling pool for %5$s", "%1$s->%2$s[%3$s] - SessionRequest failures: %4$s, Disabling pool for %5$s",
request.getLocalAddress(), request request.getLocalAddress(), request
.getRemoteAddress(), .getRemoteAddress(),
maxSessionFailures, target); maxSessionFailures, target);
exception.set(request.getException()); exception.set(request.getException());
} }
} }
public void timeout(SessionRequest request) { public void timeout(SessionRequest request) {
logger.warn("%1$s->%2$s[%3$s] - SessionRequest timeout", request logger.warn("%1$s->%2$s[%3$s] - SessionRequest timeout", request
.getLocalAddress(), request.getRemoteAddress(), request .getLocalAddress(), request.getRemoteAddress(), request
.getAttachment()); .getAttachment());
releaseConnectionAndCancelResponse(request); releaseConnectionAndCancelResponse(request);
} }
} }
public void connectionOpen(NHttpConnection conn) { public void connectionOpen(NHttpConnection conn) {
conn.setSocketTimeout(0); conn.setSocketTimeout(0);
available.offer(conn); available.offer(conn);
logger.trace("%1$s - %2$d - open", conn, conn.hashCode()); logger.trace("%1$s - %2$d - open", conn, conn.hashCode());
} }
public void connectionTimeout(NHttpConnection conn) { public void connectionTimeout(NHttpConnection conn) {
String message = String.format("%1$s - %2$d - timeout %2$d", conn, conn String message = String.format("%1$s - %2$d - timeout %2$d", conn, conn
.hashCode(), conn.getSocketTimeout()); .hashCode(), conn.getSocketTimeout());
logger.warn(message); logger.warn(message);
resubmitIfRequestIsReplayable(conn, new TimeoutException(message)); resubmitIfRequestIsReplayable(conn, new TimeoutException(message));
} }
public void connectionClosed(NHttpConnection conn) { public void connectionClosed(NHttpConnection conn) {
logger.trace("%1$s - %2$d - closed", conn, conn.hashCode()); logger.trace("%1$s - %2$d - closed", conn, conn.hashCode());
} }
public void fatalIOException(IOException ex, NHttpConnection conn) { public void fatalIOException(IOException ex, NHttpConnection conn) {
logger.error(ex, "%3$s-%1$d{%2$s} - io error", conn, conn.hashCode(), logger.error(ex, "%3$s-%1$d{%2$s} - io error", conn, conn.hashCode(),
target); target);
resubmitIfRequestIsReplayable(conn, ex); resubmitIfRequestIsReplayable(conn, ex);
} }
public void fatalProtocolException(HttpException ex, NHttpConnection conn) { public void fatalProtocolException(HttpException ex, NHttpConnection conn) {
logger.error(ex, "%3$s-%1$d{%2$s} - http error", conn, conn.hashCode(), logger.error(ex, "%3$s-%1$d{%2$s} - http error", conn, conn.hashCode(),
target); target);
setExceptionOnCommand(conn, ex); setExceptionOnCommand(conn, ex);
} }
public static interface FutureCommandConnectionHandleFactory public static interface FutureCommandConnectionHandleFactory
extends extends
FutureCommandConnectionPool.FutureCommandConnectionHandleFactory<NHttpConnection, HttpFutureCommand<?>> { FutureCommandConnectionPool.FutureCommandConnectionHandleFactory<NHttpConnection, HttpFutureCommand<?>> {
HttpNioFutureCommandConnectionHandle create( HttpNioFutureCommandConnectionHandle create(
HttpFutureCommand<?> command, NHttpConnection conn); HttpFutureCommand<?> command, NHttpConnection conn);
} }
@Override @Override
protected boolean isReplayable(HttpFutureCommand<?> command) { protected boolean isReplayable(HttpFutureCommand<?> command) {
return command.getRequest().isReplayable(); return command.getRequest().isReplayable();
} }
} }

View File

@ -23,12 +23,7 @@
*/ */
package org.jclouds.http.httpnio.pool; package org.jclouds.http.httpnio.pool;
import java.io.IOException; import com.google.inject.Inject;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
@ -45,7 +40,10 @@ import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import org.jclouds.http.httpnio.util.HttpNioUtils; import org.jclouds.http.httpnio.util.HttpNioUtils;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.inject.Inject; import javax.annotation.Resource;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
/** /**
* // TODO: Adrian: Document this! * // TODO: Adrian: Document this!
@ -53,7 +51,7 @@ import com.google.inject.Inject;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class HttpNioFutureCommandExecutionHandler implements public class HttpNioFutureCommandExecutionHandler implements
NHttpRequestExecutionHandler { NHttpRequestExecutionHandler {
private final ExecutorService executor; private final ExecutorService executor;
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@ -73,105 +71,105 @@ public class HttpNioFutureCommandExecutionHandler implements
private HttpResponseHandler serverErrorHandler = new CloseContentAndSetExceptionHandler(); private HttpResponseHandler serverErrorHandler = new CloseContentAndSetExceptionHandler();
public interface ConsumingNHttpEntityFactory { public interface ConsumingNHttpEntityFactory {
public ConsumingNHttpEntity create(HttpEntity httpEntity); public ConsumingNHttpEntity create(HttpEntity httpEntity);
} }
@Inject @Inject
public HttpNioFutureCommandExecutionHandler( public HttpNioFutureCommandExecutionHandler(
ConsumingNHttpEntityFactory entityFactory, ConsumingNHttpEntityFactory entityFactory,
ExecutorService executor, ExecutorService executor,
BlockingQueue<HttpFutureCommand<?>> commandQueue) { BlockingQueue<HttpFutureCommand<?>> commandQueue) {
this.executor = executor; this.executor = executor;
this.entityFactory = entityFactory; this.entityFactory = entityFactory;
this.commandQueue = commandQueue; this.commandQueue = commandQueue;
} }
public void initalizeContext(HttpContext context, Object attachment) { public void initalizeContext(HttpContext context, Object attachment) {
} }
public HttpEntityEnclosingRequest submitRequest(HttpContext context) { public HttpEntityEnclosingRequest submitRequest(HttpContext context) {
HttpFutureCommand<?> command = (HttpFutureCommand<?>) context HttpFutureCommand<?> command = (HttpFutureCommand<?>) context
.removeAttribute("command"); .removeAttribute("command");
if (command != null) { if (command != null) {
HttpRequest object = command.getRequest(); HttpRequest object = command.getRequest();
return HttpNioUtils.convertToApacheRequest(object); return HttpNioUtils.convertToApacheRequest(object);
} }
return null; return null;
} }
public ConsumingNHttpEntity responseEntity(HttpResponse response, public ConsumingNHttpEntity responseEntity(HttpResponse response,
HttpContext context) throws IOException { HttpContext context) throws IOException {
return entityFactory.create(response.getEntity()); return entityFactory.create(response.getEntity());
} }
public void handleResponse(HttpResponse apacheResponse, HttpContext context) public void handleResponse(HttpResponse apacheResponse, HttpContext context)
throws IOException { throws IOException {
HttpNioFutureCommandConnectionHandle handle = (HttpNioFutureCommandConnectionHandle) context HttpNioFutureCommandConnectionHandle handle = (HttpNioFutureCommandConnectionHandle) context
.removeAttribute("command-handle"); .removeAttribute("command-handle");
if (handle != null) { if (handle != null) {
try { try {
HttpFutureCommand<?> command = handle.getCommand(); HttpFutureCommand<?> command = handle.getCommand();
org.jclouds.http.HttpResponse response = HttpNioUtils org.jclouds.http.HttpResponse response = HttpNioUtils
.convertToJavaCloudsResponse(apacheResponse); .convertToJavaCloudsResponse(apacheResponse);
int code = response.getStatusCode(); int code = response.getStatusCode();
if (code >= 500) { if (code >= 500) {
if (isRetryable(command)) { if (isRetryable(command)) {
commandQueue.add(command); commandQueue.add(command);
} else { } else {
this.serverErrorHandler.handle(command, response); this.serverErrorHandler.handle(command, response);
} }
} else if (code >= 400 && code < 500) { } else if (code >= 400 && code < 500) {
this.clientErrorHandler.handle(command, response); this.clientErrorHandler.handle(command, response);
} else if (code >= 300 && code < 400) { } else if (code >= 300 && code < 400) {
this.redirectHandler.handle(command, response); this.redirectHandler.handle(command, response);
} else { } else {
processResponse(response, command); processResponse(response, command);
} }
} finally { } finally {
releaseConnectionToPool(handle); releaseConnectionToPool(handle);
} }
} else { } else {
throw new IllegalStateException(String.format( throw new IllegalStateException(String.format(
"No command-handle associated with command %1$s", context)); "No command-handle associated with command %1$s", context));
} }
} }
protected boolean isRetryable(HttpFutureCommand<?> command) { protected boolean isRetryable(HttpFutureCommand<?> command) {
if (command.getRequest().isReplayable()) { if (command.getRequest().isReplayable()) {
logger.info("resubmitting command: %1$s", command); logger.debug("resubmitting command: %1$s", command);
return true; return true;
} }
return false; return false;
} }
protected void releaseConnectionToPool( protected void releaseConnectionToPool(
HttpNioFutureCommandConnectionHandle handle) { HttpNioFutureCommandConnectionHandle handle) {
try { try {
handle.release(); handle.release();
} catch (InterruptedException e) { } catch (InterruptedException e) {
logger.error(e, "Interrupted releasing handle %1$s", handle); logger.error(e, "Interrupted releasing handle %1$s", handle);
} }
} }
protected void processResponse(org.jclouds.http.HttpResponse response, protected void processResponse(org.jclouds.http.HttpResponse response,
HttpFutureCommand<?> command) throws IOException { HttpFutureCommand<?> command) throws IOException {
command.getResponseFuture().setResponse(response); command.getResponseFuture().setResponse(response);
logger.trace("submitting response task %1$s", command logger.trace("submitting response task %1$s", command
.getResponseFuture()); .getResponseFuture());
executor.submit(command.getResponseFuture()); executor.submit(command.getResponseFuture());
} }
public void finalizeContext(HttpContext context) { public void finalizeContext(HttpContext context) {
HttpNioFutureCommandConnectionHandle handle = (HttpNioFutureCommandConnectionHandle) context HttpNioFutureCommandConnectionHandle handle = (HttpNioFutureCommandConnectionHandle) context
.removeAttribute("command-handle"); .removeAttribute("command-handle");
if (handle != null) { if (handle != null) {
try { try {
handle.cancel(); handle.cancel();
} catch (Exception e) { } catch (Exception e) {
logger.error(e, "Error cancelling handle %1$s", handle); logger.error(e, "Error cancelling handle %1$s", handle);
} }
} }
} }
} }

View File

@ -55,8 +55,7 @@
<dependency> <dependency>
<groupId>net.java.dev.jets3t</groupId> <groupId>net.java.dev.jets3t</groupId>
<artifactId>jets3t</artifactId> <artifactId>jets3t</artifactId>
<version>0.7.0</version> <version>0.7.1</version>
<optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>

View File

@ -51,6 +51,7 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<configuration> <configuration>
<quiet>true</quiet>
<links> <links>
<link>http://java.sun.com/j2se/1.5.0/docs/api/</link> <link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
<link>http://java.sun.com/javaee/5/docs/api/</link> <link>http://java.sun.com/javaee/5/docs/api/</link>

View File

@ -182,6 +182,7 @@
<goal>jar</goal> <goal>jar</goal>
</goals> </goals>
<configuration> <configuration>
<quiet>true</quiet>
<links> <links>
<link>http://java.sun.com/j2se/1.5.0/docs/api/</link> <link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
<link>http://java.sun.com/javaee/5/docs/api/</link> <link>http://java.sun.com/javaee/5/docs/api/</link>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -80,8 +80,7 @@
<dependency> <dependency>
<groupId>net.java.dev.jets3t</groupId> <groupId>net.java.dev.jets3t</groupId>
<artifactId>jets3t</artifactId> <artifactId>jets3t</artifactId>
<version>0.7.0</version> <version>0.7.1</version>
<optional>true</optional>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -49,6 +49,9 @@
<properties> <properties>
<jclouds.aws.accesskeyid></jclouds.aws.accesskeyid> <jclouds.aws.accesskeyid></jclouds.aws.accesskeyid>
<jclouds.aws.secretaccesskey></jclouds.aws.secretaccesskey> <jclouds.aws.secretaccesskey></jclouds.aws.secretaccesskey>
<jclouds.s3.httpstream.url>http://apache.rediris.es/maven/binaries/apache-maven-2.1.0-bin.tar.bz2
</jclouds.s3.httpstream.url>
<jclouds.s3.httpstream.md5>9268c9de2cccfd0d8fbcdbcfaf517a87</jclouds.s3.httpstream.md5>
</properties> </properties>
<dependencies> <dependencies>
@ -67,25 +70,115 @@
<artifactId>bcprov-jdk15</artifactId> <artifactId>bcprov-jdk15</artifactId>
<version>140</version> <version>140</version>
</dependency> </dependency>
<dependency>
<groupId>xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.2</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <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>
<!-- note that the groups/excluded groups don't work due to some problem
in surefire or testng. instead, we have to exclude via file path
<groups>integration</groups>
<excludedGroups>unit,performance,live</excludedGroups> -->
<excludes>
<exclude>**/*LiveTest.java</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
<systemProperties>
<property>
<name>jclouds.s3.httpstream.url</name>
<value>${jclouds.s3.httpstream.url}</value>
</property>
<property>
<name>jclouds.s3.httpstream.md5</name>
<value>${jclouds.s3.httpstream.md5}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
<configuration> <configuration>
<systemProperties> <!-- note that the groups/excluded groups don't work due to some problem
<property> in surefire or testng. instead, we have to exclude via file path
<name>jclouds.aws.accesskeyid</name> <groups>unit,performance</groups>
<value>${jclouds.aws.accesskeyid}</value> <excludedGroups>integration,live</excludedGroups> -->
</property> <excludes>
<property> <exclude>**/*IntegrationTest.java</exclude>
<name>jclouds.aws.secretaccesskey</name> <exclude>**/*LiveTest.java</exclude>
<value>${jclouds.aws.secretaccesskey}</value> </excludes>
</property>
</systemProperties>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<profiles>
<profile>
<id>live</id>
<build>
<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>
<!-- note that the groups/excluded groups don't work due to some problem
in surefire or testng. instead, we have to exclude via file path
<groups>live,integration</groups>
<excludedGroups>unit,performance</excludedGroups> -->
<excludes>
<exclude>none</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
<include>**/*LiveTest.java</include>
</includes>
<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>jclouds.s3.httpstream.url</name>
<value>${jclouds.s3.httpstream.url}</value>
</property>
<property>
<name>jclouds.s3.httpstream.md5</name>
<value>${jclouds.s3.httpstream.md5}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project> </project>

View File

@ -23,42 +23,34 @@
*/ */
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import org.jclouds.aws.s3.commands.options.*;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import org.jclouds.aws.s3.commands.options.CopyObjectOptions;
import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.commands.options.ListBucketOptions;
import org.jclouds.aws.s3.commands.options.PutBucketOptions;
import org.jclouds.aws.s3.commands.options.PutObjectOptions;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object;
/** /**
* Provides access to S3 via their REST API. * Provides access to S3 via their REST API.
* * <p/>
* All commands return a Future of the result from S3. Any exceptions incurred * All commands return a Future of the result from S3. Any exceptions incurred
* during processing will be wrapped in an {@link ExecutionException} as * during processing will be wrapped in an {@link ExecutionException} as
* documented in {@link Future#get()}. * documented in {@link Future#get()}.
* *
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAPI.html" />
*
* @author Adrian Cole * @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAPI.html" />
*/ */
public interface S3Connection { public interface S3Connection {
/** /**
* Retrieve a complete <code>S3Object</code>. * Retrieve a complete <code>S3Object</code>.
* *
* @see GetObject * @param bucketName namespace of the object you are retrieving
* @param bucketName * @param key unique key in the s3Bucket identifying the object
* namespace of the object you are retrieving
*
* @param key
* unique key in the s3Bucket identifying the object
* @return Future reference to a fully populated S3Object including data * @return Future reference to a fully populated S3Object including data
* stored in S3 or {@link S3Object#NOT_FOUND} if not present. * stored in S3 or {@link S3Object#NOT_FOUND} if not present.
* @see org.jclouds.aws.s3.commands.GetObject
*/ */
Future<S3Object> getObject(String bucketName, String key); Future<S3Object> getObject(String bucketName, String key);
@ -66,44 +58,38 @@ public interface S3Connection {
* Like {@link #getObject(String, String)} except you can use * Like {@link #getObject(String, String)} except you can use
* {@link GetObjectOptions} to control delivery. * {@link GetObjectOptions} to control delivery.
* *
* @see #getObject(String, String)
* @see GetObjectOptions
* @return S3Object containing data relevant to the * @return S3Object containing data relevant to the
* <code>options</options> specified or {@link S3Object#NOT_FOUND} if not present. * <code>options</options> specified or {@link S3Object#NOT_FOUND} if not present.
* * @throws org.jclouds.http.HttpResponseException
* @throws HttpResponseException * if the conditions requested set were not satisfied by the
* if the conditions requested set were not satisfied by the * object on the server.
* object on the server. * @see #getObject(String, String)
* @see GetObjectOptions
*/ */
Future<S3Object> getObject(String bucketName, String key, Future<S3Object> getObject(String bucketName, String key,
GetObjectOptions options); GetObjectOptions options);
/** /**
* Retrieves the {@link S3Object.Metadata metadata} of the object associated * Retrieves the {@link org.jclouds.aws.s3.domain.S3Object.Metadata metadata} of the object associated
* with the key. * with the key.
* *
* @see HeadObject * @param bucketName namespace of the metadata you are retrieving
* @param bucketName * @param key unique key in the s3Bucket identifying the object
* namespace of the metadata you are retrieving
*
* @param key
* unique key in the s3Bucket identifying the object
* @return metadata associated with the key or * @return metadata associated with the key or
* {@link S3Object.Metadata#NOT_FOUND} if not present; * {@link org.jclouds.aws.s3.domain.S3Object.Metadata#NOT_FOUND} if not present;
* @see org.jclouds.aws.s3.commands.HeadObject
*/ */
Future<S3Object.Metadata> headObject(String bucketName, String key); Future<S3Object.Metadata> headObject(String bucketName, String key);
/** /**
* Removes the object and metadata associated with the key. * Removes the object and metadata associated with the key.
* *
* @see DeleteObject * @param bucketName namespace of the object you are deleting
* @param bucketName * @param key unique key in the s3Bucket identifying the object
* namespace of the object you are deleting
* @param key
* unique key in the s3Bucket identifying the object
* @return true if deleted * @return true if deleted
* @throws HttpResponseException * @throws org.jclouds.http.HttpResponseException
* if the bucket is not available * if the bucket is not available
* @see org.jclouds.aws.s3.commands.DeleteObject
*/ */
Future<Boolean> deleteObject(String bucketName, String key); Future<Boolean> deleteObject(String bucketName, String key);
@ -113,39 +99,36 @@ public interface S3Connection {
* This method will store the object with the default <code>private</code> * This method will store the object with the default <code>private</code>
* acl. * acl.
* *
* @see CannedAccessPolicy#PRIVATE * @param bucketName namespace of the object you are storing
* @see PutObject * @param object contains the data and metadata to create or overwrite
* @param bucketName
* namespace of the object you are storing
* @param object
* contains the data and metadata to create or overwrite
* @return MD5 hash of the content uploaded * @return MD5 hash of the content uploaded
* @see org.jclouds.aws.s3.domain.acl.CannedAccessPolicy#PRIVATE
* @see org.jclouds.aws.s3.commands.PutObject
*/ */
Future<byte[]> putObject(String bucketName, S3Object object); Future<byte[]> putObject(String bucketName, S3Object object);
/** /**
* Like {@link #putObject(String, S3Object)} except you can use * Like {@link #putObject(String, S3Object)} except you can use
* {@link CopyObjectOptions} to specify an alternate * {@link CopyObjectOptions} to specify an alternate
* {@link CannedAccessPolicy acl}, override * {@link org.jclouds.aws.s3.domain.acl.CannedAccessPolicy acl}, override
* {@link S3Object.Metadata#getUserMetadata() userMetadata}, or specify * {@link org.jclouds.aws.s3.domain.S3Object.Metadata#getUserMetadata() userMetadata}, or specify
* conditions for copying the object. * conditions for copying the object.
* *
* @param options options for creating the object
* @throws org.jclouds.http.HttpResponseException
* if the conditions requested set are not satisfied by the
* object on the server.
* @see S3Connection#putObject(String, S3Object) * @see S3Connection#putObject(String, S3Object)
* @see PutObjectOptions * @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<byte[]> putObject(String bucketName, S3Object object, Future<byte[]> putObject(String bucketName, S3Object object,
PutObjectOptions options); PutObjectOptions options);
/** /**
* Create and name your own bucket in which to store your objects. * Create and name your own bucket in which to store your objects.
* *
* @see PutBucket
* @return true, if the bucket was created or already exists * @return true, if the bucket was created or already exists
* @see org.jclouds.aws.s3.commands.PutBucket
*/ */
Future<Boolean> putBucketIfNotExists(String name); Future<Boolean> putBucketIfNotExists(String name);
@ -153,19 +136,17 @@ public interface S3Connection {
* Like {@link #putBucketIfNotExists(String)} except that you can use * Like {@link #putBucketIfNotExists(String)} except that you can use
* {@link PutBucketOptions} to create the bucket in EU. Create and name your * {@link PutBucketOptions} to create the bucket in EU. Create and name your
* *
* @param options for creating your bucket
* @see PutBucketOptions * @see PutBucketOptions
* @param options
* for creating your bucket
*/ */
Future<Boolean> putBucketIfNotExists(String name, PutBucketOptions options); Future<Boolean> putBucketIfNotExists(String name, PutBucketOptions options);
/** /**
* Deletes the bucket, if it is empty. * Deletes the bucket, if it is empty.
* *
* @see DeleteBucket * @param s3Bucket what to delete
* @param s3Bucket
* what to delete
* @return false, if the bucket was not empty and therefore not deleted * @return false, if the bucket was not empty and therefore not deleted
* @see org.jclouds.aws.s3.commands.DeleteBucket
*/ */
Future<Boolean> deleteBucketIfEmpty(String s3Bucket); Future<Boolean> deleteBucketIfEmpty(String s3Bucket);
@ -173,65 +154,61 @@ public interface S3Connection {
* Copies one object to another bucket, retaining UserMetadata from the * Copies one object to another bucket, retaining UserMetadata from the
* source. The destination will have a private acl. * source. The destination will have a private acl.
* *
* @see CopyObject
* @return metadata populated with lastModified and md5 of the new object * @return metadata populated with lastModified and md5 of the new object
* @see org.jclouds.aws.s3.commands.CopyObject
*/ */
Future<S3Object.Metadata> copyObject(String sourceBucket, Future<S3Object.Metadata> copyObject(String sourceBucket,
String sourceObject, String destinationBucket, String sourceObject, String destinationBucket,
String destinationObject); String destinationObject);
/** /**
* Like {@link #putObject(String, S3Object)} except you can use * Like {@link #putObject(String, S3Object)} except you can use
* {@link PutObjectOptions} to specify an alternate * {@link PutObjectOptions} to specify an alternate
* {@link CannedAccessPolicy acl}. * {@link org.jclouds.aws.s3.domain.acl.CannedAccessPolicy acl}.
* *
* @param options options for creating the object
* @throws org.jclouds.http.HttpResponseException
* if the conditions requested set are not satisfied by the
* object on the server.
* @see S3Connection#putObject(String, S3Object) * @see S3Connection#putObject(String, S3Object)
* @see PutObjectOptions * @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, Future<S3Object.Metadata> copyObject(String sourceBucket,
String sourceObject, String destinationBucket, String sourceObject, String destinationBucket,
String destinationObject, CopyObjectOptions options); String destinationObject, CopyObjectOptions options);
/** /**
* @see HeadBucket * @see org.jclouds.aws.s3.commands.BucketExists
*/ */
Future<Boolean> bucketExists(String name); Future<Boolean> bucketExists(String name);
/** /**
* Retrieve a complete <code>S3Bucket</code> listing. * Retrieve a complete <code>S3Bucket</code> listing.
* *
* @see ListBucket * @param bucketName namespace of the objects you wish to list
* @param bucketName
* namespace of the objects you wish to list
*
* @return Future reference to a fully populated S3Bucket including metadata * @return Future reference to a fully populated S3Bucket including metadata
* of the S3Objects it contains or {@link S3Bucket#NOT_FOUND} if not * of the S3Objects it contains or {@link S3Bucket#NOT_FOUND} if not
* present. * present.
* @see org.jclouds.aws.s3.commands.ListBucket
*/ */
Future<S3Bucket> listBucket(String bucketName); Future<S3Bucket> listBucket(String bucketName);
/** /**
* Like {@link #listBucket(String)} except you can use * Like {@link #listBucket(String)} except you can use
* {@link ListObjectOptions} to control the amount of S3Objects to return. * {@link ListBucketOptions} to control the amount of S3Objects to return.
* *
* @see #listBucket(String) * @return S3Bucket containing a subset of {@link org.jclouds.aws.s3.domain.S3Object.Metadata}
* @see ListBucketOptions
* @return S3Bucket containing a subset of {@link S3Object.Metadata}
* depending on * depending on
* <code>options</options> specified or {@link S3Bucket#NOT_FOUND} if not present. * <code>options</options> specified or {@link S3Bucket#NOT_FOUND} if not present.
* * @see #listBucket(String)
* @see ListBucketOptions
*/ */
Future<S3Bucket> listBucket(String name, ListBucketOptions options); Future<S3Bucket> listBucket(String name, ListBucketOptions options);
/** /**
* @see ListOwnedBuckets
* @return list of all of the buckets owned by the authenticated sender of * @return list of all of the buckets owned by the authenticated sender of
* the request. * the request.
* @see org.jclouds.aws.s3.commands.ListOwnedBuckets
*/ */
Future<List<S3Bucket.Metadata>> listOwnedBuckets(); Future<List<S3Bucket.Metadata>> listOwnedBuckets();
} }

View File

@ -50,7 +50,6 @@ public interface S3Context {
* bucket. * bucket.
* *
* @param bucket * @param bucket
* @return
*/ */
S3InputStreamMap createInputStreamMap(String bucket); S3InputStreamMap createInputStreamMap(String bucket);
@ -58,7 +57,6 @@ public interface S3Context {
* Creates a <code>Map<String,S3Object></code> view of the specified bucket. * Creates a <code>Map<String,S3Object></code> view of the specified bucket.
* *
* @param bucket * @param bucket
* @return
*/ */
S3ObjectMap createS3ObjectMap(String bucket); S3ObjectMap createS3ObjectMap(String bucket);

View File

@ -23,28 +23,8 @@
*/ */
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import static com.google.common.base.Preconditions.checkNotNull;
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;
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES;
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_REQUEST_INVOKER_THREADS;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_ADDRESS;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_PORT;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_SECURE;
import java.util.List;
import java.util.Properties;
import org.jclouds.aws.s3.config.S3ContextModule;
import org.jclouds.http.config.HttpFutureCommandClientModule;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -54,6 +34,21 @@ import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.name.Names; import com.google.inject.name.Names;
import org.jclouds.aws.s3.config.LiveS3ConnectionModule;
import org.jclouds.aws.s3.config.S3ConnectionModule;
import org.jclouds.aws.s3.config.S3ContextModule;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_AWS_SECRETACCESSKEY;
import org.jclouds.aws.s3.internal.LiveS3Connection;
import static org.jclouds.command.pool.PoolConstants.*;
import static org.jclouds.http.HttpConstants.*;
import org.jclouds.http.config.HttpFutureCommandClientModule;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import java.util.List;
import java.util.Properties;
/** /**
* Creates {@link S3Context} or {@link Injector} instances based on the most * Creates {@link S3Context} or {@link Injector} instances based on the most
@ -61,115 +56,115 @@ import com.google.inject.name.Names;
* <p/> * <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or * Note that Threadsafe objects will be bound as singletons to the Injector or
* Context provided. * Context provided.
* * <p/>
* <p/> * <p/>
* If no <code>Module</code>s are specified, the default * If no <code>Module</code>s are specified, the default
* {@link JDKLoggingModule logging} and * {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpFutureCommandClientModule http transports} will be * {@link JavaUrlHttpFutureCommandClientModule http transports} will be
* installed. * installed.
* *
* @see S3Context
* @author Adrian Cole * @author Adrian Cole
* @see S3Context
*/ */
public class S3ContextFactory { public class S3ContextFactory {
public static final Properties DEFAULT_PROPERTIES; public static final Properties DEFAULT_PROPERTIES;
static { static {
DEFAULT_PROPERTIES = new Properties(); DEFAULT_PROPERTIES = new Properties();
DEFAULT_PROPERTIES.setProperty(PROPERTY_HTTP_ADDRESS, DEFAULT_PROPERTIES.setProperty(PROPERTY_HTTP_ADDRESS,
"s3.amazonaws.com"); "s3.amazonaws.com");
DEFAULT_PROPERTIES.setProperty(PROPERTY_HTTP_PORT, "443"); DEFAULT_PROPERTIES.setProperty(PROPERTY_HTTP_PORT, "443");
DEFAULT_PROPERTIES.setProperty(PROPERTY_HTTP_SECURE, "true"); DEFAULT_PROPERTIES.setProperty(PROPERTY_HTTP_SECURE, "true");
DEFAULT_PROPERTIES DEFAULT_PROPERTIES
.setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, "75"); .setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, "75");
DEFAULT_PROPERTIES.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, "2"); DEFAULT_PROPERTIES.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, "2");
DEFAULT_PROPERTIES.setProperty(PROPERTY_POOL_REQUEST_INVOKER_THREADS, DEFAULT_PROPERTIES.setProperty(PROPERTY_POOL_REQUEST_INVOKER_THREADS,
"1"); "1");
DEFAULT_PROPERTIES.setProperty(PROPERTY_POOL_IO_WORKER_THREADS, "2"); DEFAULT_PROPERTIES.setProperty(PROPERTY_POOL_IO_WORKER_THREADS, "2");
DEFAULT_PROPERTIES.setProperty(PROPERTY_POOL_MAX_CONNECTIONS, "12"); DEFAULT_PROPERTIES.setProperty(PROPERTY_POOL_MAX_CONNECTIONS, "12");
} }
public static Injector createInjector(String awsAccessKeyId, public static Injector createInjector(String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) { String awsSecretAccessKey, Module... modules) {
Properties properties = new Properties(DEFAULT_PROPERTIES); Properties properties = new Properties(DEFAULT_PROPERTIES);
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, awsAccessKeyId); properties.setProperty(PROPERTY_AWS_ACCESSKEYID, awsAccessKeyId);
properties properties
.setProperty(PROPERTY_AWS_SECRETACCESSKEY, awsSecretAccessKey); .setProperty(PROPERTY_AWS_SECRETACCESSKEY, awsSecretAccessKey);
return createInjector(properties, modules); return createInjector(properties, modules);
} }
public static S3Context createS3Context(String awsAccessKeyId, public static S3Context createS3Context(String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) { String awsSecretAccessKey, Module... modules) {
return createInjector(awsAccessKeyId, awsSecretAccessKey, modules) return createInjector(awsAccessKeyId, awsSecretAccessKey, modules)
.getInstance(S3Context.class); .getInstance(S3Context.class);
} }
public static Injector createInjector(String awsAccessKeyId, public static Injector createInjector(String awsAccessKeyId,
String awsSecretAccessKey, boolean isSecure, Module... modules) { String awsSecretAccessKey, boolean isSecure, Module... modules) {
Properties properties = new Properties(DEFAULT_PROPERTIES); Properties properties = new Properties(DEFAULT_PROPERTIES);
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, awsAccessKeyId); properties.setProperty(PROPERTY_AWS_ACCESSKEYID, awsAccessKeyId);
properties properties
.setProperty(PROPERTY_AWS_SECRETACCESSKEY, awsSecretAccessKey); .setProperty(PROPERTY_AWS_SECRETACCESSKEY, awsSecretAccessKey);
properties properties
.setProperty(PROPERTY_HTTP_SECURE, Boolean.toString(isSecure)); .setProperty(PROPERTY_HTTP_SECURE, Boolean.toString(isSecure));
if (!isSecure) if (!isSecure)
properties.setProperty(PROPERTY_HTTP_PORT, "80"); properties.setProperty(PROPERTY_HTTP_PORT, "80");
return createInjector(properties, modules); return createInjector(properties, modules);
} }
public static S3Context createS3Context(String awsAccessKeyId, public static S3Context createS3Context(String awsAccessKeyId,
String awsSecretAccessKey, boolean isSecure, Module... modules) { String awsSecretAccessKey, boolean isSecure, Module... modules) {
return createInjector(awsAccessKeyId, awsSecretAccessKey, isSecure, return createInjector(awsAccessKeyId, awsSecretAccessKey, isSecure,
modules).getInstance(S3Context.class); modules).getInstance(S3Context.class);
} }
public static Injector createInjector(String awsAccessKeyId, public static Injector createInjector(String awsAccessKeyId,
String awsSecretAccessKey, boolean isSecure, String server, String awsSecretAccessKey, boolean isSecure, String server,
Module... modules) { Module... modules) {
Properties properties = new Properties(DEFAULT_PROPERTIES); Properties properties = new Properties(DEFAULT_PROPERTIES);
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, awsAccessKeyId); properties.setProperty(PROPERTY_AWS_ACCESSKEYID, awsAccessKeyId);
properties properties
.setProperty(PROPERTY_AWS_SECRETACCESSKEY, awsSecretAccessKey); .setProperty(PROPERTY_AWS_SECRETACCESSKEY, awsSecretAccessKey);
properties properties
.setProperty(PROPERTY_HTTP_SECURE, Boolean.toString(isSecure)); .setProperty(PROPERTY_HTTP_SECURE, Boolean.toString(isSecure));
properties.setProperty(PROPERTY_HTTP_ADDRESS, server); properties.setProperty(PROPERTY_HTTP_ADDRESS, server);
if (!isSecure) if (!isSecure)
properties.setProperty(PROPERTY_HTTP_PORT, "80"); properties.setProperty(PROPERTY_HTTP_PORT, "80");
return createInjector(properties, modules); return createInjector(properties, modules);
} }
public static S3Context createS3Context(String awsAccessKeyId, public static S3Context createS3Context(String awsAccessKeyId,
String awsSecretAccessKey, boolean isSecure, String server, String awsSecretAccessKey, boolean isSecure, String server,
Module... modules) { Module... modules) {
return createInjector(awsAccessKeyId, awsSecretAccessKey, isSecure, return createInjector(awsAccessKeyId, awsSecretAccessKey, isSecure,
server, modules).getInstance(S3Context.class); server, modules).getInstance(S3Context.class);
} }
public static S3Context createS3Context(String awsAccessKeyId, public static S3Context createS3Context(String awsAccessKeyId,
String awsSecretAccessKey, boolean isSecure, String server, String awsSecretAccessKey, boolean isSecure, String server,
int port, Module... modules) { int port, Module... modules) {
return createInjector(awsAccessKeyId, awsSecretAccessKey, isSecure, return createInjector(awsAccessKeyId, awsSecretAccessKey, isSecure,
server, port, modules).getInstance(S3Context.class); server, port, modules).getInstance(S3Context.class);
} }
public static Injector createInjector(String awsAccessKeyId, public static Injector createInjector(String awsAccessKeyId,
String awsSecretAccessKey, boolean isSecure, String server, String awsSecretAccessKey, boolean isSecure, String server,
int port, Module... modules) { int port, Module... modules) {
Properties properties = new Properties(DEFAULT_PROPERTIES); Properties properties = new Properties(DEFAULT_PROPERTIES);
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, awsAccessKeyId); properties.setProperty(PROPERTY_AWS_ACCESSKEYID, awsAccessKeyId);
properties properties
.setProperty(PROPERTY_AWS_SECRETACCESSKEY, awsSecretAccessKey); .setProperty(PROPERTY_AWS_SECRETACCESSKEY, awsSecretAccessKey);
properties properties
.setProperty(PROPERTY_HTTP_SECURE, Boolean.toString(isSecure)); .setProperty(PROPERTY_HTTP_SECURE, Boolean.toString(isSecure));
properties.setProperty(PROPERTY_HTTP_ADDRESS, server); properties.setProperty(PROPERTY_HTTP_ADDRESS, server);
properties.setProperty(PROPERTY_HTTP_PORT, port + ""); properties.setProperty(PROPERTY_HTTP_PORT, port + "");
return createInjector(properties, modules); return createInjector(properties, modules);
} }
public static S3Context createS3Context(Properties properties, public static S3Context createS3Context(Properties properties,
Module... modules) { Module... modules) {
return createInjector(properties, modules).getInstance(S3Context.class); return createInjector(properties, modules).getInstance(S3Context.class);
} }
/** /**
@ -177,46 +172,65 @@ public class S3ContextFactory {
* are specified, install the default {@link JDKLoggingModule} * are specified, install the default {@link JDKLoggingModule}
* {@link JavaUrlHttpFutureCommandClientModule} * {@link JavaUrlHttpFutureCommandClientModule}
* *
* @param properties * @param properties - contains constants used by jclouds
* - contains constants used by jclouds * {@link #DEFAULT_PROPERTIES}
* {@link #DEFAULT_PROPERTIES} * @param configModules - alternative configuration modules
* @param configModules
* - alternative configuration modules
*/ */
public static Injector createInjector(final Properties properties, public static Injector createInjector(final Properties properties,
Module... configModules) { Module... configModules) {
final List<Module> modules = Lists.newArrayList(configModules); final List<Module> modules = Lists.newArrayList(configModules);
addLoggingModuleIfNotPresent(modules); addLoggingModuleIfNotPresent(modules);
addHttpModuleIfNotPresent(modules); addHttpModuleIfNeededAndNotPresent(modules);
return Guice.createInjector(new AbstractModule() { addS3ConnectionModuleIfNotPresent(modules);
@Override
protected void configure() { return Guice.createInjector(new AbstractModule() {
Names.bindProperties(binder(), checkNotNull(properties, @Override
"properties")); protected void configure() {
for (Module module : modules) Names.bindProperties(binder(), checkNotNull(properties,
install(module); "properties"));
} for (Module module : modules)
}, new S3ContextModule()); install(module);
}
}, new S3ContextModule());
} }
@VisibleForTesting @VisibleForTesting
static void addHttpModuleIfNotPresent(final List<Module> modules) { static void addHttpModuleIfNeededAndNotPresent(final List<Module> modules) {
if (!Iterables.any(modules, new Predicate<Module>() { if (Iterables.any(modules, new Predicate<Module>() {
public boolean apply(Module input) { public boolean apply(Module input) {
return input.getClass().isAnnotationPresent( return input instanceof LiveS3ConnectionModule;
HttpFutureCommandClientModule.class); }
}
})) }) && (!Iterables.any(modules, new Predicate<Module>() {
modules.add(new JavaUrlHttpFutureCommandClientModule()); public boolean apply(Module input) {
return input.getClass().isAnnotationPresent(
HttpFutureCommandClientModule.class);
}
})))
modules.add(new JavaUrlHttpFutureCommandClientModule());
}
@VisibleForTesting
static void addS3ConnectionModuleIfNotPresent(final List<Module> modules) {
if (!Iterables.any(modules, new Predicate<Module>() {
public boolean apply(Module input) {
return input.getClass().isAnnotationPresent(
S3ConnectionModule
.class);
}
})){
modules.add(new LiveS3ConnectionModule());
}
} }
@VisibleForTesting @VisibleForTesting
static void addLoggingModuleIfNotPresent(final List<Module> modules) { static void addLoggingModuleIfNotPresent(final List<Module> modules) {
if (!Iterables.any(modules, Predicates.instanceOf(LoggingModule.class))) if (!Iterables.any(modules, Predicates.instanceOf(LoggingModule.class)))
modules.add(new JDKLoggingModule()); modules.add(new JDKLoggingModule());
} }
} }

View File

@ -28,17 +28,16 @@ import java.io.InputStream;
import java.util.Map; import java.util.Map;
/** /**
* Map view of an {@link S3Bucket}. Provides additional methods for inserting * Map view of an {@link org.jclouds.aws.s3.domain.S3Bucket}. Provides additional methods for inserting
* common object types. * common object types.
* * <p/>
* <h2>Note</h2> All <code>put</code> operations will invoke * <h2>Note</h2> All <code>put</code> operations will invoke
* {@link S3Object#generateMd5}. By extension, {@link #put(String, InputStream)} * {@link org.jclouds.aws.s3.domain.S3Object#generateMd5}. By extension, {@link #put(Object, Object)}
* will result in the InputStream being converted to a byte array. For this * 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 * reason, do not use {@link #put(Object, Object)} to store files. Use
* {@link #putFile(String, File)} or {@link S3ObjectMap} instead. * {@link #putFile(String, File)} or {@link S3ObjectMap} instead.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
public interface S3InputStreamMap extends S3Map<String, InputStream> { public interface S3InputStreamMap extends S3Map<String, InputStream> {
InputStream putString(String key, String value); InputStream putString(String key, String value);

View File

@ -33,7 +33,7 @@ import org.jclouds.http.HttpResponseException;
* *
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingRESTError.html" /> * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingRESTError.html" />
* @see S3Error * @see S3Error
* @see ParseS3ErrorFromXmlContent * @see org.jclouds.aws.s3.handlers.ParseS3ErrorFromXmlContent
* @author Adrian Cole * @author Adrian Cole
* *
*/ */

View File

@ -23,12 +23,10 @@
*/ */
package org.jclouds.aws.s3.commands.options; package org.jclouds.aws.s3.commands.options;
import static com.google.common.base.Preconditions.checkArgument; import com.google.common.base.Preconditions;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.*;
import static com.google.common.base.Preconditions.checkState; import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import java.io.UnsupportedEncodingException;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.DateService; import org.jclouds.aws.s3.util.DateService;
@ -36,9 +34,7 @@ import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.options.BaseHttpRequestOptions; import org.jclouds.http.options.BaseHttpRequestOptions;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import com.google.common.base.Preconditions; import java.io.UnsupportedEncodingException;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
/** /**
* Contains options supported in the REST API for the COPY object operation. * Contains options supported in the REST API for the COPY object operation.
@ -49,26 +45,24 @@ import com.google.common.collect.Multimap;
* <p/> * <p/>
* <code> * <code>
* import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.* * import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.*
* * <p/>
* S3Connection connection = // get connection * S3Connection connection = // get connection
* * <p/>
* Multimap<String,String> metadata = HashMultimap.create(); * Multimap<String,String> metadata = HashMultimap.create();
* metadata.put("x-amz-meta-adrian", "foo"); * metadata.put("x-amz-meta-adrian", "foo");
* * <p/>
* // this will copy the object, provided it wasn't modified since yesterday. * // 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. * // 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", * "destinationBucket", "destinationName",
* overrideMetadataWith(meta). * overrideMetadataWith(meta).
* ifSourceModifiedSince(new DateTime().minusDays(1)) * ifSourceModifiedSince(new DateTime().minusDays(1))
* ); * );
* <code> * <code>
* *
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectCOPY.html?" * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectCOPY.html?"
* /> * />
* @author Adrian Cole
*
*
*/ */
public class CopyObjectOptions extends BaseHttpRequestOptions { public class CopyObjectOptions extends BaseHttpRequestOptions {
private final static DateService dateService = new DateService(); private final static DateService dateService = new DateService();
@ -85,56 +79,56 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
* @see CannedAccessPolicy * @see CannedAccessPolicy
*/ */
public CopyObjectOptions overrideAcl(CannedAccessPolicy acl) { public CopyObjectOptions overrideAcl(CannedAccessPolicy acl) {
this.acl = checkNotNull(acl, "acl"); this.acl = checkNotNull(acl, "acl");
if (!acl.equals(CannedAccessPolicy.PRIVATE)) if (!acl.equals(CannedAccessPolicy.PRIVATE))
this.replaceHeader(S3Headers.CANNED_ACL, acl.toString()); this.replaceHeader(S3Headers.CANNED_ACL, acl.toString());
return this; return this;
} }
/** /**
* @see CopyObjectOptions#overrideAcl(CannedAccessPolicy) * @see CopyObjectOptions#overrideAcl(CannedAccessPolicy)
*/ */
public CannedAccessPolicy getAcl() { public CannedAccessPolicy getAcl() {
return acl; return acl;
} }
/** /**
* For use in the header x-amz-copy-source-if-unmodified-since * For use in the header x-amz-copy-source-if-unmodified-since
* <p /> * <p/>
* Copies the object if it hasn't been modified since the specified time; * Copies the object if it hasn't been modified since the specified time;
* otherwise returns a 412 (precondition failed). * otherwise returns a 412 (precondition failed).
* <p /> * <p/>
* This header can be used with x-amz-copy-source-if-match, but cannot be * This header can be used with x-amz-copy-source-if-match, but cannot be
* used with other conditional copy headers. * used with other conditional copy headers.
* *
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
* @return valid HTTP date * @return valid HTTP date
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
* @see CopyObjectOptions#ifSourceModifiedSince(DateTime) * @see CopyObjectOptions#ifSourceModifiedSince(DateTime)
*/ */
public String getIfModifiedSince() { public String getIfModifiedSince() {
return getFirstHeaderOrNull("x-amz-copy-source-if-modified-since"); return getFirstHeaderOrNull("x-amz-copy-source-if-modified-since");
} }
/** /**
* For use in the header x-amz-copy-source-if-modified-since * For use in the header x-amz-copy-source-if-modified-since
* <p /> * <p/>
* Copies the object if it has been modified since the specified time; * Copies the object if it has been modified since the specified time;
* otherwise returns a 412 (failed condition). * otherwise returns a 412 (failed condition).
* <p/> * <p/>
* This header can be used with x-amz-copy-source-if-none-match, but cannot * This header can be used with x-amz-copy-source-if-none-match, but cannot
* be used with other conditional copy headers. * be used with other conditional copy headers.
* *
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
* @return valid HTTP date * @return valid HTTP date
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
* @see CopyObjectOptions#ifSourceUnmodifiedSince(DateTime) * @see CopyObjectOptions#ifSourceUnmodifiedSince(DateTime)
*/ */
public String getIfUnmodifiedSince() { public String getIfUnmodifiedSince() {
return getFirstHeaderOrNull("x-amz-copy-source-if-unmodified-since"); return getFirstHeaderOrNull("x-amz-copy-source-if-unmodified-since");
} }
/** /**
* For use in the request header: x-amz-copy-source-if-match * For use in the request header: x-amz-copy-source-if-match
* <p /> * <p/>
* Copies the object if its entity tag (ETag) matches the specified tag; * Copies the object if its entity tag (ETag) matches the specified tag;
* otherwise return a 412 (precondition failed). * otherwise return a 412 (precondition failed).
* <p/> * <p/>
@ -144,12 +138,12 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
* @see CopyObjectOptions#ifSourceMd5Matches(byte[]) * @see CopyObjectOptions#ifSourceMd5Matches(byte[])
*/ */
public String getIfMatch() { public String getIfMatch() {
return getFirstHeaderOrNull("x-amz-copy-source-if-match"); return getFirstHeaderOrNull("x-amz-copy-source-if-match");
} }
/** /**
* For use in the request header: x-amz-copy-source-if-none-match * For use in the request header: x-amz-copy-source-if-none-match
* <p /> * <p/>
* Copies the object if its entity tag (ETag) is different than the * Copies the object if its entity tag (ETag) is different than the
* specified Etag; otherwise returns a 412 (failed condition). * specified Etag; otherwise returns a 412 (failed condition).
* <p/> * <p/>
@ -159,7 +153,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
* @see CopyObjectOptions#ifSourceMd5DoesntMatch(byte[]) * @see CopyObjectOptions#ifSourceMd5DoesntMatch(byte[])
*/ */
public String getIfNoneMatch() { public String getIfNoneMatch() {
return getFirstHeaderOrNull("x-amz-copy-source-if-none-match"); return getFirstHeaderOrNull("x-amz-copy-source-if-none-match");
} }
/** /**
@ -170,168 +164,164 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
* @see #overrideMetadataWith(Multimap) * @see #overrideMetadataWith(Multimap)
*/ */
public Multimap<String, String> getMetadata() { public Multimap<String, String> getMetadata() {
return metadata; return metadata;
} }
/** /**
* Only return the object if it has changed since this time. * Only return the object if it has changed since this time.
* <p /> * <p/>
* Not compatible with {@link #ifSourceMd5Matches(byte[])} or * Not compatible with {@link #ifSourceMd5Matches(byte[])} or
* {@link #ifSourceUnmodifiedSince(DateTime)} * {@link #ifSourceUnmodifiedSince(DateTime)}
*/ */
public CopyObjectOptions ifSourceModifiedSince(DateTime ifModifiedSince) { public CopyObjectOptions ifSourceModifiedSince(DateTime ifModifiedSince) {
checkState(getIfMatch() == null, checkState(getIfMatch() == null,
"ifMd5Matches() is not compatible with ifModifiedSince()"); "ifMd5Matches() is not compatible with ifModifiedSince()");
checkState(getIfUnmodifiedSince() == null, checkState(getIfUnmodifiedSince() == null,
"ifUnmodifiedSince() is not compatible with ifModifiedSince()"); "ifUnmodifiedSince() is not compatible with ifModifiedSince()");
replaceHeader("x-amz-copy-source-if-modified-since", replaceHeader("x-amz-copy-source-if-modified-since",
dateService.toHeaderString(checkNotNull(ifModifiedSince, dateService.toHeaderString(checkNotNull(ifModifiedSince,
"ifModifiedSince"))); "ifModifiedSince")));
return this; return this;
} }
/** /**
* Only return the object if it hasn't changed since this time. * Only return the object if it hasn't changed since this time.
* <p /> * <p/>
* Not compatible with {@link #ifSourceMd5DoesntMatch(byte[])} or * Not compatible with {@link #ifSourceMd5DoesntMatch(byte[])} or
* {@link #ifSourceModifiedSince(DateTime)} * {@link #ifSourceModifiedSince(DateTime)}
*/ */
public CopyObjectOptions ifSourceUnmodifiedSince(DateTime ifUnmodifiedSince) { public CopyObjectOptions ifSourceUnmodifiedSince(DateTime ifUnmodifiedSince) {
checkState(getIfNoneMatch() == null, checkState(getIfNoneMatch() == null,
"ifMd5DoesntMatch() is not compatible with ifUnmodifiedSince()"); "ifMd5DoesntMatch() is not compatible with ifUnmodifiedSince()");
checkState(getIfModifiedSince() == null, checkState(getIfModifiedSince() == null,
"ifModifiedSince() is not compatible with ifUnmodifiedSince()"); "ifModifiedSince() is not compatible with ifUnmodifiedSince()");
replaceHeader("x-amz-copy-source-if-unmodified-since", dateService replaceHeader("x-amz-copy-source-if-unmodified-since", dateService
.toHeaderString(checkNotNull(ifUnmodifiedSince, .toHeaderString(checkNotNull(ifUnmodifiedSince,
"ifUnmodifiedSince"))); "ifUnmodifiedSince")));
return this; return this;
} }
/** /**
* The object's md5 hash should match the parameter <code>md5</code>. * The object's md5 hash should match the parameter <code>md5</code>.
* * <p/>
* <p /> * <p/>
* Not compatible with {@link #ifSourceMd5DoesntMatch(byte[])} or * Not compatible with {@link #ifSourceMd5DoesntMatch(byte[])} or
* {@link #ifSourceModifiedSince(DateTime)} * {@link #ifSourceModifiedSince(DateTime)}
* *
* @param md5 * @param md5 hash representing the entity
* hash representing the entity * @throws UnsupportedEncodingException if there was a problem converting this into an S3 eTag string
* @throws UnsupportedEncodingException
* if there was a problem converting this into an S3 eTag string
*/ */
public CopyObjectOptions ifSourceMd5Matches(byte[] md5) public CopyObjectOptions ifSourceMd5Matches(byte[] md5)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
checkState(getIfNoneMatch() == null, checkState(getIfNoneMatch() == null,
"ifMd5DoesntMatch() is not compatible with ifMd5Matches()"); "ifMd5DoesntMatch() is not compatible with ifMd5Matches()");
checkState(getIfModifiedSince() == null, checkState(getIfModifiedSince() == null,
"ifModifiedSince() is not compatible with ifMd5Matches()"); "ifModifiedSince() is not compatible with ifMd5Matches()");
replaceHeader("x-amz-copy-source-if-match", String.format("\"%1$s\"", replaceHeader("x-amz-copy-source-if-match", String.format("\"%1$s\"",
S3Utils.toHexString(checkNotNull(md5, "md5")))); S3Utils.toHexString(checkNotNull(md5, "md5"))));
return this; return this;
} }
/** /**
* The object should not have a md5 hash corresponding with the parameter * The object should not have a md5 hash corresponding with the parameter
* <code>md5</code>. * <code>md5</code>.
* <p /> * <p/>
* Not compatible with {@link #ifSourceMd5Matches(byte[])} or * Not compatible with {@link #ifSourceMd5Matches(byte[])} or
* {@link #ifSourceUnmodifiedSince(DateTime)} * {@link #ifSourceUnmodifiedSince(DateTime)}
* *
* @param md5 * @param md5 hash representing the entity
* hash representing the entity * @throws UnsupportedEncodingException if there was a problem converting this into an S3 eTag string
* @throws UnsupportedEncodingException
* if there was a problem converting this into an S3 eTag string
*/ */
public CopyObjectOptions ifSourceMd5DoesntMatch(byte[] md5) public CopyObjectOptions ifSourceMd5DoesntMatch(byte[] md5)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
checkState(getIfMatch() == null, checkState(getIfMatch() == null,
"ifMd5Matches() is not compatible with ifMd5DoesntMatch()"); "ifMd5Matches() is not compatible with ifMd5DoesntMatch()");
Preconditions Preconditions
.checkState(getIfUnmodifiedSince() == null, .checkState(getIfUnmodifiedSince() == null,
"ifUnmodifiedSince() is not compatible with ifMd5DoesntMatch()"); "ifUnmodifiedSince() is not compatible with ifMd5DoesntMatch()");
replaceHeader("x-amz-copy-source-if-none-match", String.format( replaceHeader("x-amz-copy-source-if-none-match", String.format(
"\"%1$s\"", S3Utils.toHexString(checkNotNull(md5, "\"%1$s\"", S3Utils.toHexString(checkNotNull(md5,
"ifMd5DoesntMatch")))); "ifMd5DoesntMatch"))));
return this; return this;
} }
@Override @Override
public Multimap<String, String> buildRequestHeaders() { public Multimap<String, String> buildRequestHeaders() {
Multimap<String, String> returnVal = HashMultimap.create(); Multimap<String, String> returnVal = HashMultimap.create();
returnVal.putAll(headers); returnVal.putAll(headers);
if (metadata != null) { if (metadata != null) {
returnVal.putAll(metadata); returnVal.putAll(metadata);
returnVal.put("x-amz-metadata-directive", "REPLACE"); returnVal.put("x-amz-metadata-directive", "REPLACE");
} }
return returnVal; return returnVal;
} }
/** /**
* Use the provided metadata instead of what is on the source object. * Use the provided metadata instead of what is on the source object.
*/ */
public CopyObjectOptions overrideMetadataWith( public CopyObjectOptions overrideMetadataWith(
Multimap<String, String> metadata) { Multimap<String, String> metadata) {
checkNotNull(metadata, "metadata"); checkNotNull(metadata, "metadata");
for (String header : metadata.keySet()) { for (String header : metadata.keySet()) {
checkArgument(header.startsWith("x-amz-meta-"), checkArgument(header.startsWith("x-amz-meta-"),
"Metadata keys must start with x-amz-meta-"); "Metadata keys must start with x-amz-meta-");
} }
this.metadata = metadata; this.metadata = metadata;
return this; return this;
} }
public static class Builder { public static class Builder {
/** /**
* @see CopyObjectOptions#overrideAcl(CannedAccessPolicy) * @see CopyObjectOptions#overrideAcl(CannedAccessPolicy)
*/ */
public static CopyObjectOptions overrideAcl(CannedAccessPolicy acl) { public static CopyObjectOptions overrideAcl(CannedAccessPolicy acl) {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
return options.overrideAcl(acl); return options.overrideAcl(acl);
} }
/** /**
* @see CopyObjectOptions#getIfModifiedSince() * @see CopyObjectOptions#getIfModifiedSince()
*/ */
public static CopyObjectOptions ifSourceModifiedSince( public static CopyObjectOptions ifSourceModifiedSince(
DateTime ifModifiedSince) { DateTime ifModifiedSince) {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceModifiedSince(ifModifiedSince); return options.ifSourceModifiedSince(ifModifiedSince);
} }
/** /**
* @see CopyObjectOptions#ifSourceUnmodifiedSince(DateTime) * @see CopyObjectOptions#ifSourceUnmodifiedSince(DateTime)
*/ */
public static CopyObjectOptions ifSourceUnmodifiedSince( public static CopyObjectOptions ifSourceUnmodifiedSince(
DateTime ifUnmodifiedSince) { DateTime ifUnmodifiedSince) {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceUnmodifiedSince(ifUnmodifiedSince); return options.ifSourceUnmodifiedSince(ifUnmodifiedSince);
} }
/** /**
* @see CopyObjectOptions#ifSourceMd5Matches(byte[]) * @see CopyObjectOptions#ifSourceMd5Matches(byte[])
*/ */
public static CopyObjectOptions ifSourceMd5Matches(byte[] md5) public static CopyObjectOptions ifSourceMd5Matches(byte[] md5)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceMd5Matches(md5); return options.ifSourceMd5Matches(md5);
} }
/** /**
* @see CopyObjectOptions#ifSourceMd5DoesntMatch(byte[]) * @see CopyObjectOptions#ifSourceMd5DoesntMatch(byte[])
*/ */
public static CopyObjectOptions ifSourceMd5DoesntMatch(byte[] md5) public static CopyObjectOptions ifSourceMd5DoesntMatch(byte[] md5)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceMd5DoesntMatch(md5); return options.ifSourceMd5DoesntMatch(md5);
} }
/** /**
* @see #overrideMetadataWith(Multimap) * @see #overrideMetadataWith(Multimap)
*/ */
public static CopyObjectOptions overrideMetadataWith( public static CopyObjectOptions overrideMetadataWith(
Multimap<String, String> metadata) { Multimap<String, String> metadata) {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
return options.overrideMetadataWith(metadata); return options.overrideMetadataWith(metadata);
} }
} }
} }

View File

@ -25,12 +25,11 @@ package org.jclouds.aws.s3.commands.options;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import org.jclouds.http.options.BaseHttpRequestOptions;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import org.jclouds.http.options.BaseHttpRequestOptions;
/** /**
* Contains options supported in the REST API for the GET bucket operation. <h2> * Contains options supported in the REST API for the GET bucket operation. <h2>
* Usage</h2> The recommended way to instantiate a GetBucketOptions object is to * Usage</h2> The recommended way to instantiate a GetBucketOptions object is to
@ -39,17 +38,14 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
* <p/> * <p/>
* <code> * <code>
* import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.* * import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.*
* * <p/>
* S3Connection connection = // get connection * S3Connection connection = // get connection
* Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000)); * Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
* <code> * <code>
* *
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html?" * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html?"
* /> * />
*
* @author Adrian Cole
*
*
*/ */
public class ListBucketOptions extends BaseHttpRequestOptions { public class ListBucketOptions extends BaseHttpRequestOptions {
public static final ListBucketOptions NONE = new ListBucketOptions(); public static final ListBucketOptions NONE = new ListBucketOptions();
@ -62,17 +58,17 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
* @throws UnsupportedEncodingException * @throws UnsupportedEncodingException
*/ */
public ListBucketOptions withPrefix(String prefix) public ListBucketOptions withPrefix(String prefix)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
options.put("prefix", URLEncoder.encode(checkNotNull(prefix, "prefix"), options.put("prefix", URLEncoder.encode(checkNotNull(prefix, "prefix"),
"UTF-8")); "UTF-8"));
return this; return this;
} }
/** /**
* @see ListBucketOptions#withPrefix(String) * @see ListBucketOptions#withPrefix(String)
*/ */
public String getPrefix() { public String getPrefix() {
return options.get("prefix"); return options.get("prefix");
} }
/** /**
@ -84,17 +80,17 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
* @throws UnsupportedEncodingException * @throws UnsupportedEncodingException
*/ */
public ListBucketOptions afterMarker(String marker) public ListBucketOptions afterMarker(String marker)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
options.put("marker", URLEncoder.encode(checkNotNull(marker, "marker"), options.put("marker", URLEncoder.encode(checkNotNull(marker, "marker"),
"UTF-8")); "UTF-8"));
return this; return this;
} }
/** /**
* @see ListBucketOptions#afterMarker(String) * @see ListBucketOptions#afterMarker(String)
*/ */
public String getMarker() { public String getMarker() {
return options.get("marker"); return options.get("marker");
} }
/** /**
@ -102,16 +98,16 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
* server might return fewer than this many keys, but will not return more. * server might return fewer than this many keys, but will not return more.
*/ */
public ListBucketOptions maxResults(long maxKeys) { public ListBucketOptions maxResults(long maxKeys) {
checkState(maxKeys >= 0, "maxKeys must be >= 0"); checkState(maxKeys >= 0, "maxKeys must be >= 0");
options.put("max-keys", Long.toString(maxKeys)); options.put("max-keys", Long.toString(maxKeys));
return this; return this;
} }
/** /**
* @see ListBucketOptions#maxResults(long) * @see ListBucketOptions#maxResults(long)
*/ */
public String getMaxKeys() { public String getMaxKeys() {
return options.get("max-keys"); return options.get("max-keys");
} }
/** /**
@ -122,59 +118,59 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
* *
* @throws UnsupportedEncodingException * @throws UnsupportedEncodingException
*/ */
public ListBucketOptions setDelimiter(String delimiter) public ListBucketOptions delimiter(String delimiter)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
options.put("delimiter", URLEncoder.encode(checkNotNull(delimiter, options.put("delimiter", URLEncoder.encode(checkNotNull(delimiter,
"delimiter"), "UTF-8")); "delimiter"), "UTF-8"));
return this; return this;
} }
/** /**
* @see ListBucketOptions#setDelimiter(String) * @see ListBucketOptions#delimiter(String)
*/ */
public String getDelimiter() { public String getDelimiter() {
return options.get("delimiter"); return options.get("delimiter");
} }
public static class Builder { public static class Builder {
/** /**
* @throws UnsupportedEncodingException * @throws UnsupportedEncodingException
* @see ListBucketOptions#withPrefix(String) * @see ListBucketOptions#withPrefix(String)
*/ */
public static ListBucketOptions withPrefix(String prefix) public static ListBucketOptions withPrefix(String prefix)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions(); ListBucketOptions options = new ListBucketOptions();
return options.withPrefix(prefix); return options.withPrefix(prefix);
} }
/** /**
* @throws UnsupportedEncodingException * @throws UnsupportedEncodingException
* @see ListBucketOptions#afterMarker(String) * @see ListBucketOptions#afterMarker(String)
*/ */
public static ListBucketOptions afterMarker(String marker) public static ListBucketOptions afterMarker(String marker)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions(); ListBucketOptions options = new ListBucketOptions();
return options.afterMarker(marker); return options.afterMarker(marker);
} }
/** /**
* @see ListBucketOptions#maxResults(long) * @see ListBucketOptions#maxResults(long)
*/ */
public static ListBucketOptions maxResults(long maxKeys) { public static ListBucketOptions maxResults(long maxKeys) {
ListBucketOptions options = new ListBucketOptions(); ListBucketOptions options = new ListBucketOptions();
return options.maxResults(maxKeys); return options.maxResults(maxKeys);
} }
/** /**
* @throws UnsupportedEncodingException * @throws UnsupportedEncodingException
* @see ListBucketOptions#delimiter(String) * @see ListBucketOptions#delimiter(String)
*/ */
public static ListBucketOptions delimiter(String delimiter) public static ListBucketOptions delimiter(String delimiter)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions(); ListBucketOptions options = new ListBucketOptions();
return options.setDelimiter(delimiter); return options.delimiter(delimiter);
} }
} }
} }

View File

@ -23,13 +23,12 @@
*/ */
package org.jclouds.aws.s3.commands.options; package org.jclouds.aws.s3.commands.options;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.http.options.BaseHttpRequestOptions; import org.jclouds.http.options.BaseHttpRequestOptions;
import static com.google.common.base.Preconditions.*;
/** /**
* Contains options supported in the REST API for the PUT bucket operation. <h2> * Contains options supported in the REST API for the PUT bucket operation. <h2>
* Usage</h2> The recommended way to instantiate a PutBucketOptions object is to * Usage</h2> The recommended way to instantiate a PutBucketOptions object is to
@ -40,16 +39,14 @@ import static com.google.common.base.Preconditions.*;
* import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.* * 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; * import org.jclouds.aws.s3.S3Connection;
* * <p/>
* S3Connection connection = // get connection * S3Connection connection = // get connection
* Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU)); * Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
* <code> * <code>
* *
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT.html?" * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT.html?"
* /> * />
*
* @author Adrian Cole
*
*/ */
public class PutBucketOptions extends BaseHttpRequestOptions { public class PutBucketOptions extends BaseHttpRequestOptions {
public static final PutBucketOptions NONE = new PutBucketOptions(); public static final PutBucketOptions NONE = new PutBucketOptions();
@ -62,12 +59,12 @@ public class PutBucketOptions extends BaseHttpRequestOptions {
* You can currently specify a Europe (EU) location constraint. * You can currently specify a Europe (EU) location constraint.
*/ */
public PutBucketOptions createIn(LocationConstraint constraint) { public PutBucketOptions createIn(LocationConstraint constraint) {
this.constraint = checkNotNull(constraint, "constraint"); this.constraint = checkNotNull(constraint, "constraint");
this.payload = String this.payload = String
.format( .format(
"<CreateBucketConfiguration><LocationConstraint>%1$s</LocationConstraint></CreateBucketConfiguration>", "<CreateBucketConfiguration><LocationConstraint>%1$s</LocationConstraint></CreateBucketConfiguration>",
constraint.toString()); constraint.toString());
return this; return this;
} }
/** /**
@ -76,41 +73,41 @@ public class PutBucketOptions extends BaseHttpRequestOptions {
* @see CannedAccessPolicy * @see CannedAccessPolicy
*/ */
public PutBucketOptions withBucketAcl(CannedAccessPolicy acl) { public PutBucketOptions withBucketAcl(CannedAccessPolicy acl) {
this.acl = checkNotNull(acl, "acl"); this.acl = checkNotNull(acl, "acl");
if (!acl.equals(CannedAccessPolicy.PRIVATE)) if (!acl.equals(CannedAccessPolicy.PRIVATE))
this.replaceHeader(S3Headers.CANNED_ACL, acl.toString()); this.replaceHeader(S3Headers.CANNED_ACL, acl.toString());
return this; return this;
} }
/** /**
* @see PutBucketOptions#withBucketAcl(CannedAccessPolicy) * @see PutBucketOptions#withBucketAcl(CannedAccessPolicy)
*/ */
public CannedAccessPolicy getAcl() { public CannedAccessPolicy getAcl() {
return acl; return acl;
} }
/** /**
* @see PutBucketOptions#createIn(LocationConstraint) * @see PutBucketOptions#createIn(org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint)
*/ */
public LocationConstraint getLocationConstraint() { public LocationConstraint getLocationConstraint() {
return constraint; return constraint;
} }
public static class Builder { public static class Builder {
/** /**
* @see PutBucketOptions#createIn(LocationConstraint) * @see PutBucketOptions#createIn(org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint)
*/ */
public static PutBucketOptions createIn(LocationConstraint constraint) { public static PutBucketOptions createIn(LocationConstraint constraint) {
PutBucketOptions options = new PutBucketOptions(); PutBucketOptions options = new PutBucketOptions();
return options.createIn(constraint); return options.createIn(constraint);
} }
/** /**
* @see PutBucketOptions#withBucketAcl(CannedAccessPolicy) * @see PutBucketOptions#withBucketAcl(CannedAccessPolicy)
*/ */
public static PutBucketOptions withBucketAcl(CannedAccessPolicy acl) { public static PutBucketOptions withBucketAcl(CannedAccessPolicy acl) {
PutBucketOptions options = new PutBucketOptions(); PutBucketOptions options = new PutBucketOptions();
return options.withBucketAcl(acl); return options.withBucketAcl(acl);
} }
} }
} }

View File

@ -0,0 +1,96 @@
/**
*
* 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.config;
import com.google.inject.*;
import com.google.inject.assistedinject.FactoryProvider;
import com.google.inject.name.Named;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.commands.config.S3CommandsModule;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.handlers.ParseS3ErrorFromXmlContent;
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.HttpConstants;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponseHandler;
import org.jclouds.http.annotation.ClientErrorHandler;
import org.jclouds.http.annotation.RedirectHandler;
import org.jclouds.http.annotation.ServerErrorHandler;
import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import org.jclouds.logging.Logger;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* Configures the S3 connection, including logging and http transport.
*
* @author Adrian Cole
*/
@S3ConnectionModule
public class LiveS3ConnectionModule extends AbstractModule {
@Resource
protected Logger logger = Logger.NULL;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_ADDRESS)
String address;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_PORT)
int port;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_SECURE)
boolean isSecure;
@Override
protected void configure() {
bind(S3Connection.class).to(LiveS3Connection.class)
.in(Scopes.SINGLETON);
bind(HttpResponseHandler.class).annotatedWith(RedirectHandler.class)
.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 = %1$s://%2$s:%3$s", (isSecure ? "https"
: "http"), address, port);
}
@Provides
@Singleton
List<HttpRequestFilter> provideRequestFilters(
RequestAuthorizeSignature requestAuthorizeSignature) {
List<HttpRequestFilter> filters = new ArrayList<HttpRequestFilter>();
filters.add(requestAuthorizeSignature);
return filters;
}
}

View File

@ -0,0 +1,21 @@
package org.jclouds.aws.s3.config;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.jclouds.http.HttpFutureCommandClient;
/**
* designates the the module configures a {@link org.jclouds.aws.s3.S3Connection}
*
* @author Adrian Cole
*
*/
@Retention(RUNTIME)
@Target(TYPE)
public @interface S3ConnectionModule {
}

View File

@ -23,89 +23,37 @@
*/ */
package org.jclouds.aws.s3.config; package org.jclouds.aws.s3.config;
import java.util.ArrayList; import com.google.inject.AbstractModule;
import java.util.List; import com.google.inject.assistedinject.FactoryProvider;
import javax.annotation.Resource;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Context; import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.commands.config.S3CommandsModule; import org.jclouds.aws.s3.commands.config.S3CommandsModule;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.handlers.ParseS3ErrorFromXmlContent;
import org.jclouds.aws.s3.internal.GuiceS3Context; 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.LiveS3InputStreamMap;
import org.jclouds.aws.s3.internal.LiveS3ObjectMap; import org.jclouds.aws.s3.internal.LiveS3ObjectMap;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponseHandler;
import org.jclouds.http.annotation.ClientErrorHandler;
import org.jclouds.http.annotation.RedirectHandler;
import org.jclouds.http.annotation.ServerErrorHandler;
import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import org.jclouds.logging.Logger;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.FactoryProvider;
import com.google.inject.name.Named;
/** /**
* Configures the S3 connection, including logging and http transport. * Configures the {@link S3Context}; requires {@link S3Connection} bound.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class S3ContextModule extends AbstractModule { public class S3ContextModule extends AbstractModule {
@Resource
protected Logger logger = Logger.NULL;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_ADDRESS)
String address;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_PORT)
int port;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_SECURE)
boolean isSecure;
@Override @Override
protected void configure() { protected void configure() {
install(new S3CommandsModule()); this.requireBinding(S3Connection.class);
bind(S3Connection.class).to(LiveS3Connection.class) install(new S3CommandsModule());
.in(Scopes.SINGLETON); bind(GuiceS3Context.S3ObjectMapFactory.class).toProvider(
bind(GuiceS3Context.S3ObjectMapFactory.class).toProvider( FactoryProvider.newFactory(
FactoryProvider.newFactory( GuiceS3Context.S3ObjectMapFactory.class,
GuiceS3Context.S3ObjectMapFactory.class, LiveS3ObjectMap.class));
LiveS3ObjectMap.class)); bind(GuiceS3Context.S3InputStreamMapFactory.class).toProvider(
bind(GuiceS3Context.S3InputStreamMapFactory.class).toProvider( FactoryProvider.newFactory(
FactoryProvider.newFactory( GuiceS3Context.S3InputStreamMapFactory.class,
GuiceS3Context.S3InputStreamMapFactory.class, LiveS3InputStreamMap.class));
LiveS3InputStreamMap.class)); bind(S3Context.class).to(GuiceS3Context.class);
bind(S3Context.class).to(GuiceS3Context.class);
bind(HttpResponseHandler.class).annotatedWith(RedirectHandler.class)
.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 = %1$s://%2$s:%3$s", (isSecure ? "https"
: "http"), address, port);
}
@Provides
@Singleton
List<HttpRequestFilter> provideRequestFilters(
RequestAuthorizeSignature requestAuthorizeSignature) {
List<HttpRequestFilter> filters = new ArrayList<HttpRequestFilter>();
filters.add(requestAuthorizeSignature);
return filters;
} }
} }

View File

@ -24,29 +24,28 @@
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import org.joda.time.DateTime;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.joda.time.DateTime;
/** /**
* A container that provides namespace, access control and aggregation of * A container that provides namespace, access control and aggregation of
* {@link S3Object}s * {@link S3Object}s
* * <p/>
* <p/> * <p/>
* Every object stored in Amazon S3 is contained in a bucket. Buckets partition * Every object stored in Amazon S3 is contained in a bucket. Buckets partition
* the namespace of objects stored in Amazon S3 at the top level. Within a * the namespace of objects stored in Amazon S3 at the top level. Within a
* bucket, you can use any names for your objects, but bucket names must be * bucket, you can use any names for your objects, but bucket names must be
* unique across all of Amazon S3. * unique across all of Amazon S3.
* * <p/>
* Buckets are similar to Internet domain names. Just as Amazon is the only * Buckets are similar to Internet domain names. Just as Amazon is the only
* owner of the domain name Amazon.com, only one person or organization can own * owner of the domain name Amazon.com, only one person or organization can own
* a bucket within Amazon S3. Once you create a uniquely named bucket in Amazon * a bucket within Amazon S3. Once you create a uniquely named bucket in Amazon
* S3, you can organize and name the objects within the bucket in any way you * S3, you can organize and name the objects within the bucket in any way you
* like and the bucket will remain yours for as long as you like and as long as * like and the bucket will remain yours for as long as you like and as long as
* you have the Amazon S3 account. * you have the Amazon S3 account.
* * <p/>
* The similarities between buckets and domain names is not a coincidenceÑthere * The similarities between buckets and domain names is not a coincidenceÑthere
* is a direct mapping between Amazon S3 buckets and subdomains of * is a direct mapping between Amazon S3 buckets and subdomains of
* s3.amazonaws.com. Objects stored in Amazon S3 are addressable using the REST * s3.amazonaws.com. Objects stored in Amazon S3 are addressable using the REST
@ -62,148 +61,145 @@ import org.joda.time.DateTime;
public class S3Bucket { public class S3Bucket {
@Override @Override
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("S3Bucket"); sb.append("S3Bucket");
sb.append("{metadata=").append(metadata); sb.append("{metadata=").append(metadata);
sb.append(", isComplete=").append(isComplete); sb.append(", isTruncated=").append(isTruncated);
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) if (this == o)
return true; return true;
if (!(o instanceof S3Bucket)) if (!(o instanceof S3Bucket))
return false; return false;
S3Bucket s3Bucket = (S3Bucket) o; S3Bucket s3Bucket = (S3Bucket) o;
if (isComplete != s3Bucket.isComplete) if (isTruncated != s3Bucket.isTruncated)
return false; return false;
if (!metadata.equals(s3Bucket.metadata)) if (!metadata.equals(s3Bucket.metadata))
return false; return false;
if (objects != null ? !objects.equals(s3Bucket.objects) if (objects != null ? !objects.equals(s3Bucket.objects)
: s3Bucket.objects != null) : s3Bucket.objects != null)
return false; return false;
return true; return true;
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = objects != null ? objects.hashCode() : 0; int result = objects != null ? objects.hashCode() : 0;
result = 31 * result + metadata.hashCode(); result = 31 * result + metadata.hashCode();
result = 31 * result + (isComplete ? 1 : 0); result = 31 * result + (isTruncated ? 1 : 0);
return result; return result;
} }
/** /**
* System metadata of the S3Bucket * System metadata of the S3Bucket
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
public static class Metadata { public static class Metadata {
@Override @Override
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("Metadata"); sb.append("Metadata");
sb.append("{name='").append(name).append('\''); sb.append("{name='").append(name).append('\'');
sb.append(", creationDate=").append(creationDate); sb.append(", creationDate=").append(creationDate);
sb.append(", canonicalUser=").append(canonicalUser); sb.append(", canonicalUser=").append(canonicalUser);
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) if (this == o)
return true; return true;
if (!(o instanceof Metadata)) if (!(o instanceof Metadata))
return false; return false;
Metadata metadata = (Metadata) o; Metadata metadata = (Metadata) o;
if (canonicalUser != null ? !canonicalUser if (canonicalUser != null ? !canonicalUser
.equals(metadata.canonicalUser) .equals(metadata.canonicalUser)
: metadata.canonicalUser != null) : metadata.canonicalUser != null)
return false; return false;
if (!name.equals(metadata.name)) if (!name.equals(metadata.name))
return false; return false;
return true; return true;
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = name.hashCode(); int result = name.hashCode();
result = 31 * result result = 31 * result
+ (canonicalUser != null ? canonicalUser.hashCode() : 0); + (canonicalUser != null ? canonicalUser.hashCode() : 0);
return result; return result;
} }
/** /**
* Location constraint of the bucket. * Location constraint of the bucket.
* *
* @see <a href= * @author Adrian Cole
* "http://docs.amazonwebservices.com/AmazonS3/latest/RESTBucketLocationGET.html" * @see <a href=
* /> * "http://docs.amazonwebservices.com/AmazonS3/latest/RESTBucketLocationGET.html"
* @author Adrian Cole * />
* */
*/ public static enum LocationConstraint {
public static enum LocationConstraint { EU
EU }
}
private final String name; private final String name;
private DateTime creationDate; private DateTime creationDate;
private CanonicalUser canonicalUser; private CanonicalUser canonicalUser;
/** /**
* @see #getName() * @see #getName()
*/ */
public Metadata(String name) { public Metadata(String name) {
this.name = checkNotNull(name, "name"); this.name = checkNotNull(name, "name");
} }
/** /**
* To comply with Amazon S3 requirements, bucket names must: * To comply with Amazon S3 requirements, bucket names must:
* * <p/>
* Contain lowercase letters, numbers, periods (.), underscores (_), and * Contain lowercase letters, numbers, periods (.), underscores (_), and
* dashes (-) * dashes (-)
* * <p/>
* Start with a number or letter * Start with a number or letter
* * <p/>
* Be between 3 and 255 characters long * Be between 3 and 255 characters long
* * <p/>
* Not be in an IP address style (e.g., "192.168.5.4") * Not be in an IP address style (e.g., "192.168.5.4")
* */
*/ public String getName() {
public String getName() { return name;
return name; }
}
public DateTime getCreationDate() { public DateTime getCreationDate() {
return creationDate; return creationDate;
} }
public void setCreationDate(DateTime creationDate) { public void setCreationDate(DateTime creationDate) {
this.creationDate = creationDate; this.creationDate = creationDate;
} }
/** /**
* Every bucket and object in Amazon S3 has an owner, the user that * Every bucket and object in Amazon S3 has an owner, the user that
* created the bucket or object. The owner of a bucket or object cannot * created the bucket or object. The owner of a bucket or object cannot
* be changed. However, if the object is overwritten by another user * be changed. However, if the object is overwritten by another user
* (deleted and rewritten), the new object will have a new owner. * (deleted and rewritten), the new object will have a new owner.
*/ */
public CanonicalUser getOwner() { public CanonicalUser getOwner() {
return canonicalUser; return canonicalUser;
} }
public void setOwner(CanonicalUser canonicalUser) { public void setOwner(CanonicalUser canonicalUser) {
this.canonicalUser = canonicalUser; this.canonicalUser = canonicalUser;
} }
} }
@ -217,71 +213,71 @@ public class S3Bucket {
private long maxKeys; private long maxKeys;
private final Metadata metadata; private final Metadata metadata;
private boolean isComplete; private boolean isTruncated;
public S3Bucket(String name) { public S3Bucket(String name) {
this.metadata = new Metadata(name); this.metadata = new Metadata(name);
} }
public String getName() { public String getName() {
return this.metadata.getName(); return this.metadata.getName();
} }
public S3Bucket(Metadata metadata) { public S3Bucket(Metadata metadata) {
this.metadata = checkNotNull(metadata, "metadata"); this.metadata = checkNotNull(metadata, "metadata");
} }
/** /**
* @see org.jclouds.aws.s3.S3Connection#listBucket(String) * @see org.jclouds.aws.s3.S3Connection#listBucket(String)
*/ */
public Set<S3Object.Metadata> getContents() { public Set<S3Object.Metadata> getContents() {
return objects; return objects;
} }
public void setContents(Set<S3Object.Metadata> objects) { public void setContents(Set<S3Object.Metadata> objects) {
this.objects = objects; this.objects = objects;
} }
/** /**
* @return true, if the list contains all objects. * @return true, if the list contains all objects.
*/ */
public boolean isComplete() { public boolean isTruncated() {
return isComplete; return isTruncated;
} }
public void setComplete(boolean complete) { public void setTruncated(boolean truncated) {
isComplete = complete; isTruncated = truncated;
} }
public Metadata getMetadata() { public Metadata getMetadata() {
return metadata; return metadata;
} }
public void setCommonPrefixes(Set<String> commonPrefixes) { public void setCommonPrefixes(Set<String> commonPrefixes) {
this.commonPrefixes = commonPrefixes; this.commonPrefixes = commonPrefixes;
} }
/** /**
* Example: * Example:
* <p /> * <p/>
* if the following keys are in the bucket * if the following keys are in the bucket
* * <p/>
* a/1/a<br/> * a/1/a<br/>
* a/1/b<br/> * a/1/b<br/>
* a/2/a<br/> * a/2/a<br/>
* a/2/b<br/> * a/2/b<br/>
* <p /> * <p/>
* and prefix is set to <code>a/</code> and delimiter is set to * and prefix is set to <code>a/</code> and delimiter is set to
* <code>/</code> then commonprefixes would return 1,2 * <code>/</code> then commonprefixes would return 1,2
* *
* @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getPrefix() * @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getPrefix()
*/ */
public Set<String> getCommonPrefixes() { public Set<String> getCommonPrefixes() {
return commonPrefixes; return commonPrefixes;
} }
public void setPrefix(String prefix) { public void setPrefix(String prefix) {
this.prefix = prefix; this.prefix = prefix;
} }
/** /**
@ -290,11 +286,11 @@ public class S3Bucket {
* @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getPrefix() * @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getPrefix()
*/ */
public String getPrefix() { public String getPrefix() {
return prefix; return prefix;
} }
public void setMaxKeys(long maxKeys) { public void setMaxKeys(long maxKeys) {
this.maxKeys = maxKeys; this.maxKeys = maxKeys;
} }
/** /**
@ -302,11 +298,11 @@ public class S3Bucket {
* @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getMaxKeys() * @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getMaxKeys()
*/ */
public long getMaxKeys() { public long getMaxKeys() {
return maxKeys; return maxKeys;
} }
public void setMarker(String marker) { public void setMarker(String marker) {
this.marker = marker; this.marker = marker;
} }
/** /**
@ -316,11 +312,11 @@ public class S3Bucket {
* @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getMarker() * @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getMarker()
*/ */
public String getMarker() { public String getMarker() {
return marker; return marker;
} }
public void setDelimiter(String delimiter) { public void setDelimiter(String delimiter) {
this.delimiter = delimiter; this.delimiter = delimiter;
} }
/** /**

View File

@ -23,32 +23,28 @@
*/ */
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.*;
import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.collect.HashMultimap;
import static com.google.common.base.Preconditions.checkState; import com.google.common.collect.Multimap;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import org.jclouds.aws.s3.commands.options.GetObjectOptions; import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.aws.s3.util.S3Utils.Md5InputStreamResult; import org.jclouds.aws.s3.util.S3Utils.Md5InputStreamResult;
import org.jclouds.http.ContentTypes; import org.jclouds.http.ContentTypes;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import com.google.common.collect.HashMultimap; import java.io.IOException;
import com.google.common.collect.Multimap; import java.io.InputStream;
import java.util.Arrays;
/** /**
* Amazon S3 is designed to store objects. Objects are stored in * Amazon S3 is designed to store objects. Objects are stored in
* {@link S3Bucket buckets} and consist of a {@link S3Object#getValue() value}, * {@link S3Bucket buckets} and consist of a {@link org.jclouds.aws.s3.domain.S3Object#getData() value},
* a {@link S3Object#getKey key}, {@link S3Object.Metadata#getUserMetadata() * a {@link S3Object#getKey key}, {@link S3Object.Metadata#getUserMetadata()
* metadata}, and an access control policy. * metadata}, and an access control policy.
* *
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html" * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html"
* /> * />
* @author Adrian Cole
*/ */
public class S3Object { public class S3Object {
public static final S3Object NOT_FOUND = new S3Object(Metadata.NOT_FOUND); public static final S3Object NOT_FOUND = new S3Object(Metadata.NOT_FOUND);
@ -59,381 +55,372 @@ public class S3Object {
private String contentRange; private String contentRange;
public S3Object(String key) { public S3Object(String key) {
this(new Metadata(key)); this(new Metadata(key));
} }
public S3Object(Metadata metadata) { public S3Object(Metadata metadata) {
this.metadata = metadata; this.metadata = metadata;
} }
public S3Object(Metadata metadata, Object data) { public S3Object(Metadata metadata, Object data) {
this(metadata); this(metadata);
setData(data); setData(data);
} }
public S3Object(String key, Object data) { public S3Object(String key, Object data) {
this(key); this(key);
setData(data); setData(data);
} }
/** /**
* System and user Metadata for the {@link S3Object}. * System and user Metadata for the {@link S3Object}.
* *
* @author Adrian Cole
* @see <a href= * @see <a href=
* "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingMetadata.html" * "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingMetadata.html"
* /> * />
* @author Adrian Cole
*
*/ */
public static class Metadata { public static class Metadata implements Comparable<Metadata> {
public static final Metadata NOT_FOUND = new Metadata("NOT_FOUND"); public static final Metadata NOT_FOUND = new Metadata("NOT_FOUND");
// parsed during list, head, or get // parsed during list, head, or get
private final String key; private final String key;
private byte[] md5; private byte[] md5;
private volatile long size = -1; private volatile long size = -1;
// only parsed during head or get // only parsed during head or get
private Multimap<String, String> allHeaders = HashMultimap.create(); private Multimap<String, String> allHeaders = HashMultimap.create();
private Multimap<String, String> userMetadata = HashMultimap.create(); private Multimap<String, String> userMetadata = HashMultimap.create();
private DateTime lastModified; private DateTime lastModified;
private String dataType = ContentTypes.BINARY; private String dataType = ContentTypes.BINARY;
private String cacheControl; private String cacheControl;
private String dataDisposition; private String dataDisposition;
private String dataEncoding; private String dataEncoding;
// only parsed on list // only parsed on list
private CanonicalUser owner = null; private CanonicalUser owner = null;
private String storageClass = null; private String storageClass = null;
/** /**
* @see #getKey() * @param key
* @param key * @see #getKey()
*/ */
public Metadata(String key) { public Metadata(String key) {
checkNotNull(key, "key"); checkNotNull(key, "key");
checkArgument(!key.startsWith("/"), "keys cannot start with /"); checkArgument(!key.startsWith("/"), "keys cannot start with /");
this.key = key; this.key = key;
} }
@Override @Override
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("Metadata"); sb.append("Metadata");
sb.append("{key='").append(key).append('\''); sb.append("{key='").append(key).append('\'');
sb.append(", lastModified=").append(lastModified); sb.append(", lastModified=").append(lastModified);
sb.append(", md5=").append( sb.append(", md5=").append(
getMd5() == null ? "null" : Arrays.asList(getMd5()) getMd5() == null ? "null" : Arrays.asList(getMd5())
.toString()); .toString());
sb.append(", size=").append(size); sb.append(", size=").append(size);
sb.append(", dataType='").append(dataType).append('\''); sb.append(", dataType='").append(dataType).append('\'');
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) if (this == o)
return true; return true;
if (!(o instanceof Metadata)) if (!(o instanceof Metadata))
return false; return false;
Metadata metadata = (Metadata) o; Metadata metadata = (Metadata) o;
if (size != metadata.size) if (size != metadata.size)
return false; return false;
if (dataType != null ? !dataType.equals(metadata.dataType) if (dataType != null ? !dataType.equals(metadata.dataType)
: metadata.dataType != null) : metadata.dataType != null)
return false; return false;
if (!key.equals(metadata.key)) if (!key.equals(metadata.key))
return false; return false;
if (lastModified != null ? !lastModified if (lastModified != null ? !lastModified
.equals(metadata.lastModified) .equals(metadata.lastModified)
: metadata.lastModified != null) : metadata.lastModified != null)
return false; return false;
if (!Arrays.equals(getMd5(), metadata.getMd5())) if (!Arrays.equals(getMd5(), metadata.getMd5()))
return false; return false;
return true; return true;
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = key.hashCode(); int result = key.hashCode();
result = 31 * result result = 31 * result
+ (lastModified != null ? lastModified.hashCode() : 0); + (lastModified != null ? lastModified.hashCode() : 0);
result = 31 * result result = 31 * result
+ (getMd5() != null ? Arrays.hashCode(getMd5()) : 0); + (getMd5() != null ? Arrays.hashCode(getMd5()) : 0);
result = 31 * result + (int) (size ^ (size >>> 32)); result = 31 * result + (int) (size ^ (size >>> 32));
result = 31 * result + (dataType != null ? dataType.hashCode() : 0); result = 31 * result + (dataType != null ? dataType.hashCode() : 0);
return result; return result;
} }
/** /**
* The key is the handle that you assign to an object that allows you * The key is the handle that you assign to an object that allows you
* retrieve it later. A key is a sequence of Unicode characters whose * retrieve it later. A key is a sequence of Unicode characters whose
* UTF-8 encoding is at most 1024 bytes long. Each object in a bucket * UTF-8 encoding is at most 1024 bytes long. Each object in a bucket
* must have a unique key. * must have a unique key.
* *
* @see <a href= * @see <a href=
* "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingKeys.html" * "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingKeys.html"
* /> * />
*/ */
public String getKey() { public String getKey() {
return key; return key;
} }
public DateTime getLastModified() { public DateTime getLastModified() {
return lastModified; return lastModified;
} }
public void setLastModified(DateTime lastModified) { public void setLastModified(DateTime lastModified) {
this.lastModified = lastModified; this.lastModified = lastModified;
} }
/** /**
* The size of the object, in bytes. * The size of the object, in bytes.
* *
* @see <a href= * @see <a href=
* "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.13." * "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.13."
* /> * />
* */
* @return public long getSize() {
*/ return size;
public long getSize() { }
return size;
}
public void setSize(long size) { public void setSize(long size) {
this.size = size; this.size = size;
} }
/** /**
* A standard MIME type describing the format of the contents. If none * A standard MIME type describing the format of the contents. If none
* is provided, the default is binary/octet-stream. * is provided, the default is binary/octet-stream.
* * @see <a href=
* @see <a href= * "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.17."
* "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.17." * />
* /> */
* public String getContentType() {
* @return return dataType;
*/ }
public String getContentType() {
return dataType;
}
public void setContentType(String dataType) { public void setContentType(String dataType) {
this.dataType = dataType; this.dataType = dataType;
} }
public void setMd5(byte[] md5) { public void setMd5(byte[] md5) {
this.md5 = md5; this.md5 = Arrays.copyOf(md5, md5.length);
} }
/** /**
* @return the md5 value stored in the Etag header returned by S3. * @return the md5 value stored in the Etag header returned by S3.
*/ */
public byte[] getMd5() { public byte[] getMd5() {
return md5; return (md5 == null) ? null : Arrays.copyOf(md5, md5.length);
} }
public void setUserMetadata(Multimap<String, String> userMetadata) { public void setUserMetadata(Multimap<String, String> userMetadata) {
this.userMetadata = userMetadata; this.userMetadata = userMetadata;
} }
/** /**
* * Any header starting with <code>x-amz-meta-</code> is considered user
* Any header starting with <code>x-amz-meta-</code> is considered user * metadata. It will be stored with the object and returned when you
* metadata. It will be stored with the object and returned when you * retrieve the object. The total size of the HTTP request, not
* retrieve the object. The total size of the HTTP request, not * including the body, must be less than 8 KB.
* including the body, must be less than 8 KB. */
* public Multimap<String, String> getUserMetadata() {
*/ return userMetadata;
public Multimap<String, String> getUserMetadata() { }
return userMetadata;
}
public void setOwner(CanonicalUser owner) { public void setOwner(CanonicalUser owner) {
this.owner = owner; this.owner = owner;
} }
/** /**
* Every bucket and object in Amazon S3 has an owner, the user that * Every bucket and object in Amazon S3 has an owner, the user that
* created the bucket or object. The owner of a bucket or object cannot * created the bucket or object. The owner of a bucket or object cannot
* be changed. However, if the object is overwritten by another user * be changed. However, if the object is overwritten by another user
* (deleted and rewritten), the new object will have a new owner. * (deleted and rewritten), the new object will have a new owner.
*/ */
public CanonicalUser getOwner() { public CanonicalUser getOwner() {
return owner; return owner;
} }
public void setStorageClass(String storageClass) { public void setStorageClass(String storageClass) {
this.storageClass = storageClass; this.storageClass = storageClass;
} }
/** /**
* Currently defaults to 'STANDARD' and not used. * Currently defaults to 'STANDARD' and not used.
*/ */
public String getStorageClass() { public String getStorageClass() {
return storageClass; return storageClass;
} }
public void setCacheControl(String cacheControl) { public void setCacheControl(String cacheControl) {
this.cacheControl = cacheControl; this.cacheControl = cacheControl;
} }
/** /**
* Can be used to specify caching behavior along the request/reply * Can be used to specify caching behavior along the request/reply
* chain. * chain.
* *
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.9. * @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.9.
*/ */
public String getCacheControl() { public String getCacheControl() {
return cacheControl; return cacheControl;
} }
public void setContentDisposition(String dataDisposition) { public void setContentDisposition(String dataDisposition) {
this.dataDisposition = dataDisposition; this.dataDisposition = dataDisposition;
} }
/** /**
* Specifies presentational information for the object. * Specifies presentational information for the object.
* *
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html?sec19.5.1."/> * @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html?sec19.5.1."/>
*/ */
public String getContentDisposition() { public String getContentDisposition() {
return dataDisposition; return dataDisposition;
} }
public void setContentEncoding(String dataEncoding) { public void setContentEncoding(String dataEncoding) {
this.dataEncoding = dataEncoding; this.dataEncoding = dataEncoding;
} }
/** /**
* Specifies what content encodings have been applied to the object and * Specifies what content encodings have been applied to the object and
* thus what decoding mechanisms must be applied in order to obtain the * thus what decoding mechanisms must be applied in order to obtain the
* media-type referenced by the Content-Type header field. * media-type referenced by the Content-Type header field.
* *
* @see <a href= * @see <a href=
* "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.11" * "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.11"
* /> * />
*/ */
public String getContentEncoding() { public String getContentEncoding() {
return dataEncoding; return dataEncoding;
} }
public void setAllHeaders(Multimap<String, String> allHeaders) { public void setAllHeaders(Multimap<String, String> allHeaders) {
this.allHeaders = allHeaders; this.allHeaders = allHeaders;
} }
/** /**
* * @return all http response headers associated with this S3Object
* @return all http response headers associated with this S3Object */
*/ public Multimap<String, String> getAllHeaders() {
public Multimap<String, String> getAllHeaders() { return allHeaders;
return allHeaders; }
}
public int compareTo(Metadata o) {
return (this == o) ? 0 : getKey().compareTo(o.getKey());
}
} }
/** /**
* @see Metadata#getKey() * @see Metadata#getKey()
*/ */
public String getKey() { public String getKey() {
return metadata.getKey(); return metadata.getKey();
} }
/** /**
* Sets payload for the request or the content from the response. If size * Sets payload for the request or the content from the response. If size
* isn't set, this will attempt to discover it. * isn't set, this will attempt to discover it.
* *
* @param data * @param data typically InputStream for downloads, or File, byte [], String,
* typically InputStream for downloads, or File, byte [], String, * or InputStream for uploads.
* or InputStream for uploads.
*/ */
public void setData(Object data) { public void setData(Object data) {
this.data = checkNotNull(data, "data"); this.data = checkNotNull(data, "data");
if (getMetadata().getSize() == -1) if (getMetadata().getSize() == -1)
this.getMetadata().setSize(S3Utils.calculateSize(data)); this.getMetadata().setSize(S3Utils.calculateSize(data));
} }
/** /**
* generate an MD5 Hash for the current data. * generate an MD5 Hash for the current data.
* * <p/>
* <h2>Note</h2> * <h2>Note</h2>
* <p/> * <p/>
* If this is an InputStream, it will be converted to a byte array first. * If this is an InputStream, it will be converted to a byte array first.
* *
* @throws IOException * @throws IOException if there is a problem generating the hash.
* if there is a problem generating the hash.
*/ */
public void generateMd5() throws IOException { public void generateMd5() throws IOException {
checkState(data != null, "data"); checkState(data != null, "data");
if (data instanceof InputStream) { if (data instanceof InputStream) {
Md5InputStreamResult result = S3Utils Md5InputStreamResult result = S3Utils
.generateMd5Result((InputStream) data); .generateMd5Result((InputStream) data);
getMetadata().setSize(result.length); getMetadata().setSize(result.length);
getMetadata().setMd5(result.md5); getMetadata().setMd5(result.md5);
setData(result.data); setData(result.data);
} else { } else {
getMetadata().setMd5(S3Utils.md5(data)); getMetadata().setMd5(S3Utils.md5(data));
} }
} }
/** /**
*
* @return InputStream, if downloading, or whatever was set during * @return InputStream, if downloading, or whatever was set during
* {@link #setData(Object)} * {@link #setData(Object)}
*/ */
public Object getData() { public Object getData() {
return data; return data;
} }
public void setMetadata(Metadata metadata) { public void setMetadata(Metadata metadata) {
this.metadata = metadata; this.metadata = metadata;
} }
/** /**
*
* @return System and User metadata relevant to this object. * @return System and User metadata relevant to this object.
*/ */
public Metadata getMetadata() { public Metadata getMetadata() {
return metadata; return metadata;
} }
@Override @Override
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("S3Object"); sb.append("S3Object");
sb.append("{metadata=").append(metadata); sb.append("{metadata=").append(metadata);
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) if (this == o)
return true; return true;
if (!(o instanceof S3Object)) if (!(o instanceof S3Object))
return false; return false;
S3Object s3Object = (S3Object) o; S3Object s3Object = (S3Object) o;
if (data != null ? !data.equals(s3Object.data) : s3Object.data != null) if (data != null ? !data.equals(s3Object.data) : s3Object.data != null)
return false; return false;
if (!metadata.equals(s3Object.metadata)) if (!metadata.equals(s3Object.metadata))
return false; return false;
return true; return true;
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = data != null ? data.hashCode() : 0; int result = data != null ? data.hashCode() : 0;
result = 31 * result + metadata.hashCode(); result = 31 * result + metadata.hashCode();
return result; return result;
} }
public void setContentLength(long contentLength) { public void setContentLength(long contentLength) {
this.contentLength = contentLength; this.contentLength = contentLength;
} }
/** /**
@ -444,18 +431,17 @@ public class S3Object {
* {@link org.jclouds.aws.s3.S3Connection#getObject(String, String, org.jclouds.aws.s3.commands.options.GetObjectOptions) } * {@link org.jclouds.aws.s3.S3Connection#getObject(String, String, org.jclouds.aws.s3.commands.options.GetObjectOptions) }
* is called with options like tail, range, or startAt. * is called with options like tail, range, or startAt.
* *
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
* @see GetObjectOptions
* @return the length in bytes that can be be obtained from * @return the length in bytes that can be be obtained from
* {@link #getData()} * {@link #getData()}
* * @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
* @see GetObjectOptions
*/ */
public long getContentLength() { public long getContentLength() {
return contentLength; return contentLength;
} }
public void setContentRange(String contentRange) { public void setContentRange(String contentRange) {
this.contentRange = contentRange; this.contentRange = contentRange;
} }
/** /**
@ -466,7 +452,7 @@ public class S3Object {
* @see GetObjectOptions * @see GetObjectOptions
*/ */
public String getContentRange() { public String getContentRange() {
return contentRange; return contentRange;
} }
} }

View File

@ -24,19 +24,9 @@
package org.jclouds.aws.s3.internal; package org.jclouds.aws.s3.internal;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.Inject;
import java.io.FileNotFoundException; import com.google.inject.assistedinject.Assisted;
import java.io.IOException; import com.google.inject.name.Named;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Map; import org.jclouds.aws.s3.S3Map;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
@ -44,9 +34,13 @@ import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.inject.Inject; import java.io.FileNotFoundException;
import com.google.inject.assistedinject.Assisted; import java.io.IOException;
import com.google.inject.name.Named; import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/** /**
* Implements core Map functionality with an {@link S3Connection} * Implements core Map functionality with an {@link S3Connection}
@ -55,9 +49,8 @@ import com.google.inject.name.Named;
* complete before throwing an exception. * complete before throwing an exception.
* *
* @author Adrian Cole * @author Adrian Cole
*
* @param <V> * @param <V>
* value of the map * value of the map
*/ */
public abstract class BaseS3Map<V> implements S3Map<String, V> { public abstract class BaseS3Map<V> implements S3Map<String, V> {
@ -73,8 +66,8 @@ public abstract class BaseS3Map<V> implements S3Map<String, V> {
@Inject @Inject
public BaseS3Map(S3Connection connection, @Assisted String bucket) { public BaseS3Map(S3Connection connection, @Assisted String bucket) {
this.connection = checkNotNull(connection, "connection"); this.connection = checkNotNull(connection, "connection");
this.bucket = checkNotNull(bucket, "bucket"); this.bucket = checkNotNull(bucket, "bucketName");
} }
/** /**
@ -85,38 +78,38 @@ public abstract class BaseS3Map<V> implements S3Map<String, V> {
* @see S3Bucket#getContents() * @see S3Bucket#getContents()
*/ */
public int size() { public int size() {
try { try {
S3Bucket bucket = refreshBucket(); S3Bucket bucket = refreshBucket();
Set<S3Object.Metadata> contents = bucket.getContents(); Set<S3Object.Metadata> contents = bucket.getContents();
return contents.size(); return contents.size();
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error getting size of bucket" throw new S3RuntimeException("Error getting size of bucketName"
+ bucket, e); + bucket, e);
} }
} }
protected boolean containsMd5(byte[] md5) throws InterruptedException, protected boolean containsMd5(byte[] md5) throws InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
for (S3Object.Metadata metadata : refreshBucket().getContents()) { for (S3Object.Metadata metadata : refreshBucket().getContents()) {
if (Arrays.equals(md5, metadata.getMd5())) if (Arrays.equals(md5, metadata.getMd5()))
return true; return true;
} }
return false; return false;
} }
protected byte[] getMd5(Object value) throws IOException, protected byte[] getMd5(Object value) throws IOException,
FileNotFoundException, InterruptedException, ExecutionException, FileNotFoundException, InterruptedException, ExecutionException,
TimeoutException { TimeoutException {
S3Object object = null; S3Object object = null;
if (value instanceof S3Object) { if (value instanceof S3Object) {
object = (S3Object) value; object = (S3Object) value;
} else { } else {
object = new S3Object("dummy", value); object = new S3Object("dummy", value);
} }
if (object.getMetadata().getMd5() == null) if (object.getMetadata().getMd5() == null)
object.generateMd5(); object.generateMd5();
return object.getMetadata().getMd5(); return object.getMetadata().getMd5();
} }
/** /**
@ -125,120 +118,119 @@ public abstract class BaseS3Map<V> implements S3Map<String, V> {
* @see S3Connection#getObject(String, String) * @see S3Connection#getObject(String, String)
*/ */
protected Set<S3Object> getAllObjects() { protected Set<S3Object> getAllObjects() {
Set<S3Object> objects = new HashSet<S3Object>(); Set<S3Object> objects = new HashSet<S3Object>();
Set<Future<S3Object>> futureObjects = new HashSet<Future<S3Object>>(); Set<Future<S3Object>> futureObjects = new HashSet<Future<S3Object>>();
for (String key : keySet()) { for (String key : keySet()) {
futureObjects.add(connection.getObject(bucket, key)); futureObjects.add(connection.getObject(bucket, key));
} }
for (Future<S3Object> futureObject : futureObjects) { for (Future<S3Object> futureObject : futureObjects) {
S3Object object = null; S3Object object = null;
try { try {
object = futureObject.get(requestTimeoutMilliseconds, object = futureObject.get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format( throw new S3RuntimeException(String.format(
"Error getting value from bucket %1$s:%2$s", bucket, "Error getting value from bucket %1$s", bucket), e);
object != null ? object.getKey() : "unknown"), e); }
} if (object != S3Object.NOT_FOUND)
if (object != S3Object.NOT_FOUND) objects.add(object);
objects.add(object); }
} return objects;
return objects;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* * <p/>
* Note that if value is an instance of InputStream, it will be read and * Note that if value is an instance of InputStream, it will be read and
* closed following this method. To reuse data from InputStreams, pass * closed following this method. To reuse data from InputStreams, pass
* {@link InputStream}s inside {@link S3Object}s * {@link java.io.InputStream}s inside {@link S3Object}s
*/ */
public boolean containsValue(Object value) { public boolean containsValue(Object value) {
try { try {
byte[] md5 = getMd5(value); byte[] md5 = getMd5(value);
return containsMd5(md5); return containsMd5(md5);
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format( throw new S3RuntimeException(String.format(
"Error searching for ETAG of value: [%2$s] in bucket:%1$s", "Error searching for ETAG of value: [%2$s] in bucketName:%1$s",
bucket, value), e); bucket, value), e);
} }
} }
public static class S3RuntimeException extends RuntimeException { public static class S3RuntimeException extends RuntimeException {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
S3RuntimeException(String s) { S3RuntimeException(String s) {
super(s); super(s);
} }
public S3RuntimeException(String s, Throwable throwable) { public S3RuntimeException(String s, Throwable throwable) {
super(s, throwable); super(s, throwable);
} }
} }
public void clear() { public void clear() {
try { try {
List<Future<Boolean>> deletes = new ArrayList<Future<Boolean>>(); List<Future<Boolean>> deletes = new ArrayList<Future<Boolean>>();
for (String key : keySet()) { for (String key : keySet()) {
deletes.add(connection.deleteObject(bucket, key)); deletes.add(connection.deleteObject(bucket, key));
} }
for (Future<Boolean> isdeleted : deletes) for (Future<Boolean> isdeleted : deletes)
if (!isdeleted.get(requestTimeoutMilliseconds, if (!isdeleted.get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS)) { TimeUnit.MILLISECONDS)) {
throw new S3RuntimeException("failed to delete entry"); throw new S3RuntimeException("failed to delete entry");
} }
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error clearing bucket" + bucket, e); throw new S3RuntimeException("Error clearing bucketName" + bucket, e);
} }
} }
protected S3Bucket refreshBucket() throws InterruptedException, protected S3Bucket refreshBucket() throws InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
S3Bucket currentBucket = connection.listBucket(bucket).get( S3Bucket currentBucket = connection.listBucket(bucket).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
if (currentBucket == S3Bucket.NOT_FOUND) if (currentBucket == S3Bucket.NOT_FOUND)
throw new S3RuntimeException("bucket not found: " + bucket); throw new S3RuntimeException("bucketName not found: " + bucket);
else else
return currentBucket; return currentBucket;
} }
public Set<String> keySet() { public Set<String> keySet() {
try { try {
Set<String> keys = new HashSet<String>(); Set<String> keys = new HashSet<String>();
for (S3Object.Metadata object : refreshBucket().getContents()) for (S3Object.Metadata object : refreshBucket().getContents())
keys.add(object.getKey()); keys.add(object.getKey());
return keys; return keys;
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error getting keys in bucket: " throw new S3RuntimeException("Error getting keys in bucketName: "
+ bucket, e); + bucket, e);
} }
} }
public boolean containsKey(Object key) { public boolean containsKey(Object key) {
try { try {
return connection.headObject(bucket, key.toString()).get( return connection.headObject(bucket, key.toString()).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS) != S3Object.Metadata.NOT_FOUND; requestTimeoutMilliseconds, TimeUnit.MILLISECONDS) != S3Object.Metadata.NOT_FOUND;
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format( throw new S3RuntimeException(String.format(
"Error searching for %1$s:%2$s", bucket, key), e); "Error searching for %1$s:%2$s", bucket, key), e);
} }
} }
public boolean isEmpty() { public boolean isEmpty() {
return keySet().size() == 0; return keySet().size() == 0;
} }
public S3Bucket getBucket() { public S3Bucket getBucket() {
try { try {
return refreshBucket(); return refreshBucket();
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error getting bucket" + bucket, e); throw new S3RuntimeException("Error getting bucketName" + bucket, e);
} }
} }
} }

View File

@ -23,10 +23,8 @@
*/ */
package org.jclouds.aws.s3.internal; package org.jclouds.aws.s3.internal;
import java.io.IOException; import com.google.inject.Inject;
import com.google.inject.Injector;
import javax.annotation.Resource;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Context; import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.S3InputStreamMap; import org.jclouds.aws.s3.S3InputStreamMap;
@ -34,22 +32,22 @@ import org.jclouds.aws.s3.S3ObjectMap;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.inject.Inject; import javax.annotation.Resource;
import com.google.inject.Injector; import java.io.IOException;
/** /**
* Uses a Guice Injector to configure the objects served by S3Context methods. * Uses a Guice Injector to configure the objects served by S3Context methods.
* *
* @see Injector
* @author Adrian Cole * @author Adrian Cole
* @see Injector
*/ */
public class GuiceS3Context implements S3Context { public class GuiceS3Context implements S3Context {
public interface S3ObjectMapFactory { public interface S3ObjectMapFactory {
S3ObjectMap createMapView(String bucket); S3ObjectMap createMapView(String bucket);
} }
public interface S3InputStreamMapFactory { public interface S3InputStreamMapFactory {
S3InputStreamMap createMapView(String bucket); S3InputStreamMap createMapView(String bucket);
} }
@Resource @Resource
@ -61,35 +59,35 @@ public class GuiceS3Context implements S3Context {
@Inject @Inject
private GuiceS3Context(Injector injector, Closer closer, private GuiceS3Context(Injector injector, Closer closer,
S3ObjectMapFactory s3ObjectMapFactory, S3ObjectMapFactory s3ObjectMapFactory,
S3InputStreamMapFactory s3InputStreamMapFactory) { S3InputStreamMapFactory s3InputStreamMapFactory) {
this.injector = injector; this.injector = injector;
this.s3InputStreamMapFactory = s3InputStreamMapFactory; this.s3InputStreamMapFactory = s3InputStreamMapFactory;
this.s3ObjectMapFactory = s3ObjectMapFactory; this.s3ObjectMapFactory = s3ObjectMapFactory;
this.closer = closer; this.closer = closer;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public S3Connection getConnection() { public S3Connection getConnection() {
return injector.getInstance(S3Connection.class); return injector.getInstance(S3Connection.class);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public S3InputStreamMap createInputStreamMap(String bucket) { public S3InputStreamMap createInputStreamMap(String bucket) {
getConnection().putBucketIfNotExists(bucket); getConnection().putBucketIfNotExists(bucket);
return s3InputStreamMapFactory.createMapView(bucket); return s3InputStreamMapFactory.createMapView(bucket);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public S3ObjectMap createS3ObjectMap(String bucket) { public S3ObjectMap createS3ObjectMap(String bucket) {
getConnection().putBucketIfNotExists(bucket); getConnection().putBucketIfNotExists(bucket);
return s3ObjectMapFactory.createMapView(bucket); return s3ObjectMapFactory.createMapView(bucket);
} }
/** /**
@ -98,11 +96,11 @@ public class GuiceS3Context implements S3Context {
* @see Closer * @see Closer
*/ */
public void close() { public void close() {
try { try {
closer.close(); closer.close();
} catch (IOException e) { } catch (IOException e) {
logger.error(e, "error closing content"); logger.error(e, "error closing content");
} }
} }
} }

View File

@ -23,42 +23,35 @@
*/ */
package org.jclouds.aws.s3.internal; package org.jclouds.aws.s3.internal;
import java.io.File; import com.google.common.annotations.VisibleForTesting;
import java.io.InputStream; import com.google.inject.Inject;
import java.util.ArrayList; import com.google.inject.assistedinject.Assisted;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3InputStreamMap; import org.jclouds.aws.s3.S3InputStreamMap;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting; import java.io.File;
import com.google.inject.Inject; import java.io.InputStream;
import com.google.inject.assistedinject.Assisted; import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/** /**
* Map representation of a live connection to S3. All put operations will result * Map representation of a live connection to S3. All put operations will result
* in Md5 calculation. If this is not desired, use {@link LiveS3ObjectMap} * in Md5 calculation. If this is not desired, use {@link LiveS3ObjectMap}
* instead. * instead.
* *
* @author Adrian Cole
* @see S3Connection * @see S3Connection
* @see BaseS3Map * @see BaseS3Map
* @author Adrian Cole
*/ */
public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
S3InputStreamMap { S3InputStreamMap {
@Inject @Inject
public LiveS3InputStreamMap(S3Connection connection, @Assisted String bucket) { public LiveS3InputStreamMap(S3Connection connection, @Assisted String bucket) {
super(connection, bucket); super(connection, bucket);
} }
/** /**
@ -67,15 +60,15 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
* @see S3Connection#getObject(String, String) * @see S3Connection#getObject(String, String)
*/ */
public InputStream get(Object o) { public InputStream get(Object o) {
try { try {
return (InputStream) (connection.getObject(bucket, o.toString()) return (InputStream) (connection.getObject(bucket, o.toString())
.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)) .get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS))
.getData(); .getData();
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format( throw new S3RuntimeException(String.format(
"Error geting object %1$s:%2$s", bucket, o), e); "Error geting object %1$s:%2$s", bucket, o), e);
} }
} }
/** /**
@ -84,16 +77,16 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
* @see S3Connection#deleteObject(String, String) * @see S3Connection#deleteObject(String, String)
*/ */
public InputStream remove(Object o) { public InputStream remove(Object o) {
InputStream old = get(o); InputStream old = get(o);
try { try {
connection.deleteObject(bucket, o.toString()).get( connection.deleteObject(bucket, o.toString()).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format( throw new S3RuntimeException(String.format(
"Error removing object %1$s:%2$s", bucket, o), e); "Error removing object %1$s:%2$s", bucket, o), e);
} }
return old; return old;
} }
/** /**
@ -102,12 +95,12 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
* @see #getAllObjects() * @see #getAllObjects()
*/ */
public Collection<InputStream> values() { public Collection<InputStream> values() {
Collection<InputStream> values = new LinkedList<InputStream>(); Collection<InputStream> values = new LinkedList<InputStream>();
Set<S3Object> objects = getAllObjects(); Set<S3Object> objects = getAllObjects();
for (S3Object object : objects) { for (S3Object object : objects) {
values.add((InputStream) object.getData()); values.add((InputStream) object.getData());
} }
return values; return values;
} }
/** /**
@ -116,43 +109,40 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
* @see #getAllObjects() * @see #getAllObjects()
*/ */
public Set<Map.Entry<String, InputStream>> entrySet() { public Set<Map.Entry<String, InputStream>> entrySet() {
Set<Map.Entry<String, InputStream>> entrySet = new HashSet<Map.Entry<String, InputStream>>(); Set<Map.Entry<String, InputStream>> entrySet = new HashSet<Map.Entry<String, InputStream>>();
for (S3Object object : getAllObjects()) { for (S3Object object : getAllObjects()) {
entrySet.add(new Entry(object.getKey(), (InputStream) object entrySet.add(new Entry(object.getKey(), (InputStream) object
.getData())); .getData()));
} }
return entrySet; return entrySet;
} }
/**
* {@inheritDoc}
*/
public class Entry implements java.util.Map.Entry<String, InputStream> { public class Entry implements java.util.Map.Entry<String, InputStream> {
private InputStream value; private InputStream value;
private String key; private String key;
Entry(String key, InputStream value) { Entry(String key, InputStream value) {
this.key = key; this.key = key;
this.value = value; this.value = value;
} }
public String getKey() { public String getKey() {
return key; return key;
} }
public InputStream getValue() { public InputStream getValue() {
return value; return value;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
* @see LiveS3InputStreamMap#put(String, InputStream) * @see LiveS3InputStreamMap#put(String, InputStream)
*/ */
public InputStream setValue(InputStream value) { public InputStream setValue(InputStream value) {
return put(key, value); return put(key, value);
} }
} }
@ -162,7 +152,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
* @see #putAllInternal(Map) * @see #putAllInternal(Map)
*/ */
public void putAll(Map<? extends String, ? extends InputStream> map) { public void putAll(Map<? extends String, ? extends InputStream> map) {
putAllInternal(map); putAllInternal(map);
} }
/** /**
@ -171,7 +161,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
* @see #putAllInternal(Map) * @see #putAllInternal(Map)
*/ */
public void putAllBytes(Map<? extends String, ? extends byte[]> map) { public void putAllBytes(Map<? extends String, ? extends byte[]> map) {
putAllInternal(map); putAllInternal(map);
} }
/** /**
@ -180,7 +170,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
* @see #putAllInternal(Map) * @see #putAllInternal(Map)
*/ */
public void putAllFiles(Map<? extends String, ? extends File> map) { public void putAllFiles(Map<? extends String, ? extends File> map) {
putAllInternal(map); putAllInternal(map);
} }
/** /**
@ -189,7 +179,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
* @see #putAllInternal(Map) * @see #putAllInternal(Map)
*/ */
public void putAllStrings(Map<? extends String, ? extends String> map) { public void putAllStrings(Map<? extends String, ? extends String> map) {
putAllInternal(map); putAllInternal(map);
} }
/** /**
@ -201,22 +191,22 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
*/ */
@VisibleForTesting @VisibleForTesting
void putAllInternal(Map<? extends String, ? extends Object> map) { void putAllInternal(Map<? extends String, ? extends Object> map) {
try { try {
List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>(); List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>();
for (String key : map.keySet()) { for (Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
S3Object object = new S3Object(key); S3Object object = new S3Object(entry.getKey());
object.setData(map.get(key)); object.setData(entry.getValue());
object.generateMd5(); object.generateMd5();
puts.add(connection.putObject(bucket, object)); puts.add(connection.putObject(bucket, object));
} }
for (Future<byte[]> put : puts) for (Future<byte[]> put : puts)
// this will throw an exception if there was a problem // this will throw an exception if there was a problem
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error putting into bucket" + bucket, throw new S3RuntimeException("Error putting into bucketName" + bucket,
e); e);
} }
} }
/** /**
@ -225,7 +215,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
* @see #putInternal(String, Object) * @see #putInternal(String, Object)
*/ */
public InputStream putString(String key, String value) { public InputStream putString(String key, String value) {
return putInternal(key, value); return putInternal(key, value);
} }
/** /**
@ -234,7 +224,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
* @see #putInternal(String, Object) * @see #putInternal(String, Object)
*/ */
public InputStream putFile(String key, File value) { public InputStream putFile(String key, File value) {
return putInternal(key, value); return putInternal(key, value);
} }
/** /**
@ -243,7 +233,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
* @see #putInternal(String, Object) * @see #putInternal(String, Object)
*/ */
public InputStream putBytes(String key, byte[] value) { public InputStream putBytes(String key, byte[] value) {
return putInternal(key, value); return putInternal(key, value);
} }
/** /**
@ -252,11 +242,10 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
* @see #putInternal(String, Object) * @see #putInternal(String, Object)
*/ */
public InputStream put(String key, InputStream value) { public InputStream put(String key, InputStream value) {
return putInternal(key, value); return putInternal(key, value);
} }
/** /**
*
* calculates md5 before adding the object to s3. As a side-effect of this, * calculates md5 before adding the object to s3. As a side-effect of this,
* the content will be copied into a byte []. * * the content will be copied into a byte []. *
* *
@ -264,19 +253,19 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
*/ */
@VisibleForTesting @VisibleForTesting
InputStream putInternal(String s, Object o) { InputStream putInternal(String s, Object o) {
S3Object object = new S3Object(s); S3Object object = new S3Object(s);
try { try {
InputStream returnVal = containsKey(s) ? get(s) : null; InputStream returnVal = containsKey(s) ? get(s) : null;
object.setData(o); object.setData(o);
object.generateMd5(); object.generateMd5();
connection.putObject(bucket, object).get( connection.putObject(bucket, object).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
return returnVal; return returnVal;
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format( throw new S3RuntimeException(String.format(
"Error adding object %1$s:%2$s", bucket, object), e); "Error adding object %1$s:%2$s", bucket, object), e);
} }
} }
} }

View File

@ -127,7 +127,7 @@ public class LiveS3ObjectMap extends BaseS3Map<S3Object> implements S3ObjectMap
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException( throw new S3RuntimeException(
String.format("Error putting object %1$s:%2$s%n%1$s", String.format("Error putting object %1$s:%2$s%n%3$s",
bucket, key, value), e); bucket, key, value), e);
} }
return returnVal; return returnVal;
@ -149,7 +149,7 @@ public class LiveS3ObjectMap extends BaseS3Map<S3Object> implements S3ObjectMap
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error putting into bucket" + bucket, throw new S3RuntimeException("Error putting into bucketName" + bucket,
e); e);
} }
} }

View File

@ -22,7 +22,7 @@
* ==================================================================== * ====================================================================
*/ */
/** /**
* This package contains an Amazon S3 client implemented by {@link HttpFutureCommand} commands. * This package contains an Amazon S3 client implemented by {@link org.jclouds.http.HttpFutureCommandClient} commands.
* *
* @see <a href="http://aws.amazon.com/s3"/> * @see <a href="http://aws.amazon.com/s3"/>
* @author Adrian Cole * @author Adrian Cole

View File

@ -25,17 +25,6 @@ package org.jclouds.aws.s3.util;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.io.output.ByteArrayOutputStream;
import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.crypto.digests.MD5Digest;
@ -46,205 +35,211 @@ import org.bouncycastle.util.encoders.Base64;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.regex.Pattern;
/** /**
* Encryption, Hashing, and IO Utilities needed to sign and verify S3 requests * Encryption, Hashing, and IO Utilities needed to sign and verify S3 requests
* and responses. * and responses.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
public class S3Utils extends Utils { public class S3Utils extends Utils {
private static final Pattern IP_PATTERN = Pattern private static final Pattern IP_PATTERN = Pattern
.compile("b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)" .compile("b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)"
+ "{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)b"); + "{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)b");
public static String validateBucketName(String bucketName) { public static String validateBucketName(String bucketName) {
checkNotNull(bucketName, "bucketName"); checkNotNull(bucketName, "bucketName");
checkArgument(bucketName.matches("^[a-z0-9].*"), checkArgument(bucketName.matches("^[a-z0-9].*"),
"bucket name must start with a number or letter"); "bucketName name must start with a number or letter");
checkArgument( checkArgument(
bucketName.matches("^[-_.a-z0-9]+"), bucketName.matches("^[-_.a-z0-9]+"),
"bucket name can only contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)"); "bucketName name can only contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)");
checkArgument(bucketName.length() > 2 && bucketName.length() < 256, checkArgument(bucketName.length() > 2 && bucketName.length() < 256,
"bucket name must be between 3 and 255 characters long"); "bucketName name must be between 3 and 255 characters long");
checkArgument(!IP_PATTERN.matcher(bucketName).matches(), checkArgument(!IP_PATTERN.matcher(bucketName).matches(),
"bucket name cannot be ip address style"); "bucketName name cannot be ip address style");
return bucketName; return bucketName;
} }
static final byte[] HEX_CHAR_TABLE = { (byte) '0', (byte) '1', (byte) '2', static final byte[] HEX_CHAR_TABLE = {(byte) '0', (byte) '1', (byte) '2',
(byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
(byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c',
(byte) 'd', (byte) 'e', (byte) 'f' }; (byte) 'd', (byte) 'e', (byte) 'f'};
public static String toHexString(byte[] raw) public static String toHexString(byte[] raw)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
byte[] hex = new byte[2 * raw.length]; byte[] hex = new byte[2 * raw.length];
int index = 0; int index = 0;
for (byte b : raw) { for (byte b : raw) {
int v = b & 0xFF; int v = b & 0xFF;
hex[index++] = HEX_CHAR_TABLE[v >>> 4]; hex[index++] = HEX_CHAR_TABLE[v >>> 4];
hex[index++] = HEX_CHAR_TABLE[v & 0xF]; hex[index++] = HEX_CHAR_TABLE[v & 0xF];
} }
return new String(hex, "ASCII"); return new String(hex, "ASCII");
} }
public static long calculateSize(Object data) { public static long calculateSize(Object data) {
long size = -1; long size = -1;
if (data instanceof byte[]) { if (data instanceof byte[]) {
size = ((byte[]) data).length; size = ((byte[]) data).length;
} else if (data instanceof String) { } else if (data instanceof String) {
size = ((String) data).length(); size = ((String) data).length();
} else if (data instanceof File) { } else if (data instanceof File) {
size = ((File) data).length(); size = ((File) data).length();
} }
return size; return size;
} }
/** /**
*
* @throws IOException * @throws IOException
*/ */
public static byte[] md5(Object data) throws IOException { public static byte[] md5(Object data) throws IOException {
checkNotNull(data, "data must be set before calling generateMd5()"); checkNotNull(data, "data must be set before calling generateMd5()");
byte[] md5 = null; byte[] md5 = null;
if (data == null || data instanceof byte[]) { if (data == null) {
md5 = S3Utils.md5((byte[]) data); } else if (data instanceof byte[]) {
} else if (data instanceof String) { md5 = S3Utils.md5((byte[]) data);
md5 = S3Utils.md5(((String) data).getBytes()); } else if (data instanceof String) {
} else if (data instanceof File) { md5 = S3Utils.md5(((String) data).getBytes());
md5 = S3Utils.md5(((File) data)); } else if (data instanceof File) {
} else { md5 = S3Utils.md5(((File) data));
throw new UnsupportedOperationException("Content not supported " } else {
+ data.getClass()); throw new UnsupportedOperationException("Content not supported "
} + data.getClass());
return md5; }
return md5;
} }
public static byte[] fromHexString(String hex) { public static byte[] fromHexString(String hex) {
byte[] bytes = new byte[hex.length() / 2]; byte[] bytes = new byte[hex.length() / 2];
for (int i = 0; i < bytes.length; i++) { for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), bytes[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2),
16); 16);
} }
return bytes; return bytes;
} }
public static String hmacSha1Base64(String toEncode, byte[] key) public static String hmacSha1Base64(String toEncode, byte[] key)
throws NoSuchAlgorithmException, NoSuchProviderException, throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException { InvalidKeyException {
HMac hmac = new HMac(new SHA1Digest()); HMac hmac = new HMac(new SHA1Digest());
byte[] resBuf = new byte[hmac.getMacSize()]; byte[] resBuf = new byte[hmac.getMacSize()];
byte[] plainBytes = toEncode.getBytes(); byte[] plainBytes = toEncode.getBytes();
byte[] keyBytes = key; byte[] keyBytes = key;
hmac.init(new KeyParameter(keyBytes)); hmac.init(new KeyParameter(keyBytes));
hmac.update(plainBytes, 0, plainBytes.length); hmac.update(plainBytes, 0, plainBytes.length);
hmac.doFinal(resBuf, 0); hmac.doFinal(resBuf, 0);
return toBase64String(resBuf); return toBase64String(resBuf);
} }
public static String md5Hex(byte[] toEncode) public static String md5Hex(byte[] toEncode)
throws NoSuchAlgorithmException, NoSuchProviderException, throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException, UnsupportedEncodingException { InvalidKeyException, UnsupportedEncodingException {
byte[] resBuf = md5(toEncode); byte[] resBuf = md5(toEncode);
return toHexString(resBuf); return toHexString(resBuf);
} }
public static String md5Base64(byte[] toEncode) public static String md5Base64(byte[] toEncode)
throws NoSuchAlgorithmException, NoSuchProviderException, throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException { InvalidKeyException {
byte[] resBuf = md5(toEncode); byte[] resBuf = md5(toEncode);
return toBase64String(resBuf); return toBase64String(resBuf);
} }
public static String toBase64String(byte[] resBuf) { public static String toBase64String(byte[] resBuf) {
return new String(Base64.encode(resBuf)); return new String(Base64.encode(resBuf));
} }
public static byte[] md5(byte[] plainBytes) { public static byte[] md5(byte[] plainBytes) {
MD5Digest md5 = new MD5Digest(); MD5Digest md5 = new MD5Digest();
byte[] resBuf = new byte[md5.getDigestSize()]; byte[] resBuf = new byte[md5.getDigestSize()];
md5.update(plainBytes, 0, plainBytes.length); md5.update(plainBytes, 0, plainBytes.length);
md5.doFinal(resBuf, 0); md5.doFinal(resBuf, 0);
return resBuf; return resBuf;
} }
public static byte[] md5(File toEncode) throws IOException { public static byte[] md5(File toEncode) throws IOException {
MD5Digest md5 = new MD5Digest(); MD5Digest md5 = new MD5Digest();
byte[] resBuf = new byte[md5.getDigestSize()]; byte[] resBuf = new byte[md5.getDigestSize()];
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int numRead = -1; int numRead = -1;
InputStream i = new FileInputStream(toEncode); InputStream i = new FileInputStream(toEncode);
try { try {
do { do {
numRead = i.read(buffer); numRead = i.read(buffer);
if (numRead > 0) { if (numRead > 0) {
md5.update(buffer, 0, numRead); md5.update(buffer, 0, numRead);
} }
} while (numRead != -1); } while (numRead != -1);
} finally { } finally {
IOUtils.closeQuietly(i); IOUtils.closeQuietly(i);
} }
md5.doFinal(resBuf, 0); md5.doFinal(resBuf, 0);
return resBuf; return resBuf;
} }
public static Md5InputStreamResult generateMd5Result(InputStream toEncode) public static Md5InputStreamResult generateMd5Result(InputStream toEncode)
throws IOException { throws IOException {
MD5Digest md5 = new MD5Digest(); MD5Digest md5 = new MD5Digest();
byte[] resBuf = new byte[md5.getDigestSize()]; byte[] resBuf = new byte[md5.getDigestSize()];
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
long length = 0; long length = 0;
int numRead = -1; int numRead = -1;
try { try {
do { do {
numRead = toEncode.read(buffer); numRead = toEncode.read(buffer);
if (numRead > 0) { if (numRead > 0) {
length += numRead; length += numRead;
md5.update(buffer, 0, numRead); md5.update(buffer, 0, numRead);
out.write(buffer, 0, numRead); out.write(buffer, 0, numRead);
} }
} while (numRead != -1); } while (numRead != -1);
} finally { } finally {
IOUtils.closeQuietly(toEncode); out.close();
} IOUtils.closeQuietly(toEncode);
md5.doFinal(resBuf, 0); }
return new Md5InputStreamResult(out.toByteArray(), resBuf, length); md5.doFinal(resBuf, 0);
return new Md5InputStreamResult(out.toByteArray(), resBuf, length);
} }
public static class Md5InputStreamResult { public static class Md5InputStreamResult {
public final byte[] data; public final byte[] data;
public final byte[] md5; public final byte[] md5;
public final long length; public final long length;
Md5InputStreamResult(byte[] data, byte[] md5, long length) { Md5InputStreamResult(byte[] data, byte[] md5, long length) {
this.data = checkNotNull(data, "data"); this.data = checkNotNull(data, "data");
this.md5 = checkNotNull(md5, "md5"); this.md5 = checkNotNull(md5, "md5");
checkArgument(length >= 0, "length cannot me negative"); checkArgument(length >= 0, "length cannot me negative");
this.length = length; this.length = length;
} }
} }
public static String getContentAsStringAndClose(S3Object object) public static String getContentAsStringAndClose(S3Object object)
throws IOException { throws IOException {
checkNotNull(object, "s3Object"); checkNotNull(object, "s3Object");
checkNotNull(object.getData(), "s3Object.content"); checkNotNull(object.getData(), "s3Object.content");
Object o = object.getData(); Object o = object.getData();
if (o instanceof InputStream) { if (o instanceof InputStream) {
String returnVal = toStringAndClose((InputStream) o); String returnVal = toStringAndClose((InputStream) o);
if (object.getMetadata().getContentType().indexOf("xml") >= 0) { if (object.getMetadata().getContentType().indexOf("xml") >= 0) {
} }
return returnVal; return returnVal;
} else { } else {
throw new IllegalArgumentException("Object type not supported: " throw new IllegalArgumentException("Object type not supported: "
+ o.getClass().getName()); + o.getClass().getName());
} }
} }
} }

View File

@ -24,7 +24,7 @@
package org.jclouds.aws.s3.xml; package org.jclouds.aws.s3.xml;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.Inject;
import org.jclouds.aws.s3.domain.CanonicalUser; import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
@ -33,16 +33,14 @@ import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import com.google.inject.Inject;
/** /**
* Parses the following XML document: * Parses the following XML document:
* <p/> * <p/>
* ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01" * ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01"
* *
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html" * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html"
* /> * />
* @author Adrian Cole
*/ */
public class ListBucketHandler extends ParseSax.HandlerWithResult<S3Bucket> { public class ListBucketHandler extends ParseSax.HandlerWithResult<S3Bucket> {
private S3Bucket s3Bucket; private S3Bucket s3Bucket;
@ -54,72 +52,72 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<S3Bucket> {
@Inject @Inject
public ListBucketHandler(DateService dateParser) { public ListBucketHandler(DateService dateParser) {
this.dateParser = dateParser; this.dateParser = dateParser;
} }
public S3Bucket getResult() { public S3Bucket getResult() {
return s3Bucket; return s3Bucket;
} }
public void setBucketName(String bucketName) { public void setBucketName(String bucketName) {
this.s3Bucket = new S3Bucket(checkNotNull(bucketName, "bucketName")); this.s3Bucket = new S3Bucket(checkNotNull(bucketName, "bucketName"));
} }
private boolean inCommonPrefixes; private boolean inCommonPrefixes;
public void startElement(String uri, String name, String qName, public void startElement(String uri, String name, String qName,
Attributes attrs) { Attributes attrs) {
if (qName.equals("CommonPrefixes")) { if (qName.equals("CommonPrefixes")) {
inCommonPrefixes = true; inCommonPrefixes = true;
} }
} }
public void endElement(String uri, String name, String qName) { public void endElement(String uri, String name, String qName) {
if (qName.equals("ID")) { if (qName.equals("ID")) {
currentOwner = new CanonicalUser(currentText.toString()); currentOwner = new CanonicalUser(currentText.toString());
} else if (qName.equals("DisplayName")) { } else if (qName.equals("DisplayName")) {
currentOwner.setDisplayName(currentText.toString()); currentOwner.setDisplayName(currentText.toString());
} else if (qName.equals("Key")) { // content stuff } else if (qName.equals("Key")) { // content stuff
currentObjectMetadata = new S3Object.Metadata(currentText currentObjectMetadata = new S3Object.Metadata(currentText
.toString()); .toString());
} else if (qName.equals("LastModified")) { } else if (qName.equals("LastModified")) {
currentObjectMetadata.setLastModified(dateParser currentObjectMetadata.setLastModified(dateParser
.dateTimeFromXMLFormat(currentText.toString())); .dateTimeFromXMLFormat(currentText.toString()));
} else if (qName.equals("ETag")) { } else if (qName.equals("ETag")) {
currentObjectMetadata.setMd5(S3Utils.fromHexString(currentText currentObjectMetadata.setMd5(S3Utils.fromHexString(currentText
.toString().replaceAll("\"", ""))); .toString().replaceAll("\"", "")));
} else if (qName.equals("Size")) { } else if (qName.equals("Size")) {
currentObjectMetadata.setSize(Long currentObjectMetadata.setSize(Long
.parseLong(currentText.toString())); .parseLong(currentText.toString()));
} else if (qName.equals("Owner")) { } else if (qName.equals("Owner")) {
currentObjectMetadata.setOwner(currentOwner); currentObjectMetadata.setOwner(currentOwner);
} else if (qName.equals("StorageClass")) { } else if (qName.equals("StorageClass")) {
currentObjectMetadata.setStorageClass(currentText.toString()); currentObjectMetadata.setStorageClass(currentText.toString());
} else if (qName.equals("Contents")) { } 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("Name")) {// bucketName stuff last, as least likely
} else if (qName.equals("Prefix")) { } else if (qName.equals("Prefix")) {
String prefix = currentText.toString().trim(); String prefix = currentText.toString().trim();
if (inCommonPrefixes) if (inCommonPrefixes)
s3Bucket.getCommonPrefixes().add(prefix); s3Bucket.getCommonPrefixes().add(prefix);
else else
s3Bucket.setPrefix(prefix); s3Bucket.setPrefix(prefix);
} else if (qName.equals("Delimiter")) { } else if (qName.equals("Delimiter")) {
if (!currentText.toString().equals("")) if (!currentText.toString().equals(""))
s3Bucket.setDelimiter(currentText.toString().trim()); s3Bucket.setDelimiter(currentText.toString().trim());
} else if (qName.equals("Marker")) { } else if (qName.equals("Marker")) {
if (!currentText.toString().equals("")) if (!currentText.toString().equals(""))
s3Bucket.setMarker(currentText.toString()); s3Bucket.setMarker(currentText.toString());
} else if (qName.equals("MaxKeys")) { } else if (qName.equals("MaxKeys")) {
s3Bucket.setMaxKeys(Long.parseLong(currentText.toString())); s3Bucket.setMaxKeys(Long.parseLong(currentText.toString()));
} else if (qName.equals("IsTruncated")) { } else if (qName.equals("IsTruncated")) {
boolean isTruncated = Boolean.parseBoolean(currentText.toString()); boolean isTruncated = Boolean.parseBoolean(currentText.toString());
s3Bucket.setComplete(!isTruncated); s3Bucket.setTruncated(isTruncated);
} }
currentText = new StringBuilder(); currentText = new StringBuilder();
} }
public void characters(char ch[], int start, int length) { public void characters(char ch[], int start, int length) {
currentText.append(ch, start, length); currentText.append(ch, start, length);
} }
} }

View File

@ -23,16 +23,15 @@
*/ */
package org.jclouds.aws.s3.xml; package org.jclouds.aws.s3.xml;
import java.util.List; import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Error; import org.jclouds.aws.s3.domain.S3Error;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
import com.google.common.annotations.VisibleForTesting; import java.util.List;
import com.google.inject.Inject;
import com.google.inject.Provider;
/** /**
* Creates Parsers needed to interpret S3 Server messages. This class uses guice * Creates Parsers needed to interpret S3 Server messages. This class uses guice
@ -48,18 +47,18 @@ public class S3ParserFactory {
@VisibleForTesting @VisibleForTesting
public static interface GenericParseFactory<T> { public static interface GenericParseFactory<T> {
ParseSax<T> create(ParseSax.HandlerWithResult<T> handler); ParseSax<T> create(ParseSax.HandlerWithResult<T> handler);
} }
@Inject @Inject
Provider<ListAllMyBucketsHandler> ListAllMyBucketsHandlerprovider; Provider<ListAllMyBucketsHandler> ListAllMyBucketsHandlerprovider;
/** /**
* @return a parser used to handle {@link ListOwnedBuckets} responses * @return a parser used to handle {@link org.jclouds.aws.s3.commands.ListOwnedBuckets} responses
*/ */
public ParseSax<List<S3Bucket.Metadata>> createListBucketsParser() { public ParseSax<List<S3Bucket.Metadata>> createListBucketsParser() {
return parseListAllMyBucketsFactory return parseListAllMyBucketsFactory
.create(ListAllMyBucketsHandlerprovider.get()); .create(ListAllMyBucketsHandlerprovider.get());
} }
@Inject @Inject
@ -69,10 +68,10 @@ public class S3ParserFactory {
Provider<ListBucketHandler> ListBucketHandlerprovider; Provider<ListBucketHandler> ListBucketHandlerprovider;
/** /**
* @return a parser used to handle {@link ListBucket} responses * @return a parser used to handle {@link org.jclouds.aws.s3.commands.ListBucket} responses
*/ */
public ParseSax<S3Bucket> createListBucketParser() { public ParseSax<S3Bucket> createListBucketParser() {
return parseListBucketFactory.create(ListBucketHandlerprovider.get()); return parseListBucketFactory.create(ListBucketHandlerprovider.get());
} }
@Inject @Inject
@ -82,10 +81,10 @@ public class S3ParserFactory {
Provider<CopyObjectHandler> copyObjectHandlerProvider; Provider<CopyObjectHandler> copyObjectHandlerProvider;
/** /**
* @return a parser used to handle {@link CopyObject} responses * @return a parser used to handle {@link org.jclouds.aws.s3.commands.CopyObject} responses
*/ */
public ParseSax<S3Object.Metadata> createCopyObjectParser() { public ParseSax<S3Object.Metadata> createCopyObjectParser() {
return parseCopyObjectFactory.create(copyObjectHandlerProvider.get()); return parseCopyObjectFactory.create(copyObjectHandlerProvider.get());
} }
@Inject @Inject
@ -98,7 +97,7 @@ public class S3ParserFactory {
* @return a parser used to handle error conditions. * @return a parser used to handle error conditions.
*/ */
public ParseSax<S3Error> createErrorParser() { public ParseSax<S3Error> createErrorParser() {
return parseErrorFactory.create(errorHandlerProvider.get()); return parseErrorFactory.create(errorHandlerProvider.get());
} }
} }

View File

@ -35,7 +35,7 @@ import java.util.concurrent.Executors;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", sequential = true, testName = "s3.PerformanceTest") @Test(groups = "performance", sequential = true, testName = "s3.PerformanceTest")
public class PerformanceTest { public class PerformanceTest {
protected static int LOOP_COUNT = 1000; protected static int LOOP_COUNT = 1000;
protected ExecutorService exec; protected ExecutorService exec;

View File

@ -0,0 +1,141 @@
/**
*
* 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;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.internal.BaseS3Map;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.io.*;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
@Test
public abstract class BaseS3MapIntegrationTest<T> extends S3IntegrationTest {
public abstract void testPutAll();
public abstract void testEntrySet() throws IOException;
public abstract void testValues() throws IOException;
protected BaseS3Map<T> map;
protected Map<String, String> fiveStrings = ImmutableMap.of("one", "apple",
"two", "bear", "three", "candy", "four", "dogma", "five", "emma");
protected Map<String, byte[]> fiveBytes = ImmutableMap.of("one", "apple"
.getBytes(), "two", "bear".getBytes(), "three", "candy".getBytes(),
"four", "dogma".getBytes(), "five", "emma".getBytes());
protected Map<String, InputStream> fiveInputs;
protected Map<String, File> fiveFiles;
String tmpDirectory;
@BeforeMethod(dependsOnMethods = "setUpBucket", groups = {"integration", "live"})
@Parameters({"basedir"})
protected void setUpTempDir(String basedir) throws InterruptedException,
ExecutionException, FileNotFoundException, IOException,
TimeoutException {
tmpDirectory = basedir + File.separator + "target" + File.separator
+ "testFiles" + File.separator + getClass().getSimpleName();
new File(tmpDirectory).mkdirs();
fiveFiles = ImmutableMap.of("one", new File(tmpDirectory, "apple"),
"two", new File(tmpDirectory, "bear"), "three", new File(
tmpDirectory, "candy"), "four", new File(tmpDirectory,
"dogma"), "five", new File(tmpDirectory, "emma"));
for (File file : fiveFiles.values()) {
IOUtils.write(file.getName(), new FileOutputStream(file));
}
fiveInputs = ImmutableMap.of("one", IOUtils.toInputStream("apple"),
"two", IOUtils.toInputStream("bear"), "three", IOUtils
.toInputStream("candy"), "four", IOUtils
.toInputStream("dogma"), "five", IOUtils
.toInputStream("emma"));
map = createMap(context, bucketName);
map.clear();
}
protected abstract BaseS3Map<T> createMap(S3Context context, String bucket);
@Test(groups = {"integration", "live"})
public void testClear() {
map.clear();
assertEquals(map.size(), 0);
putString("one", "apple");
assertEquals(map.size(), 1);
map.clear();
assertEquals(map.size(), 0);
}
@Test(groups = {"integration", "live"})
public abstract void testRemove() throws IOException;
@Test(groups = {"integration", "live"})
public void testKeySet() {
assertEquals(map.keySet().size(), 0);
putString("one", "two");
assertEquals(map.keySet(), ImmutableSet.of("one"));
}
@Test(groups = {"integration", "live"})
public void testContainsKey() {
assert !map.containsKey("one");
putString("one", "apple");
assert map.containsKey("one");
}
@Test(groups = {"integration", "live"})
public void testIsEmpty() {
assert map.isEmpty();
putString("one", "apple");
assert !map.isEmpty();
}
abstract protected void putString(String key, String value);
protected void fourLeftRemovingOne() {
map.remove("one");
assertEquals(map.size(), 4);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
ImmutableSet.of("two", "three", "four", "five")));
}
@Test(groups = {"integration", "live"})
public abstract void testPut() throws IOException;
@Test(groups = {"integration", "live"})
public void testGetBucket() {
assertEquals(map.getBucket().getName(), bucketName);
}
}

View File

@ -1,156 +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;
import static org.testng.Assert.assertEquals;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.internal.BaseS3Map;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
public abstract class BaseS3MapTest<T> extends S3IntegrationTest {
public abstract void testPutAll();
public abstract void testEntrySet() throws IOException;
public abstract void testValues() throws IOException;
protected BaseS3Map<T> map;
protected Map<String, String> fiveStrings = ImmutableMap.of("one", "apple",
"two", "bear", "three", "candy", "four", "dogma", "five", "emma");
protected Map<String, byte[]> fiveBytes = ImmutableMap.of("one", "apple"
.getBytes(), "two", "bear".getBytes(), "three", "candy".getBytes(),
"four", "dogma".getBytes(), "five", "emma".getBytes());
protected Map<String, InputStream> fiveInputs;
protected Map<String, File> fiveFiles;
String tmpDirectory;
private String bucket;
@BeforeMethod
@Parameters( { "basedir" })
protected void setUpTempDir(String basedir) throws InterruptedException,
ExecutionException, FileNotFoundException, IOException,
TimeoutException {
tmpDirectory = basedir + File.separator + "target" + File.separator
+ "testFiles" + File.separator + getClass().getSimpleName();
new File(tmpDirectory).mkdirs();
fiveFiles = ImmutableMap.of("one", new File(tmpDirectory, "apple"),
"two", new File(tmpDirectory, "bear"), "three", new File(
tmpDirectory, "candy"), "four", new File(tmpDirectory,
"dogma"), "five", new File(tmpDirectory, "emma"));
for (File file : fiveFiles.values()) {
IOUtils.write(file.getName(), new FileOutputStream(file));
}
fiveInputs = ImmutableMap.of("one", IOUtils.toInputStream("apple"),
"two", IOUtils.toInputStream("bear"), "three", IOUtils
.toInputStream("candy"), "four", IOUtils
.toInputStream("dogma"), "five", IOUtils
.toInputStream("emma"));
bucket = (bucketPrefix + ".mimi").toLowerCase();
client.putBucketIfNotExists(bucket).get(10, TimeUnit.SECONDS);
map = createMap(context, bucket);
map.clear();
}
protected abstract BaseS3Map<T> createMap(S3Context context, String bucket);
@AfterMethod
public void tearDown() {
map.clear();
map = null;
}
@Test
public void testClear() {
map.clear();
assertEquals(map.size(), 0);
putString("one", "apple");
assertEquals(map.size(), 1);
map.clear();
assertEquals(map.size(), 0);
}
@Test()
public abstract void testRemove() throws IOException;
@Test()
public void testKeySet() {
assertEquals(map.keySet().size(), 0);
putString("one", "two");
assertEquals(map.keySet(), ImmutableSet.of("one"));
}
@Test()
public void testContainsKey() {
assert !map.containsKey("one");
putString("one", "apple");
assert map.containsKey("one");
}
@Test()
public void testIsEmpty() {
assert map.isEmpty();
putString("one", "apple");
assert !map.isEmpty();
}
abstract protected void putString(String key, String value);
protected void fourLeftRemovingOne() {
map.remove("one");
assertEquals(map.size(), 4);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
ImmutableSet.of("two", "three", "four", "five")));
}
@Test
public abstract void testPut() throws IOException;
@Test()
public void testGetBucket() {
assertEquals(map.getBucket().getName(), bucket);
}
}

View File

@ -0,0 +1,94 @@
/**
*
* 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;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.util.S3Utils;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Tests connection by listing all the buckets and their size
*
* @author Adrian Cole
*/
@Test(testName = "s3.S3ConnectionIntegrationTest")
public class S3ConnectionIntegrationTest extends S3IntegrationTest {
@Test(groups = {"integration"})
void testListBuckets() throws Exception {
List<S3Bucket.Metadata> myBuckets = client.listOwnedBuckets().get(10,
TimeUnit.SECONDS);
for (S3Bucket.Metadata bucket : myBuckets) {
context.createInputStreamMap(bucket.getName()).size();
}
}
private static final String sysHttpStreamUrl = System
.getProperty("jclouds.s3.httpstream.url");
private static final String sysHttpStreamMd5 = System
.getProperty("jclouds.s3.httpstream.md5");
@Test(groups = {"integration"})
@Parameters({"jclouds.s3.httpstream.url", "jclouds.s3.httpstream.md5"})
public void testCopyUrl(@Optional String httpStreamUrl,
@Optional String httpStreamMd5) throws Exception {
httpStreamUrl = checkNotNull(httpStreamUrl != null ? httpStreamUrl
: sysHttpStreamUrl, "httpStreamUrl");
httpStreamMd5 = checkNotNull(httpStreamMd5 != null ? httpStreamMd5
: sysHttpStreamMd5, "httpStreamMd5");
String bucketName = bucketPrefix + "tcu";
createBucketAndEnsureEmpty(bucketName);
String key = "hello";
URL url = new URL(httpStreamUrl);
byte[] md5 = S3Utils
.fromHexString(httpStreamMd5);
URLConnection connection = url.openConnection();
int length = connection.getContentLength();
InputStream input = connection.getInputStream();
S3Object object = new S3Object(key, input);
object.setContentLength(length);
object.getMetadata().setMd5(md5);
object.getMetadata().setSize(length);
byte[] newMd5 = client.putObject(bucketName, object).get(30,
TimeUnit.SECONDS);
assertEquals(newMd5, md5);
}
}

View File

@ -1,50 +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;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.testng.annotations.Test;
/**
* Tests connection by listing all the buckets and their size
*
* @author Adrian Cole
*
*/
@Test(groups = "unit", testName = "s3.S3ConnectionTest")
public class S3ConnectionTest extends S3IntegrationTest {
@Test
void testListBuckets() throws Exception {
List<S3Bucket.Metadata> myBuckets = client.listOwnedBuckets().get(10,
TimeUnit.SECONDS);
for (S3Bucket.Metadata bucket : myBuckets) {
context.createInputStreamMap(bucket.getName()).size();
}
}
}

View File

@ -23,79 +23,89 @@
*/ */
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import static org.testng.Assert.assertEquals; import com.google.inject.AbstractModule;
import com.google.inject.Module;
import java.util.ArrayList; import org.jclouds.aws.s3.config.LiveS3ConnectionModule;
import java.util.List;
import org.jclouds.http.config.HttpFutureCommandClientModule; import org.jclouds.http.config.HttpFutureCommandClientModule;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule; import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.jclouds.logging.config.LoggingModule; import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.config.NullLoggingModule; import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule; import org.jclouds.logging.jdk.config.JDKLoggingModule;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.inject.AbstractModule; import java.util.ArrayList;
import com.google.inject.Module; import java.util.List;
/** /**
* Tests behavior of modules configured in S3ContextFactory * Tests behavior of modules configured in S3ContextFactory
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "unit", testName = "s3.S3ContextFactoryTest")
public class S3ContextFactoryTest { public class S3ContextFactoryTest {
@HttpFutureCommandClientModule @HttpFutureCommandClientModule
static class HttpModule extends AbstractModule { static class HttpModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
} }
} }
@Test @Test
public void testAddHttpModuleIfNotPresent() { public void testAddHttpModuleIfNotPresent() {
List<Module> modules = new ArrayList<Module>(); List<Module> modules = new ArrayList<Module>();
HttpModule module = new HttpModule(); HttpModule module = new HttpModule();
modules.add(module); modules.add(module);
S3ContextFactory.addHttpModuleIfNotPresent(modules); S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules);
assertEquals(modules.size(), 1); assertEquals(modules.size(), 1);
assertEquals(modules.remove(0), module); assertEquals(modules.remove(0), module);
} }
@Test @Test
public void testAddLoggingModuleIfNotPresent() { public void testAddLoggingModuleIfNotPresent() {
List<Module> modules = new ArrayList<Module>(); List<Module> modules = new ArrayList<Module>();
LoggingModule module = new NullLoggingModule(); LoggingModule module = new NullLoggingModule();
modules.add(module); modules.add(module);
S3ContextFactory.addLoggingModuleIfNotPresent(modules); S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 1); assertEquals(modules.size(), 1);
assertEquals(modules.remove(0), module); assertEquals(modules.remove(0), module);
} }
@Test @Test
public void testAddNone() { public void testAddNone() {
List<Module> modules = new ArrayList<Module>(); List<Module> modules = new ArrayList<Module>();
LoggingModule loggingModule = new NullLoggingModule(); LoggingModule loggingModule = new NullLoggingModule();
modules.add(loggingModule); modules.add(loggingModule);
HttpModule httpModule = new HttpModule(); HttpModule httpModule = new HttpModule();
modules.add(httpModule); modules.add(httpModule);
S3ContextFactory.addHttpModuleIfNotPresent(modules); S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules);
S3ContextFactory.addLoggingModuleIfNotPresent(modules); S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 2); assertEquals(modules.size(), 2);
assertEquals(modules.remove(0), loggingModule); assertEquals(modules.remove(0), loggingModule);
assertEquals(modules.remove(0), httpModule); assertEquals(modules.remove(0), httpModule);
} }
@Test @Test
public void testAddBoth() { public void testAddBothWhenNotLive() {
List<Module> modules = new ArrayList<Module>(); List<Module> modules = new ArrayList<Module>();
S3ContextFactory.addHttpModuleIfNotPresent(modules); S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules);
S3ContextFactory.addLoggingModuleIfNotPresent(modules); S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 2); assertEquals(modules.size(), 1);
assert modules.remove(0) instanceof JavaUrlHttpFutureCommandClientModule; assert modules.remove(0) instanceof JDKLoggingModule;
assert modules.remove(0) instanceof JDKLoggingModule; }
@Test
public void testAddBothWhenLive() {
List<Module> modules = new ArrayList<Module>();
modules.add(new LiveS3ConnectionModule());
S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules);
S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 3);
assert modules.remove(0) instanceof LiveS3ConnectionModule;
assert modules.remove(0) instanceof JavaUrlHttpFutureCommandClientModule;
assert modules.remove(0) instanceof JDKLoggingModule;
} }
} }

View File

@ -0,0 +1,210 @@
/**
*
* 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;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.internal.BaseS3Map;
import org.jclouds.util.Utils;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
/**
* Tests to cover @{link LiveS3ObjectMap}
*
* @author Adrian Cole
*/
@Test(testName = "s3.S3InputStreamMapIntegrationTest")
public class S3InputStreamMapIntegrationTest extends BaseS3MapIntegrationTest<InputStream> {
S3InputStreamMap map = null;
@SuppressWarnings("unchecked")
protected BaseS3Map<InputStream> createMap(S3Context context, String bucket) {
map = context.createInputStreamMap(bucket);
return (BaseS3Map<InputStream>) map;
}
@Override
@Test(groups = {"integration", "live"})
public void testValues() throws IOException {
map.putAll(this.fiveInputs);
Collection<InputStream> values = map.values();
assertEquals(values.size(), 5);
Set<String> valuesAsString = new HashSet<String>();
for (InputStream stream : values) {
valuesAsString.add(Utils.toStringAndClose(stream));
}
valuesAsString.removeAll(fiveStrings.values());
assert valuesAsString.size() == 0;
}
@Test(groups = {"integration", "live"})
public void testRemove() throws IOException {
putString("one", "two");
InputStream old = map.remove("one");
assertEquals(Utils.toStringAndClose(old), "two");
old = map.remove("one");
assert old == null;
old = map.get("one");
assert old == null;
assertEquals(map.keySet().size(), 0);
}
@Override
@Test(groups = {"integration", "live"})
public void testEntrySet() throws IOException {
map.putAllStrings(this.fiveStrings);
Set<Entry<String, InputStream>> entries = map.entrySet();
assertEquals(entries.size(), 5);
for (Entry<String, InputStream> entry : entries) {
assertEquals(IOUtils.toString(entry.getValue()), fiveStrings
.get(entry.getKey()));
entry.setValue(IOUtils.toInputStream(""));
}
assertEquals(map.size(), 5);
for (InputStream value : map.values()) {
assertEquals(IOUtils.toString(value), "");
}
}
@Test(groups = {"integration", "live"})
public void testContainsStringValue() {
map.putString("one", "apple");
assert map.containsValue(fiveStrings.get("one"));
}
@Test(groups = {"integration", "live"})
public void testContainsFileValue() {
map.putString("one", "apple");
assert map.containsValue(fiveFiles.get("one"));
}
@Test(groups = {"integration", "live"})
public void testContainsInputStreamValue() {
map.putString("one", "apple");
assert map.containsValue(this.fiveInputs.get("one"));
}
@Test(groups = {"integration", "live"})
public void testContainsBytesValue() {
map.putString("one", "apple");
assert map.containsValue(this.fiveBytes.get("one"));
}
@Override
@Test(groups = {"integration", "live"})
public void testPutAll() {
map.putAll(this.fiveInputs);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveInputs.keySet()));
fourLeftRemovingOne();
}
@Test(groups = {"integration", "live"})
public void testPutAllBytes() {
map.putAllBytes(this.fiveBytes);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveBytes.keySet()));
fourLeftRemovingOne();
}
@Test(groups = {"integration", "live"})
public void testPutAllFiles() {
map.putAllFiles(this.fiveFiles);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveFiles.keySet()));
fourLeftRemovingOne();
}
@Test(groups = {"integration", "live"})
public void testPutAllStrings() {
map.putAllStrings(this.fiveStrings);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveStrings.keySet()));
fourLeftRemovingOne();
}
@Test(groups = {"integration", "live"})
public void testPutString() throws IOException {
InputStream old = map.putString("one", "apple");
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.putString("one", "bear");
getOneReturnsBearAndOldValueIsApple(apple);
}
void getOneReturnsAppleAndOldValueIsNull(InputStream old)
throws IOException {
assert old == null;
assertEquals(Utils.toStringAndClose(map.get("one")), "apple");
assertEquals(map.size(), 1);
}
void getOneReturnsBearAndOldValueIsApple(InputStream oldValue)
throws IOException {
assertEquals(Utils.toStringAndClose(map.get("one")), "bear");
assertEquals(Utils.toStringAndClose(oldValue), "apple");
assertEquals(map.size(), 1);
}
@Test(groups = {"integration", "live"})
public void testPutFile() throws IOException {
InputStream old = map.putFile("one", fiveFiles.get("one"));
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.putFile("one", fiveFiles.get("two"));
getOneReturnsBearAndOldValueIsApple(apple);
}
@Test(groups = {"integration", "live"})
public void testPutBytes() throws IOException {
InputStream old = map.putBytes("one", "apple".getBytes());
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.putBytes("one", "bear".getBytes());
getOneReturnsBearAndOldValueIsApple(apple);
}
@Test(groups = {"integration", "live"})
public void testPut() throws IOException {
InputStream old = map.put("one", IOUtils.toInputStream("apple"));
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.put("one", IOUtils.toInputStream("bear"));
getOneReturnsBearAndOldValueIsApple(apple);
}
@Override
protected void putString(String key, String value) {
map.putString(key, value);
}
}

View File

@ -1,211 +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;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.Map.Entry;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.internal.BaseS3Map;
import org.jclouds.util.Utils;
import org.testng.annotations.Test;
/**
* Tests to cover @{link LiveS3ObjectMap}
*
* @author Adrian Cole
*/
@Test(groups = "unit", sequential = true, testName = "s3.S3InputStreamMapTest")
public class S3InputStreamMapTest extends BaseS3MapTest<InputStream> {
S3InputStreamMap map = null;
@SuppressWarnings("unchecked")
protected BaseS3Map<InputStream> createMap(S3Context context, String bucket) {
map = context.createInputStreamMap(bucket);
return (BaseS3Map<InputStream>) map;
}
@Override
@Test()
public void testValues() throws IOException {
map.putAll(this.fiveInputs);
Collection<InputStream> values = map.values();
assertEquals(values.size(), 5);
Set<String> valuesAsString = new HashSet<String>();
for (InputStream stream : values) {
valuesAsString.add(Utils.toStringAndClose(stream));
}
valuesAsString.removeAll(fiveStrings.values());
assert valuesAsString.size() == 0;
}
@Test()
public void testRemove() throws IOException {
putString("one", "two");
InputStream old = map.remove("one");
assertEquals(Utils.toStringAndClose(old), "two");
old = map.remove("one");
assert old == null;
old = map.get("one");
assert old == null;
assertEquals(map.keySet().size(), 0);
}
@Override
@Test()
public void testEntrySet() throws IOException {
map.putAllStrings(this.fiveStrings);
Set<Entry<String, InputStream>> entries = map.entrySet();
assertEquals(entries.size(), 5);
for (Entry<String, InputStream> entry : entries) {
assertEquals(IOUtils.toString(entry.getValue()), fiveStrings
.get(entry.getKey()));
entry.setValue(IOUtils.toInputStream(""));
}
assertEquals(map.size(), 5);
for (InputStream value : map.values()) {
assertEquals(IOUtils.toString(value), "");
}
}
@Test()
public void testContainsStringValue() {
map.putString("one", "apple");
assert map.containsValue(fiveStrings.get("one"));
}
@Test()
public void testContainsFileValue() {
map.putString("one", "apple");
assert map.containsValue(fiveFiles.get("one"));
}
@Test()
public void testContainsInputStreamValue() {
map.putString("one", "apple");
assert map.containsValue(this.fiveInputs.get("one"));
}
@Test()
public void testContainsBytesValue() {
map.putString("one", "apple");
assert map.containsValue(this.fiveBytes.get("one"));
}
@Override
@Test()
public void testPutAll() {
map.putAll(this.fiveInputs);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveInputs.keySet()));
fourLeftRemovingOne();
}
@Test()
public void testPutAllBytes() {
map.putAllBytes(this.fiveBytes);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveBytes.keySet()));
fourLeftRemovingOne();
}
@Test
public void testPutAllFiles() {
map.putAllFiles(this.fiveFiles);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveFiles.keySet()));
fourLeftRemovingOne();
}
@Test()
public void testPutAllStrings() {
map.putAllStrings(this.fiveStrings);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveStrings.keySet()));
fourLeftRemovingOne();
}
@Test()
public void testPutString() throws IOException {
InputStream old = map.putString("one", "apple");
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.putString("one", "bear");
getOneReturnsBearAndOldValueIsApple(apple);
}
void getOneReturnsAppleAndOldValueIsNull(InputStream old)
throws IOException {
assert old == null;
assertEquals(Utils.toStringAndClose(map.get("one")), "apple");
assertEquals(map.size(), 1);
}
void getOneReturnsBearAndOldValueIsApple(InputStream oldValue)
throws IOException {
assertEquals(Utils.toStringAndClose(map.get("one")), "bear");
assertEquals(Utils.toStringAndClose(oldValue), "apple");
assertEquals(map.size(), 1);
}
@Test()
public void testPutFile() throws IOException {
InputStream old = map.putFile("one", fiveFiles.get("one"));
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.putFile("one", fiveFiles.get("two"));
getOneReturnsBearAndOldValueIsApple(apple);
}
@Test()
public void testPutBytes() throws IOException {
InputStream old = map.putBytes("one", "apple".getBytes());
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.putBytes("one", "bear".getBytes());
getOneReturnsBearAndOldValueIsApple(apple);
}
@Test()
public void testPut() throws IOException {
InputStream old = map.put("one", IOUtils.toInputStream("apple"));
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.put("one", IOUtils.toInputStream("bear"));
getOneReturnsBearAndOldValueIsApple(apple);
}
@Override
protected void putString(String key, String value) {
map.putString(key, value);
}
}

View File

@ -24,196 +24,215 @@
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals; import com.google.inject.Module;
import org.jclouds.aws.s3.config.StubS3ConnectionModule;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpConstants; import org.jclouds.http.HttpConstants;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule; import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.testng.annotations.AfterTest; import static org.testng.Assert.assertEquals;
import org.testng.annotations.BeforeTest; import org.testng.ITestContext;
import org.testng.annotations.Optional; import org.testng.annotations.*;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import com.google.inject.Module; import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.*;
import java.util.logging.Formatter;
@Test
public class S3IntegrationTest { public class S3IntegrationTest {
protected static final String TEST_STRING = "<apples><apple name=\"fuji\"></apple> </apples>"; protected static final String TEST_STRING = "<apples><apple name=\"fuji\"></apple> </apples>";
protected byte[] goodMd5; protected byte[] goodMd5;
protected byte[] badMd5; protected byte[] badMd5;
protected String bucketName;
protected void createBucketAndEnsureEmpty(String sourceBucket) protected void createBucketAndEnsureEmpty(String sourceBucket)
throws InterruptedException, ExecutionException, TimeoutException { throws InterruptedException, ExecutionException, TimeoutException {
client.putBucketIfNotExists(sourceBucket).get(10, TimeUnit.SECONDS); client.putBucketIfNotExists(sourceBucket).get(10, TimeUnit.SECONDS);
assertEquals(client.listBucket(sourceBucket).get(10, TimeUnit.SECONDS) assertEquals(client.listBucket(sourceBucket).get(10, TimeUnit.SECONDS)
.getContents().size(), 0); .getContents().size(), 0);
} }
protected void addObjectToBucket(String sourceBucket, String key) protected void addObjectToBucket(String sourceBucket, String key)
throws InterruptedException, ExecutionException, TimeoutException, throws InterruptedException, ExecutionException, TimeoutException,
IOException { IOException {
S3Object sourceObject = new S3Object(key); S3Object sourceObject = new S3Object(key);
sourceObject.getMetadata().setContentType("text/xml"); sourceObject.getMetadata().setContentType("text/xml");
sourceObject.setData(TEST_STRING); sourceObject.setData(TEST_STRING);
addObjectToBucket(sourceBucket, sourceObject); addObjectToBucket(sourceBucket, sourceObject);
} }
protected void addObjectToBucket(String sourceBucket, S3Object object) protected void addObjectToBucket(String sourceBucket, S3Object object)
throws InterruptedException, ExecutionException, TimeoutException, throws InterruptedException, ExecutionException, TimeoutException,
IOException { IOException {
; client.putObject(sourceBucket, object).get(10, TimeUnit.SECONDS);
client.putObject(sourceBucket, object).get(10, TimeUnit.SECONDS);
} }
protected S3Object validateContent(String sourceBucket, String key) protected S3Object validateContent(String sourceBucket, String key)
throws InterruptedException, ExecutionException, TimeoutException, throws InterruptedException, ExecutionException, TimeoutException,
IOException { IOException {
assertEquals(client.listBucket(sourceBucket).get(10, TimeUnit.SECONDS) assertEquals(client.listBucket(sourceBucket).get(10, TimeUnit.SECONDS)
.getContents().size(), 1); .getContents().size(), 1);
S3Object newObject = client.getObject(sourceBucket, key).get(10, S3Object newObject = client.getObject(sourceBucket, key).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
assert newObject != S3Object.NOT_FOUND; assert newObject != S3Object.NOT_FOUND;
assertEquals(S3Utils.getContentAsStringAndClose(newObject), TEST_STRING); assertEquals(S3Utils.getContentAsStringAndClose(newObject), TEST_STRING);
return newObject; return newObject;
} }
@BeforeTest @BeforeClass(groups = {"integration", "live"})
void enableDebug() { void enableDebug() {
if (debugEnabled()) { if (debugEnabled()) {
Handler HANDLER = new ConsoleHandler() { Handler HANDLER = new ConsoleHandler() {
{ {
setLevel(Level.ALL); setLevel(Level.ALL);
setFormatter(new Formatter() { setFormatter(new Formatter() {
@Override @Override
public String format(LogRecord record) { public String format(LogRecord record) {
return String.format( return String.format(
"[%tT %-7s] [%-7s] [%s]: %s %s\n", "[%tT %-7s] [%-7s] [%s]: %s %s\n",
new Date(record.getMillis()), record new Date(record.getMillis()), record
.getLevel(), Thread.currentThread() .getLevel(), Thread.currentThread()
.getName(), record.getLoggerName(), .getName(), record.getLoggerName(),
record.getMessage(), record.getMessage(),
record.getThrown() == null ? "" : record record.getThrown() == null ? "" : record
.getThrown()); .getThrown());
} }
}); });
} }
}; };
Logger guiceLogger = Logger.getLogger("org.jclouds"); Logger guiceLogger = Logger.getLogger("org.jclouds");
guiceLogger.addHandler(HANDLER); guiceLogger.addHandler(HANDLER);
guiceLogger.setLevel(Level.ALL); guiceLogger.setLevel(Level.ALL);
} }
} }
protected S3Connection client; protected S3Connection client;
protected S3Context context = null; protected S3Context context = null;
protected String bucketPrefix = (System.getProperty("user.name") + "." + this protected String bucketPrefix = (System.getProperty("user.name") + "." + this
.getClass().getSimpleName()).toLowerCase(); .getClass().getSimpleName()).toLowerCase();
private static final String sysAWSAccessKeyId = System private static final String sysAWSAccessKeyId = System
.getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID); .getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID);
private static final String sysAWSSecretAccessKey = System private static final String sysAWSSecretAccessKey = System
.getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY); .getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
@BeforeTest @BeforeClass(inheritGroups = false, groups = {"integration", "live"})
@Parameters( { S3Constants.PROPERTY_AWS_ACCESSKEYID, @Parameters({S3Constants.PROPERTY_AWS_ACCESSKEYID,
S3Constants.PROPERTY_AWS_SECRETACCESSKEY }) S3Constants.PROPERTY_AWS_SECRETACCESSKEY})
protected void setUpClient(@Optional String AWSAccessKeyId, protected void setUpCredentials(@Optional String AWSAccessKeyId,
@Optional String AWSSecretAccessKey) throws Exception { @Optional String AWSSecretAccessKey, ITestContext testContext) throws Exception {
context = createS3Context(AWSAccessKeyId != null ? AWSAccessKeyId AWSAccessKeyId = AWSAccessKeyId != null ? AWSAccessKeyId
: sysAWSAccessKeyId, : sysAWSAccessKeyId;
AWSSecretAccessKey != null ? AWSSecretAccessKey AWSSecretAccessKey = AWSSecretAccessKey != null ? AWSSecretAccessKey
: sysAWSSecretAccessKey); : sysAWSSecretAccessKey;
client = context.getConnection(); if (AWSAccessKeyId != null)
deleteEverything(); testContext.setAttribute(S3Constants.PROPERTY_AWS_ACCESSKEYID, AWSAccessKeyId);
goodMd5 = S3Utils.md5(TEST_STRING); if (AWSSecretAccessKey != null)
badMd5 = S3Utils.md5("alf"); testContext.setAttribute(S3Constants.PROPERTY_AWS_SECRETACCESSKEY, AWSSecretAccessKey);
}
@BeforeClass(dependsOnMethods = {"setUpCredentials"}, groups = {"integration", "live"})
protected void setUpClient(ITestContext testContext) throws Exception {
if (testContext.getAttribute(S3Constants.PROPERTY_AWS_ACCESSKEYID) != null) {
String AWSAccessKeyId = (String) testContext.getAttribute(S3Constants.PROPERTY_AWS_ACCESSKEYID);
String AWSSecretAccessKey = (String) testContext.getAttribute(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
context = S3ContextFactory.createS3Context(buildS3Properties(
checkNotNull(AWSAccessKeyId, "AWSAccessKeyId"),
checkNotNull(AWSSecretAccessKey, "AWSSecretAccessKey")),
createHttpModule());
} else {
Properties props = new Properties();
props.setProperty(S3Constants.PROPERTY_HTTP_ADDRESS, "stub");
context = S3ContextFactory.createS3Context(props, new StubS3ConnectionModule());
}
client = context.getConnection();
assert client != null;
deleteEverything();
goodMd5 = S3Utils.md5(TEST_STRING);
badMd5 = S3Utils.md5("alf");
}
@BeforeMethod(dependsOnMethods = "deleteBucket", groups = {"integration", "live"})
public void setUpBucket(Method method) throws TimeoutException, ExecutionException, InterruptedException {
bucketName = (bucketPrefix + method.getName()).toLowerCase();
createBucketAndEnsureEmpty(bucketName);
}
@BeforeMethod(groups = {"integration", "live"})
@AfterMethod(groups = {"integration", "live"})
public void deleteBucket() throws TimeoutException, ExecutionException, InterruptedException {
if (bucketName != null)
deleteBucket(bucketName);
} }
protected boolean debugEnabled() { protected boolean debugEnabled() {
return false; return false;
}
protected S3Context createS3Context(String AWSAccessKeyId,
String AWSSecretAccessKey) {
return S3ContextFactory.createS3Context(buildS3Properties(
AWSAccessKeyId, AWSSecretAccessKey), createHttpModule());
} }
protected Properties buildS3Properties(String AWSAccessKeyId, protected Properties buildS3Properties(String AWSAccessKeyId,
String AWSSecretAccessKey) { String AWSSecretAccessKey) {
Properties properties = new Properties( Properties properties = new Properties(
S3ContextFactory.DEFAULT_PROPERTIES); S3ContextFactory.DEFAULT_PROPERTIES);
properties.setProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID, properties.setProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID,
checkNotNull(AWSAccessKeyId, "AWSAccessKeyId")); checkNotNull(AWSAccessKeyId, "AWSAccessKeyId"));
properties.setProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY, properties.setProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY,
checkNotNull(AWSSecretAccessKey, "AWSSecretAccessKey")); checkNotNull(AWSSecretAccessKey, "AWSSecretAccessKey"));
properties.setProperty(HttpConstants.PROPERTY_HTTP_SECURE, "false"); properties.setProperty(HttpConstants.PROPERTY_HTTP_SECURE, "false");
properties.setProperty(HttpConstants.PROPERTY_HTTP_PORT, "80"); properties.setProperty(HttpConstants.PROPERTY_HTTP_PORT, "80");
return properties; return properties;
} }
protected Module createHttpModule() { protected Module createHttpModule() {
return new JavaUrlHttpFutureCommandClientModule(); return new JavaUrlHttpFutureCommandClientModule();
} }
protected void deleteEverything() throws Exception { protected void deleteEverything() throws Exception {
try { try {
List<S3Bucket.Metadata> metadata = client.listOwnedBuckets().get( List<S3Bucket.Metadata> metadata = client.listOwnedBuckets().get(
10, TimeUnit.SECONDS); 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())) {
if (metaDatum.getName().startsWith(bucketPrefix.toLowerCase())) { deleteBucket(metaDatum.getName());
S3Bucket bucket = client.listBucket(metaDatum.getName()) }
.get(10, TimeUnit.SECONDS);
for (S3Object.Metadata objectMeta : bucket.getContents()) {
results.add(client.deleteObject(metaDatum.getName(),
objectMeta.getKey()));
}
Iterator<Future<Boolean>> iterator = results.iterator();
while (iterator.hasNext()) {
iterator.next().get(10, TimeUnit.SECONDS);
iterator.remove();
}
client.deleteBucketIfEmpty(metaDatum.getName()).get(10,
TimeUnit.SECONDS);
}
} }
} catch (CancellationException e) { } catch (CancellationException e) {
throw e; throw e;
} }
} }
@AfterTest private void deleteBucket(String name) throws InterruptedException, ExecutionException, TimeoutException {
if (client.bucketExists(name).get(10, TimeUnit.SECONDS)) {
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
S3Bucket bucket = client.listBucket(name)
.get(10, TimeUnit.SECONDS);
for (S3Object.Metadata objectMeta : bucket.getContents()) {
results.add(client.deleteObject(name,
objectMeta.getKey()));
}
Iterator<Future<Boolean>> iterator = results.iterator();
while (iterator.hasNext()) {
iterator.next().get(10, TimeUnit.SECONDS);
iterator.remove();
}
client.deleteBucketIfEmpty(name).get(10,
TimeUnit.SECONDS);
}
}
@AfterClass
protected void tearDownClient() throws Exception { protected void tearDownClient() throws Exception {
deleteEverything(); deleteEverything();
context.close(); context.close();
context = null; context = null;
} }
} }

View File

@ -0,0 +1,166 @@
/**
*
* 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;
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 static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
/**
* Tests to cover @{link LiveS3ObjectMap}
*
* @author Adrian Cole
*/
@Test(testName = "s3.S3ObjectMapIntegrationTest")
public class S3ObjectMapIntegrationTest extends BaseS3MapIntegrationTest<S3Object> {
S3ObjectMap map = null;
@SuppressWarnings("unchecked")
protected BaseS3Map<S3Object> createMap(S3Context context, String bucket) {
map = context.createS3ObjectMap(bucket);
return (BaseS3Map<S3Object>) map;
}
@Override
@Test(groups = {"integration", "live"})
public void testValues() throws IOException {
putFiveStrings();
Collection<S3Object> values = map.values();
assertEquals(values.size(), 5);
Set<String> valuesAsString = new HashSet<String>();
for (S3Object object : values) {
valuesAsString.add(S3Utils.getContentAsStringAndClose(object));
}
valuesAsString.removeAll(fiveStrings.values());
assert valuesAsString.size() == 0;
}
@Test(groups = {"integration", "live"})
public void testRemove() throws IOException {
putString("one", "two");
S3Object old = map.remove("one");
assertEquals(S3Utils.getContentAsStringAndClose(old), "two");
old = map.remove("one");
assert old == S3Object.NOT_FOUND;
old = map.get("one");
assert old == S3Object.NOT_FOUND;
assertEquals(map.keySet().size(), 0);
}
@Override
@Test(groups = {"integration", "live"})
public void testEntrySet() throws IOException {
putFiveStrings();
Set<Entry<String, S3Object>> entries = map.entrySet();
assertEquals(entries.size(), 5);
for (Entry<String, S3Object> entry : entries) {
assertEquals(S3Utils.getContentAsStringAndClose(entry.getValue()),
fiveStrings.get(entry.getKey()));
S3Object value = entry.getValue();
value.setData("");
value.generateMd5();
entry.setValue(value);
}
assertEquals(map.size(), 5);
for (S3Object value : map.values()) {
assertEquals(S3Utils.getContentAsStringAndClose(value), "");
}
}
@Test(groups = {"integration", "live"})
public void testContains() {
putString("one", "apple");
S3Object object = new S3Object("one");
object.setData("apple");
assert map.containsValue(object);
}
void getOneReturnsAppleAndOldValueIsNull(S3Object old) throws IOException {
assert old == S3Object.NOT_FOUND;
assertEquals(S3Utils.getContentAsStringAndClose(map.get("one")),
"apple");
assert map.size() == 1;
}
void getOneReturnsBearAndOldValueIsApple(S3Object oldValue)
throws IOException {
assertEquals(S3Utils.getContentAsStringAndClose(map.get("one")), "bear");
assertEquals(S3Utils.getContentAsStringAndClose(oldValue), "apple");
assert map.size() == 1;
}
@Test(groups = {"integration", "live"})
public void testPut() throws IOException {
S3Object object = new S3Object("one");
object.setData(IOUtils.toInputStream("apple"));
object.generateMd5();
S3Object old = map.put(object.getKey(), object);
getOneReturnsAppleAndOldValueIsNull(old);
object.setData(IOUtils.toInputStream("bear"));
object.generateMd5();
S3Object apple = map.put(object.getKey(), object);
getOneReturnsBearAndOldValueIsApple(apple);
}
@Test(groups = {"integration", "live"})
public void testPutAll() {
Map<String, S3Object> newMap = new HashMap<String, S3Object>();
for (String key : fiveInputs.keySet()) {
S3Object object = new S3Object(key);
object.setData(fiveInputs.get(key));
object.getMetadata().setSize(fiveBytes.get(key).length);
newMap.put(key, object);
}
map.putAll(newMap);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveInputs.keySet()));
fourLeftRemovingOne();
}
@Override
protected void putString(String key, String value) {
S3Object object = new S3Object(key);
object.setData(value);
map.put(key, object);
}
protected void putFiveStrings() {
Map<String, S3Object> newMap = new HashMap<String, S3Object>();
for (Map.Entry<String, String> entry : fiveStrings.entrySet()) {
S3Object object = new S3Object(entry.getKey());
object.setData(entry.getValue());
newMap.put(entry.getKey(), object);
}
map.putAll(newMap);
}
}

View File

@ -1,172 +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;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
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;
/**
* Tests to cover @{link LiveS3ObjectMap}
*
* @author Adrian Cole
*/
@Test(groups = "unit", sequential = true, testName = "s3.S3ObjectMapTest")
public class S3ObjectMapTest extends BaseS3MapTest<S3Object> {
S3ObjectMap map = null;
@SuppressWarnings("unchecked")
protected BaseS3Map<S3Object> createMap(S3Context context, String bucket) {
map = context.createS3ObjectMap(bucket);
return (BaseS3Map<S3Object>) map;
}
@Override
@Test()
public void testValues() throws IOException {
putFiveStrings();
Collection<S3Object> values = map.values();
assertEquals(values.size(), 5);
Set<String> valuesAsString = new HashSet<String>();
for (S3Object object : values) {
valuesAsString.add(S3Utils.getContentAsStringAndClose(object));
}
valuesAsString.removeAll(fiveStrings.values());
assert valuesAsString.size() == 0;
}
@Test()
public void testRemove() throws IOException {
putString("one", "two");
S3Object old = map.remove("one");
assertEquals(S3Utils.getContentAsStringAndClose(old), "two");
old = map.remove("one");
assert old == S3Object.NOT_FOUND;
old = map.get("one");
assert old == S3Object.NOT_FOUND;
assertEquals(map.keySet().size(), 0);
}
@Override
@Test()
public void testEntrySet() throws IOException {
putFiveStrings();
Set<Entry<String, S3Object>> entries = map.entrySet();
assertEquals(entries.size(), 5);
for (Entry<String, S3Object> entry : entries) {
assertEquals(S3Utils.getContentAsStringAndClose(entry.getValue()),
fiveStrings.get(entry.getKey()));
S3Object value = entry.getValue();
value.setData("");
value.generateMd5();
entry.setValue(value);
}
assertEquals(map.size(), 5);
for (S3Object value : map.values()) {
assertEquals(S3Utils.getContentAsStringAndClose(value), "");
}
}
@Test()
public void testContains() {
putString("one", "apple");
S3Object object = new S3Object("one");
object.setData("apple");
assert map.containsValue(object);
}
void getOneReturnsAppleAndOldValueIsNull(S3Object old) throws IOException {
assert old == S3Object.NOT_FOUND;
assertEquals(S3Utils.getContentAsStringAndClose(map.get("one")),
"apple");
assert map.size() == 1;
}
void getOneReturnsBearAndOldValueIsApple(S3Object oldValue)
throws IOException {
assertEquals(S3Utils.getContentAsStringAndClose(map.get("one")), "bear");
assertEquals(S3Utils.getContentAsStringAndClose(oldValue), "apple");
assert map.size() == 1;
}
@Test
public void testPut() throws IOException {
S3Object object = new S3Object("one");
object.setData(IOUtils.toInputStream("apple"));
object.generateMd5();
S3Object old = map.put(object.getKey(), object);
getOneReturnsAppleAndOldValueIsNull(old);
object.setData(IOUtils.toInputStream("bear"));
object.generateMd5();
S3Object apple = map.put(object.getKey(), object);
getOneReturnsBearAndOldValueIsApple(apple);
}
@Test
public void testPutAll() {
Map<String, S3Object> newMap = new HashMap<String, S3Object>();
for (String key : fiveInputs.keySet()) {
S3Object object = new S3Object(key);
object.setData(fiveInputs.get(key));
object.getMetadata().setSize(fiveBytes.get(key).length);
newMap.put(key, object);
}
map.putAll(newMap);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveInputs.keySet()));
fourLeftRemovingOne();
}
@Override
protected void putString(String key, String value) {
S3Object object = new S3Object(key);
object.setData(value);
map.put(key, object);
}
protected void putFiveStrings() {
Map<String, S3Object> newMap = new HashMap<String, S3Object>();
for (Map.Entry<String, String> entry : fiveStrings.entrySet()) {
S3Object object = new S3Object(entry.getKey());
object.setData(entry.getValue());
newMap.put(entry.getKey(), object);
}
map.putAll(newMap);
}
}

View File

@ -26,6 +26,7 @@ package org.jclouds.aws.s3;
import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Base64;
import org.jclouds.aws.PerformanceTest; import org.jclouds.aws.PerformanceTest;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -38,90 +39,89 @@ import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorCompletionService;
import static org.testng.Assert.*;
/** /**
* This tests the performance of Digest commands. * This tests the performance of Digest commands.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", sequential = true, testName = "s3.PerformanceTest") @Test(groups = "performance", sequential = true, testName = "s3.PerformanceTest")
public class S3UtilsTest extends PerformanceTest { public class S3UtilsTest extends PerformanceTest {
@Test(dataProvider = "hmacsha1") @Test(dataProvider = "hmacsha1")
void testBouncyCastleDigestSerialResponseTime(byte[] key, String message, void testBouncyCastleDigestSerialResponseTime(byte[] key, String message,
String base64Digest) throws NoSuchProviderException, String base64Digest) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException { NoSuchAlgorithmException, InvalidKeyException {
for (int i = 0; i < 10000; i++) for (int i = 0; i < 10000; i++)
testBouncyCastleHmacSha1Base64(key, message, base64Digest); testBouncyCastleHmacSha1Base64(key, message, base64Digest);
} }
@Test(dataProvider = "hmacsha1") @Test(dataProvider = "hmacsha1")
void testBouncyCastleDigestParallelResponseTime(final byte[] key, void testBouncyCastleDigestParallelResponseTime(final byte[] key,
final String message, final String base64Digest) final String message, final String base64Digest)
throws NoSuchProviderException, NoSuchAlgorithmException, throws NoSuchProviderException, NoSuchAlgorithmException,
InvalidKeyException, InterruptedException, ExecutionException { InvalidKeyException, InterruptedException, ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>( CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
exec); exec);
for (int i = 0; i < 10000; i++) for (int i = 0; i < 10000; i++)
completer.submit(new Callable<Boolean>() { completer.submit(new Callable<Boolean>() {
public Boolean call() throws Exception { public Boolean call() throws Exception {
testBouncyCastleHmacSha1Base64(key, message, base64Digest); testBouncyCastleHmacSha1Base64(key, message, base64Digest);
return true; return true;
} }
}); });
for (int i = 0; i < 10000; i++) for (int i = 0; i < 10000; i++)
assert completer.take().get(); assert completer.take().get();
} }
@DataProvider(name = "md5") @DataProvider(name = "md5")
public Object[][] createMD5Data() { public Object[][] createMD5Data() {
return base64MD5MessageDigest; return base64MD5MessageDigest;
} }
public final static Object[][] base64MD5MessageDigest = { public final static Object[][] base64MD5MessageDigest = {
{ "apple", "1f3870be274f6c49b3e31a0c6728957f" }, {"apple", "1f3870be274f6c49b3e31a0c6728957f"},
{ "bear", "893b56e3cfe153fb770a120b83bac20c" }, {"bear", "893b56e3cfe153fb770a120b83bac20c"},
{ "candy", "c48ba993d35c3abe0380f91738fe2a34" }, {"candy", "c48ba993d35c3abe0380f91738fe2a34"},
{ "dogma", "95eb470e4faee302e9cd3063b1923dab" }, {"dogma", "95eb470e4faee302e9cd3063b1923dab"},
{ "emma", "00a809937eddc44521da9521269e75c6" } }; {"emma", "00a809937eddc44521da9521269e75c6"}};
public final static Object[][] base64KeyMessageDigest = { public final static Object[][] base64KeyMessageDigest = {
{ Base64.decode("CwsLCwsLCwsLCwsLCwsLCwsLCws="), "Hi There", {Base64.decode("CwsLCwsLCwsLCwsLCwsLCwsLCws="), "Hi There",
"thcxhlUFcmTii8C2+zeMjvFGvgA=" }, "thcxhlUFcmTii8C2+zeMjvFGvgA="},
{ Base64.decode("SmVmZQ=="), "what do ya want for nothing?", {Base64.decode("SmVmZQ=="), "what do ya want for nothing?",
"7/zfauXrL6LSdBbV8YTfnCWafHk=" }, "7/zfauXrL6LSdBbV8YTfnCWafHk="},
{ Base64.decode("DAwMDAwMDAwMDAwMDAwMDAwMDAw="), {Base64.decode("DAwMDAwMDAwMDAwMDAwMDAwMDAw="),
"Test With Truncation", "TBoDQktV4H/n8nvh1Yu5MkqaWgQ=" }, "Test With Truncation", "TBoDQktV4H/n8nvh1Yu5MkqaWgQ="},
{ {
Base64 Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="), .decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key - Hash Key First", "Test Using Larger Than Block-Size Key - Hash Key First",
"qkrl4VJy0A6VcFY3zoo7Ve1AIRI=" }, "qkrl4VJy0A6VcFY3zoo7Ve1AIRI="},
{ {
Base64 Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="), .decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
"6OmdD0UjfXhta7qnllx4CLv/GpE=" } }; "6OmdD0UjfXhta7qnllx4CLv/GpE="}};
@DataProvider(name = "hmacsha1") @DataProvider(name = "hmacsha1")
public Object[][] createData1() { public Object[][] createData1() {
return base64KeyMessageDigest; return base64KeyMessageDigest;
} }
@Test(dataProvider = "hmacsha1") @Test(dataProvider = "hmacsha1")
public void testBouncyCastleHmacSha1Base64(byte[] key, String message, public void testBouncyCastleHmacSha1Base64(byte[] key, String message,
String base64Digest) throws NoSuchProviderException, String base64Digest) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException { NoSuchAlgorithmException, InvalidKeyException {
String b64 = S3Utils.hmacSha1Base64(message, key); String b64 = S3Utils.hmacSha1Base64(message, key);
assertEquals(b64, base64Digest); assertEquals(b64, base64Digest);
} }
@Test(dataProvider = "md5") @Test(dataProvider = "md5")
public void testBouncyCastleMD5Digest(String message, public void testBouncyCastleMD5Digest(String message,
String base64Digest) throws NoSuchProviderException, String base64Digest) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException { NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
String b64 = S3Utils.md5Hex(message.getBytes()); String b64 = S3Utils.md5Hex(message.getBytes());
assertEquals(base64Digest,b64); assertEquals(base64Digest, b64);
} }
} }

View File

@ -28,20 +28,20 @@ import org.testng.annotations.Test;
import java.util.Properties; import java.util.Properties;
/** /**
* This performs the same test as {@link S3ConnectionTest}, except using SSL. * This performs the same test as {@link S3ConnectionIntegrationTest}, except using SSL.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "s3.SecureS3ConnectionTest") @Test(groups = {"live"}, testName = "s3.SecureS3ConnectionIntegrationTest")
public class SecureS3ConnectionTest extends S3ConnectionTest { public class SecureS3ConnectionIntegrationTest extends S3ConnectionIntegrationTest {
@Override @Override
protected Properties buildS3Properties(String AWSAccessKeyId, protected Properties buildS3Properties(String AWSAccessKeyId,
String AWSSecretAccessKey) { String AWSSecretAccessKey) {
Properties properties = super.buildS3Properties(AWSAccessKeyId, Properties properties = super.buildS3Properties(AWSAccessKeyId,
AWSSecretAccessKey); AWSSecretAccessKey);
properties.setProperty("jclouds.http.secure", Boolean.toString(true)); properties.setProperty("jclouds.http.secure", Boolean.toString(true));
properties.setProperty("jclouds.http.port", "443"); properties.setProperty("jclouds.http.port", "443");
return properties; return properties;
} }
} }

View File

@ -23,25 +23,32 @@
*/ */
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import java.util.ArrayList; import com.google.common.base.Function;
import java.util.HashSet; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List; import com.google.common.base.Predicate;
import java.util.Map; import com.google.common.collect.Iterables;
import java.util.Set; import com.google.common.collect.Lists;
import java.util.concurrent.ConcurrentHashMap; import com.google.common.collect.Sets;
import java.util.concurrent.ExecutionException; import com.thoughtworks.xstream.XStream;
import java.util.concurrent.Future; import org.apache.commons.io.IOUtils;
import java.util.concurrent.TimeUnit; import org.apache.commons.io.output.ByteArrayOutputStream;
import java.util.concurrent.TimeoutException; import static org.easymock.classextension.EasyMock.createNiceMock;
import org.jclouds.aws.s3.commands.CopyObject;
import org.jclouds.aws.s3.commands.options.CopyObjectOptions; import org.jclouds.aws.s3.commands.options.*;
import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.commands.options.ListBucketOptions;
import org.jclouds.aws.s3.commands.options.PutBucketOptions;
import org.jclouds.aws.s3.commands.options.PutObjectOptions;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata; import org.jclouds.aws.s3.domain.S3Bucket.Metadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.util.DateService;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.joda.time.DateTime;
import java.io.*;
import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.*;
/** /**
* // TODO: Adrian: Document this! * // TODO: Adrian: Document this!
@ -49,200 +56,426 @@ import org.jclouds.aws.s3.domain.S3Bucket.Metadata;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class StubS3Connection implements S3Connection { public class StubS3Connection implements S3Connection {
private static Map<String, Map<String, Object>> bucketToContents = new ConcurrentHashMap<String, Map<String, Object>>(); private static Map<String, Map<String, S3Object>> bucketToContents = new ConcurrentHashMap<String, Map<String, S3Object>>();
private static Map<String, Metadata.LocationConstraint> bucketToLocation = new ConcurrentHashMap<String, Metadata.LocationConstraint>();
private static Map<String, CannedAccessPolicy> keyToAcl = new ConcurrentHashMap<String, CannedAccessPolicy>();
/**
* @throws java.io.IOException
*/
public static byte[] toByteArray(Object data) throws IOException {
checkNotNull(data, "data must be set before calling generateMd5()");
byte[] bytes = null;
if (data == null || data instanceof byte[]) {
bytes = (byte[]) data;
} else if (data instanceof String) {
bytes = ((String) data).getBytes();
} else if (data instanceof File || data instanceof InputStream) {
InputStream io = (data instanceof InputStream) ? (InputStream) data : new FileInputStream((File) data);
bytes = IOUtils.toByteArray(io);
IOUtils.closeQuietly(io);
} else {
throw new UnsupportedOperationException("Content not supported "
+ data.getClass());
}
return bytes;
}
public Future<S3Object> getObject(final String s3Bucket, final String key) { public Future<S3Object> getObject(final String s3Bucket, final String key) {
return new FutureBase<S3Object>() { return getObject(s3Bucket, key, new GetObjectOptions());
public S3Object get() throws InterruptedException,
ExecutionException { }
if (!bucketToContents.containsKey(s3Bucket))
return S3Object.NOT_FOUND; public S3Object.Metadata copy(S3Object.Metadata in) {
Map<String, Object> realContents = bucketToContents return (S3Object.Metadata) xstream.fromXML(xstream.toXML(in));
.get(s3Bucket); }
if (!realContents.containsKey(key))
return S3Object.NOT_FOUND; public S3Object.Metadata copy(S3Object.Metadata in, String newKey) {
S3Object object = new S3Object(key); return (S3Object.Metadata) xstream.fromXML(xstream.toXML(in).replaceAll(in.getKey(), newKey));
object.setData(realContents.get(key));
return object;
}
};
} }
public Future<S3Object.Metadata> headObject(final String s3Bucket, public Future<S3Object.Metadata> headObject(final String s3Bucket,
final String key) { final String key) {
return new FutureBase<S3Object.Metadata>() { return new FutureBase<S3Object.Metadata>() {
public S3Object.Metadata get() throws InterruptedException, public S3Object.Metadata get() throws InterruptedException,
ExecutionException { ExecutionException {
if (!bucketToContents.containsKey(s3Bucket)) if (!bucketToContents.containsKey(s3Bucket))
return S3Object.Metadata.NOT_FOUND; return S3Object.Metadata.NOT_FOUND;
Map<String, Object> realContents = bucketToContents Map<String, S3Object> realContents = bucketToContents
.get(s3Bucket); .get(s3Bucket);
if (!realContents.containsKey(key)) if (!realContents.containsKey(key))
return S3Object.Metadata.NOT_FOUND; return S3Object.Metadata.NOT_FOUND;
S3Object.Metadata metadata = new S3Object.Metadata(key); return realContents.get(key).getMetadata();
return metadata; }
} };
};
} }
public Future<Boolean> deleteObject(final String s3Bucket, final String key) { public Future<Boolean> deleteObject(final String s3Bucket, final String key) {
return new FutureBase<Boolean>() { return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException, public Boolean get() throws InterruptedException,
ExecutionException { ExecutionException {
if (bucketToContents.containsKey(s3Bucket)) { if (bucketToContents.containsKey(s3Bucket)) {
bucketToContents.get(s3Bucket).remove(key); bucketToContents.get(s3Bucket).remove(key);
} }
return true; return true;
} }
}; };
} }
public Future<byte[]> putObject(final String s3Bucket, final S3Object object) { public Future<byte[]> putObject(final String s3Bucket, final S3Object object) {
return new FutureBase<byte[]>() { return putObject(s3Bucket, object, new PutObjectOptions());
public byte[] get() throws InterruptedException, ExecutionException {
if (!bucketToContents.containsKey(s3Bucket)) {
throw new ExecutionException(new RuntimeException(
"bucket not found: " + s3Bucket));
}
bucketToContents.get(s3Bucket).put(object.getKey(),
object.getClass());
return object.getKey().getBytes();// todo actually md5
}
};
} }
public Future<Boolean> putBucketIfNotExists(final String s3Bucket) { public Future<Boolean> putBucketIfNotExists(final String s3Bucket) {
return new FutureBase<Boolean>() { return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException, public Boolean get() throws InterruptedException,
ExecutionException { ExecutionException {
if (!bucketToContents.containsKey(s3Bucket)) { if (!bucketToContents.containsKey(s3Bucket)) {
bucketToContents.put(s3Bucket, bucketToContents.put(s3Bucket,
new ConcurrentHashMap<String, Object>()); new ConcurrentHashMap<String, S3Object>());
} }
return bucketToContents.containsKey(s3Bucket); return bucketToContents.containsKey(s3Bucket);
} }
}; };
} }
public Future<Boolean> deleteBucketIfEmpty(final String s3Bucket) { public Future<Boolean> deleteBucketIfEmpty(final String s3Bucket) {
return new FutureBase<Boolean>() { return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException, public Boolean get() throws InterruptedException,
ExecutionException { ExecutionException {
if (bucketToContents.containsKey(s3Bucket)) { if (bucketToContents.containsKey(s3Bucket)) {
if (bucketToContents.get(s3Bucket).size() == 0) if (bucketToContents.get(s3Bucket).size() == 0)
return true; bucketToContents.remove(s3Bucket);
} else
return false; return false;
} }
}; return true;
}
};
} }
XStream xstream = new XStream();
public Future<S3Object.Metadata> copyObject(final String sourceBucket, public Future<S3Object.Metadata> copyObject(final String sourceBucket,
final String sourceObject, final String destinationBucket, final String sourceObject, final String destinationBucket,
final String destinationObject) { final String destinationObject) {
return new FutureBase<S3Object.Metadata>() { return copyObject(sourceBucket, sourceObject, destinationBucket, destinationObject, new CopyObjectOptions());
public S3Object.Metadata get() throws InterruptedException,
ExecutionException {
Map<String, Object> source = bucketToContents.get(sourceBucket);
Map<String, Object> dest = bucketToContents
.get(destinationBucket);
if (source.containsKey(sourceObject)) {
dest.put(destinationObject, source.get(sourceObject));
return new S3Object.Metadata(destinationObject);
}
return S3Object.Metadata.NOT_FOUND;
}
};
} }
public Future<Boolean> bucketExists(final String s3Bucket) { public Future<Boolean> bucketExists(final String s3Bucket) {
return new FutureBase<Boolean>() { return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException, public Boolean get() throws InterruptedException,
ExecutionException { ExecutionException {
return bucketToContents.containsKey(s3Bucket); return bucketToContents.containsKey(s3Bucket);
} }
}; };
} }
public Future<S3Bucket> listBucket(final String s3Bucket) { public Future<S3Bucket> listBucket(final String s3Bucket) {
return new FutureBase<S3Bucket>() { return listBucket(s3Bucket, new ListBucketOptions());
public S3Bucket get() throws InterruptedException,
ExecutionException {
Set<S3Object.Metadata> contents = new HashSet<S3Object.Metadata>();
Map<String, Object> realContents = bucketToContents
.get(s3Bucket);
if (realContents != null) {
for (String key : realContents.keySet()) {
S3Object.Metadata metadata = new S3Object.Metadata(key);
contents.add(metadata);
}
}
S3Bucket returnVal = new S3Bucket(s3Bucket);
returnVal.setContents(contents);
return returnVal;
}
}
;
} }
private abstract class FutureBase<V> implements Future<V> { private abstract class FutureBase<V> implements Future<V> {
public boolean cancel(boolean b) { public boolean cancel(boolean b) {
return false; return false;
} }
public boolean isCancelled() { public boolean isCancelled() {
return false; return false;
} }
public boolean isDone() { public boolean isDone() {
return true; return true;
} }
public V get(long l, TimeUnit timeUnit) throws InterruptedException, public V get(long l, TimeUnit timeUnit) throws InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
return get(); return get();
} }
} }
public Future<List<Metadata>> listOwnedBuckets() { public Future<List<Metadata>> listOwnedBuckets() {
return new FutureBase<List<S3Bucket.Metadata>>() { return new FutureBase<List<S3Bucket.Metadata>>() {
public List<S3Bucket.Metadata> get() throws InterruptedException, public List<S3Bucket.Metadata> get() throws InterruptedException,
ExecutionException { ExecutionException {
List<S3Bucket.Metadata> list = new ArrayList<S3Bucket.Metadata>(); return Lists.newArrayList(Iterables.transform(
for (String name : bucketToContents.keySet()) bucketToContents.keySet(),
list.add(new S3Bucket.Metadata(name)); new Function<String, Metadata>() {
return list; public Metadata apply(String name) {
} return new S3Bucket.Metadata(name);
}; }
}));
}
};
} }
public Future<Boolean> putBucketIfNotExists(String name, public Future<Boolean> putBucketIfNotExists(String name,
PutBucketOptions options) { PutBucketOptions options) {
throw new UnsupportedOperationException("todo"); if (options.getLocationConstraint() != null)
bucketToLocation.put(name, options.getLocationConstraint());
keyToAcl.put(name, options.getAcl());
return putBucketIfNotExists(name);
} }
public Future<S3Bucket> listBucket(String name, ListBucketOptions options) { class DelimiterFilter implements Predicate<S3Object.Metadata> {
throw new UnsupportedOperationException("todo"); private final String prefix;
private final String delimiter;
DelimiterFilter(String prefix, String delimiter) {
this.prefix = prefix;
this.delimiter = delimiter;
}
public boolean apply(S3Object.Metadata metadata) {
if (prefix == null)
return metadata.getKey().indexOf(delimiter) == -1;
if (metadata.getKey().startsWith(prefix))
return metadata.getKey().replaceFirst(prefix, "").indexOf(delimiter) == -1;
return false;
}
}
class CommonPrefixes implements Function<S3Object.Metadata, String> {
private final String prefix;
private final String delimiter;
static final String NO_PREFIX = "NO_PREFIX";
CommonPrefixes(String prefix, String delimiter) {
this.prefix = prefix;
this.delimiter = delimiter;
}
public String apply(S3Object.Metadata metadata) {
String working = metadata.getKey();
if (prefix != null) {
if (working.startsWith(prefix)) {
working = working.replaceFirst(prefix, "");
}
}
if (working.contains(delimiter)) {
return working.substring(0, working.indexOf(delimiter));
}
return NO_PREFIX;
}
}
public Future<S3Bucket> listBucket(final String name, final ListBucketOptions options) {
return new FutureBase<S3Bucket>() {
public S3Bucket get() throws InterruptedException,
ExecutionException {
final Map<String, S3Object> realContents = bucketToContents
.get(name);
if (realContents == null) return S3Bucket.NOT_FOUND;
SortedSet<S3Object.Metadata> contents = Sets.newTreeSet(
Iterables.transform(realContents.keySet(),
new Function<String, S3Object.Metadata>() {
public S3Object.Metadata apply(String key) {
return realContents.get(key).getMetadata();
}
}));
S3Bucket returnVal = new S3Bucket(name);
if (options.getMarker() != null) {
contents = contents.tailSet(new S3Object.Metadata(URLDecoder.decode(options.getMarker())));
// amazon spec means after the marker, not including it.
contents.remove(new S3Object.Metadata(options.getMarker()));
returnVal.setMarker(URLDecoder.decode(options.getMarker()));
}
if (options.getPrefix() != null) {
contents = Sets.newTreeSet(Iterables.filter(contents, new Predicate<S3Object.Metadata>() {
public boolean apply(S3Object.Metadata o) {
return (o != null && o.getKey().startsWith(URLDecoder.decode(options.getPrefix())));
}
}));
returnVal.setPrefix(URLDecoder.decode(options.getPrefix()));
}
if (options.getDelimiter() != null) {
Iterable<String> iterable = Iterables.transform(contents, new CommonPrefixes(
options.getPrefix() != null ? URLDecoder.decode(options.getPrefix()) : null, URLDecoder.decode(options.getDelimiter())));
Set<String> commonPrefixes = iterable != null ? Sets.newTreeSet(iterable) : new HashSet<String>();
commonPrefixes.remove(CommonPrefixes.NO_PREFIX);
contents = Sets.newTreeSet(Iterables.filter(contents, new DelimiterFilter(
options.getPrefix() != null ? URLDecoder.decode(options.getPrefix()) : null, URLDecoder.decode(options.getDelimiter()))));
returnVal.setCommonPrefixes(commonPrefixes);
returnVal.setDelimiter(URLDecoder.decode(options.getDelimiter()));
}
if (options.getMaxKeys() != null) {
contents = firstSliceOfSize(contents, Integer.parseInt(options.getMaxKeys()));
returnVal.setMaxKeys(Integer.parseInt(options.getMaxKeys()));
returnVal.setTruncated(true);
}
returnVal.setContents(contents);
return returnVal;
}
};
}
public static <T extends Comparable> SortedSet<T> firstSliceOfSize(Iterable<T> elements, int size) {
List<List<T>> slices = Lists.partition(
Lists.newArrayList(elements), size);
return Sets.newTreeSet(slices.get(0));
} }
public Future<org.jclouds.aws.s3.domain.S3Object.Metadata> copyObject( public Future<org.jclouds.aws.s3.domain.S3Object.Metadata> copyObject(
String sourceBucket, String sourceObject, String destinationBucket, final String sourceBucket, final String sourceObject, final String destinationBucket,
String destinationObject, CopyObjectOptions options) { final String destinationObject, final CopyObjectOptions options) {
// TODO Auto-generated method stub
return null; return new FutureBase<S3Object.Metadata>() {
public S3Object.Metadata get() throws InterruptedException,
ExecutionException {
Map<String, S3Object> source = bucketToContents.get(sourceBucket);
Map<String, S3Object> dest = bucketToContents
.get(destinationBucket);
if (source.containsKey(sourceObject)) {
S3Object object = source.get(sourceObject);
if (options.getIfMatch() != null) {
if (!Arrays.equals(object.getMetadata().getMd5(), S3Utils.fromHexString(options.getIfMatch().replaceAll("\"", ""))))
throwResponseException(412);
}
if (options.getIfNoneMatch() != null) {
if (Arrays.equals(object.getMetadata().getMd5(), S3Utils.fromHexString(options.getIfNoneMatch().replaceAll("\"", ""))))
throwResponseException(412);
}
if (options.getIfModifiedSince() != null) {
DateTime modifiedSince = dateService.dateTimeFromHeaderFormat(options.getIfModifiedSince());
if (modifiedSince.isAfter(object.getMetadata().getLastModified()))
throw new ExecutionException(new RuntimeException("after"));
}
if (options.getIfUnmodifiedSince() != null) {
DateTime unmodifiedSince = dateService.dateTimeFromHeaderFormat(options.getIfUnmodifiedSince());
if (unmodifiedSince.isAfter(object.getMetadata().getLastModified()))
throw new ExecutionException(new RuntimeException("after"));
}
S3Object sourceS3 = source.get(sourceObject);
S3Object.Metadata newMd = copy(sourceS3.getMetadata(), destinationObject);
if (options.getAcl() != null)
keyToAcl.put(destinationBucket + destinationObject, options.getAcl());
if (options.getMetadata() != null) {
newMd.setUserMetadata(options.getMetadata());
}
newMd.setLastModified(new DateTime());
dest.put(destinationObject, new S3Object(newMd,
sourceS3.getData()));
return copy(newMd);
}
return S3Object.Metadata.NOT_FOUND;
}
};
} }
public Future<byte[]> putObject(String bucketName, S3Object object, private void throwResponseException(int code) throws ExecutionException {
PutObjectOptions options) { HttpResponse response = new HttpResponse();
// TODO Auto-generated method stub response.setStatusCode(code);
return null; throw new ExecutionException(
new HttpResponseException(createNiceMock(CopyObject.class), response));
} }
public Future<S3Object> getObject(String bucketName, String key, public Future<byte[]> putObject(final String bucketName, final S3Object object,
GetObjectOptions options) { final PutObjectOptions options) {
// TODO Auto-generated method stub if (!bucketToContents.containsKey(bucketName)) {
return null; new RuntimeException(
"bucketName not found: " + bucketName);
}
try {
S3Object.Metadata newMd = copy(object.getMetadata());
newMd.setLastModified(new DateTime());
byte[] data = toByteArray(object.getData());
final byte[] md5 = S3Utils.md5(data);
newMd.setMd5(md5);
newMd.setContentType("binary/octet-stream");
if (options.getAcl() != null)
keyToAcl.put(bucketName + object, options.getAcl());
bucketToContents.get(bucketName).put(object.getKey(),
new S3Object(newMd, data));
return new FutureBase<byte[]>() {
public byte[] get() throws InterruptedException, ExecutionException {
return md5;
}
};
} catch (IOException e) {
throw new RuntimeException(e);
}
}
DateService dateService = new DateService();
public Future<S3Object> getObject(final String bucketName, final String key,
final GetObjectOptions options) {
return new FutureBase<S3Object>() {
public S3Object get() throws InterruptedException,
ExecutionException {
if (!bucketToContents.containsKey(bucketName))
return S3Object.NOT_FOUND;
Map<String, S3Object> realContents = bucketToContents
.get(bucketName);
if (!realContents.containsKey(key))
return S3Object.NOT_FOUND;
S3Object object = realContents.get(key);
if (options.getIfMatch() != null) {
if (!Arrays.equals(object.getMetadata().getMd5(), S3Utils.fromHexString(options.getIfMatch().replaceAll("\"", ""))))
throwResponseException(412);
}
if (options.getIfNoneMatch() != null) {
if (Arrays.equals(object.getMetadata().getMd5(), S3Utils.fromHexString(options.getIfNoneMatch().replaceAll("\"", ""))))
throwResponseException(304);
}
if (options.getIfModifiedSince() != null) {
DateTime modifiedSince = dateService.dateTimeFromHeaderFormat(options.getIfModifiedSince());
if (modifiedSince.isAfter(object.getMetadata().getLastModified()))
throw new ExecutionException(new RuntimeException("after"));
}
if (options.getIfUnmodifiedSince() != null) {
DateTime unmodifiedSince = dateService.dateTimeFromHeaderFormat(options.getIfUnmodifiedSince());
if (unmodifiedSince.isAfter(object.getMetadata().getLastModified()))
throw new ExecutionException(new RuntimeException("after"));
}
S3Object returnVal = new S3Object(copy(object.getMetadata()), object.getData());
if (options.getRange() != null) {
byte[] data = (byte[]) returnVal.getData();
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (String s : options.getRange().replaceAll("bytes=", "").split(",")) {
if (s.startsWith("-")) {
int length = Integer.parseInt(s.replaceAll("\\-", ""));
out.write(data, data.length - length, length);
} else if (s.endsWith("-")) {
int offset = Integer.parseInt(s.replaceAll("\\-", ""));
out.write(data, offset, data.length - offset);
} else if (s.contains("-")) {
String[] firstLast = s.split("\\-");
int offset = Integer.parseInt(firstLast[0]);
int last = Integer.parseInt(firstLast[1]);
int length = (last < data.length) ? last + 1 : data.length - offset;
out.write(data, offset, length);
} else {
throw new IllegalArgumentException("first and last were null!");
}
}
returnVal.setData(out.toByteArray());
returnVal.setContentLength(out.size());
returnVal.getMetadata().setSize(data.length);
}
returnVal.setData(new ByteArrayInputStream((byte[]) returnVal.getData()));
return returnVal;
}
};
} }
} }

View File

@ -23,10 +23,11 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3IntegrationTest; import org.jclouds.aws.s3.S3IntegrationTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import java.util.concurrent.TimeUnit;
/** /**
* Tests integrated functionality of all bucketExists commands. * Tests integrated functionality of all bucketExists commands.
@ -35,23 +36,22 @@ import org.testng.annotations.Test;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.BucketExistsIntegrationTest") @Test(groups = {"integration", "live"}, testName = "s3.BucketExistsIntegrationTest")
public class BucketExistsIntegrationTest extends S3IntegrationTest { public class BucketExistsIntegrationTest extends S3IntegrationTest {
@Test() @Test
void bucketDoesntExist() throws Exception { void bucketDoesntExist() throws Exception {
String bucketName = bucketPrefix + "shouldntexist"; String bucketName= bucketPrefix+"be";
assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS); assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
} }
@Test() @Test
void bucketExists() throws Exception { void bucketExists() throws Exception {
String bucketName = bucketPrefix + "needstoexist"; String bucketName= bucketPrefix+"bde";
assert client.putBucketIfNotExists(bucketName).get(10, assert client.putBucketIfNotExists(bucketName).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
assert client.bucketExists(bucketName).get(10, TimeUnit.SECONDS); assert client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
} }
} }

View File

@ -23,32 +23,24 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5DoesntMatch; import com.google.common.collect.HashMultimap;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5Matches; import com.google.common.collect.Multimap;
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.S3IntegrationTest; import org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.*;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.IOException;
import com.google.common.collect.HashMultimap; import java.net.URL;
import com.google.common.collect.Multimap; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/** /**
* Tests integrated functionality of all copyObject commands. * Tests integrated functionality of all copyObject commands.
@ -57,185 +49,159 @@ import com.google.common.collect.Multimap;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.CopyObjectIntegrationTest") @Test(testName = "s3.CopyObjectIntegrationTest")
public class CopyObjectIntegrationTest extends S3IntegrationTest { public class CopyObjectIntegrationTest extends S3IntegrationTest {
String sourceKey = "apples"; String sourceKey = "apples";
String destinationKey = "pears"; String destinationKey = "pears";
@Test(groups = {"integration","live"})
@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 { void testCopyObject() throws Exception {
String sourceBucket = bucketPrefix + "testcopyobject";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey); String destinationBucket = bucketName + "dest";
createBucketAndEnsureEmpty(destinationBucket); addToBucketAndValidate(bucketName, sourceKey);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey).get(10, TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey); createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey).get(10, TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
} }
private void setupSourceBucket(String sourceBucket, String sourceKey)
throws InterruptedException, ExecutionException, TimeoutException, private void addToBucketAndValidate(String bucketName, String sourceKey)
IOException { throws InterruptedException, ExecutionException, TimeoutException,
createBucketAndEnsureEmpty(sourceBucket); IOException {
addToBucketAndValidate(sourceBucket, sourceKey); addObjectToBucket(bucketName, sourceKey);
validateContent(bucketName, sourceKey);
} }
private void addToBucketAndValidate(String sourceBucket, String sourceKey) @Test(groups = {"integration","live"})
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
addObjectToBucket(sourceBucket, sourceKey);
validateContent(sourceBucket, sourceKey);
}
@Test
void testCopyIfModifiedSince() throws InterruptedException, void testCopyIfModifiedSince() throws InterruptedException,
ExecutionException, TimeoutException, IOException { ExecutionException, TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcims";
String destinationBucket = sourceBucket + "dest";
DateTime before = new DateTime(); String destinationBucket = bucketName + "dest";
setupSourceBucket(sourceBucket, sourceKey);
DateTime after = new DateTime().plusSeconds(1);
createBucketAndEnsureEmpty(destinationBucket); DateTime before = new DateTime();
client.copyObject(sourceBucket, sourceKey, destinationBucket, addToBucketAndValidate(bucketName, sourceKey);
destinationKey, ifSourceModifiedSince(before)).get(10, DateTime after = new DateTime().plusSeconds(1);
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
try { createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(after)).get(10, destinationKey, ifSourceModifiedSince(before)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
} catch (ExecutionException e) { validateContent(destinationBucket, destinationKey);
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412); try {
} client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(after)).get(10,
TimeUnit.SECONDS);
} catch (ExecutionException e) {
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412);
}
} }
@Test @Test(groups = {"integration","live"})
void testCopyIfUnmodifiedSince() throws InterruptedException, void testCopyIfUnmodifiedSince() throws InterruptedException,
ExecutionException, TimeoutException, IOException { ExecutionException, TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcius";
String destinationBucket = sourceBucket + "dest";
DateTime before = new DateTime(); String destinationBucket = bucketName + "dest";
setupSourceBucket(sourceBucket, sourceKey);
DateTime after = new DateTime().plusSeconds(1);
createBucketAndEnsureEmpty(destinationBucket); DateTime before = new DateTime();
client.copyObject(sourceBucket, sourceKey, destinationBucket, addToBucketAndValidate(bucketName, sourceKey);
destinationKey, ifSourceUnmodifiedSince(after)).get(10, DateTime after = new DateTime().plusSeconds(1);
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
try { createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(before)).get(10, destinationKey, ifSourceUnmodifiedSince(after)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
} catch (ExecutionException e) { validateContent(destinationBucket, destinationKey);
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412); try {
} client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(before)).get(10,
TimeUnit.SECONDS);
} catch (ExecutionException e) {
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412);
}
} }
@Test @Test(groups = {"integration","live"})
void testCopyIfMatch() throws InterruptedException, ExecutionException, void testCopyIfMatch() throws InterruptedException, ExecutionException,
TimeoutException, IOException { TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcim";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey); String destinationBucket = bucketName + "dest";
createBucketAndEnsureEmpty(destinationBucket); addToBucketAndValidate(bucketName, sourceKey);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey, ifSourceMd5Matches(goodMd5)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
try { createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5Matches(badMd5)).get(10, destinationKey, ifSourceMd5Matches(goodMd5)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
} catch (ExecutionException e) { validateContent(destinationBucket, destinationKey);
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412); try {
} client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5Matches(badMd5)).get(10,
TimeUnit.SECONDS);
} catch (ExecutionException e) {
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412);
}
} }
@Test @Test(groups = {"integration","live"})
void testCopyIfNoneMatch() throws IOException, InterruptedException, void testCopyIfNoneMatch() throws IOException, InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
String sourceBucket = bucketPrefix + "tcinm";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey); String destinationBucket = bucketName + "dest";
createBucketAndEnsureEmpty(destinationBucket); addToBucketAndValidate(bucketName, sourceKey);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey, ifSourceMd5DoesntMatch(badMd5)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
try { createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5DoesntMatch(goodMd5)).get(10, destinationKey, ifSourceMd5DoesntMatch(badMd5)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
} catch (ExecutionException e) { validateContent(destinationBucket, destinationKey);
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412); try {
} client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5DoesntMatch(goodMd5)).get(10,
TimeUnit.SECONDS);
} catch (ExecutionException e) {
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412);
}
} }
@Test @Test(groups = {"integration","live"})
void testCopyWithMetadata() throws InterruptedException, void testCopyWithMetadata() throws InterruptedException,
ExecutionException, TimeoutException, IOException { ExecutionException, TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcwm";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey); String destinationBucket = bucketName + "dest";
Multimap<String, String> metadata = HashMultimap.create(); addToBucketAndValidate(bucketName, sourceKey);
metadata.put(S3Headers.USER_METADATA_PREFIX + "adrian", "cole");
createBucketAndEnsureEmpty(destinationBucket); Multimap<String, String> metadata = HashMultimap.create();
client.copyObject(sourceBucket, sourceKey, destinationBucket, metadata.put(S3Headers.USER_METADATA_PREFIX + "adrian", "cole");
destinationKey, overrideMetadataWith(metadata)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey); createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, overrideMetadataWith(metadata)).get(10,
TimeUnit.SECONDS);
S3Object.Metadata objectMeta = client.headObject(destinationBucket, validateContent(destinationBucket, destinationKey);
destinationKey).get(10, TimeUnit.SECONDS);
assertEquals(objectMeta.getUserMetadata(), metadata); S3Object.Metadata objectMeta = client.headObject(destinationBucket,
destinationKey).get(10, TimeUnit.SECONDS);
assertEquals(objectMeta.getUserMetadata(), metadata);
} }
} }

View File

@ -0,0 +1,68 @@
/**
*
* 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 org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideAcl;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.util.S3Utils;
import org.testng.annotations.Test;
import java.net.URL;
import java.util.concurrent.TimeUnit;
/**
* Tests integrated functionality of all copyObject commands.
* <p/>
* Each test uses a different bucket name, so it should be perfectly fine to run
* in parallel.
*
* @author Adrian Cole
*/
@Test(testName = "s3.CopyObjectLiveTest")
public class CopyObjectLiveTest extends S3IntegrationTest {
String sourceKey = "apples";
String destinationKey = "pears";
@Test(groups = "live")
void testCannedAccessPolicyPublic() throws Exception {
String destinationBucket = bucketName + "dest";
addObjectToBucket(bucketName, sourceKey);
validateContent(bucketName, sourceKey);
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(bucketName, 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());
}
}

View File

@ -23,11 +23,11 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3IntegrationTest; import org.jclouds.aws.s3.S3IntegrationTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.concurrent.TimeUnit;
/** /**
* Tests integrated functionality of all deleteBucket commands. * Tests integrated functionality of all deleteBucket commands.
* <p/> * <p/>
@ -35,30 +35,28 @@ import org.testng.annotations.Test;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.DeleteBucketIntegrationTest") @Test(groups = {"integration", "live"}, testName = "s3.DeleteBucketIntegrationTest")
public class DeleteBucketIntegrationTest extends S3IntegrationTest { public class DeleteBucketIntegrationTest extends S3IntegrationTest {
@Test() @Test
/**
* this method overrides bucketName to ensure it isn't found
*/
void deleteBucketIfEmptyNotFound() throws Exception { void deleteBucketIfEmptyNotFound() throws Exception {
String bucketName = bucketPrefix + "dbienf"; String bucketName = bucketPrefix + "dbienf";
assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS); assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
} }
@Test() @Test()
void deleteBucketIfEmptyButHasContents() throws Exception { void deleteBucketIfEmptyButHasContents() throws Exception {
String bucketName = bucketPrefix + "dbiebhc"; addObjectToBucket(bucketName, "test");
createBucketAndEnsureEmpty(bucketName); assert !client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
addObjectToBucket(bucketName,"test");
assert !client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
} }
@Test() @Test()
void deleteBucketIfEmpty() throws Exception { void deleteBucketIfEmpty() throws Exception {
String bucketName = bucketPrefix + "dbie"; assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
createBucketAndEnsureEmpty(bucketName); assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
} }
} }

View File

@ -23,14 +23,14 @@
*/ */
package org.jclouds.aws.s3.commands; 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.S3IntegrationTest;
import org.jclouds.aws.s3.S3ResponseException; import org.jclouds.aws.s3.S3ResponseException;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/** /**
* Tests integrated functionality of all deleteObject commands. * Tests integrated functionality of all deleteObject commands.
@ -39,40 +39,39 @@ import static org.testng.Assert.assertEquals;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.DeleteObjectIntegrationTest") @Test(groups = {"integration", "live"}, testName = "s3.DeleteObjectIntegrationTest")
public class DeleteObjectIntegrationTest extends S3IntegrationTest { public class DeleteObjectIntegrationTest extends S3IntegrationTest {
@Test() @Test()
void deleteObjectNotFound() throws Exception { void deleteObjectNotFound() throws Exception {
String bucketName = bucketPrefix + "donf"; String bucketName = bucketPrefix + "donf";
createBucketAndEnsureEmpty(bucketName); createBucketAndEnsureEmpty(bucketName);
addObjectToBucket(bucketName, "test"); addObjectToBucket(bucketName, "test");
assert client.deleteObject(bucketName, "test") assert client.deleteObject(bucketName, "test")
.get(10, TimeUnit.SECONDS); .get(10, TimeUnit.SECONDS);
} }
@Test @Test
void deleteObjectNoBucket() throws Exception { void deleteObjectNoBucket() throws Exception {
String bucketName = bucketPrefix + "donb"; String bucketName = bucketPrefix + "donb";
try { try {
client.deleteObject(bucketName, "test").get(10, TimeUnit.SECONDS); client.deleteObject(bucketName, "test").get(10, TimeUnit.SECONDS);
} catch (ExecutionException e) { } catch (ExecutionException e) {
assert e.getCause() instanceof S3ResponseException; assert e.getCause() instanceof S3ResponseException;
assertEquals(((S3ResponseException) e.getCause()).getResponse() assertEquals(((S3ResponseException) e.getCause()).getResponse()
.getStatusCode(), 404); .getStatusCode(), 404);
} }
} }
@Test() @Test()
void deleteObject() throws Exception { void deleteObject() throws Exception {
String bucketName = bucketPrefix + "do"; String bucketName = bucketPrefix + "do";
createBucketAndEnsureEmpty(bucketName); createBucketAndEnsureEmpty(bucketName);
addObjectToBucket(bucketName, "test"); addObjectToBucket(bucketName, "test");
assert client.deleteObject(bucketName, "test") assert client.deleteObject(bucketName, "test")
.get(10, TimeUnit.SECONDS); .get(10, TimeUnit.SECONDS);
assert client.headObject(bucketName, "test").get(10, TimeUnit.SECONDS) == S3Object.Metadata.NOT_FOUND; assert client.headObject(bucketName, "test").get(10, TimeUnit.SECONDS) == S3Object.Metadata.NOT_FOUND;
} }
} }

View File

@ -11,7 +11,7 @@
* "License"); you may not use this file except in compliance * "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at * with the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http:www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, * Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an * software distributed under the License is distributed on an
@ -23,19 +23,21 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.jclouds.aws.s3.S3ResponseException;
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.*; import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.*;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpResponseException;
import org.joda.time.DateTime;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; 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;
/** /**
* Tests integrated functionality of all GetObject commands. * Tests integrated functionality of all GetObject commands.
* <p/> * <p/>
@ -43,192 +45,187 @@ import org.testng.annotations.Test;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.GetObjectIntegrationTest") @Test(groups = {"integration", "live"}, testName = "s3.GetObjectIntegrationTest")
public class GetObjectIntegrationTest extends S3IntegrationTest { 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
// @Test void testGetIfModifiedSince() throws InterruptedException,
// void testGetIfUnmodifiedSince() throws InterruptedException, ExecutionException, TimeoutException, IOException {
// ExecutionException, TimeoutException, IOException {
// String bucket = bucketPrefix + "testGetIfUnmodifiedSince".toLowerCase(); String key = "apples";
// String key = "apples";
// DateTime before = new DateTime();
// DateTime before = new DateTime(); addObjectAndValidateContent(bucketName, key);
// setUpBucket(bucket, key); DateTime after = new DateTime().plusSeconds(1);
// DateTime after = new DateTime().plusSeconds(1);
// client.getObject(bucketName, key, ifModifiedSince(before)).get(10,
// client.getObject(bucket, key, ifUnmodifiedSince(after)).get(10, TimeUnit.SECONDS);
// TimeUnit.SECONDS); validateContent(bucketName, key);
// validateContent(bucket, key);
// try {
// try { client.getObject(bucketName, key, ifModifiedSince(after)).get(10,
// client.getObject(bucket, key, ifUnmodifiedSince(before)).get(10, TimeUnit.SECONDS);
// TimeUnit.SECONDS); validateContent(bucketName, key);
// validateContent(bucket, key); } catch (ExecutionException e) {
// } catch (ExecutionException e) { if (e.getCause() instanceof HttpResponseException) {
// if (e.getCause() instanceof S3ResponseException) { HttpResponseException ex = (HttpResponseException) e.getCause();
// S3ResponseException ex = (S3ResponseException) e.getCause(); assertEquals(ex.getResponse().getStatusCode(), 304);
// assertEquals(ex.getResponse().getStatusCode(), 412); } else {
// } else { throw e;
// throw e; }
// } }
// }
// }
// }
// @Test
// @Test void testGetIfUnmodifiedSince() throws InterruptedException,
// void testGetIfMatch() throws InterruptedException, ExecutionException, ExecutionException, TimeoutException, IOException {
// TimeoutException, IOException {
// String bucket = bucketPrefix + "testGetIfMatch".toLowerCase(); String key = "apples";
// String key = "apples";
// DateTime before = new DateTime();
// setUpBucket(bucket, key); addObjectAndValidateContent(bucketName, key);
// DateTime after = new DateTime().plusSeconds(1);
// client.getObject(bucket, key, ifMd5Matches(goodMd5)).get(10,
// TimeUnit.SECONDS); client.getObject(bucketName, key, ifUnmodifiedSince(after)).get(10,
// validateContent(bucket, key); TimeUnit.SECONDS);
// validateContent(bucketName, key);
// try {
// client.getObject(bucket, key, ifMd5Matches(badMd5)).get(10, try {
// TimeUnit.SECONDS); client.getObject(bucketName, key, ifUnmodifiedSince(before)).get(10,
// validateContent(bucket, key); TimeUnit.SECONDS);
// } catch (ExecutionException e) { validateContent(bucketName, key);
// if (e.getCause() instanceof S3ResponseException) { } catch (ExecutionException e) {
// S3ResponseException ex = (S3ResponseException) e.getCause(); if (e.getCause() instanceof HttpResponseException) {
// assertEquals(ex.getResponse().getStatusCode(), 412); HttpResponseException ex = (HttpResponseException) e.getCause();
// } else { assertEquals(ex.getResponse().getStatusCode(), 412);
// throw e; } else {
// } throw e;
// } }
// } }
//
// @Test }
// void testGetIfNoneMatch() throws InterruptedException,
// ExecutionException, @Test
// TimeoutException, IOException { void testGetIfMatch() throws InterruptedException, ExecutionException,
// String bucket = bucketPrefix + "testGetIfNoneMatch".toLowerCase(); TimeoutException, IOException {
// String key = "apples";
// String key = "apples";
// setUpBucket(bucket, key);
// addObjectAndValidateContent(bucketName, key);
// client.getObject(bucket, key, ifMd5DoesntMatch(badMd5)).get(10,
// TimeUnit.SECONDS); client.getObject(bucketName, key, ifMd5Matches(goodMd5)).get(10,
// validateContent(bucket, key); TimeUnit.SECONDS);
// validateContent(bucketName, key);
// try {
// client.getObject(bucket, key, ifMd5DoesntMatch(goodMd5)).get(10, try {
// TimeUnit.SECONDS); client.getObject(bucketName, key, ifMd5Matches(badMd5)).get(10,
// validateContent(bucket, key); TimeUnit.SECONDS);
// } catch (ExecutionException e) { validateContent(bucketName, key);
// if (e.getCause() instanceof HttpResponseException) { } catch (ExecutionException e) {
// HttpResponseException ex = (HttpResponseException) e.getCause(); if (e.getCause() instanceof HttpResponseException) {
// assertEquals(ex.getResponse().getStatusCode(), 304); HttpResponseException ex = (HttpResponseException) e.getCause();
// } else { assertEquals(ex.getResponse().getStatusCode(), 412);
// throw e; } else {
// } throw e;
// } }
// } }
}
@Test
void testGetIfNoneMatch() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
String key = "apples";
addObjectAndValidateContent(bucketName, key);
client.getObject(bucketName, key, ifMd5DoesntMatch(badMd5)).get(10,
TimeUnit.SECONDS);
validateContent(bucketName, key);
try {
client.getObject(bucketName, key, ifMd5DoesntMatch(goodMd5)).get(10,
TimeUnit.SECONDS);
validateContent(bucketName, key);
} catch (ExecutionException e) {
if (e.getCause() instanceof HttpResponseException) {
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 304);
} else {
throw e;
}
}
}
@Test @Test
void testGetRange() throws InterruptedException, ExecutionException, void testGetRange() throws InterruptedException, ExecutionException,
TimeoutException, IOException { TimeoutException, IOException {
String bucket = bucketPrefix + "testGetRange".toLowerCase();
String key = "apples";
setUpBucket(bucket, key); String key = "apples";
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, addObjectAndValidateContent(bucketName, key);
range(5, TEST_STRING.length())).get(10, TimeUnit.SECONDS); S3Object object1 = client.getObject(bucketName, key, range(0, 5)).get(10,
assertEquals(S3Utils.getContentAsStringAndClose(object2), TEST_STRING TimeUnit.SECONDS);
.substring(5, TEST_STRING.length())); assertEquals(S3Utils.getContentAsStringAndClose(object1), TEST_STRING
.substring(0, 6));
S3Object object2 = client.getObject(bucketName, key,
range(6, TEST_STRING.length())).get(10, TimeUnit.SECONDS);
assertEquals(S3Utils.getContentAsStringAndClose(object2), TEST_STRING
.substring(6, TEST_STRING.length()));
} }
@Test @Test
void testGetTwoRanges() throws InterruptedException, ExecutionException, void testGetTwoRanges() throws InterruptedException, ExecutionException,
TimeoutException, IOException { TimeoutException, IOException {
String bucket = bucketPrefix + "testGetTwoRanges".toLowerCase();
String key = "apples";
setUpBucket(bucket, key); String key = "apples";
S3Object object = client.getObject(bucket, key,
range(0, 5).range(5, TEST_STRING.length())).get(10,
TimeUnit.SECONDS);
assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING); addObjectAndValidateContent(bucketName, key);
S3Object object = client.getObject(bucketName, key,
range(0, 5).range(6, TEST_STRING.length())).get(10,
TimeUnit.SECONDS);
assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING);
} }
@Test @Test
void testGetTail() throws InterruptedException, ExecutionException, void testGetTail() throws InterruptedException, ExecutionException,
TimeoutException, IOException { TimeoutException, IOException {
String bucket = bucketPrefix + "testGetTail".toLowerCase();
String key = "apples";
setUpBucket(bucket, key); String key = "apples";
S3Object object = client.getObject(bucket, key, tail(5)).get(10,
TimeUnit.SECONDS); addObjectAndValidateContent(bucketName, key);
assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING S3Object object = client.getObject(bucketName, key, tail(5)).get(10,
.substring(TEST_STRING.length() - 5)); TimeUnit.SECONDS);
assertEquals(object.getContentLength(), 5); assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING
assertEquals(object.getMetadata().getSize(), TEST_STRING.length()); .substring(TEST_STRING.length() - 5));
assertEquals(object.getContentLength(), 5);
assertEquals(object.getMetadata().getSize(), TEST_STRING.length());
} }
@Test @Test
void testGetStartAt() throws InterruptedException, ExecutionException, void testGetStartAt() throws InterruptedException, ExecutionException,
TimeoutException, IOException { TimeoutException, IOException {
String bucket = bucketPrefix + "testGetStartAt".toLowerCase();
String key = "apples";
setUpBucket(bucket, key); String key = "apples";
S3Object object = client.getObject(bucket, key, startAt(5)).get(10,
TimeUnit.SECONDS); addObjectAndValidateContent(bucketName, key);
assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING S3Object object = client.getObject(bucketName, key, startAt(5)).get(10,
.substring(5, TEST_STRING.length())); TimeUnit.SECONDS);
assertEquals(object.getContentLength(), TEST_STRING.length() - 5); assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING
assertEquals(object.getMetadata().getSize(), TEST_STRING.length()); .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) private void addObjectAndValidateContent(String sourcebucketName, String sourceKey)
throws InterruptedException, ExecutionException, TimeoutException, throws InterruptedException, ExecutionException, TimeoutException,
IOException { IOException {
createBucketAndEnsureEmpty(sourceBucket); addObjectToBucket(sourcebucketName, sourceKey);
addObjectToBucket(sourceBucket, sourceKey); validateContent(sourcebucketName, sourceKey);
validateContent(sourceBucket, sourceKey);
} }
} }

View File

@ -23,23 +23,18 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import static org.jclouds.aws.s3.commands.options.ListBucketOptions.Builder.delimiter; import org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.ListBucketOptions.Builder.afterMarker; import static org.jclouds.aws.s3.commands.options.ListBucketOptions.Builder.*;
import static org.jclouds.aws.s3.commands.options.ListBucketOptions.Builder.withPrefix; import org.jclouds.aws.s3.domain.S3Bucket;
import static org.jclouds.aws.s3.commands.options.ListBucketOptions.Builder.maxResults; import org.jclouds.aws.s3.domain.S3Object;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object;
import org.testng.annotations.Test;
/** /**
* Tests integrated functionality of all getBucket commands. * Tests integrated functionality of all getBucket commands.
* <p/> * <p/>
@ -47,92 +42,93 @@ import org.testng.annotations.Test;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.ListBucketIntegrationTest") @Test(groups = {"integration", "live"}, testName = "s3.ListBucketIntegrationTest")
public class ListBucketIntegrationTest extends S3IntegrationTest { public class ListBucketIntegrationTest extends S3IntegrationTest {
@Test() @Test()
void testListBucketDelimiter() throws InterruptedException, void testListBucketDelimiter() throws InterruptedException,
ExecutionException, TimeoutException, UnsupportedEncodingException { ExecutionException, TimeoutException, UnsupportedEncodingException {
String bucketName = bucketPrefix + "delimiter"; String prefix = "apps";
assert client.putBucketIfNotExists(bucketName).get(10, addTenObjectsUnderPrefix(bucketName, prefix);
TimeUnit.SECONDS); add15UnderRoot(bucketName);
String prefix = "apps"; S3Bucket bucket = client.listBucket(bucketName, delimiter("/")).get(10,
addTenObjectsUnderPrefix(bucketName, prefix); TimeUnit.SECONDS);
add15UnderRoot(bucketName); assertEquals(bucket.getDelimiter(), "/");
S3Bucket bucket = client.listBucket(bucketName, delimiter("/")).get(10, assert !bucket.isTruncated();
TimeUnit.SECONDS); assertEquals(bucket.getContents().size(), 15);
assertEquals(bucket.getDelimiter(), "/"); assertEquals(bucket.getCommonPrefixes().size(), 1);
assertEquals(bucket.getContents().size(), 15);
assertEquals(bucket.getCommonPrefixes().size(), 1);
} }
private void addAlphabetUnderRoot(String bucketName) private void addAlphabetUnderRoot(String bucketName)
throws InterruptedException, ExecutionException, TimeoutException { throws InterruptedException, ExecutionException, TimeoutException {
for (char letter = 'a'; letter <= 'z'; letter++) { for (char letter = 'a'; letter <= 'z'; letter++) {
client.putObject(bucketName, client.putObject(bucketName,
new S3Object(letter + "", letter + "content")).get(10, new S3Object(letter + "", letter + "content")).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
} }
} }
@Test @Test
void testListBucketMarker() throws InterruptedException, void testListBucketMarker() throws InterruptedException,
ExecutionException, TimeoutException, UnsupportedEncodingException { ExecutionException, TimeoutException, UnsupportedEncodingException {
String bucketName = bucketPrefix + "marker"; addAlphabetUnderRoot(bucketName);
assert client.putBucketIfNotExists(bucketName).get(10, S3Bucket bucket = client.listBucket(bucketName, afterMarker("y")).get(
TimeUnit.SECONDS); 10, TimeUnit.SECONDS);
addAlphabetUnderRoot(bucketName); assertEquals(bucket.getMarker(), "y");
S3Bucket bucket = client.listBucket(bucketName, afterMarker("y")).get( assert !bucket.isTruncated();
10, TimeUnit.SECONDS); assertEquals(bucket.getContents().size(), 1);
assertEquals(bucket.getMarker(), "y");
assertEquals(bucket.getContents().size(), 1);
} }
@Test @Test
void testListBucketMaxResults() throws InterruptedException, void testListBucketMaxResults() throws InterruptedException,
ExecutionException, TimeoutException, UnsupportedEncodingException { ExecutionException, TimeoutException, UnsupportedEncodingException {
String bucketName = bucketPrefix + "max"; addAlphabetUnderRoot(bucketName);
assert client.putBucketIfNotExists(bucketName).get(10, S3Bucket bucket = client.listBucket(bucketName, maxResults(5)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
addAlphabetUnderRoot(bucketName); assertEquals(bucket.getMaxKeys(), 5);
S3Bucket bucket = client.listBucket(bucketName, maxResults(5)).get(10, assert bucket.isTruncated();
TimeUnit.SECONDS); assertEquals(bucket.getContents().size(), 5);
assertEquals(bucket.getMaxKeys(), 5);
assertEquals(bucket.getContents().size(), 5);
} }
@Test() @Test()
void testListBucketPrefix() throws InterruptedException, void testListBucketPrefix() throws InterruptedException,
ExecutionException, TimeoutException, UnsupportedEncodingException { ExecutionException, TimeoutException, UnsupportedEncodingException {
String bucketName = bucketPrefix + "prefix"; String prefix = "apps";
assert client.putBucketIfNotExists(bucketName).get(10, addTenObjectsUnderPrefix(bucketName, prefix);
TimeUnit.SECONDS); add15UnderRoot(bucketName);
String prefix = "apps";
addTenObjectsUnderPrefix(bucketName, prefix);
add15UnderRoot(bucketName);
S3Bucket bucket = client.listBucket(bucketName, withPrefix("apps/")) S3Bucket bucket = client.listBucket(bucketName, withPrefix("apps/"))
.get(10, TimeUnit.SECONDS); .get(10, TimeUnit.SECONDS);
assertEquals(bucket.getContents().size(), 10); assert !bucket.isTruncated();
assertEquals(bucket.getPrefix(), "apps/"); assertEquals(bucket.getContents().size(), 10);
assertEquals(bucket.getPrefix(), "apps/");
} }
@Test()
void testListBucket() throws InterruptedException,
ExecutionException, TimeoutException, UnsupportedEncodingException {
String prefix = "apps";
addTenObjectsUnderPrefix(bucketName, prefix);
S3Bucket bucket = client.listBucket(bucketName)
.get(10, TimeUnit.SECONDS);
assertEquals(bucket.getContents().size(), 10);
}
private void add15UnderRoot(String bucketName) throws InterruptedException, private void add15UnderRoot(String bucketName) throws InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
for (int i = 0; i < 15; i++) for (int i = 0; i < 15; i++)
client.putObject(bucketName, new S3Object(i + "", i + "content")) client.putObject(bucketName, new S3Object(i + "", i + "content"))
.get(10, TimeUnit.SECONDS); .get(10, TimeUnit.SECONDS);
} }
private void addTenObjectsUnderPrefix(String bucketName, String prefix) private void addTenObjectsUnderPrefix(String bucketName, String prefix)
throws InterruptedException, ExecutionException, TimeoutException { throws InterruptedException, ExecutionException, TimeoutException {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
client.putObject(bucketName, client.putObject(bucketName,
new S3Object(prefix + "/" + i, i + "content")).get(10, new S3Object(prefix + "/" + i, i + "content")).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
} }
} }

View File

@ -23,13 +23,13 @@
*/ */
package org.jclouds.aws.s3.commands; 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.S3IntegrationTest;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.List;
import java.util.concurrent.TimeUnit;
/** /**
* Tests integrated functionality of all listOwnedBucket commands. * Tests integrated functionality of all listOwnedBucket commands.
* <p/> * <p/>
@ -37,30 +37,29 @@ import org.testng.annotations.Test;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.ListOwnedBucketsIntegrationTest") @Test(groups = {"integration", "live"}, testName = "s3.ListOwnedBucketsIntegrationTest")
public class ListOwnedBucketsIntegrationTest extends S3IntegrationTest { public class ListOwnedBucketsIntegrationTest extends S3IntegrationTest {
@Test() @Test()
void bucketDoesntExist() throws Exception { void bucketDoesntExist() throws Exception {
String bucketName = bucketPrefix + "shouldntexist"; String bucketName = bucketPrefix + "shouldntexist";
List<S3Bucket.Metadata> list = client.listOwnedBuckets().get(10, List<S3Bucket.Metadata> list = client.listOwnedBuckets().get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
assert !list.contains(new S3Bucket(bucketName)); assert !list.contains(new S3Bucket(bucketName));
} }
@Test() @Test()
void bucketExists() throws Exception { void bucketExists() throws Exception {
String bucketName = bucketPrefix + "needstoexist"; String bucketName = bucketPrefix + "needstoexist";
assert client.putBucketIfNotExists(bucketName) assert client.putBucketIfNotExists(bucketName)
.get(10, TimeUnit.SECONDS); .get(10, TimeUnit.SECONDS);
List<S3Bucket.Metadata> list = client.listOwnedBuckets().get(10, List<S3Bucket.Metadata> list = client.listOwnedBuckets().get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
S3Bucket.Metadata firstBucket = list.get(0); S3Bucket.Metadata firstBucket = list.get(0);
S3Bucket.Metadata toMatch = new S3Bucket.Metadata(bucketName); S3Bucket.Metadata toMatch = new S3Bucket.Metadata(bucketName);
toMatch.setOwner(firstBucket.getOwner()); toMatch.setOwner(firstBucket.getOwner());
assert list.contains(toMatch); assert list.contains(toMatch);
} }
} }

View File

@ -23,19 +23,18 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.createIn; import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.createIn;
import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl; import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
/** /**
* Tests integrated functionality of all PutBucket commands. * Tests integrated functionality of all PutBucket commands.
* <p/> * <p/>
@ -43,44 +42,46 @@ import org.testng.annotations.Test;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.PutBucketIntegrationTest") @Test(testName = "s3.PutBucketLiveTest")
public class PutBucketIntegrationTest extends S3IntegrationTest { public class PutBucketLiveTest extends S3IntegrationTest {
@Test() /**
* overriding bucketName as we are changing access permissions
*/
@Test(groups = {"live"})
void testPublicReadAccessPolicy() throws Exception { void testPublicReadAccessPolicy() throws Exception {
String bucketName = bucketPrefix + "public"; String bucketName = bucketPrefix + "public";
client.putBucketIfNotExists(bucketName, client.putBucketIfNotExists(bucketName,
withBucketAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, withBucketAcl(CannedAccessPolicy.PUBLIC_READ)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com", URL url = new URL(String.format("http://%1$s.s3.amazonaws.com",
bucketName)); bucketName));
S3Utils.toStringAndClose(url.openStream()); S3Utils.toStringAndClose(url.openStream());
} }
@Test(expectedExceptions = IOException.class) @Test(expectedExceptions = IOException.class, groups = {"live"})
void testDefaultAccessPolicy() throws Exception { void testDefaultAccessPolicy() throws Exception {
String bucketName = bucketPrefix + "private"; URL url = new URL(String.format("http://%1$s.s3.amazonaws.com",
bucketName));
client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS); S3Utils.toStringAndClose(url.openStream());
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com",
bucketName));
S3Utils.toStringAndClose(url.openStream());
} }
@Test() /**
* overriding bucketName as we are changing location
*/
@Test(groups = "live")
void testEu() throws Exception { void testEu() throws Exception {
String bucketName = (bucketPrefix + "wow").toLowerCase(); String bucketName = (bucketPrefix + "wow").toLowerCase();
client.putBucketIfNotExists( client.putBucketIfNotExists(
bucketName, bucketName,
createIn(LocationConstraint.EU).withBucketAcl( createIn(LocationConstraint.EU).withBucketAcl(
CannedAccessPolicy.PUBLIC_READ)).get(10, CannedAccessPolicy.PUBLIC_READ)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com", URL url = new URL(String.format("http://%1$s.s3.amazonaws.com",
bucketName)); bucketName));
S3Utils.toStringAndClose(url.openStream()); S3Utils.toStringAndClose(url.openStream());
} }
} }

View File

@ -23,9 +23,18 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl; import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl;
import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.withAcl;
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 static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -34,16 +43,6 @@ import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.S3IntegrationTest;
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. * Tests integrated functionality of all PutObject commands.
@ -52,97 +51,77 @@ import org.testng.annotations.Test;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.PutObjectIntegrationTest") @Test(testName = "s3.PutObjectIntegrationTest")
public class PutObjectIntegrationTest extends S3IntegrationTest { public class PutObjectIntegrationTest extends S3IntegrationTest {
@DataProvider(name = "putTests") @DataProvider(name = "putTests")
public Object[][] createData1() throws IOException { public Object[][] createData1() throws IOException {
String realObject = IOUtils.toString(new FileInputStream("pom.xml")); String realObject = IOUtils.toString(new FileInputStream("pom.xml"));
return new Object[][] { return new Object[][]{
{ "file", "text/xml", new File("pom.xml"), realObject }, {"file", "text/xml", new File("pom.xml"), realObject},
{ "string", "text/xml", realObject, realObject }, {"string", "text/xml", realObject, realObject},
{ "bytes", "application/octet-stream", realObject.getBytes(), {"bytes", "application/octet-stream", realObject.getBytes(),
realObject } }; realObject}};
} }
@Test(dataProvider = "putTests") @Test(dataProvider = "putTests", groups = {"integration", "live"})
void testPutObject(String key, String type, Object content, void testPutObject(String key, String type, Object content,
Object realObject) throws Exception { Object realObject) throws Exception {
String bucketName = bucketPrefix + "tpo"; String bucketName = bucketPrefix + "tpo";
client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS); client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS);
context.createS3ObjectMap(bucketName).clear(); context.createS3ObjectMap(bucketName).clear();
assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS) assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS)
.getContents().size(), 0); .getContents().size(), 0);
S3Object object = new S3Object(key); S3Object object = new S3Object(key);
object.getMetadata().setContentType(type); object.getMetadata().setContentType(type);
object.setData(content); object.setData(content);
if (content instanceof InputStream) { if (content instanceof InputStream) {
object.generateMd5(); object.generateMd5();
} }
assertNotNull(client.putObject(bucketName, object).get(10, assertNotNull(client.putObject(bucketName, object).get(10,
TimeUnit.SECONDS)); TimeUnit.SECONDS));
object = client.getObject(bucketName, object.getKey()).get(10, object = client.getObject(bucketName, object.getKey()).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
String returnedString = S3Utils.getContentAsStringAndClose(object); String returnedString = S3Utils.getContentAsStringAndClose(object);
assertEquals(returnedString, realObject); assertEquals(returnedString, realObject);
assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS) assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS)
.getContents().size(), 1); .getContents().size(), 1);
} }
@Test @Test(groups = {"integration", "live"})
void testMetadata() throws Exception { void testMetadata() throws Exception {
String bucketName = bucketPrefix + "tmd"; String bucketName = bucketPrefix + "tmd";
createBucketAndEnsureEmpty(bucketName); createBucketAndEnsureEmpty(bucketName);
String key = "hello"; String key = "hello";
S3Object object = new S3Object(key, TEST_STRING); S3Object object = new S3Object(key, TEST_STRING);
object.getMetadata().setCacheControl("no-cache"); object.getMetadata().setCacheControl("no-cache");
object.getMetadata().setContentType("text/plain"); object.getMetadata().setContentType("text/plain");
object.getMetadata().setContentEncoding("x-compress"); object.getMetadata().setContentEncoding("x-compress");
object.getMetadata().setSize(TEST_STRING.length()); object.getMetadata().setSize(TEST_STRING.length());
object.getMetadata().setContentDisposition( object.getMetadata().setContentDisposition(
"attachment; filename=hello.txt"); "attachment; filename=hello.txt");
object.getMetadata().getUserMetadata().put( object.getMetadata().getUserMetadata().put(
S3Headers.USER_METADATA_PREFIX + "adrian", "powderpuff"); 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); addObjectToBucket(bucketName, object);
S3Object newObject = validateContent(bucketName, key); S3Object newObject = validateContent(bucketName, key);
// TODO.. why does this come back as binary/octetstring
assertEquals(newObject.getMetadata().getContentType(),
"binary/octet-stream");
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()
.iterator().next(), "powderpuff");
assertEquals(newObject.getMetadata().getMd5(), S3Utils.md5(TEST_STRING
.getBytes()));
}
@Test()
void testCannedAccessPolicyPublic() throws Exception {
String bucketName = bucketPrefix + "tcapp";
createBucketAndEnsureEmpty(bucketName);
String key = "hello";
client.putBucketIfNotExists(bucketName,
withBucketAcl(CannedAccessPolicy.PUBLIC_READ)).get(10,
TimeUnit.SECONDS);
client.putObject(bucketName, new S3Object(key, TEST_STRING),
withAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com/%2$s",
bucketName, key));
S3Utils.toStringAndClose(url.openStream());
// TODO.. why does this come back as binary/octetstring
assertEquals(newObject.getMetadata().getContentType(),
"binary/octet-stream");
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()
.iterator().next(), "powderpuff");
assertEquals(newObject.getMetadata().getMd5(), S3Utils.md5(TEST_STRING
.getBytes()));
} }
} }

View File

@ -0,0 +1,69 @@
/**
*
* 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 org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl;
import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.withAcl;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.util.S3Utils;
import org.testng.annotations.Test;
import java.net.URL;
import java.util.concurrent.TimeUnit;
/**
* Tests integrated functionality of all PutObject commands.
* <p/>
* Each test uses a different bucket name, so it should be perfectly fine to run
* in parallel.
*
* @author Adrian Cole
*/
@Test(testName = "s3.PutObjectLiveTest")
public class PutObjectLiveTest extends S3IntegrationTest {
@Test(groups = {"live"})
void testCannedAccessPolicyPublic() throws Exception {
String bucketName = bucketPrefix + "tcapp";
createBucketAndEnsureEmpty(bucketName);
String key = "hello";
client.putBucketIfNotExists(bucketName,
withBucketAcl(CannedAccessPolicy.PUBLIC_READ)).get(10,
TimeUnit.SECONDS);
client.putObject(bucketName, new S3Object(key, TEST_STRING),
withAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com/%2$s",
bucketName, key));
S3Utils.toStringAndClose(url.openStream());
}
}

View File

@ -23,140 +23,131 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import org.jclouds.aws.s3.commands.config.S3CommandsModule;
import org.jclouds.aws.s3.commands.options.CopyObjectOptions;
import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.commands.options.ListBucketOptions;
import org.jclouds.aws.s3.commands.options.PutBucketOptions;
import org.jclouds.aws.s3.commands.options.PutObjectOptions;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.name.Names; import com.google.inject.name.Names;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import org.jclouds.aws.s3.commands.config.S3CommandsModule;
import org.jclouds.aws.s3.commands.options.*;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.jclouds.aws.s3.domain.S3Object;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test @Test(groups = {"unit"}, testName = "s3.S3CommandFactoryTest")
public class S3CommandFactoryTest { public class S3CommandFactoryTest {
Injector injector = null; Injector injector = null;
S3CommandFactory commandFactory = null; S3CommandFactory commandFactory = null;
public static final String listAllMyBucketsResult = "<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/callables/\"><Owner ><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID></Owner><Buckets><Bucket><Name>adrianjbosstest</Name><CreationDate>2009-03-12T02:00:07.000Z</CreationDate></Bucket><Bucket><Name>adrianjbosstest2</Name><CreationDate>2009-03-12T02:00:09.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>";
@BeforeMethod @BeforeMethod
void setUpInjector() { void setUpInjector() {
injector = Guice.createInjector(new S3CommandsModule() { injector = Guice.createInjector(new S3CommandsModule() {
@Override @Override
protected void configure() { protected void configure() {
bindConstant().annotatedWith( bindConstant().annotatedWith(
Names.named("jclouds.http.address")).to("localhost"); Names.named("jclouds.http.address")).to("localhost");
super.configure(); super.configure();
} }
}); });
commandFactory = injector.getInstance(S3CommandFactory.class); commandFactory = injector.getInstance(S3CommandFactory.class);
} }
@AfterMethod @AfterMethod
void tearDownInjector() { void tearDownInjector() {
commandFactory = null; commandFactory = null;
injector = null; injector = null;
} }
@Test @Test
void testCreateCopyObject() { void testCreateCopyObject() {
assert commandFactory.createCopyObject("sourcebucket", "sourceObject", assert commandFactory.createCopyObject("sourcebucket", "sourceObject",
"destbucket", "destObject", CopyObjectOptions.NONE) != null; "destbucket", "destObject", CopyObjectOptions.NONE) != null;
} }
@Test @Test
void testCreateCopyObjectOptions() { void testCreateCopyObjectOptions() {
assert commandFactory.createCopyObject("sourcebucket", "sourceObject", assert commandFactory.createCopyObject("sourcebucket", "sourceObject",
"destbucket", "destObject", new CopyObjectOptions()) != null; "destbucket", "destObject", new CopyObjectOptions()) != null;
} }
@Test @Test
void testCreateDeleteBucket() { void testCreateDeleteBucket() {
assert commandFactory.createDeleteBucket("test") != null; assert commandFactory.createDeleteBucket("test") != null;
} }
@Test @Test
void testCreateDeleteObject() { void testCreateDeleteObject() {
assert commandFactory.createDeleteObject("test", "blah") != null; assert commandFactory.createDeleteObject("test", "blah") != null;
} }
@Test @Test
void testCreateHeadBucket() { void testCreateHeadBucket() {
assert commandFactory.createHeadBucket("test") != null; assert commandFactory.createHeadBucket("test") != null;
} }
@Test @Test
void testCreatePutBucket() { void testCreatePutBucket() {
assert commandFactory.createPutBucket("test", PutBucketOptions.NONE) != null; assert commandFactory.createPutBucket("test", PutBucketOptions.NONE) != null;
} }
@Test @Test
void testCreatePutBucketOptions() { void testCreatePutBucketOptions() {
assert commandFactory.createPutBucket("test", PutBucketOptions.Builder assert commandFactory.createPutBucket("test", PutBucketOptions.Builder
.createIn(LocationConstraint.EU)) != null; .createIn(LocationConstraint.EU)) != null;
} }
@Test @Test
void testCreatePutObject() { void testCreatePutObject() {
S3Object.Metadata metadata = createMock(S3Object.Metadata.class); S3Object.Metadata metadata = createMock(S3Object.Metadata.class);
S3Object object = new S3Object(metadata); S3Object object = new S3Object(metadata);
expect(metadata.getSize()).andReturn(4L).atLeastOnce(); expect(metadata.getSize()).andReturn(4L).atLeastOnce();
expect(metadata.getKey()).andReturn("rawr"); expect(metadata.getKey()).andReturn("rawr");
expect(metadata.getContentType()).andReturn("text/xml").atLeastOnce(); expect(metadata.getContentType()).andReturn("text/xml").atLeastOnce();
expect(metadata.getCacheControl()).andReturn("no-cache").atLeastOnce(); expect(metadata.getCacheControl()).andReturn("no-cache").atLeastOnce();
expect(metadata.getContentDisposition()).andReturn("disposition") expect(metadata.getContentDisposition()).andReturn("disposition")
.atLeastOnce(); .atLeastOnce();
expect(metadata.getContentEncoding()).andReturn("encoding") expect(metadata.getContentEncoding()).andReturn("encoding")
.atLeastOnce(); .atLeastOnce();
expect(metadata.getMd5()).andReturn("encoding".getBytes()) expect(metadata.getMd5()).andReturn("encoding".getBytes())
.atLeastOnce(); .atLeastOnce();
Multimap<String, String> userMdata = HashMultimap.create(); 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>"); object.setData("<a></a>");
assert commandFactory.createPutObject("test", object, assert commandFactory.createPutObject("test", object,
PutObjectOptions.NONE) != null; PutObjectOptions.NONE) != null;
} }
@Test @Test
void testCreateGetObject() { void testCreateGetObject() {
assert commandFactory.createGetObject("test", "blah", assert commandFactory.createGetObject("test", "blah",
GetObjectOptions.NONE) != null; GetObjectOptions.NONE) != null;
} }
@Test @Test
void testCreateHeadMetadata() { void testCreateHeadMetadata() {
assert commandFactory.createHeadMetadata("test", "blah") != null; assert commandFactory.createHeadMetadata("test", "blah") != null;
} }
@Test @Test
void testCreateListAllMyBuckets() { void testCreateListAllMyBuckets() {
assert commandFactory.createGetMetadataForOwnedBuckets() != null; assert commandFactory.createGetMetadataForOwnedBuckets() != null;
} }
@Test @Test
void testCreateListBucket() { void testCreateListBucket() {
assert commandFactory.createListBucket("test", ListBucketOptions.NONE) != null; assert commandFactory.createListBucket("test", ListBucketOptions.NONE) != null;
} }
} }

View File

@ -23,16 +23,8 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import static org.testng.Assert.assertEquals; import com.google.inject.Guice;
import com.google.inject.Injector;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.aws.PerformanceTest; import org.jclouds.aws.PerformanceTest;
import org.jclouds.aws.s3.domain.CanonicalUser; import org.jclouds.aws.s3.domain.CanonicalUser;
@ -46,20 +38,26 @@ import org.jclouds.aws.s3.xml.config.S3ParserModule;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import com.google.inject.Guice; import java.io.IOException;
import com.google.inject.Injector; import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
/** /**
* Tests parsing of S3 responses * Tests parsing of S3 responses
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", sequential = true, testName = "s3.S3ParserTest") @Test(groups = {"performance"}, testName = "s3.S3ParserTest")
public class S3ParserTest extends PerformanceTest { public class S3ParserTest extends PerformanceTest {
Injector injector = null; Injector injector = null;
@ -69,136 +67,136 @@ public class S3ParserTest extends PerformanceTest {
@BeforeMethod @BeforeMethod
protected void setUpInjector() { protected void setUpInjector() {
injector = Guice.createInjector(new S3ParserModule()); injector = Guice.createInjector(new S3ParserModule());
parserFactory = injector.getInstance(S3ParserFactory.class); parserFactory = injector.getInstance(S3ParserFactory.class);
assert parserFactory != null; assert parserFactory != null;
} }
@AfterMethod @AfterMethod
protected void tearDownInjector() { protected void tearDownInjector() {
parserFactory = null; parserFactory = null;
injector = null; injector = null;
} }
@Test @Test
void testParseListAllMyBucketsSerialResponseTime() throws HttpException { void testParseListAllMyBucketsSerialResponseTime() throws HttpException {
for (int i = 0; i < LOOP_COUNT; i++) for (int i = 0; i < LOOP_COUNT; i++)
runParseListAllMyBuckets(); runParseListAllMyBuckets();
} }
private List<S3Bucket.Metadata> runParseListAllMyBuckets() private List<S3Bucket.Metadata> runParseListAllMyBuckets()
throws HttpException { throws HttpException {
return parserFactory.createListBucketsParser().parse( return parserFactory.createListBucketsParser().parse(
IOUtils.toInputStream(listAllMyBucketsResultOn200)); IOUtils.toInputStream(listAllMyBucketsResultOn200));
} }
@Test @Test
void testParseListAllMyBucketsParallelResponseTime() void testParseListAllMyBucketsParallelResponseTime()
throws InterruptedException, ExecutionException { throws InterruptedException, ExecutionException {
CompletionService<List<S3Bucket.Metadata>> completer = new ExecutorCompletionService<List<S3Bucket.Metadata>>( CompletionService<List<S3Bucket.Metadata>> completer = new ExecutorCompletionService<List<S3Bucket.Metadata>>(
exec); exec);
for (int i = 0; i < LOOP_COUNT; i++) for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<List<S3Bucket.Metadata>>() { completer.submit(new Callable<List<S3Bucket.Metadata>>() {
public List<S3Bucket.Metadata> call() throws IOException, public List<S3Bucket.Metadata> call() throws IOException,
SAXException, HttpException { SAXException, HttpException {
return runParseListAllMyBuckets(); return runParseListAllMyBuckets();
} }
}); });
for (int i = 0; i < LOOP_COUNT; i++) for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get() != null; assert completer.take().get() != null;
} }
@Test @Test
public void testCanParseListAllMyBuckets() throws HttpException { public void testCanParseListAllMyBuckets() throws HttpException {
List<S3Bucket.Metadata> s3Buckets = runParseListAllMyBuckets(); List<S3Bucket.Metadata> s3Buckets = runParseListAllMyBuckets();
S3Bucket.Metadata bucket1 = s3Buckets.get(0); S3Bucket.Metadata bucket1 = s3Buckets.get(0);
assert bucket1.getName().equals("adrianjbosstest"); assert bucket1.getName().equals("adrianjbosstest");
DateTime expectedDate1 = new DateTime("2009-03-12T02:00:07.000Z"); DateTime expectedDate1 = new DateTime("2009-03-12T02:00:07.000Z");
DateTime date1 = bucket1.getCreationDate(); DateTime date1 = bucket1.getCreationDate();
assert date1.equals(expectedDate1); assert date1.equals(expectedDate1);
S3Bucket.Metadata bucket2 = s3Buckets.get(1); S3Bucket.Metadata bucket2 = s3Buckets.get(1);
assert bucket2.getName().equals("adrianjbosstest2"); assert bucket2.getName().equals("adrianjbosstest2");
DateTime expectedDate2 = new DateTime("2009-03-12T02:00:09.000Z"); DateTime expectedDate2 = new DateTime("2009-03-12T02:00:09.000Z");
DateTime date2 = bucket2.getCreationDate(); DateTime date2 = bucket2.getCreationDate();
assert date2.equals(expectedDate2); assert date2.equals(expectedDate2);
assert s3Buckets.size() == 2; assert s3Buckets.size() == 2;
CanonicalUser owner = new CanonicalUser( CanonicalUser owner = new CanonicalUser(
"e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0"); "e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
assert bucket1.getOwner().equals(owner); assert bucket1.getOwner().equals(owner);
assert bucket2.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>"; 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>";
public void testCanParseListBucketResult() throws HttpException, public void testCanParseListBucketResult() throws HttpException,
UnsupportedEncodingException { UnsupportedEncodingException {
S3Bucket bucket = runParseListBucketResult(); S3Bucket bucket = runParseListBucketResult();
assert bucket.isComplete(); assert !bucket.isTruncated();
assert bucket.getName().equals("adrianjbosstest"); assert bucket.getName().equals("adrianjbosstest");
assert bucket.getContents().size() == 1; assert bucket.getContents().size() == 1;
S3Object.Metadata object = bucket.getContents().iterator().next(); S3Object.Metadata object = bucket.getContents().iterator().next();
assert object.getKey().equals("3366"); assert object.getKey().equals("3366");
DateTime expected = new DateTime("2009-03-12T02:00:13.000Z"); DateTime expected = new DateTime("2009-03-12T02:00:13.000Z");
assert object.getLastModified().equals(expected) : String.format( assert object.getLastModified().equals(expected) : String.format(
"expected %1$s, but got %1$s", expected, object "expected %1$s, but got %1$s", expected, object
.getLastModified()); .getLastModified());
assertEquals(S3Utils.toHexString(object.getMd5()), assertEquals(S3Utils.toHexString(object.getMd5()),
"9d7bb64e8e18ee34eec06dd2cf37b766"); "9d7bb64e8e18ee34eec06dd2cf37b766");
assert object.getSize() == 136; assert object.getSize() == 136;
CanonicalUser owner = new CanonicalUser( CanonicalUser owner = new CanonicalUser(
"e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0"); "e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
owner.setDisplayName("ferncam"); owner.setDisplayName("ferncam");
assert object.getOwner().equals(owner); assert object.getOwner().equals(owner);
assert object.getStorageClass().equals("STANDARD"); assert object.getStorageClass().equals("STANDARD");
} }
private S3Bucket runParseListBucketResult() throws HttpException { private S3Bucket runParseListBucketResult() throws HttpException {
ParseSax<S3Bucket> parser = parserFactory.createListBucketParser(); ParseSax<S3Bucket> parser = parserFactory.createListBucketParser();
ListBucketHandler handler = (ListBucketHandler) parser.getHandler(); ListBucketHandler handler = (ListBucketHandler) parser.getHandler();
handler.setBucketName("adrianjbosstest"); handler.setBucketName("adrianjbosstest");
return parser.parse(IOUtils.toInputStream(listBucketResult)); return parser.parse(IOUtils.toInputStream(listBucketResult));
} }
public static final String successfulCopyObject200 = "<CopyObjectResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><LastModified>2009-03-19T13:23:27.000Z</LastModified><ETag>\"92836a3ea45a6984d1b4d23a747d46bb\"</ETag></CopyObjectResult>"; public static final String successfulCopyObject200 = "<CopyObjectResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><LastModified>2009-03-19T13:23:27.000Z</LastModified><ETag>\"92836a3ea45a6984d1b4d23a747d46bb\"</ETag></CopyObjectResult>";
private S3Object.Metadata runParseCopyObjectResult() throws HttpException { private S3Object.Metadata runParseCopyObjectResult() throws HttpException {
ParseSax<S3Object.Metadata> parser = parserFactory ParseSax<S3Object.Metadata> parser = parserFactory
.createCopyObjectParser(); .createCopyObjectParser();
CopyObjectHandler handler = (CopyObjectHandler) parser.getHandler(); CopyObjectHandler handler = (CopyObjectHandler) parser.getHandler();
handler.setKey("adrianjbosstest"); handler.setKey("adrianjbosstest");
return parser.parse(IOUtils.toInputStream(successfulCopyObject200)); return parser.parse(IOUtils.toInputStream(successfulCopyObject200));
} }
public void testCanParseCopyObjectResult() throws HttpException, public void testCanParseCopyObjectResult() throws HttpException,
UnsupportedEncodingException { UnsupportedEncodingException {
S3Object.Metadata metadata = runParseCopyObjectResult(); S3Object.Metadata metadata = runParseCopyObjectResult();
DateTime expected = new DateTime("2009-03-19T13:23:27.000Z"); DateTime expected = new DateTime("2009-03-19T13:23:27.000Z");
assertEquals(metadata.getLastModified(), expected); assertEquals(metadata.getLastModified(), expected);
assertEquals(S3Utils.toHexString(metadata.getMd5()), assertEquals(S3Utils.toHexString(metadata.getMd5()),
"92836a3ea45a6984d1b4d23a747d46bb"); "92836a3ea45a6984d1b4d23a747d46bb");
assertEquals(metadata.getKey(), "adrianjbosstest"); assertEquals(metadata.getKey(), "adrianjbosstest");
} }
@Test @Test
void testParseListBucketResultSerialResponseTime() throws HttpException { void testParseListBucketResultSerialResponseTime() throws HttpException {
for (int i = 0; i < LOOP_COUNT; i++) for (int i = 0; i < LOOP_COUNT; i++)
runParseListBucketResult(); runParseListBucketResult();
} }
@Test @Test
void testParseListBucketResultParallelResponseTime() void testParseListBucketResultParallelResponseTime()
throws InterruptedException, ExecutionException { throws InterruptedException, ExecutionException {
CompletionService<S3Bucket> completer = new ExecutorCompletionService<S3Bucket>( CompletionService<S3Bucket> completer = new ExecutorCompletionService<S3Bucket>(
exec); exec);
for (int i = 0; i < LOOP_COUNT; i++) for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<S3Bucket>() { completer.submit(new Callable<S3Bucket>() {
public S3Bucket call() throws IOException, SAXException, public S3Bucket call() throws IOException, SAXException,
HttpException { HttpException {
return runParseListBucketResult(); return runParseListBucketResult();
} }
}); });
for (int i = 0; i < LOOP_COUNT; i++) for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get() != null; assert completer.take().get() != null;
} }
} }

View File

@ -23,77 +23,74 @@
*/ */
package org.jclouds.aws.s3.commands.callables; 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.apache.commons.io.IOUtils;
import static org.easymock.classextension.EasyMock.*;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.S3Object.Metadata; import org.jclouds.aws.s3.domain.S3Object.Metadata;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpHeaders; import org.jclouds.http.HttpHeaders;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test @Test(groups = "unit", testName = "s3.ParseObjectFromHeadersAndHttpContentTest")
public class ParseObjectFromHeadersAndHttpContentTest { public class ParseObjectFromHeadersAndHttpContentTest {
ParseObjectFromHeadersAndHttpContent callable; ParseObjectFromHeadersAndHttpContent callable;
ParseMetadataFromHeaders metadataParser; ParseMetadataFromHeaders metadataParser;
@BeforeMethod @BeforeMethod
void setUp() { void setUp() {
metadataParser = createMock(ParseMetadataFromHeaders.class); metadataParser = createMock(ParseMetadataFromHeaders.class);
callable = new ParseObjectFromHeadersAndHttpContent(metadataParser); callable = new ParseObjectFromHeadersAndHttpContent(metadataParser);
} }
@AfterMethod @AfterMethod
void tearDown() { void tearDown() {
callable = null; callable = null;
} }
@Test(expectedExceptions = IllegalStateException.class) @Test(expectedExceptions = IllegalStateException.class)
public void testCall() throws HttpException { public void testCall() throws HttpException {
HttpResponse response = createMock(HttpResponse.class); HttpResponse response = createMock(HttpResponse.class);
expect(response.getStatusCode()).andReturn(409).atLeastOnce(); expect(response.getStatusCode()).andReturn(409).atLeastOnce();
expect(response.getContent()).andReturn(null); expect(response.getContent()).andReturn(null);
replay(response); replay(response);
callable.setResponse(response); callable.setResponse(response);
callable.call(); callable.call();
} }
@Test @Test
public void testParseContentLengthWhenContentRangeSet() public void testParseContentLengthWhenContentRangeSet()
throws HttpException { throws HttpException {
HttpResponse response = createMock(HttpResponse.class); HttpResponse response = createMock(HttpResponse.class);
metadataParser.setResponse(response); metadataParser.setResponse(response);
Metadata meta = createMock(Metadata.class); Metadata meta = createMock(Metadata.class);
expect(metadataParser.call()).andReturn(meta); expect(metadataParser.call()).andReturn(meta);
expect(meta.getSize()).andReturn(-1l); expect(meta.getSize()).andReturn(-1l);
meta.setSize(-1l); meta.setSize(-1l);
expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH)) expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH))
.andReturn("10485760").atLeastOnce(); .andReturn("10485760").atLeastOnce();
expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_RANGE)) expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_RANGE))
.andReturn("0-10485759/20232760").atLeastOnce(); .andReturn("0-10485759/20232760").atLeastOnce();
meta.setSize(20232760l); meta.setSize(20232760l);
expect(meta.getSize()).andReturn(20232760l); expect(meta.getSize()).andReturn(20232760l);
expect(response.getStatusCode()).andReturn(200).atLeastOnce(); expect(response.getStatusCode()).andReturn(200).atLeastOnce();
expect(response.getContent()).andReturn(IOUtils.toInputStream("test")); expect(response.getContent()).andReturn(IOUtils.toInputStream("test"));
replay(response); replay(response);
replay(metadataParser); replay(metadataParser);
replay(meta); replay(meta);
callable.setResponse(response); callable.setResponse(response);
S3Object object = callable.call(); S3Object object = callable.call();
assertEquals(object.getContentLength(), 10485760); assertEquals(object.getContentLength(), 10485760);
assertEquals(object.getMetadata().getSize(), 20232760); assertEquals(object.getMetadata().getSize(), 20232760);
assertEquals(object.getContentRange(), "0-10485759/20232760"); assertEquals(object.getContentRange(), "0-10485759/20232760");
} }

View File

@ -23,34 +23,26 @@
*/ */
package org.jclouds.aws.s3.commands.options; package org.jclouds.aws.s3.commands.options;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5DoesntMatch; import com.google.common.collect.HashMultimap;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5Matches; import com.google.common.collect.Multimap;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceModifiedSince; import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.*;
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;
import static org.testng.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.DateService; import org.jclouds.aws.s3.util.DateService;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import static org.testng.Assert.*;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.HashMultimap; import java.io.UnsupportedEncodingException;
import com.google.common.collect.Multimap;
/** /**
* Tests possible uses of CopyObjectOptions and CopyObjectOptions.Builder.* * Tests possible uses of CopyObjectOptions and CopyObjectOptions.Builder.*
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "s3.CopyObjectOptionsTest")
public class CopyObjectOptionsTest { public class CopyObjectOptionsTest {
private byte[] testBytes; private byte[] testBytes;
@ -61,279 +53,279 @@ public class CopyObjectOptionsTest {
@BeforeMethod @BeforeMethod
void setUp() { void setUp() {
goodMeta = HashMultimap.create(); goodMeta = HashMultimap.create();
goodMeta.put("x-amz-meta-adrian", "foo"); goodMeta.put("x-amz-meta-adrian", "foo");
badMeta = HashMultimap.create(); badMeta = HashMultimap.create();
badMeta.put("x-google-meta-adrian", "foo"); badMeta.put("x-google-meta-adrian", "foo");
now = new DateTime(); now = new DateTime();
nowExpected = new DateService().toHeaderString(now); nowExpected = new DateService().toHeaderString(now);
testBytes = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; testBytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
} }
@Test @Test
void testGoodMetaStatic() { void testGoodMetaStatic() {
CopyObjectOptions options = overrideMetadataWith(goodMeta); CopyObjectOptions options = overrideMetadataWith(goodMeta);
assertGoodMeta(options); assertGoodMeta(options);
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testMetaNPE() { public void testMetaNPE() {
overrideMetadataWith(null); overrideMetadataWith(null);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testBadMeta() { public void testBadMeta() {
overrideMetadataWith(badMeta); overrideMetadataWith(badMeta);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testBadMetaStatic() { public void testBadMetaStatic() {
overrideMetadataWith(badMeta); overrideMetadataWith(badMeta);
} }
private void assertGoodMeta(CopyObjectOptions options) { private void assertGoodMeta(CopyObjectOptions options) {
assert options != null; assert options != null;
assert options.getMetadata() != null; assert options.getMetadata() != null;
Multimap<String,String> headers = options.buildRequestHeaders(); Multimap<String, String> headers = options.buildRequestHeaders();
assertEquals(headers.size(), 2); assertEquals(headers.size(), 2);
assertEquals(headers.get( assertEquals(headers.get(
"x-amz-metadata-directive").iterator().next(), "x-amz-metadata-directive").iterator().next(),
"REPLACE"); "REPLACE");
assertEquals(options.getMetadata().size(), 1); assertEquals(options.getMetadata().size(), 1);
assertEquals(headers.get("x-amz-meta-adrian").iterator() assertEquals(headers.get("x-amz-meta-adrian").iterator()
.next(), "foo"); .next(), "foo");
assertEquals(options.getMetadata().get("x-amz-meta-adrian").iterator() assertEquals(options.getMetadata().get("x-amz-meta-adrian").iterator()
.next(), "foo"); .next(), "foo");
} }
@Test @Test
void testGoodMeta() { void testGoodMeta() {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
options.overrideMetadataWith(goodMeta); options.overrideMetadataWith(goodMeta);
assertGoodMeta(options); assertGoodMeta(options);
} }
@Test @Test
public void testIfModifiedSince() { public void testIfModifiedSince() {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
options.ifSourceModifiedSince(now); options.ifSourceModifiedSince(now);
assertEquals(options.getIfModifiedSince(), nowExpected); assertEquals(options.getIfModifiedSince(), nowExpected);
} }
@Test @Test
public void testNullIfModifiedSince() { public void testNullIfModifiedSince() {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
assertNull(options.getIfModifiedSince()); assertNull(options.getIfModifiedSince());
} }
@Test @Test
public void testIfModifiedSinceStatic() { public void testIfModifiedSinceStatic() {
CopyObjectOptions options = ifSourceModifiedSince(now); CopyObjectOptions options = ifSourceModifiedSince(now);
assertEquals(options.getIfModifiedSince(), nowExpected); assertEquals(options.getIfModifiedSince(), nowExpected);
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testIfModifiedSinceNPE() { public void testIfModifiedSinceNPE() {
ifSourceModifiedSince(null); ifSourceModifiedSince(null);
} }
@Test @Test
public void testIfUnmodifiedSince() { public void testIfUnmodifiedSince() {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
options.ifSourceUnmodifiedSince(now); options.ifSourceUnmodifiedSince(now);
isNowExpected(options); isNowExpected(options);
} }
@Test @Test
public void testNullIfUnmodifiedSince() { public void testNullIfUnmodifiedSince() {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
assertNull(options.getIfUnmodifiedSince()); assertNull(options.getIfUnmodifiedSince());
} }
@Test @Test
public void testIfUnmodifiedSinceStatic() { public void testIfUnmodifiedSinceStatic() {
CopyObjectOptions options = ifSourceUnmodifiedSince(now); CopyObjectOptions options = ifSourceUnmodifiedSince(now);
isNowExpected(options); isNowExpected(options);
} }
private void isNowExpected(CopyObjectOptions options) { private void isNowExpected(CopyObjectOptions options) {
assertEquals(options.getIfUnmodifiedSince(), nowExpected); assertEquals(options.getIfUnmodifiedSince(), nowExpected);
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testIfUnmodifiedSinceNPE() { public void testIfUnmodifiedSinceNPE() {
ifSourceUnmodifiedSince(null); ifSourceUnmodifiedSince(null);
} }
@Test @Test
public void testIfMd5Matches() throws UnsupportedEncodingException { public void testIfMd5Matches() throws UnsupportedEncodingException {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
options.ifSourceMd5Matches(testBytes); options.ifSourceMd5Matches(testBytes);
matchesHex(options.getIfMatch()); matchesHex(options.getIfMatch());
} }
@Test @Test
public void testNullIfMd5Matches() { public void testNullIfMd5Matches() {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
assertNull(options.getIfMatch()); assertNull(options.getIfMatch());
} }
@Test @Test
public void testIfMd5MatchesStatic() throws UnsupportedEncodingException { public void testIfMd5MatchesStatic() throws UnsupportedEncodingException {
CopyObjectOptions options = ifSourceMd5Matches(testBytes); CopyObjectOptions options = ifSourceMd5Matches(testBytes);
matchesHex(options.getIfMatch()); matchesHex(options.getIfMatch());
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testIfMd5MatchesNPE() throws UnsupportedEncodingException { public void testIfMd5MatchesNPE() throws UnsupportedEncodingException {
ifSourceMd5Matches(null); ifSourceMd5Matches(null);
} }
@Test @Test
public void testIfMd5DoesntMatch() throws UnsupportedEncodingException { public void testIfMd5DoesntMatch() throws UnsupportedEncodingException {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
options.ifSourceMd5DoesntMatch(testBytes); options.ifSourceMd5DoesntMatch(testBytes);
matchesHex(options.getIfNoneMatch()); matchesHex(options.getIfNoneMatch());
} }
@Test @Test
public void testNullIfMd5DoesntMatch() { public void testNullIfMd5DoesntMatch() {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
assertNull(options.getIfNoneMatch()); assertNull(options.getIfNoneMatch());
} }
@Test @Test
public void testIfMd5DoesntMatchStatic() public void testIfMd5DoesntMatchStatic()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
CopyObjectOptions options = ifSourceMd5DoesntMatch(testBytes); CopyObjectOptions options = ifSourceMd5DoesntMatch(testBytes);
matchesHex(options.getIfNoneMatch()); matchesHex(options.getIfNoneMatch());
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testIfMd5DoesntMatchNPE() throws UnsupportedEncodingException { public void testIfMd5DoesntMatchNPE() throws UnsupportedEncodingException {
ifSourceMd5DoesntMatch(null); ifSourceMd5DoesntMatch(null);
} }
private void matchesHex(String match) throws UnsupportedEncodingException { private void matchesHex(String match) throws UnsupportedEncodingException {
String expected = "\"" + S3Utils.toHexString(testBytes) + "\""; String expected = "\"" + S3Utils.toHexString(testBytes) + "\"";
assertEquals(match, expected); assertEquals(match, expected);
} }
@Test(expectedExceptions = IllegalStateException.class) @Test(expectedExceptions = IllegalStateException.class)
public void testIfUnmodifiedAfterModified() { public void testIfUnmodifiedAfterModified() {
ifSourceModifiedSince(now).ifSourceUnmodifiedSince(now); ifSourceModifiedSince(now).ifSourceUnmodifiedSince(now);
} }
public void testIfUnmodifiedAfterMd5Matches() public void testIfUnmodifiedAfterMd5Matches()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifSourceMd5Matches(testBytes).ifSourceUnmodifiedSince(now); ifSourceMd5Matches(testBytes).ifSourceUnmodifiedSince(now);
} }
@Test(expectedExceptions = IllegalStateException.class) @Test(expectedExceptions = IllegalStateException.class)
public void testIfUnmodifiedAfterMd5DoesntMatch() public void testIfUnmodifiedAfterMd5DoesntMatch()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifSourceMd5DoesntMatch(testBytes).ifSourceUnmodifiedSince(now); ifSourceMd5DoesntMatch(testBytes).ifSourceUnmodifiedSince(now);
} }
@Test(expectedExceptions = IllegalStateException.class) @Test(expectedExceptions = IllegalStateException.class)
public void testIfModifiedAfterUnmodified() { public void testIfModifiedAfterUnmodified() {
ifSourceUnmodifiedSince(now).ifSourceModifiedSince(now); ifSourceUnmodifiedSince(now).ifSourceModifiedSince(now);
} }
@Test(expectedExceptions = IllegalStateException.class) @Test(expectedExceptions = IllegalStateException.class)
public void testIfModifiedAfterMd5Matches() public void testIfModifiedAfterMd5Matches()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifSourceMd5Matches(testBytes).ifSourceModifiedSince(now); ifSourceMd5Matches(testBytes).ifSourceModifiedSince(now);
} }
public void testIfModifiedAfterMd5DoesntMatch() public void testIfModifiedAfterMd5DoesntMatch()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifSourceMd5DoesntMatch(testBytes).ifSourceModifiedSince(now); ifSourceMd5DoesntMatch(testBytes).ifSourceModifiedSince(now);
} }
@Test(expectedExceptions = IllegalStateException.class) @Test(expectedExceptions = IllegalStateException.class)
public void testMd5MatchesAfterIfModified() public void testMd5MatchesAfterIfModified()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifSourceModifiedSince(now).ifSourceMd5Matches(testBytes); ifSourceModifiedSince(now).ifSourceMd5Matches(testBytes);
} }
public void testMd5MatchesAfterIfUnmodified() public void testMd5MatchesAfterIfUnmodified()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifSourceUnmodifiedSince(now).ifSourceMd5Matches(testBytes); ifSourceUnmodifiedSince(now).ifSourceMd5Matches(testBytes);
} }
@Test(expectedExceptions = IllegalStateException.class) @Test(expectedExceptions = IllegalStateException.class)
public void testMd5MatchesAfterMd5DoesntMatch() public void testMd5MatchesAfterMd5DoesntMatch()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifSourceMd5DoesntMatch(testBytes).ifSourceMd5Matches(testBytes); ifSourceMd5DoesntMatch(testBytes).ifSourceMd5Matches(testBytes);
} }
public void testMd5DoesntMatchAfterIfModified() public void testMd5DoesntMatchAfterIfModified()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifSourceModifiedSince(now).ifSourceMd5DoesntMatch(testBytes); ifSourceModifiedSince(now).ifSourceMd5DoesntMatch(testBytes);
} }
@Test(expectedExceptions = IllegalStateException.class) @Test(expectedExceptions = IllegalStateException.class)
public void testMd5DoesntMatchAfterIfUnmodified() public void testMd5DoesntMatchAfterIfUnmodified()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifSourceUnmodifiedSince(now).ifSourceMd5DoesntMatch(testBytes); ifSourceUnmodifiedSince(now).ifSourceMd5DoesntMatch(testBytes);
} }
@Test(expectedExceptions = IllegalStateException.class) @Test(expectedExceptions = IllegalStateException.class)
public void testMd5DoesntMatchAfterMd5Matches() public void testMd5DoesntMatchAfterMd5Matches()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifSourceMd5Matches(testBytes).ifSourceMd5DoesntMatch(testBytes); ifSourceMd5Matches(testBytes).ifSourceMd5DoesntMatch(testBytes);
} }
@Test @Test
void testBuildRequestHeadersWhenMetadataNull() void testBuildRequestHeadersWhenMetadataNull()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
assert new CopyObjectOptions().buildRequestHeaders() != null; assert new CopyObjectOptions().buildRequestHeaders() != null;
} }
@Test @Test
void testBuildRequestHeaders() throws UnsupportedEncodingException { void testBuildRequestHeaders() throws UnsupportedEncodingException {
Multimap<String, String> headers = ifSourceModifiedSince(now) Multimap<String, String> headers = ifSourceModifiedSince(now)
.ifSourceMd5DoesntMatch(testBytes).overrideMetadataWith( .ifSourceMd5DoesntMatch(testBytes).overrideMetadataWith(
goodMeta).buildRequestHeaders(); goodMeta).buildRequestHeaders();
assertEquals(headers.get("x-amz-copy-source-if-modified-since") assertEquals(headers.get("x-amz-copy-source-if-modified-since")
.iterator().next(), new DateService().toHeaderString(now)); .iterator().next(), new DateService().toHeaderString(now));
assertEquals(headers.get("x-amz-copy-source-if-none-match").iterator() assertEquals(headers.get("x-amz-copy-source-if-none-match").iterator()
.next(), "\"" + S3Utils.toHexString(testBytes) + "\""); .next(), "\"" + S3Utils.toHexString(testBytes) + "\"");
for (String value : goodMeta.values()) for (String value : goodMeta.values())
assertTrue(headers.containsValue(value)); assertTrue(headers.containsValue(value));
} }
@Test @Test
public void testAclDefault() { public void testAclDefault() {
CopyObjectOptions options = new CopyObjectOptions(); CopyObjectOptions options = new CopyObjectOptions();
assertEquals(options.getAcl(), CannedAccessPolicy.PRIVATE); assertEquals(options.getAcl(), CannedAccessPolicy.PRIVATE);
} }
@Test @Test
public void testAclStatic() { public void testAclStatic() {
CopyObjectOptions options = overrideAcl(CannedAccessPolicy.AUTHENTICATED_READ); CopyObjectOptions options = overrideAcl(CannedAccessPolicy.AUTHENTICATED_READ);
assertEquals(options.getAcl(), CannedAccessPolicy.AUTHENTICATED_READ); assertEquals(options.getAcl(), CannedAccessPolicy.AUTHENTICATED_READ);
} }
@Test @Test
void testBuildRequestHeadersACL() throws UnsupportedEncodingException { void testBuildRequestHeadersACL() throws UnsupportedEncodingException {
Multimap<String, String> headers = overrideAcl( Multimap<String, String> headers = overrideAcl(
CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders(); CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders();
assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(), assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(),
CannedAccessPolicy.AUTHENTICATED_READ.toString()); CannedAccessPolicy.AUTHENTICATED_READ.toString());
} }
} }

View File

@ -23,29 +23,23 @@
*/ */
package org.jclouds.aws.s3.commands.options; 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.*;
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;
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.ifUnmodifiedSince;
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.range;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.io.UnsupportedEncodingException;
import org.jclouds.aws.s3.util.DateService; import org.jclouds.aws.s3.util.DateService;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.UnsupportedEncodingException;
/** /**
* Tests possible uses of GetObjectOptions and GetObjectOptions.Builder.* * Tests possible uses of GetObjectOptions and GetObjectOptions.Builder.*
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "s3.GetObjectOptionsTest")
public class GetObjectOptionsTest { public class GetObjectOptionsTest {
private byte[] testBytes; private byte[] testBytes;
@ -54,287 +48,287 @@ public class GetObjectOptionsTest {
@BeforeTest @BeforeTest
void setUp() { void setUp() {
now = new DateTime(); now = new DateTime();
nowExpected = new DateService().toHeaderString(now); nowExpected = new DateService().toHeaderString(now);
testBytes = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; testBytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
} }
@Test @Test
public void testIfModifiedSince() { public void testIfModifiedSince() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.ifModifiedSince(now); options.ifModifiedSince(now);
assertEquals(options.getIfModifiedSince(), nowExpected); assertEquals(options.getIfModifiedSince(), nowExpected);
} }
@Test @Test
public void testNullIfModifiedSince() { public void testNullIfModifiedSince() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
assertNull(options.getIfModifiedSince()); assertNull(options.getIfModifiedSince());
} }
@Test @Test
public void testIfModifiedSinceStatic() { public void testIfModifiedSinceStatic() {
GetObjectOptions options = ifModifiedSince(now); GetObjectOptions options = ifModifiedSince(now);
assertEquals(options.getIfModifiedSince(), nowExpected); assertEquals(options.getIfModifiedSince(), nowExpected);
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testIfModifiedSinceNPE() { public void testIfModifiedSinceNPE() {
ifModifiedSince(null); ifModifiedSince(null);
} }
@Test @Test
public void testIfUnmodifiedSince() { public void testIfUnmodifiedSince() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.ifUnmodifiedSince(now); options.ifUnmodifiedSince(now);
isNowExpected(options); isNowExpected(options);
} }
@Test @Test
public void testNullIfUnmodifiedSince() { public void testNullIfUnmodifiedSince() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
assertNull(options.getIfUnmodifiedSince()); assertNull(options.getIfUnmodifiedSince());
} }
@Test @Test
public void testIfUnmodifiedSinceStatic() { public void testIfUnmodifiedSinceStatic() {
GetObjectOptions options = ifUnmodifiedSince(now); GetObjectOptions options = ifUnmodifiedSince(now);
isNowExpected(options); isNowExpected(options);
} }
private void isNowExpected(GetObjectOptions options) { private void isNowExpected(GetObjectOptions options) {
assertEquals(options.getIfUnmodifiedSince(), nowExpected); assertEquals(options.getIfUnmodifiedSince(), nowExpected);
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testIfUnmodifiedSinceNPE() { public void testIfUnmodifiedSinceNPE() {
ifUnmodifiedSince(null); ifUnmodifiedSince(null);
} }
public void testModifiedSinceAndRange() { public void testModifiedSinceAndRange() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.ifModifiedSince(now); options.ifModifiedSince(now);
options.range(0, 1024); options.range(0, 1024);
isNowExpected(options); assertEquals(options.getIfModifiedSince(), nowExpected);
bytes1to1024(options); bytes1to1024(options);
} }
@Test @Test
public void testRange() { public void testRange() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.range(0, 1024); options.range(0, 1024);
bytes1to1024(options); bytes1to1024(options);
} }
private void bytes1to1024(GetObjectOptions options) { private void bytes1to1024(GetObjectOptions options) {
assertEquals(options.getRange(), "bytes=0-1024"); assertEquals(options.getRange(), "bytes=0-1024");
} }
@Test @Test
public void testRangeZeroToFive() { public void testRangeZeroToFive() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.range(0, 5); options.range(0, 5);
assertEquals(options.getRange(), "bytes=0-5"); assertEquals(options.getRange(), "bytes=0-5");
} }
@Test @Test
public void testTail() { public void testTail() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.tail(100); options.tail(100);
assertEquals(options.getRange(), "bytes=-100"); assertEquals(options.getRange(), "bytes=-100");
} }
@Test @Test
public void testTailStatic() { public void testTailStatic() {
GetObjectOptions options = tail(100); GetObjectOptions options = tail(100);
assertEquals(options.getRange(), "bytes=-100"); assertEquals(options.getRange(), "bytes=-100");
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testTailFail() { public void testTailFail() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.tail(0); options.tail(0);
} }
@Test @Test
public void testStartAt() { public void testStartAt() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.startAt(100); options.startAt(100);
assertEquals(options.getRange(), "bytes=100-"); assertEquals(options.getRange(), "bytes=100-");
} }
@Test @Test
public void testStartAtStatic() { public void testStartAtStatic() {
GetObjectOptions options = startAt(100); GetObjectOptions options = startAt(100);
assertEquals(options.getRange(), "bytes=100-"); assertEquals(options.getRange(), "bytes=100-");
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testStartAtFail() { public void testStartAtFail() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.startAt(-1); options.startAt(-1);
} }
@Test @Test
public void testRangeZeroToFiveAnd10through100() { public void testRangeZeroToFiveAnd10through100() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.range(0, 5).range(10, 100); options.range(0, 5).range(10, 100);
assertEquals(options.getRange(), "bytes=0-5,10-100"); assertEquals(options.getRange(), "bytes=0-5,10-100");
} }
@Test @Test
public void testNullRange() { public void testNullRange() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
assertNull(options.getRange()); assertNull(options.getRange());
} }
@Test @Test
public void testRangeStatic() { public void testRangeStatic() {
GetObjectOptions options = range(0, 1024); GetObjectOptions options = range(0, 1024);
bytes1to1024(options); bytes1to1024(options);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testRangeNegative1() { public void testRangeNegative1() {
range(-1, 0); range(-1, 0);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testRangeNegative2() { public void testRangeNegative2() {
range(0, -1); range(0, -1);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testRangeNegative() { public void testRangeNegative() {
range(-1, -1); range(-1, -1);
} }
@Test @Test
public void testIfMd5Matches() throws UnsupportedEncodingException { public void testIfMd5Matches() throws UnsupportedEncodingException {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.ifMd5Matches(testBytes); options.ifMd5Matches(testBytes);
matchesHex(options.getIfMatch()); matchesHex(options.getIfMatch());
} }
@Test @Test
public void testNullIfMd5Matches() { public void testNullIfMd5Matches() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
assertNull(options.getIfMatch()); assertNull(options.getIfMatch());
} }
@Test @Test
public void testIfMd5MatchesStatic() throws UnsupportedEncodingException { public void testIfMd5MatchesStatic() throws UnsupportedEncodingException {
GetObjectOptions options = ifMd5Matches(testBytes); GetObjectOptions options = ifMd5Matches(testBytes);
matchesHex(options.getIfMatch()); matchesHex(options.getIfMatch());
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testIfMd5MatchesNPE() throws UnsupportedEncodingException { public void testIfMd5MatchesNPE() throws UnsupportedEncodingException {
ifMd5Matches(null); ifMd5Matches(null);
} }
@Test @Test
public void testIfMd5DoesntMatch() throws UnsupportedEncodingException { public void testIfMd5DoesntMatch() throws UnsupportedEncodingException {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.ifMd5DoesntMatch(testBytes); options.ifMd5DoesntMatch(testBytes);
matchesHex(options.getIfNoneMatch()); matchesHex(options.getIfNoneMatch());
} }
@Test @Test
public void testNullIfMd5DoesntMatch() { public void testNullIfMd5DoesntMatch() {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
assertNull(options.getIfNoneMatch()); assertNull(options.getIfNoneMatch());
} }
@Test @Test
public void testIfMd5DoesntMatchStatic() public void testIfMd5DoesntMatchStatic()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
GetObjectOptions options = ifMd5DoesntMatch(testBytes); GetObjectOptions options = ifMd5DoesntMatch(testBytes);
matchesHex(options.getIfNoneMatch()); matchesHex(options.getIfNoneMatch());
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testIfMd5DoesntMatchNPE() throws UnsupportedEncodingException { public void testIfMd5DoesntMatchNPE() throws UnsupportedEncodingException {
ifMd5DoesntMatch(null); ifMd5DoesntMatch(null);
} }
private void matchesHex(String match) throws UnsupportedEncodingException { private void matchesHex(String match) throws UnsupportedEncodingException {
String expected = "\"" + S3Utils.toHexString(testBytes) + "\""; String expected = "\"" + S3Utils.toHexString(testBytes) + "\"";
assertEquals(match, expected); assertEquals(match, expected);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testIfUnmodifiedAfterModified() { public void testIfUnmodifiedAfterModified() {
ifModifiedSince(now).ifUnmodifiedSince(now); ifModifiedSince(now).ifUnmodifiedSince(now);
} }
public void testIfUnmodifiedAfterMd5Matches() public void testIfUnmodifiedAfterMd5Matches()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifMd5Matches(testBytes).ifUnmodifiedSince(now); ifMd5Matches(testBytes).ifUnmodifiedSince(now);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testIfUnmodifiedAfterMd5DoesntMatch() public void testIfUnmodifiedAfterMd5DoesntMatch()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifMd5DoesntMatch(testBytes).ifUnmodifiedSince(now); ifMd5DoesntMatch(testBytes).ifUnmodifiedSince(now);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testIfModifiedAfterUnmodified() { public void testIfModifiedAfterUnmodified() {
ifUnmodifiedSince(now).ifModifiedSince(now); ifUnmodifiedSince(now).ifModifiedSince(now);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testIfModifiedAfterMd5Matches() public void testIfModifiedAfterMd5Matches()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifMd5Matches(testBytes).ifModifiedSince(now); ifMd5Matches(testBytes).ifModifiedSince(now);
} }
public void testIfModifiedAfterMd5DoesntMatch() public void testIfModifiedAfterMd5DoesntMatch()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifMd5DoesntMatch(testBytes).ifModifiedSince(now); ifMd5DoesntMatch(testBytes).ifModifiedSince(now);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testMd5MatchesAfterIfModified() public void testMd5MatchesAfterIfModified()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifModifiedSince(now).ifMd5Matches(testBytes); ifModifiedSince(now).ifMd5Matches(testBytes);
} }
public void testMd5MatchesAfterIfUnmodified() public void testMd5MatchesAfterIfUnmodified()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifUnmodifiedSince(now).ifMd5Matches(testBytes); ifUnmodifiedSince(now).ifMd5Matches(testBytes);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testMd5MatchesAfterMd5DoesntMatch() public void testMd5MatchesAfterMd5DoesntMatch()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifMd5DoesntMatch(testBytes).ifMd5Matches(testBytes); ifMd5DoesntMatch(testBytes).ifMd5Matches(testBytes);
} }
public void testMd5DoesntMatchAfterIfModified() public void testMd5DoesntMatchAfterIfModified()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifModifiedSince(now).ifMd5DoesntMatch(testBytes); ifModifiedSince(now).ifMd5DoesntMatch(testBytes);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testMd5DoesntMatchAfterIfUnmodified() public void testMd5DoesntMatchAfterIfUnmodified()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifUnmodifiedSince(now).ifMd5DoesntMatch(testBytes); ifUnmodifiedSince(now).ifMd5DoesntMatch(testBytes);
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testMd5DoesntMatchAfterMd5Matches() public void testMd5DoesntMatchAfterMd5Matches()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ifMd5Matches(testBytes).ifMd5DoesntMatch(testBytes); ifMd5Matches(testBytes).ifMd5DoesntMatch(testBytes);
} }
} }

View File

@ -82,7 +82,7 @@ public class ListBucketOptionsTest {
public void testPrefixAndDelimiterUrlEncodingQueryString() public void testPrefixAndDelimiterUrlEncodingQueryString()
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions(); ListBucketOptions options = new ListBucketOptions();
options.withPrefix("/test").setDelimiter("/"); options.withPrefix("/test").delimiter("/");
String query = options.buildQueryString(); String query = options.buildQueryString();
checkEncodedQuery(query); checkEncodedQuery(query);
checkEncodedQuery(checkNotNull(query)); checkEncodedQuery(checkNotNull(query));
@ -165,7 +165,7 @@ public class ListBucketOptionsTest {
@Test @Test
public void testDelimiter() throws UnsupportedEncodingException { public void testDelimiter() throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions(); ListBucketOptions options = new ListBucketOptions();
options.setDelimiter("test"); options.delimiter("test");
assertEquals(options.getDelimiter(), "test"); assertEquals(options.getDelimiter(), "test");
} }

View File

@ -23,79 +23,77 @@
*/ */
package org.jclouds.aws.s3.commands.options; package org.jclouds.aws.s3.commands.options;
import com.google.common.collect.Multimap;
import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.createIn; import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.createIn;
import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl; import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.io.UnsupportedEncodingException;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.UnsupportedEncodingException;
import com.google.common.collect.Multimap;
/** /**
* Tests possible uses of PutBucketOptions and PutBucketOptions.Builder.* * Tests possible uses of PutBucketOptions and PutBucketOptions.Builder.*
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "s3.PutBucketOptionsTest")
public class PutBucketOptionsTest { public class PutBucketOptionsTest {
@Test @Test
public void testLocationConstraint() { public void testLocationConstraint() {
PutBucketOptions options = new PutBucketOptions(); PutBucketOptions options = new PutBucketOptions();
options.createIn(LocationConstraint.EU); options.createIn(LocationConstraint.EU);
assertEquals(options.getLocationConstraint(), LocationConstraint.EU); assertEquals(options.getLocationConstraint(), LocationConstraint.EU);
} }
@Test @Test
public void testPayload() { public void testPayload() {
PutBucketOptions options = new PutBucketOptions(); PutBucketOptions options = new PutBucketOptions();
options.createIn(LocationConstraint.EU); options.createIn(LocationConstraint.EU);
assertEquals( assertEquals(
options.buildPayload(), options.buildPayload(),
"<CreateBucketConfiguration><LocationConstraint>EU</LocationConstraint></CreateBucketConfiguration>"); "<CreateBucketConfiguration><LocationConstraint>EU</LocationConstraint></CreateBucketConfiguration>");
} }
@Test @Test
public void testNullLocationConstraint() { public void testNullLocationConstraint() {
PutBucketOptions options = new PutBucketOptions(); PutBucketOptions options = new PutBucketOptions();
assertNull(options.getLocationConstraint()); assertNull(options.getLocationConstraint());
} }
@Test @Test
public void testLocationConstraintStatic() { public void testLocationConstraintStatic() {
PutBucketOptions options = createIn(LocationConstraint.EU); PutBucketOptions options = createIn(LocationConstraint.EU);
assertEquals(options.getLocationConstraint(), LocationConstraint.EU); assertEquals(options.getLocationConstraint(), LocationConstraint.EU);
} }
@Test(expectedExceptions = NullPointerException.class) @Test(expectedExceptions = NullPointerException.class)
public void testNPE() { public void testNPE() {
createIn(null); createIn(null);
} }
@Test @Test
public void testAclDefault() { public void testAclDefault() {
PutBucketOptions options = new PutBucketOptions(); PutBucketOptions options = new PutBucketOptions();
assertEquals(options.getAcl(), CannedAccessPolicy.PRIVATE); assertEquals(options.getAcl(), CannedAccessPolicy.PRIVATE);
} }
@Test @Test
public void testAclStatic() { public void testAclStatic() {
PutBucketOptions options = withBucketAcl(CannedAccessPolicy.AUTHENTICATED_READ); PutBucketOptions options = withBucketAcl(CannedAccessPolicy.AUTHENTICATED_READ);
assertEquals(options.getAcl(), CannedAccessPolicy.AUTHENTICATED_READ); assertEquals(options.getAcl(), CannedAccessPolicy.AUTHENTICATED_READ);
} }
@Test @Test
void testBuildRequestHeaders() throws UnsupportedEncodingException { void testBuildRequestHeaders() throws UnsupportedEncodingException {
Multimap<String, String> headers = withBucketAcl( Multimap<String, String> headers = withBucketAcl(
CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders(); CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders();
assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(), assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(),
CannedAccessPolicy.AUTHENTICATED_READ.toString()); CannedAccessPolicy.AUTHENTICATED_READ.toString());
} }
} }

View File

@ -23,43 +23,41 @@
*/ */
package org.jclouds.aws.s3.commands.options; package org.jclouds.aws.s3.commands.options;
import com.google.common.collect.Multimap;
import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.withAcl; import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.withAcl;
import static org.testng.Assert.assertEquals;
import java.io.UnsupportedEncodingException;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.UnsupportedEncodingException;
import com.google.common.collect.Multimap;
/** /**
* Tests possible uses of PutObjectOptions and PutObjectOptions.Builder.* * Tests possible uses of PutObjectOptions and PutObjectOptions.Builder.*
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "s3.PutObjectOptionsTest")
public class PutObjectOptionsTest { public class PutObjectOptionsTest {
@Test @Test
public void testAclDefault() { public void testAclDefault() {
PutObjectOptions options = new PutObjectOptions(); PutObjectOptions options = new PutObjectOptions();
assertEquals(options.getAcl(), CannedAccessPolicy.PRIVATE); assertEquals(options.getAcl(), CannedAccessPolicy.PRIVATE);
} }
@Test @Test
public void testAclStatic() { public void testAclStatic() {
PutObjectOptions options = withAcl(CannedAccessPolicy.AUTHENTICATED_READ); PutObjectOptions options = withAcl(CannedAccessPolicy.AUTHENTICATED_READ);
assertEquals(options.getAcl(), CannedAccessPolicy.AUTHENTICATED_READ); assertEquals(options.getAcl(), CannedAccessPolicy.AUTHENTICATED_READ);
} }
@Test @Test
void testBuildRequestHeaders() throws UnsupportedEncodingException { void testBuildRequestHeaders() throws UnsupportedEncodingException {
Multimap<String, String> headers = withAcl( Multimap<String, String> headers = withAcl(
CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders(); CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders();
assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(), assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(),
CannedAccessPolicy.AUTHENTICATED_READ.toString()); CannedAccessPolicy.AUTHENTICATED_READ.toString());
} }
} }

View File

@ -23,8 +23,10 @@
*/ */
package org.jclouds.aws.s3.config; package org.jclouds.aws.s3.config;
import static org.testng.Assert.assertEquals; import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Names;
import org.jclouds.aws.s3.handlers.ParseS3ErrorFromXmlContent; import org.jclouds.aws.s3.handlers.ParseS3ErrorFromXmlContent;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.http.HttpResponseHandler; import org.jclouds.http.HttpResponseHandler;
@ -33,94 +35,88 @@ import org.jclouds.http.annotation.RedirectHandler;
import org.jclouds.http.annotation.ServerErrorHandler; import org.jclouds.http.annotation.ServerErrorHandler;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule; import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler; import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Names;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test @Test(groups = "unit", testName = "s3.S3ContextModuleTest")
public class S3ContextModuleTest { public class S3ContextModuleTest {
Injector injector = null; Injector injector = null;
@BeforeMethod @BeforeMethod
void setUpInjector() { void setUpInjector() {
injector = Guice.createInjector(new S3ContextModule() { injector = Guice.createInjector(new LiveS3ConnectionModule(), new S3ContextModule() {
@Override @Override
protected void configure() { protected void configure() {
bindConstant().annotatedWith( bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to( Names.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
"localhost"); "localhost");
bindConstant().annotatedWith( bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)) Names.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY))
.to("localhost"); .to("localhost");
bindConstant().annotatedWith( bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_HTTP_ADDRESS)).to( Names.named(S3Constants.PROPERTY_HTTP_ADDRESS)).to(
"localhost"); "localhost");
bindConstant().annotatedWith( bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_HTTP_PORT)).to("1000"); Names.named(S3Constants.PROPERTY_HTTP_PORT)).to("1000");
bindConstant().annotatedWith( bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_HTTP_SECURE)).to( Names.named(S3Constants.PROPERTY_HTTP_SECURE)).to(
"false"); "false");
super.configure(); super.configure();
} }
}, new JavaUrlHttpFutureCommandClientModule()); }, new JavaUrlHttpFutureCommandClientModule());
} }
@AfterMethod @AfterMethod
void tearDownInjector() { void tearDownInjector() {
injector = null; injector = null;
} }
private static class ClientErrorHandlerTest { private static class ClientErrorHandlerTest {
@Inject @Inject
@ClientErrorHandler @ClientErrorHandler
HttpResponseHandler errorHandler; HttpResponseHandler errorHandler;
} }
@Test @Test
void testClientErrorHandler() { void testClientErrorHandler() {
ClientErrorHandlerTest error = injector ClientErrorHandlerTest error = injector
.getInstance(ClientErrorHandlerTest.class); .getInstance(ClientErrorHandlerTest.class);
assertEquals(error.errorHandler.getClass(), assertEquals(error.errorHandler.getClass(),
ParseS3ErrorFromXmlContent.class); ParseS3ErrorFromXmlContent.class);
} }
private static class ServerErrorHandlerTest { private static class ServerErrorHandlerTest {
@Inject @Inject
@ServerErrorHandler @ServerErrorHandler
HttpResponseHandler errorHandler; HttpResponseHandler errorHandler;
} }
@Test @Test
void testServerErrorHandler() { void testServerErrorHandler() {
ServerErrorHandlerTest error = injector ServerErrorHandlerTest error = injector
.getInstance(ServerErrorHandlerTest.class); .getInstance(ServerErrorHandlerTest.class);
assertEquals(error.errorHandler.getClass(), assertEquals(error.errorHandler.getClass(),
ParseS3ErrorFromXmlContent.class); ParseS3ErrorFromXmlContent.class);
} }
private static class RedirectHandlerTest { private static class RedirectHandlerTest {
@Inject @Inject
@RedirectHandler @RedirectHandler
HttpResponseHandler errorHandler; HttpResponseHandler errorHandler;
} }
@Test @Test
void testRedirectHandler() { void testRedirectHandler() {
RedirectHandlerTest error = injector RedirectHandlerTest error = injector
.getInstance(RedirectHandlerTest.class); .getInstance(RedirectHandlerTest.class);
assertEquals(error.errorHandler.getClass(), assertEquals(error.errorHandler.getClass(),
CloseContentAndSetExceptionHandler.class); CloseContentAndSetExceptionHandler.class);
} }
} }

View File

@ -0,0 +1,17 @@
package org.jclouds.aws.s3.config;
import com.google.inject.AbstractModule;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.StubS3Connection;
/**
* // TODO: Adrian: Document this!
*
* @author Adrian Cole
*/
@S3ConnectionModule
public class StubS3ConnectionModule extends AbstractModule {
protected void configure() {
bind(S3Connection.class).to(StubS3Connection.class);
}
}

View File

@ -23,23 +23,21 @@
*/ */
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
import java.io.File;
import static org.testng.Assert.*;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.http.ContentTypes; import org.jclouds.http.ContentTypes;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@Test import java.io.File;
@Test(groups = "unit", testName = "s3.S3ObjectTest")
public class S3ObjectTest { public class S3ObjectTest {
@Test @Test
void testSetNoContentType() { void testSetNoContentType() {
S3Object object = new S3Object("test"); S3Object object = new S3Object("test");
File file = new File("hello.txt"); File file = new File("hello.txt");
object.setData(file); object.setData(file);
assertEquals(object.getMetadata().getContentType(), assertEquals(object.getMetadata().getContentType(),
ContentTypes.BINARY); ContentTypes.BINARY);
} }
} }

View File

@ -26,14 +26,12 @@ package org.jclouds.aws.s3.filters;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.name.Names; import com.google.inject.name.Names;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.s3.util.DateService; import org.jclouds.aws.s3.util.DateService;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@Test(groups = "unit", testName = "s3.RequestAuthorizeSignatureTest")
@Test(groups = "unit", sequential = true, testName = "s3.RequestAuthorizeSignatureTest")
public class RequestAuthorizeSignatureTest { public class RequestAuthorizeSignatureTest {
RequestAuthorizeSignature filter = null; RequestAuthorizeSignature filter = null;

View File

@ -23,20 +23,19 @@
*/ */
package org.jclouds.aws.s3.xml; package org.jclouds.aws.s3.xml;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.jclouds.aws.s3.xml.config.S3ParserModule; import org.jclouds.aws.s3.xml.config.S3ParserModule;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class BaseHandlerTest { public class BaseHandlerTest {
protected S3ParserFactory parserFactory = null; protected S3ParserFactory parserFactory = null;
private Injector injector; private Injector injector;
public BaseHandlerTest() { public BaseHandlerTest() {
super(); super();
} }
@BeforeMethod @BeforeMethod

View File

@ -23,43 +23,42 @@
*/ */
package org.jclouds.aws.s3.xml; package org.jclouds.aws.s3.xml;
import static org.testng.Assert.assertEquals;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.domain.S3Error; import org.jclouds.aws.s3.domain.S3Error;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@Test @Test(groups = "unit", testName = "s3.ErrorHandlerTest")
public class ErrorHandlerTest extends BaseHandlerTest { 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>"; 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>";
@Test @Test
public void testErrorFromAmazonIfYouDontRemoveTransferEncodingHeader() public void testErrorFromAmazonIfYouDontRemoveTransferEncodingHeader()
throws HttpException { throws HttpException {
ParseSax<S3Error> parser = parserFactory.createErrorParser(); ParseSax<S3Error> parser = parserFactory.createErrorParser();
S3Error error = parser S3Error error = parser
.parse(IOUtils .parse(IOUtils
.toInputStream(errorFromAmazonIfYouDontRemoveTransferEncodingHeader)); .toInputStream(errorFromAmazonIfYouDontRemoveTransferEncodingHeader));
assertEquals(error.getCode(), "NotImplemented"); assertEquals(error.getCode(), "NotImplemented");
assertEquals(error.getMessage(), assertEquals(error.getMessage(),
"A header you provided implies functionality that is not implemented"); "A header you provided implies functionality that is not implemented");
assertEquals(error.getDetails().get("Header"), "Transfer-Encoding"); assertEquals(error.getDetails().get("Header"), "Transfer-Encoding");
assertEquals(error.getRequestId(), "7C59925D75D15561"); assertEquals(error.getRequestId(), "7C59925D75D15561");
assertEquals(error.getDetails().get("HostId"), assertEquals(error.getDetails().get("HostId"),
"fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb"); "fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb");
} }
public static final String badRequestWhenSourceIsDestBucketOnCopy400 = "<Error><Code>InvalidRequest</Code><Message>The Source and Destination may not be the same when the MetadataDirective is Copy.</Message><RequestId>54C77CAF4D42474B</RequestId><HostId>SJecknEUUUx88/65VAKbCdKSOCkpuVTeu7ZG9in9x9NTNglGnoxdbALCfS4k/DUZ</HostId></Error>"; public static final String badRequestWhenSourceIsDestBucketOnCopy400 = "<Error><Code>InvalidRequest</Code><Message>The Source and Destination may not be the same when the MetadataDirective is Copy.</Message><RequestId>54C77CAF4D42474B</RequestId><HostId>SJecknEUUUx88/65VAKbCdKSOCkpuVTeu7ZG9in9x9NTNglGnoxdbALCfS4k/DUZ</HostId></Error>";
public static final String noSuchSourceKeyOrBucketOnCopy404 = "<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>null</Key><RequestId>9CCDF1DACA78B36F</RequestId><HostId>63cqk9YsTFBVfBfks840JVGsepPEdQM42mU+r7HN35sF4Nk5xAcWDEUPaQpK2eFU</HostId></Error>"; public static final String noSuchSourceKeyOrBucketOnCopy404 = "<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>null</Key><RequestId>9CCDF1DACA78B36F</RequestId><HostId>63cqk9YsTFBVfBfks840JVGsepPEdQM42mU+r7HN35sF4Nk5xAcWDEUPaQpK2eFU</HostId></Error>";
public static final String noSuchDestinationBucketOnCopy404 = "<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>copydestination</BucketName><RequestId>4F0CF319C5535975</RequestId><HostId>hdZyHOm7VK+JI2UCdye3d6TVkKhRBIoWflldXVDTKbgipYlamy8HgPBzHrUAVQNJ</HostId></Error>"; public static final String noSuchDestinationBucketOnCopy404 = "<Error><Code>NoSuchBucket</Code><Message>The specified bucketName does not exist</Message><BucketName>copydestination</BucketName><RequestId>4F0CF319C5535975</RequestId><HostId>hdZyHOm7VK+JI2UCdye3d6TVkKhRBIoWflldXVDTKbgipYlamy8HgPBzHrUAVQNJ</HostId></Error>";
public static final String badSign403 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" public static final String badSign403 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<Error><Code>SignatureDoesNotMatch</Code><Message>The operation signature we calculated does not match the signature you provided. Check your key and signing method.</Message><StringToSignBytes>47 45 54 0a 0a 0a 54 68 75 2c 20 31 39 20 4d 61 72 20 32 30 30 39 20 31 37 3a 34 38 3a 30 31 20 47 4d 54 0a 2f 61 64 72 69 61 6e 63 6f 6c 65 2e 73 33 2e 61 6d 61 7a 6f 6e 73 33 74 65 73 74 2e 66 69 6c 65 74 65 73 74 73 66 6f 72 61 64 72 69 61 6e 2f 66 69 6c 65</StringToSignBytes><RequestId>514AA22EB75A6E42</RequestId><HostId>H5nqnZkGjuKvB+seutvx5hnp1P+WAuC9c3Y7MdQCcYDr1TGwNX/mt+FHstK0pVld</HostId><SignatureProvided>Qm6Wss7e5e/eNXV50AxChH+xkLI=</SignatureProvided><StringToSign>GET\n" + "<Error><Code>SignatureDoesNotMatch</Code><Message>The operation signature we calculated does not match the signature you provided. Check your key and signing method.</Message><StringToSignBytes>47 45 54 0a 0a 0a 54 68 75 2c 20 31 39 20 4d 61 72 20 32 30 30 39 20 31 37 3a 34 38 3a 30 31 20 47 4d 54 0a 2f 61 64 72 69 61 6e 63 6f 6c 65 2e 73 33 2e 61 6d 61 7a 6f 6e 73 33 74 65 73 74 2e 66 69 6c 65 74 65 73 74 73 66 6f 72 61 64 72 69 61 6e 2f 66 69 6c 65</StringToSignBytes><RequestId>514AA22EB75A6E42</RequestId><HostId>H5nqnZkGjuKvB+seutvx5hnp1P+WAuC9c3Y7MdQCcYDr1TGwNX/mt+FHstK0pVld</HostId><SignatureProvided>Qm6Wss7e5e/eNXV50AxChH+xkLI=</SignatureProvided><StringToSign>GET\n"
+ "\n" + "\n"
+ "\n" + "\n"
+ "Thu, 19 Mar 2009 17:48:01 GMT\n" + "Thu, 19 Mar 2009 17:48:01 GMT\n"
+ "/adriancole.s3.amazons3test.filetestsforadrian/file</StringToSign><AWSAccessKeyId>0101100101001001</AWSAccessKeyId></Error>"; + "/adriancole.s3.amazons3test.filetestsforadrian/file</StringToSign><AWSAccessKeyId>0101100101001001</AWSAccessKeyId></Error>";
public static final String amazonHadAnError500 = "<Error><Code>InternalError</Code><Message>We encountered an internal error. Please try again.</Message><RequestId>EF6FA7A639CAFF15</RequestId><HostId>tBkX23mIeq2riHsNw2YShupMlZ9+iy3V/uN+lRhqCR4qHTE07ujFeyAUPTowvuH/</HostId></Error>"; public static final String amazonHadAnError500 = "<Error><Code>InternalError</Code><Message>We encountered an internal error. Please try again.</Message><RequestId>EF6FA7A639CAFF15</RequestId><HostId>tBkX23mIeq2riHsNw2YShupMlZ9+iy3V/uN+lRhqCR4qHTE07ujFeyAUPTowvuH/</HostId></Error>";
} }

View File

@ -23,16 +23,15 @@
*/ */
package org.jclouds.aws.s3.xml; package org.jclouds.aws.s3.xml;
import static org.testng.Assert.assertEquals;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@Test @Test(groups = "unit", testName = "s3.ListBucketHandlerTest")
public class ListBucketHandlerTest extends BaseHandlerTest { public class ListBucketHandlerTest extends BaseHandlerTest {
public static final String listBucketWithPrefixAppsSlash = "<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>adriancole.org.jclouds.aws.s3.amazons3testdelimiter</Name><Prefix>apps/</Prefix><Marker></Marker><MaxKeys>1000</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>apps/0</Key><LastModified>2009-05-07T18:27:08.000Z</LastModified><ETag>&quot;c82e6a0025c31c5de5947fda62ac51ab&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/1</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;944fab2c5a9a6bacf07db5e688310d7a&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/2</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;a227b8888045c8fd159fb495214000f0&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/3</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;c9caa76c3dec53e2a192608ce73eef03&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/4</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;1ce5d0dcc6154a647ea90c7bdf82a224&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/5</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;79433524d87462ee05708a8ef894ed55&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/6</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;dd00a060b28ddca8bc5a21a49e306f67&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/7</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;8cd06eca6e819a927b07a285d750b100&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/8</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;174495094d0633b92cbe46603eee6bad&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/9</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;cd8a19b26fea8a827276df0ad11c580d&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketResult>"; public static final String listBucketWithPrefixAppsSlash = "<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>adriancole.org.jclouds.aws.s3.amazons3testdelimiter</Name><Prefix>apps/</Prefix><Marker></Marker><MaxKeys>1000</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>apps/0</Key><LastModified>2009-05-07T18:27:08.000Z</LastModified><ETag>&quot;c82e6a0025c31c5de5947fda62ac51ab&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/1</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;944fab2c5a9a6bacf07db5e688310d7a&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/2</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;a227b8888045c8fd159fb495214000f0&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/3</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;c9caa76c3dec53e2a192608ce73eef03&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/4</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;1ce5d0dcc6154a647ea90c7bdf82a224&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/5</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;79433524d87462ee05708a8ef894ed55&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/6</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;dd00a060b28ddca8bc5a21a49e306f67&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/7</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;8cd06eca6e819a927b07a285d750b100&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/8</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;174495094d0633b92cbe46603eee6bad&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/9</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;cd8a19b26fea8a827276df0ad11c580d&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketResult>";
public static final String listBucketWithSlashDelimiterAndCommonPrefixApps = "<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"> <Delimiter>/</Delimiter> <CommonPrefixes><Prefix>apps/</Prefix></CommonPrefixes></ListBucketResult>"; public static final String listBucketWithSlashDelimiterAndCommonPrefixApps = "<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"> <Delimiter>/</Delimiter> <CommonPrefixes><Prefix>apps/</Prefix></CommonPrefixes></ListBucketResult>";
@ -40,29 +39,29 @@ public class ListBucketHandlerTest extends BaseHandlerTest {
@BeforeMethod @BeforeMethod
void setUpParser() { void setUpParser() {
parser = parserFactory.createListBucketParser(); parser = parserFactory.createListBucketParser();
((ListBucketHandler) parser.getHandler()).setBucketName("test"); ((ListBucketHandler) parser.getHandler()).setBucketName("test");
} }
@Test @Test
public void testListMyBucketsWithDelimiterSlashAndCommonPrefixesAppsSlash() public void testListMyBucketsWithDelimiterSlashAndCommonPrefixesAppsSlash()
throws HttpException { throws HttpException {
S3Bucket bucket = parser.parse(IOUtils S3Bucket bucket = parser.parse(IOUtils
.toInputStream(listBucketWithSlashDelimiterAndCommonPrefixApps)); .toInputStream(listBucketWithSlashDelimiterAndCommonPrefixApps));
assertEquals(bucket.getCommonPrefixes().iterator().next(), "apps/"); assertEquals(bucket.getCommonPrefixes().iterator().next(), "apps/");
assertEquals(bucket.getDelimiter(), "/"); assertEquals(bucket.getDelimiter(), "/");
assert bucket.getMarker() == null; assert bucket.getMarker() == null;
} }
@Test @Test
public void testListMyBucketsWithPrefixAppsSlash() throws HttpException { public void testListMyBucketsWithPrefixAppsSlash() throws HttpException {
S3Bucket bucket = parser.parse(IOUtils S3Bucket bucket = parser.parse(IOUtils
.toInputStream(listBucketWithPrefixAppsSlash)); .toInputStream(listBucketWithPrefixAppsSlash));
assertEquals(bucket.getPrefix(), "apps/"); assertEquals(bucket.getPrefix(), "apps/");
assertEquals(bucket.getMaxKeys(), 1000); assertEquals(bucket.getMaxKeys(), 1000);
assert bucket.getMarker() == null; assert bucket.getMarker() == null;
} }

View File

@ -23,19 +23,17 @@
*/ */
package org.jclouds.aws.s3.xml; package org.jclouds.aws.s3.xml;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.jclouds.aws.s3.xml.config.S3ParserModule; import org.jclouds.aws.s3.xml.config.S3ParserModule;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test @Test(groups = "unit", testName = "s3.S3ParserFactoryTest")
public class S3ParserFactoryTest { public class S3ParserFactoryTest {
Injector injector = null; Injector injector = null;
@ -43,34 +41,34 @@ public class S3ParserFactoryTest {
@BeforeMethod @BeforeMethod
void setUpInjector() { void setUpInjector() {
injector = Guice.createInjector(new S3ParserModule()); injector = Guice.createInjector(new S3ParserModule());
parserFactory = injector.getInstance(S3ParserFactory.class); parserFactory = injector.getInstance(S3ParserFactory.class);
} }
@AfterMethod @AfterMethod
void tearDownInjector() { void tearDownInjector() {
parserFactory = null; parserFactory = null;
injector = null; injector = null;
} }
@Test @Test
void testCreateListBucketsParser() { void testCreateListBucketsParser() {
assert parserFactory.createListBucketsParser() != null; assert parserFactory.createListBucketsParser() != null;
} }
@Test @Test
void testCreateListBucketParser() { void testCreateListBucketParser() {
assert parserFactory.createListBucketParser() != null; assert parserFactory.createListBucketParser() != null;
} }
@Test @Test
void testCreateCopyObjectParser() { void testCreateCopyObjectParser() {
assert parserFactory.createCopyObjectParser() != null; assert parserFactory.createCopyObjectParser() != null;
} }
@Test @Test
void testCreateErrorParser() { void testCreateErrorParser() {
assert parserFactory.createErrorParser() != null; assert parserFactory.createErrorParser() != null;
} }
} }