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

View File

@ -23,124 +23,114 @@
*/
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.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.base.Predicate;
import static com.google.common.collect.Sets.filter;
import com.google.inject.Inject;
import com.google.inject.ProvisionException;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.InjectionListener;
import com.google.inject.spi.TypeEncounter;
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
* {@link javax.annotation.Resource}
*
* <p/>
* 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.
*
* <p/>
* Note that this occurs post-object construction through
* {@link com.google.inject.Binder#bindListener}.
*
* <p/>
* Here's an example usage:
* <pre>
* <pre>
* class A {
* @Resource private Logger logger = Logger.NULL;
* @Resource private Logger logger = Logger.NULL;
* }
*
* <p/>
* Injector i = Guice.createInjector(new AbstractModule() {
* @Override protected void configure() {
* @Override protected void configure() {
* bindListener(any(), new
* BindLoggersAnnotatedWithResource( new
* JDKLogger.JDKLoggerFactory()));
* }
* });
*
* A = i.getInstance(A.class);
* <p/>
* A = i.getInstance(A.class);
* // A will now have a logger associated with it
* </pre>
*
*
* @author Adrian Cole
*
*/
public class BindLoggersAnnotatedWithResource implements TypeListener {
static class AssignLoggerToField<I> implements InjectionListener<I> {
private final Logger logger;
private final Field field;
private final Logger logger;
private final Field field;
AssignLoggerToField(Logger logger, Field field) {
this.logger = logger;
this.field = field;
}
AssignLoggerToField(Logger logger, Field field) {
this.logger = logger;
this.field = field;
}
public void afterInjection(I injectee) {
try {
field.setAccessible(true);
field.set(injectee, logger);
} catch (IllegalAccessException e) {
throw new ProvisionException(e.getMessage(), e);
}
}
public void afterInjection(I injectee) {
try {
field.setAccessible(true);
field.set(injectee, logger);
} catch (IllegalAccessException e) {
throw new ProvisionException(e.getMessage(), e);
}
}
}
static class LoggerFieldsAnnotatedWithResource implements
Function<Field, Field> {
public Field apply(Field from) {
Annotation inject = from.getAnnotation(Resource.class);
if (inject != null && from.getType().isAssignableFrom(Logger.class)) {
return from;
}
return null;
}
Predicate<Field> {
public boolean apply(Field from) {
Annotation inject = from.getAnnotation(Resource.class);
return (inject != null && from.getType().isAssignableFrom(Logger.class));
}
}
private final LoggerFactory loggerFactory;
@Inject
public BindLoggersAnnotatedWithResource(LoggerFactory loggerFactory) {
this.loggerFactory = loggerFactory;
this.loggerFactory = loggerFactory;
}
public <I> void hear(TypeLiteral<I> injectableType,
TypeEncounter<I> encounter) {
TypeEncounter<I> encounter) {
Class<? super I> type = injectableType.getRawType();
Set<Field> loggerFields = getLoggerFieldsAnnotatedWithResource(type);
if (loggerFields.size() == 0)
return;
Class<? super I> type = injectableType.getRawType();
Set<Field> loggerFields = getLoggerFieldsAnnotatedWithResource(type);
if (loggerFields.size() == 0)
return;
Logger logger = loggerFactory.getLogger(type.getName());
Logger logger = loggerFactory.getLogger(type.getName());
for (Field field : loggerFields) {
encounter.register(new AssignLoggerToField<I>(logger, field));
}
for (Field field : loggerFields) {
encounter.register(new AssignLoggerToField<I>(logger, field));
}
}
@VisibleForTesting
Set<Field> getLoggerFieldsAnnotatedWithResource(Class<?> declaredType) {
Set<Field> fields = new HashSet<Field>();
Class<?> type = declaredType;
while (type != null) {
fields.addAll(Arrays.asList(type.getDeclaredFields()));
type = type.getSuperclass();
}
Set<Field> loggerFields = Sets.newHashSet(Iterables.transform(fields,
new LoggerFieldsAnnotatedWithResource()));
loggerFields.remove(null);
return loggerFields;
Set<Field> fields = new HashSet<Field>();
Class<?> type = declaredType;
while (type != null) {
fields.addAll(Arrays.asList(type.getDeclaredFields()));
type = type.getSuperclass();
}
return filter(fields, new LoggerFieldsAnnotatedWithResource());
}
}

View File

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

View File

@ -23,129 +23,126 @@
*/
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.Guice;
import com.google.inject.Inject;
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 {
private BindLoggersAnnotatedWithResource blawr;
public static class A {
@Resource
private Logger logger = Logger.NULL;
@Resource
private Logger logger = Logger.NULL;
}
public static class B {
@Resource
private Logger logger = Logger.NULL;
@Resource
private Logger logger = Logger.NULL;
}
@BeforeMethod
void createBlawr() {
blawr = new BindLoggersAnnotatedWithResource(
new JDKLogger.JDKLoggerFactory());
blawr = new BindLoggersAnnotatedWithResource(
new JDKLogger.JDKLoggerFactory());
}
@Test
void testHear() {
Injector i = Guice.createInjector(new AbstractModule() {
Injector i = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindListener(any(), blawr);
}
@Override
protected void configure() {
bindListener(any(), blawr);
}
});
assertEquals(i.getInstance(A.class).logger.getCategory(), getClass()
.getName()
+ "$A");
assertEquals(i.getInstance(B.class).logger.getCategory(), getClass()
.getName()
+ "$B");
});
assertEquals(i.getInstance(A.class).logger.getCategory(), getClass()
.getName()
+ "$A");
assertEquals(i.getInstance(B.class).logger.getCategory(), getClass()
.getName()
+ "$B");
}
@Test
public void testAssignLoggerToField() throws SecurityException,
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
Logger logger = createMock(Logger.class);
A a = new A();
Field field = A.class.getDeclaredField("logger");
AssignLoggerToField<A> assigner = new AssignLoggerToField<A>(logger,
field);
assigner.afterInjection(a);
assert field.get(a).equals(logger);
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
Logger logger = createMock(Logger.class);
A a = new A();
Field field = A.class.getDeclaredField("logger");
AssignLoggerToField<A> assigner = new AssignLoggerToField<A>(logger,
field);
assigner.afterInjection(a);
assert field.get(a).equals(logger);
}
@Test
public void testLoggerFieldsAnnotatedWithResource()
throws SecurityException, NoSuchFieldException {
LoggerFieldsAnnotatedWithResource function = new LoggerFieldsAnnotatedWithResource();
assertEquals(function.apply(A.class.getDeclaredField("logger")),
A.class.getDeclaredField("logger"));
throws SecurityException, NoSuchFieldException {
LoggerFieldsAnnotatedWithResource predicate = new LoggerFieldsAnnotatedWithResource();
assert predicate.apply(A.class.getDeclaredField("logger"));
}
public static class C {
@SuppressWarnings("unused")
@Inject
private Logger logger = Logger.NULL;
@SuppressWarnings("unused")
@Inject
private Logger logger = Logger.NULL;
}
@Test
public void testLoggerFieldsAnnotatedWithInjectReturnsNull()
throws SecurityException, NoSuchFieldException {
LoggerFieldsAnnotatedWithResource function = new LoggerFieldsAnnotatedWithResource();
assertNull(function.apply(C.class.getDeclaredField("logger")));
throws SecurityException, NoSuchFieldException {
LoggerFieldsAnnotatedWithResource predicate = new LoggerFieldsAnnotatedWithResource();
assert ! predicate.apply(C.class.getDeclaredField("logger"));
}
public static class D {
@SuppressWarnings("unused")
@Resource
private Logger logger = Logger.NULL;
@SuppressWarnings("unused")
@Resource
private Logger logger = Logger.NULL;
@SuppressWarnings("unused")
@Resource
private Logger blogger;
@SuppressWarnings("unused")
@Resource
private Logger blogger;
}
@Test
public void testGetLoggerFieldsAnnotatedWithResourceNoLogger() {
Set<Field> fields = blawr.getLoggerFieldsAnnotatedWithResource(this
.getClass());
assertEquals(fields.size(), 0);
Set<Field> fields = blawr.getLoggerFieldsAnnotatedWithResource(this
.getClass());
assertEquals(fields.size(), 0);
}
@Test
public void testGetLoggerFieldsAnnotatedWithResourceOneLogger() {
Set<Field> fields = blawr.getLoggerFieldsAnnotatedWithResource(A.class);
assertEquals(fields.size(), 1);
Set<Field> fields = blawr.getLoggerFieldsAnnotatedWithResource(A.class);
assertEquals(fields.size(), 1);
}
@Test
public void testGetLoggerFieldsAnnotatedWithResourceTwoLoggers() {
Set<Field> fields = blawr.getLoggerFieldsAnnotatedWithResource(D.class);
assertEquals(fields.size(), 2);
Set<Field> fields = blawr.getLoggerFieldsAnnotatedWithResource(D.class);
assertEquals(fields.size(), 2);
}
}

View File

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

View File

@ -23,64 +23,59 @@
*/
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.List;
import java.util.concurrent.BlockingQueue;
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!
*
*
* @author Adrian Cole
*/
@Singleton
public class HttpNioConnectionPoolClient
extends
FutureCommandConnectionPoolClient<NHttpConnection, HttpFutureCommand<?>>
implements HttpFutureCommandClient {
extends
FutureCommandConnectionPoolClient<NHttpConnection, HttpFutureCommand<?>>
implements HttpFutureCommandClient {
private List<HttpRequestFilter> requestFilters = Collections.emptyList();
public List<HttpRequestFilter> getRequestFilters() {
return requestFilters;
return requestFilters;
}
@Inject(optional = true)
public void setRequestFilters(List<HttpRequestFilter> requestFilters) {
this.requestFilters = requestFilters;
this.requestFilters = requestFilters;
}
@Override
protected void invoke(HttpFutureCommand<?> command) {
HttpRequest request = (HttpRequest) command.getRequest();
try {
for (HttpRequestFilter filter : getRequestFilters()) {
filter.filter(request);
}
super.invoke(command);
} catch (HttpException e) {
command.setException(e);
}
HttpRequest request = (HttpRequest) command.getRequest();
try {
for (HttpRequestFilter filter : getRequestFilters()) {
filter.filter(request);
}
super.invoke(command);
} catch (HttpException e) {
command.setException(e);
}
}
@Inject
public HttpNioConnectionPoolClient(
ExecutorService executor,
HttpNioFutureCommandConnectionPool httpFutureCommandConnectionHandleNHttpConnectionNioFutureCommandConnectionPool,
BlockingQueue<HttpFutureCommand<?>> commandQueue) {
super(
executor,
httpFutureCommandConnectionHandleNHttpConnectionNioFutureCommandConnectionPool,
commandQueue);
ExecutorService executor,
HttpNioFutureCommandConnectionPool httpFutureCommandConnectionHandleNHttpConnectionNioFutureCommandConnectionPool,
BlockingQueue<HttpFutureCommand<?>> commandQueue) {
super(
executor,
httpFutureCommandConnectionHandleNHttpConnectionNioFutureCommandConnectionPool,
commandQueue);
}
}

View File

@ -23,14 +23,8 @@
*/
package org.jclouds.http.httpnio.pool;
import java.io.IOException;
import java.net.InetSocketAddress;
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 com.google.inject.Inject;
import com.google.inject.name.Named;
import org.apache.http.HttpException;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.nio.NHttpConnection;
@ -46,17 +40,18 @@ import org.jclouds.command.pool.FutureCommandConnectionPool;
import org.jclouds.command.pool.PoolConstants;
import org.jclouds.http.HttpFutureCommand;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.*;
/**
* Connection Pool for HTTP requests that utilizes Apache HTTPNio
*
*
* @author Adrian Cole
*/
public class HttpNioFutureCommandConnectionPool extends
FutureCommandConnectionPool<NHttpConnection, HttpFutureCommand<?>>
implements EventListener {
FutureCommandConnectionPool<NHttpConnection, HttpFutureCommand<?>>
implements EventListener {
private final NHttpClientConnectionPoolSessionRequestCallback sessionCallback;
private final DefaultConnectingIOReactor ioReactor;
@ -66,227 +61,227 @@ public class HttpNioFutureCommandConnectionPool extends
@Inject
public HttpNioFutureCommandConnectionPool(
ExecutorService executor,
Semaphore allConnections,
BlockingQueue<HttpFutureCommand<?>> commandQueue,
BlockingQueue<NHttpConnection> available,
AsyncNHttpClientHandler clientHandler,
DefaultConnectingIOReactor ioReactor,
IOEventDispatch dispatch,
FutureCommandConnectionHandleFactory requestHandleFactory,
InetSocketAddress target,
@Named(PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE) int maxConnectionReuse,
@Named(PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES) int maxSessionFailures) {
super(executor, allConnections, commandQueue, requestHandleFactory,
maxConnectionReuse, available);
this.ioReactor = ioReactor;
this.dispatch = dispatch;
this.target = target;
this.maxSessionFailures = maxSessionFailures;
this.sessionCallback = new NHttpClientConnectionPoolSessionRequestCallback();
clientHandler.setEventListener(this);
ExecutorService executor,
Semaphore allConnections,
BlockingQueue<HttpFutureCommand<?>> commandQueue,
BlockingQueue<NHttpConnection> available,
AsyncNHttpClientHandler clientHandler,
DefaultConnectingIOReactor ioReactor,
IOEventDispatch dispatch,
FutureCommandConnectionHandleFactory requestHandleFactory,
InetSocketAddress target,
@Named(PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE) int maxConnectionReuse,
@Named(PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES) int maxSessionFailures) {
super(executor, allConnections, commandQueue, requestHandleFactory,
maxConnectionReuse, available);
this.ioReactor = ioReactor;
this.dispatch = dispatch;
this.target = target;
this.maxSessionFailures = maxSessionFailures;
this.sessionCallback = new NHttpClientConnectionPoolSessionRequestCallback();
clientHandler.setEventListener(this);
}
@Override
public void start() {
synchronized (this.statusLock) {
if (this.status.compareTo(Status.INACTIVE) == 0) {
executor.execute(new Runnable() {
public void run() {
try {
ioReactor.execute(dispatch);
} catch (IOException e) {
exception.set(e);
logger.error(e, "Error dispatching %1$s", dispatch);
status = Status.SHUTDOWN_REQUEST;
}
}
});
}
super.start();
}
synchronized (this.statusLock) {
if (this.status.compareTo(Status.INACTIVE) == 0) {
executor.execute(new Runnable() {
public void run() {
try {
ioReactor.execute(dispatch);
} catch (IOException e) {
exception.set(e);
logger.error(e, "Error dispatching %1$s", dispatch);
status = Status.SHUTDOWN_REQUEST;
}
}
});
}
super.start();
}
}
public void shutdownReactor(long waitMs) {
try {
this.ioReactor.shutdown(waitMs);
} catch (IOException e) {
logger.error(e, "Error shutting down reactor");
}
try {
this.ioReactor.shutdown(waitMs);
} catch (IOException e) {
logger.error(e, "Error shutting down reactor");
}
}
@Override
public boolean connectionValid(NHttpConnection conn) {
return conn.isOpen() && !conn.isStale()
&& conn.getMetrics().getRequestCount() < maxConnectionReuse;
return conn.isOpen() && !conn.isStale()
&& conn.getMetrics().getRequestCount() < maxConnectionReuse;
}
@Override
public void shutdownConnection(NHttpConnection conn) {
if (conn.getMetrics().getRequestCount() >= maxConnectionReuse)
logger.debug(
"%1$s - %2$d - closing connection due to overuse %1$s/%2$s",
conn, conn.hashCode(), conn.getMetrics().getRequestCount(),
maxConnectionReuse);
if (conn.getStatus() == NHttpConnection.ACTIVE) {
try {
conn.shutdown();
} catch (IOException e) {
logger.error(e, "Error shutting down connection");
}
}
if (conn.getMetrics().getRequestCount() >= maxConnectionReuse)
logger.debug(
"%1$s - %2$d - closing connection due to overuse %1$s/%2$s",
conn, conn.hashCode(), conn.getMetrics().getRequestCount(),
maxConnectionReuse);
if (conn.getStatus() == NHttpConnection.ACTIVE) {
try {
conn.shutdown();
} catch (IOException e) {
logger.error(e, "Error shutting down connection");
}
}
}
@Override
protected void doWork() throws Exception {
createNewConnection();
createNewConnection();
}
@Override
protected void doShutdown() {
// Give the I/O reactor 1 sec to shut down
shutdownReactor(1000);
assert this.ioReactor.getStatus().equals(IOReactorStatus.SHUT_DOWN) : "incorrect status after io reactor shutdown :"
+ this.ioReactor.getStatus();
// Give the I/O reactor 1 sec to shut down
shutdownReactor(1000);
assert this.ioReactor.getStatus().equals(IOReactorStatus.SHUT_DOWN) : "incorrect status after io reactor shutdown :"
+ this.ioReactor.getStatus();
}
@Override
protected void createNewConnection() throws InterruptedException {
boolean acquired = allConnections.tryAcquire(1, TimeUnit.SECONDS);
if (acquired) {
if (shouldDoWork()) {
logger.debug("%1$s - opening new connection", target);
ioReactor.connect(target, null, null, sessionCallback);
} else {
allConnections.release();
}
}
boolean acquired = allConnections.tryAcquire(1, TimeUnit.SECONDS);
if (acquired) {
if (shouldDoWork()) {
logger.debug("%1$s - opening new connection", target);
ioReactor.connect(target, null, null, sessionCallback);
} else {
allConnections.release();
}
}
}
@Override
protected void associateHandleWithConnection(
FutureCommandConnectionHandle<NHttpConnection, HttpFutureCommand<?>> handle,
NHttpConnection connection) {
connection.getContext().setAttribute("command-handle", handle);
FutureCommandConnectionHandle<NHttpConnection, HttpFutureCommand<?>> handle,
NHttpConnection connection) {
connection.getContext().setAttribute("command-handle", handle);
}
@Override
protected HttpNioFutureCommandConnectionHandle getHandleFromConnection(
NHttpConnection connection) {
return (HttpNioFutureCommandConnectionHandle) connection.getContext()
.getAttribute("command-handle");
NHttpConnection connection) {
return (HttpNioFutureCommandConnectionHandle) connection.getContext()
.getAttribute("command-handle");
}
class NHttpClientConnectionPoolSessionRequestCallback implements
SessionRequestCallback {
SessionRequestCallback {
public void completed(SessionRequest request) {
logger.trace("%1$s->%2$s[%3$s] - SessionRequest complete", request
.getLocalAddress(), request.getRemoteAddress(), request
.getAttachment());
}
public void completed(SessionRequest request) {
logger.trace("%1$s->%2$s[%3$s] - SessionRequest complete", request
.getLocalAddress(), request.getRemoteAddress(), request
.getAttachment());
}
public void cancelled(SessionRequest request) {
logger.trace("%1$s->%2$s[%3$s] - SessionRequest cancelled", request
.getLocalAddress(), request.getRemoteAddress(), request
.getAttachment());
releaseConnectionAndCancelResponse(request);
}
public void cancelled(SessionRequest request) {
logger.trace("%1$s->%2$s[%3$s] - SessionRequest cancelled", request
.getLocalAddress(), request.getRemoteAddress(), request
.getAttachment());
releaseConnectionAndCancelResponse(request);
}
private void releaseConnectionAndCancelResponse(SessionRequest request) {
allConnections.release();
FutureCommand<?, ?, ?> frequest = (FutureCommand<?, ?, ?>) request
.getAttachment();
if (frequest != null) {
logger.error("%1$s->%2$s[%3$s] - Cancelling FutureCommand",
request.getLocalAddress(), request.getRemoteAddress(),
frequest);
frequest.cancel(true);
}
}
private void releaseConnectionAndCancelResponse(SessionRequest request) {
allConnections.release();
FutureCommand<?, ?, ?> frequest = (FutureCommand<?, ?, ?>) request
.getAttachment();
if (frequest != null) {
logger.error("%1$s->%2$s[%3$s] - Cancelling FutureCommand",
request.getLocalAddress(), request.getRemoteAddress(),
frequest);
frequest.cancel(true);
}
}
private void releaseConnectionAndSetResponseException(
SessionRequest request, Exception e) {
allConnections.release();
HttpFutureCommand<?> frequest = (HttpFutureCommand<?>) request
.getAttachment();
if (frequest != null) {
logger.error(e,
"%1$s->%2$s[%3$s] - Setting Exception on FutureCommand",
request.getLocalAddress(), request.getRemoteAddress(),
frequest);
frequest.setException(e);
}
}
private void releaseConnectionAndSetResponseException(
SessionRequest request, Exception e) {
allConnections.release();
HttpFutureCommand<?> frequest = (HttpFutureCommand<?>) request
.getAttachment();
if (frequest != null) {
logger.error(e,
"%1$s->%2$s[%3$s] - Setting Exception on FutureCommand",
request.getLocalAddress(), request.getRemoteAddress(),
frequest);
frequest.setException(e);
}
}
public void failed(SessionRequest request) {
int count = currentSessionFailures.getAndIncrement();
logger.warn("%1$s->%2$s[%3$s] - SessionRequest failed", request
.getLocalAddress(), request.getRemoteAddress(), request
.getAttachment());
releaseConnectionAndSetResponseException(request, request
.getException());
if (count >= maxSessionFailures) {
logger
.error(
request.getException(),
"%1$s->%2$s[%3$s] - SessionRequest failures: %4$s, Disabling pool for %5$s",
request.getLocalAddress(), request
.getRemoteAddress(),
maxSessionFailures, target);
exception.set(request.getException());
}
public void failed(SessionRequest request) {
int count = currentSessionFailures.getAndIncrement();
logger.warn("%1$s->%2$s[%3$s] - SessionRequest failed", request
.getLocalAddress(), request.getRemoteAddress(), request
.getAttachment());
releaseConnectionAndSetResponseException(request, request
.getException());
if (count >= maxSessionFailures) {
logger
.error(
request.getException(),
"%1$s->%2$s[%3$s] - SessionRequest failures: %4$s, Disabling pool for %5$s",
request.getLocalAddress(), request
.getRemoteAddress(),
maxSessionFailures, target);
exception.set(request.getException());
}
}
}
public void timeout(SessionRequest request) {
logger.warn("%1$s->%2$s[%3$s] - SessionRequest timeout", request
.getLocalAddress(), request.getRemoteAddress(), request
.getAttachment());
releaseConnectionAndCancelResponse(request);
}
public void timeout(SessionRequest request) {
logger.warn("%1$s->%2$s[%3$s] - SessionRequest timeout", request
.getLocalAddress(), request.getRemoteAddress(), request
.getAttachment());
releaseConnectionAndCancelResponse(request);
}
}
public void connectionOpen(NHttpConnection conn) {
conn.setSocketTimeout(0);
available.offer(conn);
logger.trace("%1$s - %2$d - open", conn, conn.hashCode());
conn.setSocketTimeout(0);
available.offer(conn);
logger.trace("%1$s - %2$d - open", conn, conn.hashCode());
}
public void connectionTimeout(NHttpConnection conn) {
String message = String.format("%1$s - %2$d - timeout %2$d", conn, conn
.hashCode(), conn.getSocketTimeout());
logger.warn(message);
resubmitIfRequestIsReplayable(conn, new TimeoutException(message));
String message = String.format("%1$s - %2$d - timeout %2$d", conn, conn
.hashCode(), conn.getSocketTimeout());
logger.warn(message);
resubmitIfRequestIsReplayable(conn, new TimeoutException(message));
}
public void connectionClosed(NHttpConnection conn) {
logger.trace("%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) {
logger.error(ex, "%3$s-%1$d{%2$s} - io error", conn, conn.hashCode(),
target);
resubmitIfRequestIsReplayable(conn, ex);
logger.error(ex, "%3$s-%1$d{%2$s} - io error", conn, conn.hashCode(),
target);
resubmitIfRequestIsReplayable(conn, ex);
}
public void fatalProtocolException(HttpException ex, NHttpConnection conn) {
logger.error(ex, "%3$s-%1$d{%2$s} - http error", conn, conn.hashCode(),
target);
setExceptionOnCommand(conn, ex);
logger.error(ex, "%3$s-%1$d{%2$s} - http error", conn, conn.hashCode(),
target);
setExceptionOnCommand(conn, ex);
}
public static interface FutureCommandConnectionHandleFactory
extends
FutureCommandConnectionPool.FutureCommandConnectionHandleFactory<NHttpConnection, HttpFutureCommand<?>> {
HttpNioFutureCommandConnectionHandle create(
HttpFutureCommand<?> command, NHttpConnection conn);
extends
FutureCommandConnectionPool.FutureCommandConnectionHandleFactory<NHttpConnection, HttpFutureCommand<?>> {
HttpNioFutureCommandConnectionHandle create(
HttpFutureCommand<?> command, NHttpConnection conn);
}
@Override
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;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import com.google.inject.Inject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpResponse;
@ -45,15 +40,18 @@ import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import org.jclouds.http.httpnio.util.HttpNioUtils;
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!
*
*
* @author Adrian Cole
*/
public class HttpNioFutureCommandExecutionHandler implements
NHttpRequestExecutionHandler {
NHttpRequestExecutionHandler {
private final ExecutorService executor;
@Resource
protected Logger logger = Logger.NULL;
@ -73,105 +71,105 @@ public class HttpNioFutureCommandExecutionHandler implements
private HttpResponseHandler serverErrorHandler = new CloseContentAndSetExceptionHandler();
public interface ConsumingNHttpEntityFactory {
public ConsumingNHttpEntity create(HttpEntity httpEntity);
public ConsumingNHttpEntity create(HttpEntity httpEntity);
}
@Inject
public HttpNioFutureCommandExecutionHandler(
ConsumingNHttpEntityFactory entityFactory,
ExecutorService executor,
BlockingQueue<HttpFutureCommand<?>> commandQueue) {
this.executor = executor;
this.entityFactory = entityFactory;
this.commandQueue = commandQueue;
ConsumingNHttpEntityFactory entityFactory,
ExecutorService executor,
BlockingQueue<HttpFutureCommand<?>> commandQueue) {
this.executor = executor;
this.entityFactory = entityFactory;
this.commandQueue = commandQueue;
}
public void initalizeContext(HttpContext context, Object attachment) {
}
public HttpEntityEnclosingRequest submitRequest(HttpContext context) {
HttpFutureCommand<?> command = (HttpFutureCommand<?>) context
.removeAttribute("command");
if (command != null) {
HttpRequest object = command.getRequest();
return HttpNioUtils.convertToApacheRequest(object);
}
return null;
HttpFutureCommand<?> command = (HttpFutureCommand<?>) context
.removeAttribute("command");
if (command != null) {
HttpRequest object = command.getRequest();
return HttpNioUtils.convertToApacheRequest(object);
}
return null;
}
public ConsumingNHttpEntity responseEntity(HttpResponse response,
HttpContext context) throws IOException {
return entityFactory.create(response.getEntity());
HttpContext context) throws IOException {
return entityFactory.create(response.getEntity());
}
public void handleResponse(HttpResponse apacheResponse, HttpContext context)
throws IOException {
HttpNioFutureCommandConnectionHandle handle = (HttpNioFutureCommandConnectionHandle) context
.removeAttribute("command-handle");
if (handle != null) {
try {
HttpFutureCommand<?> command = handle.getCommand();
org.jclouds.http.HttpResponse response = HttpNioUtils
.convertToJavaCloudsResponse(apacheResponse);
throws IOException {
HttpNioFutureCommandConnectionHandle handle = (HttpNioFutureCommandConnectionHandle) context
.removeAttribute("command-handle");
if (handle != null) {
try {
HttpFutureCommand<?> command = handle.getCommand();
org.jclouds.http.HttpResponse response = HttpNioUtils
.convertToJavaCloudsResponse(apacheResponse);
int code = response.getStatusCode();
if (code >= 500) {
if (isRetryable(command)) {
commandQueue.add(command);
} else {
this.serverErrorHandler.handle(command, response);
}
} else if (code >= 400 && code < 500) {
this.clientErrorHandler.handle(command, response);
} else if (code >= 300 && code < 400) {
this.redirectHandler.handle(command, response);
} else {
processResponse(response, command);
}
} finally {
releaseConnectionToPool(handle);
}
} else {
throw new IllegalStateException(String.format(
"No command-handle associated with command %1$s", context));
}
int code = response.getStatusCode();
if (code >= 500) {
if (isRetryable(command)) {
commandQueue.add(command);
} else {
this.serverErrorHandler.handle(command, response);
}
} else if (code >= 400 && code < 500) {
this.clientErrorHandler.handle(command, response);
} else if (code >= 300 && code < 400) {
this.redirectHandler.handle(command, response);
} else {
processResponse(response, command);
}
} finally {
releaseConnectionToPool(handle);
}
} else {
throw new IllegalStateException(String.format(
"No command-handle associated with command %1$s", context));
}
}
protected boolean isRetryable(HttpFutureCommand<?> command) {
if (command.getRequest().isReplayable()) {
logger.info("resubmitting command: %1$s", command);
return true;
}
return false;
if (command.getRequest().isReplayable()) {
logger.debug("resubmitting command: %1$s", command);
return true;
}
return false;
}
protected void releaseConnectionToPool(
HttpNioFutureCommandConnectionHandle handle) {
try {
handle.release();
} catch (InterruptedException e) {
logger.error(e, "Interrupted releasing handle %1$s", handle);
}
HttpNioFutureCommandConnectionHandle handle) {
try {
handle.release();
} catch (InterruptedException e) {
logger.error(e, "Interrupted releasing handle %1$s", handle);
}
}
protected void processResponse(org.jclouds.http.HttpResponse response,
HttpFutureCommand<?> command) throws IOException {
command.getResponseFuture().setResponse(response);
logger.trace("submitting response task %1$s", command
.getResponseFuture());
executor.submit(command.getResponseFuture());
HttpFutureCommand<?> command) throws IOException {
command.getResponseFuture().setResponse(response);
logger.trace("submitting response task %1$s", command
.getResponseFuture());
executor.submit(command.getResponseFuture());
}
public void finalizeContext(HttpContext context) {
HttpNioFutureCommandConnectionHandle handle = (HttpNioFutureCommandConnectionHandle) context
.removeAttribute("command-handle");
if (handle != null) {
try {
handle.cancel();
} catch (Exception e) {
logger.error(e, "Error cancelling handle %1$s", handle);
}
}
HttpNioFutureCommandConnectionHandle handle = (HttpNioFutureCommandConnectionHandle) context
.removeAttribute("command-handle");
if (handle != null) {
try {
handle.cancel();
} catch (Exception e) {
logger.error(e, "Error cancelling handle %1$s", handle);
}
}
}
}

View File

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

View File

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

View File

@ -182,6 +182,7 @@
<goal>jar</goal>
</goals>
<configuration>
<quiet>true</quiet>
<links>
<link>http://java.sun.com/j2se/1.5.0/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"?>
<!--
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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId>

View File

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

View File

@ -49,6 +49,9 @@
<properties>
<jclouds.aws.accesskeyid></jclouds.aws.accesskeyid>
<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>
<dependencies>
@ -67,25 +70,115 @@
<artifactId>bcprov-jdk15</artifactId>
<version>140</version>
</dependency>
<dependency>
<groupId>xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<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>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>
<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>
</systemProperties>
<!-- 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>unit,performance</groups>
<excludedGroups>integration,live</excludedGroups> -->
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>**/*LiveTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</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>

View File

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

View File

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

View File

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

View File

@ -28,17 +28,16 @@ import java.io.InputStream;
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.
*
* <p/>
* <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
* 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.
*
*
* @author Adrian Cole
*
*/
public interface S3InputStreamMap extends S3Map<String, InputStream> {
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 S3Error
* @see ParseS3ErrorFromXmlContent
* @see org.jclouds.aws.s3.handlers.ParseS3ErrorFromXmlContent
* @author Adrian Cole
*
*/

View File

@ -23,12 +23,10 @@
*/
package org.jclouds.aws.s3.commands.options;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.io.UnsupportedEncodingException;
import com.google.common.base.Preconditions;
import static com.google.common.base.Preconditions.*;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
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.joda.time.DateTime;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import java.io.UnsupportedEncodingException;
/**
* Contains options supported in the REST API for the COPY object operation.
@ -49,26 +45,24 @@ import com.google.common.collect.Multimap;
* <p/>
* <code>
* import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.*
*
* <p/>
* S3Connection connection = // get connection
*
* <p/>
* Multimap<String,String> metadata = HashMultimap.create();
* metadata.put("x-amz-meta-adrian", "foo");
*
* <p/>
* // this will copy the object, provided it wasn't modified since yesterday.
* // it will not use metadata from the source, and instead use what we pass in.
* Future<S3Object.Metadata> object = connection.copyObject("sourceBucket", "objectName",
* "destinationBucket", "destinationName",
* overrideMetadataWith(meta).
* ifSourceModifiedSince(new DateTime().minusDays(1))
* );
* "destinationBucket", "destinationName",
* overrideMetadataWith(meta).
* ifSourceModifiedSince(new DateTime().minusDays(1))
* );
* <code>
*
*
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectCOPY.html?"
* />
* @author Adrian Cole
*
*
*/
public class CopyObjectOptions extends BaseHttpRequestOptions {
private final static DateService dateService = new DateService();
@ -81,257 +75,253 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
/**
* Override the default ACL (private) with the specified one.
*
*
* @see CannedAccessPolicy
*/
public CopyObjectOptions overrideAcl(CannedAccessPolicy acl) {
this.acl = checkNotNull(acl, "acl");
if (!acl.equals(CannedAccessPolicy.PRIVATE))
this.replaceHeader(S3Headers.CANNED_ACL, acl.toString());
return this;
this.acl = checkNotNull(acl, "acl");
if (!acl.equals(CannedAccessPolicy.PRIVATE))
this.replaceHeader(S3Headers.CANNED_ACL, acl.toString());
return this;
}
/**
* @see CopyObjectOptions#overrideAcl(CannedAccessPolicy)
*/
public CannedAccessPolicy getAcl() {
return acl;
return acl;
}
/**
* 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;
* otherwise returns a 412 (precondition failed).
* <p />
* <p/>
* This header can be used with x-amz-copy-source-if-match, but cannot be
* used with other conditional copy headers.
*
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
*
* @return valid HTTP date
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
* @see CopyObjectOptions#ifSourceModifiedSince(DateTime)
*/
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
* <p />
* <p/>
* Copies the object if it has been modified since the specified time;
* otherwise returns a 412 (failed condition).
* <p/>
* This header can be used with x-amz-copy-source-if-none-match, but cannot
* be used with other conditional copy headers.
*
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
*
* @return valid HTTP date
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
* @see CopyObjectOptions#ifSourceUnmodifiedSince(DateTime)
*/
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
* <p />
* <p/>
* Copies the object if its entity tag (ETag) matches the specified tag;
* otherwise return a 412 (precondition failed).
* <p/>
* This header can be used with x-amz-copy-source-if-unmodified-since, but
* cannot be used with other conditional copy headers.
*
*
* @see CopyObjectOptions#ifSourceMd5Matches(byte[])
*/
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
* <p />
* <p/>
* Copies the object if its entity tag (ETag) is different than the
* specified Etag; otherwise returns a 412 (failed condition).
* <p/>
* This header can be used with x-amz-copy-source-if-modified-since, but
* cannot be used with other conditional copy headers.
*
*
* @see CopyObjectOptions#ifSourceMd5DoesntMatch(byte[])
*/
public String getIfNoneMatch() {
return getFirstHeaderOrNull("x-amz-copy-source-if-none-match");
return getFirstHeaderOrNull("x-amz-copy-source-if-none-match");
}
/**
* When not null, contains the header
* [x-amz-copy-source-if-unmodified-since] -> [REPLACE] and metadata headers
* passed in from the users.
*
*
* @see #overrideMetadataWith(Multimap)
*/
public Multimap<String, String> getMetadata() {
return metadata;
return metadata;
}
/**
* Only return the object if it has changed since this time.
* <p />
* <p/>
* Not compatible with {@link #ifSourceMd5Matches(byte[])} or
* {@link #ifSourceUnmodifiedSince(DateTime)}
*/
public CopyObjectOptions ifSourceModifiedSince(DateTime ifModifiedSince) {
checkState(getIfMatch() == null,
"ifMd5Matches() is not compatible with ifModifiedSince()");
checkState(getIfUnmodifiedSince() == null,
"ifUnmodifiedSince() is not compatible with ifModifiedSince()");
replaceHeader("x-amz-copy-source-if-modified-since",
dateService.toHeaderString(checkNotNull(ifModifiedSince,
"ifModifiedSince")));
return this;
checkState(getIfMatch() == null,
"ifMd5Matches() is not compatible with ifModifiedSince()");
checkState(getIfUnmodifiedSince() == null,
"ifUnmodifiedSince() is not compatible with ifModifiedSince()");
replaceHeader("x-amz-copy-source-if-modified-since",
dateService.toHeaderString(checkNotNull(ifModifiedSince,
"ifModifiedSince")));
return this;
}
/**
* Only return the object if it hasn't changed since this time.
* <p />
* <p/>
* Not compatible with {@link #ifSourceMd5DoesntMatch(byte[])} or
* {@link #ifSourceModifiedSince(DateTime)}
*/
public CopyObjectOptions ifSourceUnmodifiedSince(DateTime ifUnmodifiedSince) {
checkState(getIfNoneMatch() == null,
"ifMd5DoesntMatch() is not compatible with ifUnmodifiedSince()");
checkState(getIfModifiedSince() == null,
"ifModifiedSince() is not compatible with ifUnmodifiedSince()");
replaceHeader("x-amz-copy-source-if-unmodified-since", dateService
.toHeaderString(checkNotNull(ifUnmodifiedSince,
"ifUnmodifiedSince")));
return this;
checkState(getIfNoneMatch() == null,
"ifMd5DoesntMatch() is not compatible with ifUnmodifiedSince()");
checkState(getIfModifiedSince() == null,
"ifModifiedSince() is not compatible with ifUnmodifiedSince()");
replaceHeader("x-amz-copy-source-if-unmodified-since", dateService
.toHeaderString(checkNotNull(ifUnmodifiedSince,
"ifUnmodifiedSince")));
return this;
}
/**
* The object's md5 hash should match the parameter <code>md5</code>.
*
* <p />
* <p/>
* <p/>
* Not compatible with {@link #ifSourceMd5DoesntMatch(byte[])} or
* {@link #ifSourceModifiedSince(DateTime)}
*
* @param md5
* hash representing the entity
* @throws UnsupportedEncodingException
* if there was a problem converting this into an S3 eTag string
*
* @param md5 hash representing the entity
* @throws UnsupportedEncodingException if there was a problem converting this into an S3 eTag string
*/
public CopyObjectOptions ifSourceMd5Matches(byte[] md5)
throws UnsupportedEncodingException {
checkState(getIfNoneMatch() == null,
"ifMd5DoesntMatch() is not compatible with ifMd5Matches()");
checkState(getIfModifiedSince() == null,
"ifModifiedSince() is not compatible with ifMd5Matches()");
replaceHeader("x-amz-copy-source-if-match", String.format("\"%1$s\"",
S3Utils.toHexString(checkNotNull(md5, "md5"))));
return this;
throws UnsupportedEncodingException {
checkState(getIfNoneMatch() == null,
"ifMd5DoesntMatch() is not compatible with ifMd5Matches()");
checkState(getIfModifiedSince() == null,
"ifModifiedSince() is not compatible with ifMd5Matches()");
replaceHeader("x-amz-copy-source-if-match", String.format("\"%1$s\"",
S3Utils.toHexString(checkNotNull(md5, "md5"))));
return this;
}
/**
* The object should not have a md5 hash corresponding with the parameter
* <code>md5</code>.
* <p />
* <p/>
* Not compatible with {@link #ifSourceMd5Matches(byte[])} or
* {@link #ifSourceUnmodifiedSince(DateTime)}
*
* @param md5
* hash representing the entity
* @throws UnsupportedEncodingException
* if there was a problem converting this into an S3 eTag string
*
* @param md5 hash representing the entity
* @throws UnsupportedEncodingException if there was a problem converting this into an S3 eTag string
*/
public CopyObjectOptions ifSourceMd5DoesntMatch(byte[] md5)
throws UnsupportedEncodingException {
checkState(getIfMatch() == null,
"ifMd5Matches() is not compatible with ifMd5DoesntMatch()");
Preconditions
.checkState(getIfUnmodifiedSince() == null,
"ifUnmodifiedSince() is not compatible with ifMd5DoesntMatch()");
replaceHeader("x-amz-copy-source-if-none-match", String.format(
"\"%1$s\"", S3Utils.toHexString(checkNotNull(md5,
"ifMd5DoesntMatch"))));
return this;
throws UnsupportedEncodingException {
checkState(getIfMatch() == null,
"ifMd5Matches() is not compatible with ifMd5DoesntMatch()");
Preconditions
.checkState(getIfUnmodifiedSince() == null,
"ifUnmodifiedSince() is not compatible with ifMd5DoesntMatch()");
replaceHeader("x-amz-copy-source-if-none-match", String.format(
"\"%1$s\"", S3Utils.toHexString(checkNotNull(md5,
"ifMd5DoesntMatch"))));
return this;
}
@Override
public Multimap<String, String> buildRequestHeaders() {
Multimap<String, String> returnVal = HashMultimap.create();
returnVal.putAll(headers);
if (metadata != null) {
returnVal.putAll(metadata);
returnVal.put("x-amz-metadata-directive", "REPLACE");
}
return returnVal;
Multimap<String, String> returnVal = HashMultimap.create();
returnVal.putAll(headers);
if (metadata != null) {
returnVal.putAll(metadata);
returnVal.put("x-amz-metadata-directive", "REPLACE");
}
return returnVal;
}
/**
* Use the provided metadata instead of what is on the source object.
*/
public CopyObjectOptions overrideMetadataWith(
Multimap<String, String> metadata) {
checkNotNull(metadata, "metadata");
for (String header : metadata.keySet()) {
checkArgument(header.startsWith("x-amz-meta-"),
"Metadata keys must start with x-amz-meta-");
}
this.metadata = metadata;
return this;
Multimap<String, String> metadata) {
checkNotNull(metadata, "metadata");
for (String header : metadata.keySet()) {
checkArgument(header.startsWith("x-amz-meta-"),
"Metadata keys must start with x-amz-meta-");
}
this.metadata = metadata;
return this;
}
public static class Builder {
/**
* @see CopyObjectOptions#overrideAcl(CannedAccessPolicy)
*/
public static CopyObjectOptions overrideAcl(CannedAccessPolicy acl) {
CopyObjectOptions options = new CopyObjectOptions();
return options.overrideAcl(acl);
}
/**
* @see CopyObjectOptions#overrideAcl(CannedAccessPolicy)
*/
public static CopyObjectOptions overrideAcl(CannedAccessPolicy acl) {
CopyObjectOptions options = new CopyObjectOptions();
return options.overrideAcl(acl);
}
/**
* @see CopyObjectOptions#getIfModifiedSince()
*/
public static CopyObjectOptions ifSourceModifiedSince(
DateTime ifModifiedSince) {
CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceModifiedSince(ifModifiedSince);
}
/**
* @see CopyObjectOptions#getIfModifiedSince()
*/
public static CopyObjectOptions ifSourceModifiedSince(
DateTime ifModifiedSince) {
CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceModifiedSince(ifModifiedSince);
}
/**
* @see CopyObjectOptions#ifSourceUnmodifiedSince(DateTime)
*/
public static CopyObjectOptions ifSourceUnmodifiedSince(
DateTime ifUnmodifiedSince) {
CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceUnmodifiedSince(ifUnmodifiedSince);
}
/**
* @see CopyObjectOptions#ifSourceUnmodifiedSince(DateTime)
*/
public static CopyObjectOptions ifSourceUnmodifiedSince(
DateTime ifUnmodifiedSince) {
CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceUnmodifiedSince(ifUnmodifiedSince);
}
/**
* @see CopyObjectOptions#ifSourceMd5Matches(byte[])
*/
public static CopyObjectOptions ifSourceMd5Matches(byte[] md5)
throws UnsupportedEncodingException {
CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceMd5Matches(md5);
}
/**
* @see CopyObjectOptions#ifSourceMd5Matches(byte[])
*/
public static CopyObjectOptions ifSourceMd5Matches(byte[] md5)
throws UnsupportedEncodingException {
CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceMd5Matches(md5);
}
/**
* @see CopyObjectOptions#ifSourceMd5DoesntMatch(byte[])
*/
public static CopyObjectOptions ifSourceMd5DoesntMatch(byte[] md5)
throws UnsupportedEncodingException {
CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceMd5DoesntMatch(md5);
}
/**
* @see CopyObjectOptions#ifSourceMd5DoesntMatch(byte[])
*/
public static CopyObjectOptions ifSourceMd5DoesntMatch(byte[] md5)
throws UnsupportedEncodingException {
CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceMd5DoesntMatch(md5);
}
/**
* @see #overrideMetadataWith(Multimap)
*/
public static CopyObjectOptions overrideMetadataWith(
Multimap<String, String> metadata) {
CopyObjectOptions options = new CopyObjectOptions();
return options.overrideMetadataWith(metadata);
}
/**
* @see #overrideMetadataWith(Multimap)
*/
public static CopyObjectOptions overrideMetadataWith(
Multimap<String, String> metadata) {
CopyObjectOptions options = new CopyObjectOptions();
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.checkState;
import org.jclouds.http.options.BaseHttpRequestOptions;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* 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
@ -39,17 +38,14 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
* <p/>
* <code>
* import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.*
*
* <p/>
* S3Connection connection = // get connection
* Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
* <code>
*
*
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html?"
* />
*
* @author Adrian Cole
*
*
*/
public class ListBucketOptions extends BaseHttpRequestOptions {
public static final ListBucketOptions NONE = new ListBucketOptions();
@ -58,21 +54,21 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
* Limits the response to keys which begin with the indicated prefix. You
* can use prefixes to separate a bucket into different sets of keys in a
* way similar to how a file system uses folders.
*
*
* @throws UnsupportedEncodingException
*/
public ListBucketOptions withPrefix(String prefix)
throws UnsupportedEncodingException {
options.put("prefix", URLEncoder.encode(checkNotNull(prefix, "prefix"),
"UTF-8"));
return this;
throws UnsupportedEncodingException {
options.put("prefix", URLEncoder.encode(checkNotNull(prefix, "prefix"),
"UTF-8"));
return this;
}
/**
* @see ListBucketOptions#withPrefix(String)
*/
public String getPrefix() {
return options.get("prefix");
return options.get("prefix");
}
/**
@ -80,21 +76,21 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
* include keys that occur lexicographically after marker. This is
* convenient for pagination: To get the next page of results use the last
* key of the current page as the marker.
*
*
* @throws UnsupportedEncodingException
*/
public ListBucketOptions afterMarker(String marker)
throws UnsupportedEncodingException {
options.put("marker", URLEncoder.encode(checkNotNull(marker, "marker"),
"UTF-8"));
return this;
throws UnsupportedEncodingException {
options.put("marker", URLEncoder.encode(checkNotNull(marker, "marker"),
"UTF-8"));
return this;
}
/**
* @see ListBucketOptions#afterMarker(String)
*/
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.
*/
public ListBucketOptions maxResults(long maxKeys) {
checkState(maxKeys >= 0, "maxKeys must be >= 0");
options.put("max-keys", Long.toString(maxKeys));
return this;
checkState(maxKeys >= 0, "maxKeys must be >= 0");
options.put("max-keys", Long.toString(maxKeys));
return this;
}
/**
* @see ListBucketOptions#maxResults(long)
*/
public String getMaxKeys() {
return options.get("max-keys");
return options.get("max-keys");
}
/**
@ -119,62 +115,62 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
* occurrence of the delimiter to be rolled up into a single result element
* in the CommonPrefixes collection. These rolled-up keys are not returned
* elsewhere in the response.
*
*
* @throws UnsupportedEncodingException
*/
public ListBucketOptions setDelimiter(String delimiter)
throws UnsupportedEncodingException {
options.put("delimiter", URLEncoder.encode(checkNotNull(delimiter,
"delimiter"), "UTF-8"));
return this;
public ListBucketOptions delimiter(String delimiter)
throws UnsupportedEncodingException {
options.put("delimiter", URLEncoder.encode(checkNotNull(delimiter,
"delimiter"), "UTF-8"));
return this;
}
/**
* @see ListBucketOptions#setDelimiter(String)
* @see ListBucketOptions#delimiter(String)
*/
public String getDelimiter() {
return options.get("delimiter");
return options.get("delimiter");
}
public static class Builder {
/**
* @throws UnsupportedEncodingException
* @see ListBucketOptions#withPrefix(String)
*/
public static ListBucketOptions withPrefix(String prefix)
throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions();
return options.withPrefix(prefix);
}
/**
* @throws UnsupportedEncodingException
* @see ListBucketOptions#withPrefix(String)
*/
public static ListBucketOptions withPrefix(String prefix)
throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions();
return options.withPrefix(prefix);
}
/**
* @throws UnsupportedEncodingException
* @see ListBucketOptions#afterMarker(String)
*/
public static ListBucketOptions afterMarker(String marker)
throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions();
return options.afterMarker(marker);
}
/**
* @throws UnsupportedEncodingException
* @see ListBucketOptions#afterMarker(String)
*/
public static ListBucketOptions afterMarker(String marker)
throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions();
return options.afterMarker(marker);
}
/**
* @see ListBucketOptions#maxResults(long)
*/
public static ListBucketOptions maxResults(long maxKeys) {
ListBucketOptions options = new ListBucketOptions();
return options.maxResults(maxKeys);
}
/**
* @see ListBucketOptions#maxResults(long)
*/
public static ListBucketOptions maxResults(long maxKeys) {
ListBucketOptions options = new ListBucketOptions();
return options.maxResults(maxKeys);
}
/**
* @throws UnsupportedEncodingException
* @see ListBucketOptions#delimiter(String)
*/
public static ListBucketOptions delimiter(String delimiter)
throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions();
return options.setDelimiter(delimiter);
}
/**
* @throws UnsupportedEncodingException
* @see ListBucketOptions#delimiter(String)
*/
public static ListBucketOptions delimiter(String delimiter)
throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions();
return options.delimiter(delimiter);
}
}
}

View File

@ -23,13 +23,12 @@
*/
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.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
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>
* 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.domain.S3Bucket.Metadata.LocationConstraint.*;
* import org.jclouds.aws.s3.S3Connection;
*
* <p/>
* S3Connection connection = // get connection
* Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
* <code>
*
*
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT.html?"
* />
*
* @author Adrian Cole
*
*/
public class PutBucketOptions extends BaseHttpRequestOptions {
public static final PutBucketOptions NONE = new PutBucketOptions();
@ -62,55 +59,55 @@ public class PutBucketOptions extends BaseHttpRequestOptions {
* You can currently specify a Europe (EU) location constraint.
*/
public PutBucketOptions createIn(LocationConstraint constraint) {
this.constraint = checkNotNull(constraint, "constraint");
this.payload = String
.format(
"<CreateBucketConfiguration><LocationConstraint>%1$s</LocationConstraint></CreateBucketConfiguration>",
constraint.toString());
return this;
this.constraint = checkNotNull(constraint, "constraint");
this.payload = String
.format(
"<CreateBucketConfiguration><LocationConstraint>%1$s</LocationConstraint></CreateBucketConfiguration>",
constraint.toString());
return this;
}
/**
* Override the default ACL (private) with the specified one.
*
*
* @see CannedAccessPolicy
*/
public PutBucketOptions withBucketAcl(CannedAccessPolicy acl) {
this.acl = checkNotNull(acl, "acl");
if (!acl.equals(CannedAccessPolicy.PRIVATE))
this.replaceHeader(S3Headers.CANNED_ACL, acl.toString());
return this;
this.acl = checkNotNull(acl, "acl");
if (!acl.equals(CannedAccessPolicy.PRIVATE))
this.replaceHeader(S3Headers.CANNED_ACL, acl.toString());
return this;
}
/**
* @see PutBucketOptions#withBucketAcl(CannedAccessPolicy)
*/
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() {
return constraint;
return constraint;
}
public static class Builder {
/**
* @see PutBucketOptions#createIn(LocationConstraint)
*/
public static PutBucketOptions createIn(LocationConstraint constraint) {
PutBucketOptions options = new PutBucketOptions();
return options.createIn(constraint);
}
/**
* @see PutBucketOptions#createIn(org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint)
*/
public static PutBucketOptions createIn(LocationConstraint constraint) {
PutBucketOptions options = new PutBucketOptions();
return options.createIn(constraint);
}
/**
* @see PutBucketOptions#withBucketAcl(CannedAccessPolicy)
*/
public static PutBucketOptions withBucketAcl(CannedAccessPolicy acl) {
PutBucketOptions options = new PutBucketOptions();
return options.withBucketAcl(acl);
}
/**
* @see PutBucketOptions#withBucketAcl(CannedAccessPolicy)
*/
public static PutBucketOptions withBucketAcl(CannedAccessPolicy acl) {
PutBucketOptions options = new PutBucketOptions();
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;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import com.google.inject.AbstractModule;
import com.google.inject.assistedinject.FactoryProvider;
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 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
*/
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
protected void configure() {
install(new S3CommandsModule());
bind(S3Connection.class).to(LiveS3Connection.class)
.in(Scopes.SINGLETON);
bind(GuiceS3Context.S3ObjectMapFactory.class).toProvider(
FactoryProvider.newFactory(
GuiceS3Context.S3ObjectMapFactory.class,
LiveS3ObjectMap.class));
bind(GuiceS3Context.S3InputStreamMapFactory.class).toProvider(
FactoryProvider.newFactory(
GuiceS3Context.S3InputStreamMapFactory.class,
LiveS3InputStreamMap.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);
}
this.requireBinding(S3Connection.class);
install(new S3CommandsModule());
bind(GuiceS3Context.S3ObjectMapFactory.class).toProvider(
FactoryProvider.newFactory(
GuiceS3Context.S3ObjectMapFactory.class,
LiveS3ObjectMap.class));
bind(GuiceS3Context.S3InputStreamMapFactory.class).toProvider(
FactoryProvider.newFactory(
GuiceS3Context.S3InputStreamMapFactory.class,
LiveS3InputStreamMap.class));
bind(S3Context.class).to(GuiceS3Context.class);
@Provides
@Singleton
List<HttpRequestFilter> provideRequestFilters(
RequestAuthorizeSignature requestAuthorizeSignature) {
List<HttpRequestFilter> filters = new ArrayList<HttpRequestFilter>();
filters.add(requestAuthorizeSignature);
return filters;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -23,260 +23,249 @@
*/
package org.jclouds.aws.s3.internal;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
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 com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3InputStreamMap;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.File;
import java.io.InputStream;
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
* in Md5 calculation. If this is not desired, use {@link LiveS3ObjectMap}
* instead.
*
*
* @author Adrian Cole
* @see S3Connection
* @see BaseS3Map
* @author Adrian Cole
*/
public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
S3InputStreamMap {
S3InputStreamMap {
@Inject
public LiveS3InputStreamMap(S3Connection connection, @Assisted String bucket) {
super(connection, bucket);
super(connection, bucket);
}
/**
* {@inheritDoc}
*
*
* @see S3Connection#getObject(String, String)
*/
public InputStream get(Object o) {
try {
return (InputStream) (connection.getObject(bucket, o.toString())
.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS))
.getData();
} catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error geting object %1$s:%2$s", bucket, o), e);
}
try {
return (InputStream) (connection.getObject(bucket, o.toString())
.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS))
.getData();
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error geting object %1$s:%2$s", bucket, o), e);
}
}
/**
* {@inheritDoc}
*
*
* @see S3Connection#deleteObject(String, String)
*/
public InputStream remove(Object o) {
InputStream old = get(o);
try {
connection.deleteObject(bucket, o.toString()).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error removing object %1$s:%2$s", bucket, o), e);
}
return old;
InputStream old = get(o);
try {
connection.deleteObject(bucket, o.toString()).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error removing object %1$s:%2$s", bucket, o), e);
}
return old;
}
/**
* {@inheritDoc}
*
*
* @see #getAllObjects()
*/
public Collection<InputStream> values() {
Collection<InputStream> values = new LinkedList<InputStream>();
Set<S3Object> objects = getAllObjects();
for (S3Object object : objects) {
values.add((InputStream) object.getData());
}
return values;
Collection<InputStream> values = new LinkedList<InputStream>();
Set<S3Object> objects = getAllObjects();
for (S3Object object : objects) {
values.add((InputStream) object.getData());
}
return values;
}
/**
* {@inheritDoc}
*
*
* @see #getAllObjects()
*/
public Set<Map.Entry<String, InputStream>> entrySet() {
Set<Map.Entry<String, InputStream>> entrySet = new HashSet<Map.Entry<String, InputStream>>();
for (S3Object object : getAllObjects()) {
entrySet.add(new Entry(object.getKey(), (InputStream) object
.getData()));
}
return entrySet;
Set<Map.Entry<String, InputStream>> entrySet = new HashSet<Map.Entry<String, InputStream>>();
for (S3Object object : getAllObjects()) {
entrySet.add(new Entry(object.getKey(), (InputStream) object
.getData()));
}
return entrySet;
}
/**
* {@inheritDoc}
*/
public class Entry implements java.util.Map.Entry<String, InputStream> {
private InputStream value;
private String key;
private InputStream value;
private String key;
Entry(String key, InputStream value) {
this.key = key;
this.value = value;
}
Entry(String key, InputStream value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public String getKey() {
return key;
}
public InputStream getValue() {
return value;
}
public InputStream getValue() {
return value;
}
/**
* {@inheritDoc}
*
* @see LiveS3InputStreamMap#put(String, InputStream)
*/
public InputStream setValue(InputStream value) {
return put(key, value);
}
/**
* {@inheritDoc}
*
* @see LiveS3InputStreamMap#put(String, InputStream)
*/
public InputStream setValue(InputStream value) {
return put(key, value);
}
}
/**
* {@inheritDoc}
*
*
* @see #putAllInternal(Map)
*/
public void putAll(Map<? extends String, ? extends InputStream> map) {
putAllInternal(map);
putAllInternal(map);
}
/**
* {@inheritDoc}
*
*
* @see #putAllInternal(Map)
*/
public void putAllBytes(Map<? extends String, ? extends byte[]> map) {
putAllInternal(map);
putAllInternal(map);
}
/**
* {@inheritDoc}
*
*
* @see #putAllInternal(Map)
*/
public void putAllFiles(Map<? extends String, ? extends File> map) {
putAllInternal(map);
putAllInternal(map);
}
/**
* {@inheritDoc}
*
*
* @see #putAllInternal(Map)
*/
public void putAllStrings(Map<? extends String, ? extends String> map) {
putAllInternal(map);
putAllInternal(map);
}
/**
* submits requests to add all objects and collects the results later. All
* values will have md5 calculated first. As a side-effect of this, the
* content will be copied into a byte [].
*
*
* @see S3Connection#putObject(String, S3Object)
*/
@VisibleForTesting
void putAllInternal(Map<? extends String, ? extends Object> map) {
try {
List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>();
for (String key : map.keySet()) {
S3Object object = new S3Object(key);
object.setData(map.get(key));
object.generateMd5();
puts.add(connection.putObject(bucket, object));
}
for (Future<byte[]> put : puts)
// this will throw an exception if there was a problem
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error putting into bucket" + bucket,
e);
}
try {
List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>();
for (Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
S3Object object = new S3Object(entry.getKey());
object.setData(entry.getValue());
object.generateMd5();
puts.add(connection.putObject(bucket, object));
}
for (Future<byte[]> put : puts)
// this will throw an exception if there was a problem
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error putting into bucketName" + bucket,
e);
}
}
/**
* {@inheritDoc}
*
*
* @see #putInternal(String, Object)
*/
public InputStream putString(String key, String value) {
return putInternal(key, value);
return putInternal(key, value);
}
/**
* {@inheritDoc}
*
*
* @see #putInternal(String, Object)
*/
public InputStream putFile(String key, File value) {
return putInternal(key, value);
return putInternal(key, value);
}
/**
* {@inheritDoc}
*
*
* @see #putInternal(String, Object)
*/
public InputStream putBytes(String key, byte[] value) {
return putInternal(key, value);
return putInternal(key, value);
}
/**
* {@inheritDoc}
*
*
* @see #putInternal(String, Object)
*/
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,
* the content will be copied into a byte []. *
*
*
* @see S3Connection#putObject(String, S3Object)
*/
@VisibleForTesting
InputStream putInternal(String s, Object o) {
S3Object object = new S3Object(s);
try {
InputStream returnVal = containsKey(s) ? get(s) : null;
object.setData(o);
object.generateMd5();
connection.putObject(bucket, object).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
return returnVal;
} catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error adding object %1$s:%2$s", bucket, object), e);
}
S3Object object = new S3Object(s);
try {
InputStream returnVal = containsKey(s) ? get(s) : null;
object.setData(o);
object.generateMd5();
connection.putObject(bucket, object).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
return returnVal;
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"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) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
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);
}
return returnVal;
@ -149,7 +149,7 @@ public class LiveS3ObjectMap extends BaseS3Map<S3Object> implements S3ObjectMap
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error putting into bucket" + bucket,
throw new S3RuntimeException("Error putting into bucketName" + bucket,
e);
}
}

View File

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

View File

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

View File

@ -23,22 +23,21 @@
*/
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.S3Error;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.http.commands.callables.xml.ParseSax;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.List;
/**
* Creates Parsers needed to interpret S3 Server messages. This class uses guice
* assisted inject, which mandates the creation of many single-method
* interfaces. These interfaces are not intended for public api.
*
*
* @author Adrian Cole
*/
public class S3ParserFactory {
@ -48,18 +47,18 @@ public class S3ParserFactory {
@VisibleForTesting
public static interface GenericParseFactory<T> {
ParseSax<T> create(ParseSax.HandlerWithResult<T> handler);
ParseSax<T> create(ParseSax.HandlerWithResult<T> handler);
}
@Inject
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() {
return parseListAllMyBucketsFactory
.create(ListAllMyBucketsHandlerprovider.get());
return parseListAllMyBucketsFactory
.create(ListAllMyBucketsHandlerprovider.get());
}
@Inject
@ -69,10 +68,10 @@ public class S3ParserFactory {
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() {
return parseListBucketFactory.create(ListBucketHandlerprovider.get());
return parseListBucketFactory.create(ListBucketHandlerprovider.get());
}
@Inject
@ -82,10 +81,10 @@ public class S3ParserFactory {
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() {
return parseCopyObjectFactory.create(copyObjectHandlerProvider.get());
return parseCopyObjectFactory.create(copyObjectHandlerProvider.get());
}
@Inject
@ -98,7 +97,7 @@ public class S3ParserFactory {
* @return a parser used to handle error conditions.
*/
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
*/
@Test(groups = "unit", sequential = true, testName = "s3.PerformanceTest")
@Test(groups = "performance", sequential = true, testName = "s3.PerformanceTest")
public class PerformanceTest {
protected static int LOOP_COUNT = 1000;
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;
import static org.testng.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import org.jclouds.aws.s3.config.LiveS3ConnectionModule;
import org.jclouds.http.config.HttpFutureCommandClientModule;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import java.util.ArrayList;
import java.util.List;
/**
* Tests behavior of modules configured in S3ContextFactory
*
*
* @author Adrian Cole
*
*/
@Test(groups = "unit", testName = "s3.S3ContextFactoryTest")
public class S3ContextFactoryTest {
@HttpFutureCommandClientModule
static class HttpModule extends AbstractModule {
@Override
protected void configure() {
@Override
protected void configure() {
}
}
}
@Test
public void testAddHttpModuleIfNotPresent() {
List<Module> modules = new ArrayList<Module>();
HttpModule module = new HttpModule();
modules.add(module);
S3ContextFactory.addHttpModuleIfNotPresent(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.remove(0), module);
List<Module> modules = new ArrayList<Module>();
HttpModule module = new HttpModule();
modules.add(module);
S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.remove(0), module);
}
@Test
public void testAddLoggingModuleIfNotPresent() {
List<Module> modules = new ArrayList<Module>();
LoggingModule module = new NullLoggingModule();
modules.add(module);
S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.remove(0), module);
List<Module> modules = new ArrayList<Module>();
LoggingModule module = new NullLoggingModule();
modules.add(module);
S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.remove(0), module);
}
@Test
public void testAddNone() {
List<Module> modules = new ArrayList<Module>();
LoggingModule loggingModule = new NullLoggingModule();
modules.add(loggingModule);
HttpModule httpModule = new HttpModule();
modules.add(httpModule);
S3ContextFactory.addHttpModuleIfNotPresent(modules);
S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 2);
assertEquals(modules.remove(0), loggingModule);
assertEquals(modules.remove(0), httpModule);
List<Module> modules = new ArrayList<Module>();
LoggingModule loggingModule = new NullLoggingModule();
modules.add(loggingModule);
HttpModule httpModule = new HttpModule();
modules.add(httpModule);
S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules);
S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 2);
assertEquals(modules.remove(0), loggingModule);
assertEquals(modules.remove(0), httpModule);
}
@Test
public void testAddBoth() {
List<Module> modules = new ArrayList<Module>();
S3ContextFactory.addHttpModuleIfNotPresent(modules);
S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 2);
assert modules.remove(0) instanceof JavaUrlHttpFutureCommandClientModule;
assert modules.remove(0) instanceof JDKLoggingModule;
public void testAddBothWhenNotLive() {
List<Module> modules = new ArrayList<Module>();
S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules);
S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 1);
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;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals;
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 com.google.inject.Module;
import org.jclouds.aws.s3.config.StubS3ConnectionModule;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
import org.testng.ITestContext;
import org.testng.annotations.*;
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 {
protected static final String TEST_STRING = "<apples><apple name=\"fuji\"></apple> </apples>";
protected byte[] goodMd5;
protected byte[] badMd5;
protected String bucketName;
protected void createBucketAndEnsureEmpty(String sourceBucket)
throws InterruptedException, ExecutionException, TimeoutException {
client.putBucketIfNotExists(sourceBucket).get(10, TimeUnit.SECONDS);
assertEquals(client.listBucket(sourceBucket).get(10, TimeUnit.SECONDS)
.getContents().size(), 0);
throws InterruptedException, ExecutionException, TimeoutException {
client.putBucketIfNotExists(sourceBucket).get(10, TimeUnit.SECONDS);
assertEquals(client.listBucket(sourceBucket).get(10, TimeUnit.SECONDS)
.getContents().size(), 0);
}
protected void addObjectToBucket(String sourceBucket, String key)
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
S3Object sourceObject = new S3Object(key);
sourceObject.getMetadata().setContentType("text/xml");
sourceObject.setData(TEST_STRING);
addObjectToBucket(sourceBucket, sourceObject);
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
S3Object sourceObject = new S3Object(key);
sourceObject.getMetadata().setContentType("text/xml");
sourceObject.setData(TEST_STRING);
addObjectToBucket(sourceBucket, sourceObject);
}
protected void addObjectToBucket(String sourceBucket, S3Object object)
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
;
client.putObject(sourceBucket, object).get(10, TimeUnit.SECONDS);
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
client.putObject(sourceBucket, object).get(10, TimeUnit.SECONDS);
}
protected S3Object validateContent(String sourceBucket, String key)
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
assertEquals(client.listBucket(sourceBucket).get(10, TimeUnit.SECONDS)
.getContents().size(), 1);
S3Object newObject = client.getObject(sourceBucket, key).get(10,
TimeUnit.SECONDS);
assert newObject != S3Object.NOT_FOUND;
assertEquals(S3Utils.getContentAsStringAndClose(newObject), TEST_STRING);
return newObject;
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
assertEquals(client.listBucket(sourceBucket).get(10, TimeUnit.SECONDS)
.getContents().size(), 1);
S3Object newObject = client.getObject(sourceBucket, key).get(10,
TimeUnit.SECONDS);
assert newObject != S3Object.NOT_FOUND;
assertEquals(S3Utils.getContentAsStringAndClose(newObject), TEST_STRING);
return newObject;
}
@BeforeTest
@BeforeClass(groups = {"integration", "live"})
void enableDebug() {
if (debugEnabled()) {
Handler HANDLER = new ConsoleHandler() {
{
setLevel(Level.ALL);
setFormatter(new Formatter() {
if (debugEnabled()) {
Handler HANDLER = new ConsoleHandler() {
{
setLevel(Level.ALL);
setFormatter(new Formatter() {
@Override
public String format(LogRecord record) {
return String.format(
"[%tT %-7s] [%-7s] [%s]: %s %s\n",
new Date(record.getMillis()), record
.getLevel(), Thread.currentThread()
.getName(), record.getLoggerName(),
record.getMessage(),
record.getThrown() == null ? "" : record
.getThrown());
}
});
}
};
Logger guiceLogger = Logger.getLogger("org.jclouds");
guiceLogger.addHandler(HANDLER);
guiceLogger.setLevel(Level.ALL);
}
@Override
public String format(LogRecord record) {
return String.format(
"[%tT %-7s] [%-7s] [%s]: %s %s\n",
new Date(record.getMillis()), record
.getLevel(), Thread.currentThread()
.getName(), record.getLoggerName(),
record.getMessage(),
record.getThrown() == null ? "" : record
.getThrown());
}
});
}
};
Logger guiceLogger = Logger.getLogger("org.jclouds");
guiceLogger.addHandler(HANDLER);
guiceLogger.setLevel(Level.ALL);
}
}
protected S3Connection client;
protected S3Context context = null;
protected String bucketPrefix = (System.getProperty("user.name") + "." + this
.getClass().getSimpleName()).toLowerCase();
.getClass().getSimpleName()).toLowerCase();
private static final String sysAWSAccessKeyId = System
.getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID);
.getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID);
private static final String sysAWSSecretAccessKey = System
.getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
.getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
@BeforeTest
@Parameters( { S3Constants.PROPERTY_AWS_ACCESSKEYID,
S3Constants.PROPERTY_AWS_SECRETACCESSKEY })
protected void setUpClient(@Optional String AWSAccessKeyId,
@Optional String AWSSecretAccessKey) throws Exception {
context = createS3Context(AWSAccessKeyId != null ? AWSAccessKeyId
: sysAWSAccessKeyId,
AWSSecretAccessKey != null ? AWSSecretAccessKey
: sysAWSSecretAccessKey);
client = context.getConnection();
deleteEverything();
goodMd5 = S3Utils.md5(TEST_STRING);
badMd5 = S3Utils.md5("alf");
@BeforeClass(inheritGroups = false, groups = {"integration", "live"})
@Parameters({S3Constants.PROPERTY_AWS_ACCESSKEYID,
S3Constants.PROPERTY_AWS_SECRETACCESSKEY})
protected void setUpCredentials(@Optional String AWSAccessKeyId,
@Optional String AWSSecretAccessKey, ITestContext testContext) throws Exception {
AWSAccessKeyId = AWSAccessKeyId != null ? AWSAccessKeyId
: sysAWSAccessKeyId;
AWSSecretAccessKey = AWSSecretAccessKey != null ? AWSSecretAccessKey
: sysAWSSecretAccessKey;
if (AWSAccessKeyId != null)
testContext.setAttribute(S3Constants.PROPERTY_AWS_ACCESSKEYID, AWSAccessKeyId);
if (AWSSecretAccessKey != null)
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() {
return false;
}
protected S3Context createS3Context(String AWSAccessKeyId,
String AWSSecretAccessKey) {
return S3ContextFactory.createS3Context(buildS3Properties(
AWSAccessKeyId, AWSSecretAccessKey), createHttpModule());
return false;
}
protected Properties buildS3Properties(String AWSAccessKeyId,
String AWSSecretAccessKey) {
Properties properties = new Properties(
S3ContextFactory.DEFAULT_PROPERTIES);
properties.setProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID,
checkNotNull(AWSAccessKeyId, "AWSAccessKeyId"));
properties.setProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY,
checkNotNull(AWSSecretAccessKey, "AWSSecretAccessKey"));
properties.setProperty(HttpConstants.PROPERTY_HTTP_SECURE, "false");
properties.setProperty(HttpConstants.PROPERTY_HTTP_PORT, "80");
return properties;
String AWSSecretAccessKey) {
Properties properties = new Properties(
S3ContextFactory.DEFAULT_PROPERTIES);
properties.setProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID,
checkNotNull(AWSAccessKeyId, "AWSAccessKeyId"));
properties.setProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY,
checkNotNull(AWSSecretAccessKey, "AWSSecretAccessKey"));
properties.setProperty(HttpConstants.PROPERTY_HTTP_SECURE, "false");
properties.setProperty(HttpConstants.PROPERTY_HTTP_PORT, "80");
return properties;
}
protected Module createHttpModule() {
return new JavaUrlHttpFutureCommandClientModule();
return new JavaUrlHttpFutureCommandClientModule();
}
protected void deleteEverything() throws Exception {
try {
List<S3Bucket.Metadata> metadata = client.listOwnedBuckets().get(
10, TimeUnit.SECONDS);
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
for (S3Bucket.Metadata metaDatum : metadata) {
if (metaDatum.getName().startsWith(bucketPrefix.toLowerCase())) {
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);
}
try {
List<S3Bucket.Metadata> metadata = client.listOwnedBuckets().get(
10, TimeUnit.SECONDS);
for (S3Bucket.Metadata metaDatum : metadata) {
if (metaDatum.getName().startsWith(bucketPrefix.toLowerCase())) {
deleteBucket(metaDatum.getName());
}
}
} catch (CancellationException e) {
throw e;
}
}
} catch (CancellationException 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 {
deleteEverything();
context.close();
context = null;
deleteEverything();
context.close();
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.jclouds.aws.PerformanceTest;
import org.jclouds.aws.s3.util.S3Utils;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@ -38,90 +39,89 @@ import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import static org.testng.Assert.*;
/**
* This tests the performance of Digest commands.
*
*
* @author Adrian Cole
*/
@Test(groups = "unit", sequential = true, testName = "s3.PerformanceTest")
@Test(groups = "performance", sequential = true, testName = "s3.PerformanceTest")
public class S3UtilsTest extends PerformanceTest {
@Test(dataProvider = "hmacsha1")
void testBouncyCastleDigestSerialResponseTime(byte[] key, String message,
String base64Digest) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException {
for (int i = 0; i < 10000; i++)
testBouncyCastleHmacSha1Base64(key, message, base64Digest);
String base64Digest) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException {
for (int i = 0; i < 10000; i++)
testBouncyCastleHmacSha1Base64(key, message, base64Digest);
}
@Test(dataProvider = "hmacsha1")
void testBouncyCastleDigestParallelResponseTime(final byte[] key,
final String message, final String base64Digest)
throws NoSuchProviderException, NoSuchAlgorithmException,
InvalidKeyException, InterruptedException, ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
exec);
for (int i = 0; i < 10000; i++)
completer.submit(new Callable<Boolean>() {
public Boolean call() throws Exception {
testBouncyCastleHmacSha1Base64(key, message, base64Digest);
return true;
}
});
for (int i = 0; i < 10000; i++)
assert completer.take().get();
final String message, final String base64Digest)
throws NoSuchProviderException, NoSuchAlgorithmException,
InvalidKeyException, InterruptedException, ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
exec);
for (int i = 0; i < 10000; i++)
completer.submit(new Callable<Boolean>() {
public Boolean call() throws Exception {
testBouncyCastleHmacSha1Base64(key, message, base64Digest);
return true;
}
});
for (int i = 0; i < 10000; i++)
assert completer.take().get();
}
@DataProvider(name = "md5")
public Object[][] createMD5Data() {
return base64MD5MessageDigest;
return base64MD5MessageDigest;
}
public final static Object[][] base64MD5MessageDigest = {
{ "apple", "1f3870be274f6c49b3e31a0c6728957f" },
{ "bear", "893b56e3cfe153fb770a120b83bac20c" },
{ "candy", "c48ba993d35c3abe0380f91738fe2a34" },
{ "dogma", "95eb470e4faee302e9cd3063b1923dab" },
{ "emma", "00a809937eddc44521da9521269e75c6" } };
{"apple", "1f3870be274f6c49b3e31a0c6728957f"},
{"bear", "893b56e3cfe153fb770a120b83bac20c"},
{"candy", "c48ba993d35c3abe0380f91738fe2a34"},
{"dogma", "95eb470e4faee302e9cd3063b1923dab"},
{"emma", "00a809937eddc44521da9521269e75c6"}};
public final static Object[][] base64KeyMessageDigest = {
{ Base64.decode("CwsLCwsLCwsLCwsLCwsLCwsLCws="), "Hi There",
"thcxhlUFcmTii8C2+zeMjvFGvgA=" },
{ Base64.decode("SmVmZQ=="), "what do ya want for nothing?",
"7/zfauXrL6LSdBbV8YTfnCWafHk=" },
{ Base64.decode("DAwMDAwMDAwMDAwMDAwMDAwMDAw="),
"Test With Truncation", "TBoDQktV4H/n8nvh1Yu5MkqaWgQ=" },
{
Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key - Hash Key First",
"qkrl4VJy0A6VcFY3zoo7Ve1AIRI=" },
{
Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
"6OmdD0UjfXhta7qnllx4CLv/GpE=" } };
{Base64.decode("CwsLCwsLCwsLCwsLCwsLCwsLCws="), "Hi There",
"thcxhlUFcmTii8C2+zeMjvFGvgA="},
{Base64.decode("SmVmZQ=="), "what do ya want for nothing?",
"7/zfauXrL6LSdBbV8YTfnCWafHk="},
{Base64.decode("DAwMDAwMDAwMDAwMDAwMDAwMDAw="),
"Test With Truncation", "TBoDQktV4H/n8nvh1Yu5MkqaWgQ="},
{
Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key - Hash Key First",
"qkrl4VJy0A6VcFY3zoo7Ve1AIRI="},
{
Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
"6OmdD0UjfXhta7qnllx4CLv/GpE="}};
@DataProvider(name = "hmacsha1")
public Object[][] createData1() {
return base64KeyMessageDigest;
return base64KeyMessageDigest;
}
@Test(dataProvider = "hmacsha1")
public void testBouncyCastleHmacSha1Base64(byte[] key, String message,
String base64Digest) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException {
String b64 = S3Utils.hmacSha1Base64(message, key);
assertEquals(b64, base64Digest);
String base64Digest) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException {
String b64 = S3Utils.hmacSha1Base64(message, key);
assertEquals(b64, base64Digest);
}
@Test(dataProvider = "md5")
public void testBouncyCastleMD5Digest(String message,
String base64Digest) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
String b64 = S3Utils.md5Hex(message.getBytes());
assertEquals(base64Digest,b64);
String base64Digest) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
String b64 = S3Utils.md5Hex(message.getBytes());
assertEquals(base64Digest, b64);
}
}

View File

@ -28,20 +28,20 @@ import org.testng.annotations.Test;
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
*/
@Test(groups = "unit", testName = "s3.SecureS3ConnectionTest")
public class SecureS3ConnectionTest extends S3ConnectionTest {
@Test(groups = {"live"}, testName = "s3.SecureS3ConnectionIntegrationTest")
public class SecureS3ConnectionIntegrationTest extends S3ConnectionIntegrationTest {
@Override
protected Properties buildS3Properties(String AWSAccessKeyId,
String AWSSecretAccessKey) {
Properties properties = super.buildS3Properties(AWSAccessKeyId,
AWSSecretAccessKey);
properties.setProperty("jclouds.http.secure", Boolean.toString(true));
properties.setProperty("jclouds.http.port", "443");
return properties;
String AWSSecretAccessKey) {
Properties properties = super.buildS3Properties(AWSAccessKeyId,
AWSSecretAccessKey);
properties.setProperty("jclouds.http.secure", Boolean.toString(true));
properties.setProperty("jclouds.http.port", "443");
return properties;
}
}

View File

@ -23,226 +23,459 @@
*/
package org.jclouds.aws.s3;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
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.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 com.google.common.base.Function;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.thoughtworks.xstream.XStream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import static org.easymock.classextension.EasyMock.createNiceMock;
import org.jclouds.aws.s3.commands.CopyObject;
import org.jclouds.aws.s3.commands.options.*;
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.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!
*
*
* @author Adrian Cole
*/
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) {
return new FutureBase<S3Object>() {
public S3Object get() throws InterruptedException,
ExecutionException {
if (!bucketToContents.containsKey(s3Bucket))
return S3Object.NOT_FOUND;
Map<String, Object> realContents = bucketToContents
.get(s3Bucket);
if (!realContents.containsKey(key))
return S3Object.NOT_FOUND;
S3Object object = new S3Object(key);
object.setData(realContents.get(key));
return object;
}
};
return getObject(s3Bucket, key, new GetObjectOptions());
}
public S3Object.Metadata copy(S3Object.Metadata in) {
return (S3Object.Metadata) xstream.fromXML(xstream.toXML(in));
}
public S3Object.Metadata copy(S3Object.Metadata in, String newKey) {
return (S3Object.Metadata) xstream.fromXML(xstream.toXML(in).replaceAll(in.getKey(), newKey));
}
public Future<S3Object.Metadata> headObject(final String s3Bucket,
final String key) {
return new FutureBase<S3Object.Metadata>() {
public S3Object.Metadata get() throws InterruptedException,
ExecutionException {
if (!bucketToContents.containsKey(s3Bucket))
return S3Object.Metadata.NOT_FOUND;
Map<String, Object> realContents = bucketToContents
.get(s3Bucket);
if (!realContents.containsKey(key))
return S3Object.Metadata.NOT_FOUND;
S3Object.Metadata metadata = new S3Object.Metadata(key);
return metadata;
}
};
final String key) {
return new FutureBase<S3Object.Metadata>() {
public S3Object.Metadata get() throws InterruptedException,
ExecutionException {
if (!bucketToContents.containsKey(s3Bucket))
return S3Object.Metadata.NOT_FOUND;
Map<String, S3Object> realContents = bucketToContents
.get(s3Bucket);
if (!realContents.containsKey(key))
return S3Object.Metadata.NOT_FOUND;
return realContents.get(key).getMetadata();
}
};
}
public Future<Boolean> deleteObject(final String s3Bucket, final String key) {
return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException,
ExecutionException {
if (bucketToContents.containsKey(s3Bucket)) {
bucketToContents.get(s3Bucket).remove(key);
}
return true;
}
};
return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException,
ExecutionException {
if (bucketToContents.containsKey(s3Bucket)) {
bucketToContents.get(s3Bucket).remove(key);
}
return true;
}
};
}
public Future<byte[]> putObject(final String s3Bucket, final S3Object object) {
return new FutureBase<byte[]>() {
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
}
};
return putObject(s3Bucket, object, new PutObjectOptions());
}
public Future<Boolean> putBucketIfNotExists(final String s3Bucket) {
return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException,
ExecutionException {
if (!bucketToContents.containsKey(s3Bucket)) {
bucketToContents.put(s3Bucket,
new ConcurrentHashMap<String, Object>());
}
return bucketToContents.containsKey(s3Bucket);
}
};
return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException,
ExecutionException {
if (!bucketToContents.containsKey(s3Bucket)) {
bucketToContents.put(s3Bucket,
new ConcurrentHashMap<String, S3Object>());
}
return bucketToContents.containsKey(s3Bucket);
}
};
}
public Future<Boolean> deleteBucketIfEmpty(final String s3Bucket) {
return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException,
ExecutionException {
if (bucketToContents.containsKey(s3Bucket)) {
if (bucketToContents.get(s3Bucket).size() == 0)
return true;
}
return false;
}
};
return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException,
ExecutionException {
if (bucketToContents.containsKey(s3Bucket)) {
if (bucketToContents.get(s3Bucket).size() == 0)
bucketToContents.remove(s3Bucket);
else
return false;
}
return true;
}
};
}
XStream xstream = new XStream();
public Future<S3Object.Metadata> copyObject(final String sourceBucket,
final String sourceObject, final String destinationBucket,
final String destinationObject) {
return new FutureBase<S3Object.Metadata>() {
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;
}
};
final String sourceObject, final String destinationBucket,
final String destinationObject) {
return copyObject(sourceBucket, sourceObject, destinationBucket, destinationObject, new CopyObjectOptions());
}
public Future<Boolean> bucketExists(final String s3Bucket) {
return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException,
ExecutionException {
return bucketToContents.containsKey(s3Bucket);
}
};
return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException,
ExecutionException {
return bucketToContents.containsKey(s3Bucket);
}
};
}
public Future<S3Bucket> listBucket(final String s3Bucket) {
return new FutureBase<S3Bucket>() {
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;
}
}
;
return listBucket(s3Bucket, new ListBucketOptions());
}
private abstract class FutureBase<V> implements Future<V> {
public boolean cancel(boolean b) {
return false;
}
public boolean cancel(boolean b) {
return false;
}
public boolean isCancelled() {
return false;
}
public boolean isCancelled() {
return false;
}
public boolean isDone() {
return true;
}
public boolean isDone() {
return true;
}
public V get(long l, TimeUnit timeUnit) throws InterruptedException,
ExecutionException, TimeoutException {
return get();
}
public V get(long l, TimeUnit timeUnit) throws InterruptedException,
ExecutionException, TimeoutException {
return get();
}
}
public Future<List<Metadata>> listOwnedBuckets() {
return new FutureBase<List<S3Bucket.Metadata>>() {
public List<S3Bucket.Metadata> get() throws InterruptedException,
ExecutionException {
List<S3Bucket.Metadata> list = new ArrayList<S3Bucket.Metadata>();
for (String name : bucketToContents.keySet())
list.add(new S3Bucket.Metadata(name));
return list;
}
};
return new FutureBase<List<S3Bucket.Metadata>>() {
public List<S3Bucket.Metadata> get() throws InterruptedException,
ExecutionException {
return Lists.newArrayList(Iterables.transform(
bucketToContents.keySet(),
new Function<String, Metadata>() {
public Metadata apply(String name) {
return new S3Bucket.Metadata(name);
}
}));
}
};
}
public Future<Boolean> putBucketIfNotExists(String name,
PutBucketOptions options) {
throw new UnsupportedOperationException("todo");
PutBucketOptions options) {
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) {
throw new UnsupportedOperationException("todo");
class DelimiterFilter implements Predicate<S3Object.Metadata> {
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(
String sourceBucket, String sourceObject, String destinationBucket,
String destinationObject, CopyObjectOptions options) {
// TODO Auto-generated method stub
return null;
final String sourceBucket, final String sourceObject, final String destinationBucket,
final String destinationObject, final CopyObjectOptions options) {
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,
PutObjectOptions options) {
// TODO Auto-generated method stub
return null;
private void throwResponseException(int code) throws ExecutionException {
HttpResponse response = new HttpResponse();
response.setStatusCode(code);
throw new ExecutionException(
new HttpResponseException(createNiceMock(CopyObject.class), response));
}
public Future<S3Object> getObject(String bucketName, String key,
GetObjectOptions options) {
// TODO Auto-generated method stub
return null;
public Future<byte[]> putObject(final String bucketName, final S3Object object,
final PutObjectOptions options) {
if (!bucketToContents.containsKey(bucketName)) {
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,35 +23,35 @@
*/
package org.jclouds.aws.s3.commands;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import java.util.concurrent.TimeUnit;
/**
* Tests integrated functionality of all bucketExists commands.
* <p/>
* Each test uses a different bucket name, so it should be perfectly fine to run
* in parallel.
*
*
* @author Adrian Cole
*
*/
@Test(groups = "integration", testName = "s3.BucketExistsIntegrationTest")
@Test(groups = {"integration", "live"}, testName = "s3.BucketExistsIntegrationTest")
public class BucketExistsIntegrationTest extends S3IntegrationTest {
@Test()
@Test
void bucketDoesntExist() throws Exception {
String bucketName = bucketPrefix + "shouldntexist";
assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
String bucketName= bucketPrefix+"be";
assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
}
@Test()
@Test
void bucketExists() throws Exception {
String bucketName = bucketPrefix + "needstoexist";
assert client.putBucketIfNotExists(bucketName).get(10,
TimeUnit.SECONDS);
assert client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
String bucketName= bucketPrefix+"bde";
assert client.putBucketIfNotExists(bucketName).get(10,
TimeUnit.SECONDS);
assert client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
}
}

View File

@ -23,13 +23,18 @@
*/
package org.jclouds.aws.s3.commands;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5DoesntMatch;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5Matches;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceModifiedSince;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceUnmodifiedSince;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideAcl;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideMetadataWith;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
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.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpResponseException;
import org.joda.time.DateTime;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import java.io.IOException;
import java.net.URL;
@ -37,205 +42,166 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpResponseException;
import org.joda.time.DateTime;
import org.testng.annotations.Test;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
/**
* 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(groups = "integration", testName = "s3.CopyObjectIntegrationTest")
@Test(testName = "s3.CopyObjectIntegrationTest")
public class CopyObjectIntegrationTest extends S3IntegrationTest {
String sourceKey = "apples";
String destinationKey = "pears";
@Test()
void testCannedAccessPolicyPublic() throws Exception {
String sourceBucket = bucketPrefix + "tcapp";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey);
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey,overrideAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com/%2$s",
destinationBucket, destinationKey));
S3Utils.toStringAndClose(url.openStream());
}
@Test()
@Test(groups = {"integration","live"})
void testCopyObject() throws Exception {
String sourceBucket = bucketPrefix + "testcopyobject";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey);
String destinationBucket = bucketName + "dest";
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey).get(10, TimeUnit.SECONDS);
addToBucketAndValidate(bucketName, sourceKey);
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,
IOException {
createBucketAndEnsureEmpty(sourceBucket);
addToBucketAndValidate(sourceBucket, sourceKey);
private void addToBucketAndValidate(String bucketName, String sourceKey)
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
addObjectToBucket(bucketName, sourceKey);
validateContent(bucketName, sourceKey);
}
private void addToBucketAndValidate(String sourceBucket, String sourceKey)
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
addObjectToBucket(sourceBucket, sourceKey);
validateContent(sourceBucket, sourceKey);
}
@Test
@Test(groups = {"integration","live"})
void testCopyIfModifiedSince() throws InterruptedException,
ExecutionException, TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcims";
String destinationBucket = sourceBucket + "dest";
ExecutionException, TimeoutException, IOException {
DateTime before = new DateTime();
setupSourceBucket(sourceBucket, sourceKey);
DateTime after = new DateTime().plusSeconds(1);
String destinationBucket = bucketName + "dest";
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(before)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
DateTime before = new DateTime();
addToBucketAndValidate(bucketName, sourceKey);
DateTime after = new DateTime().plusSeconds(1);
try {
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(after)).get(10,
TimeUnit.SECONDS);
} catch (ExecutionException e) {
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412);
}
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(before)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
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,
ExecutionException, TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcius";
String destinationBucket = sourceBucket + "dest";
ExecutionException, TimeoutException, IOException {
DateTime before = new DateTime();
setupSourceBucket(sourceBucket, sourceKey);
DateTime after = new DateTime().plusSeconds(1);
String destinationBucket = bucketName + "dest";
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey, ifSourceUnmodifiedSince(after)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
DateTime before = new DateTime();
addToBucketAndValidate(bucketName, sourceKey);
DateTime after = new DateTime().plusSeconds(1);
try {
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(before)).get(10,
TimeUnit.SECONDS);
} catch (ExecutionException e) {
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412);
}
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceUnmodifiedSince(after)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
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,
TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcim";
TimeoutException, IOException {
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey);
String destinationBucket = bucketName + "dest";
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey, ifSourceMd5Matches(goodMd5)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
addToBucketAndValidate(bucketName, sourceKey);
try {
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey, ifSourceMd5Matches(badMd5)).get(10,
TimeUnit.SECONDS);
} catch (ExecutionException e) {
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412);
}
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5Matches(goodMd5)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
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,
ExecutionException, TimeoutException {
String sourceBucket = bucketPrefix + "tcinm";
ExecutionException, TimeoutException {
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey);
String destinationBucket = bucketName + "dest";
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey, ifSourceMd5DoesntMatch(badMd5)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
addToBucketAndValidate(bucketName, sourceKey);
try {
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey, ifSourceMd5DoesntMatch(goodMd5)).get(10,
TimeUnit.SECONDS);
} catch (ExecutionException e) {
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412);
}
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5DoesntMatch(badMd5)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
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,
ExecutionException, TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcwm";
String destinationBucket = sourceBucket + "dest";
ExecutionException, TimeoutException, IOException {
setupSourceBucket(sourceBucket, sourceKey);
String destinationBucket = bucketName + "dest";
Multimap<String, String> metadata = HashMultimap.create();
metadata.put(S3Headers.USER_METADATA_PREFIX + "adrian", "cole");
addToBucketAndValidate(bucketName, sourceKey);
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey, overrideMetadataWith(metadata)).get(10,
TimeUnit.SECONDS);
Multimap<String, String> metadata = HashMultimap.create();
metadata.put(S3Headers.USER_METADATA_PREFIX + "adrian", "cole");
validateContent(destinationBucket, destinationKey);
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, overrideMetadataWith(metadata)).get(10,
TimeUnit.SECONDS);
S3Object.Metadata objectMeta = client.headObject(destinationBucket,
destinationKey).get(10, TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
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,42 +23,40 @@
*/
package org.jclouds.aws.s3.commands;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.testng.annotations.Test;
import java.util.concurrent.TimeUnit;
/**
* Tests integrated functionality of all deleteBucket commands.
* <p/>
* Each test uses a different bucket name, so it should be perfectly fine to run
* in parallel.
*
*
* @author Adrian Cole
*
*/
@Test(groups = "integration", testName = "s3.DeleteBucketIntegrationTest")
@Test(groups = {"integration", "live"}, testName = "s3.DeleteBucketIntegrationTest")
public class DeleteBucketIntegrationTest extends S3IntegrationTest {
@Test()
@Test
/**
* this method overrides bucketName to ensure it isn't found
*/
void deleteBucketIfEmptyNotFound() throws Exception {
String bucketName = bucketPrefix + "dbienf";
assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
String bucketName = bucketPrefix + "dbienf";
assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
}
@Test()
void deleteBucketIfEmptyButHasContents() throws Exception {
String bucketName = bucketPrefix + "dbiebhc";
createBucketAndEnsureEmpty(bucketName);
addObjectToBucket(bucketName,"test");
assert !client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
addObjectToBucket(bucketName, "test");
assert !client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
}
@Test()
void deleteBucketIfEmpty() throws Exception {
String bucketName = bucketPrefix + "dbie";
createBucketAndEnsureEmpty(bucketName);
assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
}
}

View File

@ -23,56 +23,55 @@
*/
package org.jclouds.aws.s3.commands;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.jclouds.aws.s3.S3ResponseException;
import org.jclouds.aws.s3.domain.S3Object;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* Tests integrated functionality of all deleteObject commands.
* <p/>
* Each test uses a different bucket name, so it should be perfectly fine to run
* in parallel.
*
*
* @author Adrian Cole
*
*/
@Test(groups = "integration", testName = "s3.DeleteObjectIntegrationTest")
@Test(groups = {"integration", "live"}, testName = "s3.DeleteObjectIntegrationTest")
public class DeleteObjectIntegrationTest extends S3IntegrationTest {
@Test()
void deleteObjectNotFound() throws Exception {
String bucketName = bucketPrefix + "donf";
createBucketAndEnsureEmpty(bucketName);
addObjectToBucket(bucketName, "test");
assert client.deleteObject(bucketName, "test")
.get(10, TimeUnit.SECONDS);
String bucketName = bucketPrefix + "donf";
createBucketAndEnsureEmpty(bucketName);
addObjectToBucket(bucketName, "test");
assert client.deleteObject(bucketName, "test")
.get(10, TimeUnit.SECONDS);
}
@Test
void deleteObjectNoBucket() throws Exception {
String bucketName = bucketPrefix + "donb";
try {
client.deleteObject(bucketName, "test").get(10, TimeUnit.SECONDS);
} catch (ExecutionException e) {
assert e.getCause() instanceof S3ResponseException;
assertEquals(((S3ResponseException) e.getCause()).getResponse()
.getStatusCode(), 404);
}
String bucketName = bucketPrefix + "donb";
try {
client.deleteObject(bucketName, "test").get(10, TimeUnit.SECONDS);
} catch (ExecutionException e) {
assert e.getCause() instanceof S3ResponseException;
assertEquals(((S3ResponseException) e.getCause()).getResponse()
.getStatusCode(), 404);
}
}
@Test()
void deleteObject() throws Exception {
String bucketName = bucketPrefix + "do";
createBucketAndEnsureEmpty(bucketName);
addObjectToBucket(bucketName, "test");
assert client.deleteObject(bucketName, "test")
.get(10, TimeUnit.SECONDS);
assert client.headObject(bucketName, "test").get(10, TimeUnit.SECONDS) == S3Object.Metadata.NOT_FOUND;
String bucketName = bucketPrefix + "do";
createBucketAndEnsureEmpty(bucketName);
addObjectToBucket(bucketName, "test");
assert client.deleteObject(bucketName, "test")
.get(10, TimeUnit.SECONDS);
assert client.headObject(bucketName, "test").get(10, TimeUnit.SECONDS) == S3Object.Metadata.NOT_FOUND;
}
}

View File

@ -11,7 +11,7 @@
* "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
* 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
@ -23,212 +23,209 @@
*/
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 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 org.testng.annotations.Test;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.util.S3Utils;
import org.testng.annotations.Test;
/**
* Tests integrated functionality of all GetObject commands.
* <p/>
* Each test uses a different bucket name, so it should be perfectly fine to run
* in parallel.
*
*
* @author Adrian Cole
*
*/
@Test(groups = "integration", testName = "s3.GetObjectIntegrationTest")
@Test(groups = {"integration", "live"}, testName = "s3.GetObjectIntegrationTest")
public class GetObjectIntegrationTest extends S3IntegrationTest {
//
// @Test
// void testGetIfModifiedSince() throws InterruptedException,
// ExecutionException, TimeoutException, IOException {
// String bucket = bucketPrefix + "testGetIfModifiedSince".toLowerCase();
// String key = "apples";
//
// DateTime before = new DateTime();
// setUpBucket(bucket, key);
// DateTime after = new DateTime().plusSeconds(1);
//
// client.getObject(bucket, key, ifModifiedSince(before)).get(10,
// TimeUnit.SECONDS);
// validateContent(bucket, key);
//
// try {
// client.getObject(bucket, key, ifModifiedSince(after)).get(10,
// TimeUnit.SECONDS);
// validateContent(bucket, key);
// } catch (ExecutionException e) {
// if (e.getCause() instanceof HttpResponseException) {
// HttpResponseException ex = (HttpResponseException) e.getCause();
// assertEquals(ex.getResponse().getStatusCode(), 304);
// } else {
// throw e;
// }
// }
//
// }
//
//
// @Test
// void testGetIfUnmodifiedSince() throws InterruptedException,
// ExecutionException, TimeoutException, IOException {
// String bucket = bucketPrefix + "testGetIfUnmodifiedSince".toLowerCase();
// String key = "apples";
//
// DateTime before = new DateTime();
// setUpBucket(bucket, key);
// DateTime after = new DateTime().plusSeconds(1);
//
// client.getObject(bucket, key, ifUnmodifiedSince(after)).get(10,
// TimeUnit.SECONDS);
// validateContent(bucket, key);
//
// try {
// client.getObject(bucket, key, ifUnmodifiedSince(before)).get(10,
// TimeUnit.SECONDS);
// validateContent(bucket, key);
// } catch (ExecutionException e) {
// if (e.getCause() instanceof S3ResponseException) {
// S3ResponseException ex = (S3ResponseException) e.getCause();
// assertEquals(ex.getResponse().getStatusCode(), 412);
// } else {
// throw e;
// }
// }
//
// }
//
// @Test
// void testGetIfMatch() throws InterruptedException, ExecutionException,
// TimeoutException, IOException {
// String bucket = bucketPrefix + "testGetIfMatch".toLowerCase();
// String key = "apples";
//
// setUpBucket(bucket, key);
//
// client.getObject(bucket, key, ifMd5Matches(goodMd5)).get(10,
// TimeUnit.SECONDS);
// validateContent(bucket, key);
//
// try {
// client.getObject(bucket, key, ifMd5Matches(badMd5)).get(10,
// TimeUnit.SECONDS);
// validateContent(bucket, key);
// } catch (ExecutionException e) {
// if (e.getCause() instanceof S3ResponseException) {
// S3ResponseException ex = (S3ResponseException) e.getCause();
// assertEquals(ex.getResponse().getStatusCode(), 412);
// } else {
// throw e;
// }
// }
// }
//
// @Test
// void testGetIfNoneMatch() throws InterruptedException,
// ExecutionException,
// TimeoutException, IOException {
// String bucket = bucketPrefix + "testGetIfNoneMatch".toLowerCase();
// String key = "apples";
//
// setUpBucket(bucket, key);
//
// client.getObject(bucket, key, ifMd5DoesntMatch(badMd5)).get(10,
// TimeUnit.SECONDS);
// validateContent(bucket, key);
//
// try {
// client.getObject(bucket, key, ifMd5DoesntMatch(goodMd5)).get(10,
// TimeUnit.SECONDS);
// validateContent(bucket, key);
// } catch (ExecutionException e) {
// if (e.getCause() instanceof HttpResponseException) {
// HttpResponseException ex = (HttpResponseException) e.getCause();
// assertEquals(ex.getResponse().getStatusCode(), 304);
// } else {
// throw e;
// }
// }
// }
@Test
void testGetIfModifiedSince() throws InterruptedException,
ExecutionException, TimeoutException, IOException {
String key = "apples";
DateTime before = new DateTime();
addObjectAndValidateContent(bucketName, key);
DateTime after = new DateTime().plusSeconds(1);
client.getObject(bucketName, key, ifModifiedSince(before)).get(10,
TimeUnit.SECONDS);
validateContent(bucketName, key);
try {
client.getObject(bucketName, key, ifModifiedSince(after)).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
void testGetIfUnmodifiedSince() throws InterruptedException,
ExecutionException, TimeoutException, IOException {
String key = "apples";
DateTime before = new DateTime();
addObjectAndValidateContent(bucketName, key);
DateTime after = new DateTime().plusSeconds(1);
client.getObject(bucketName, key, ifUnmodifiedSince(after)).get(10,
TimeUnit.SECONDS);
validateContent(bucketName, key);
try {
client.getObject(bucketName, key, ifUnmodifiedSince(before)).get(10,
TimeUnit.SECONDS);
validateContent(bucketName, key);
} catch (ExecutionException e) {
if (e.getCause() instanceof HttpResponseException) {
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412);
} else {
throw e;
}
}
}
@Test
void testGetIfMatch() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
String key = "apples";
addObjectAndValidateContent(bucketName, key);
client.getObject(bucketName, key, ifMd5Matches(goodMd5)).get(10,
TimeUnit.SECONDS);
validateContent(bucketName, key);
try {
client.getObject(bucketName, key, ifMd5Matches(badMd5)).get(10,
TimeUnit.SECONDS);
validateContent(bucketName, key);
} catch (ExecutionException e) {
if (e.getCause() instanceof HttpResponseException) {
HttpResponseException ex = (HttpResponseException) e.getCause();
assertEquals(ex.getResponse().getStatusCode(), 412);
} 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
void testGetRange() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
String bucket = bucketPrefix + "testGetRange".toLowerCase();
String key = "apples";
TimeoutException, IOException {
setUpBucket(bucket, key);
S3Object object1 = client.getObject(bucket, key, range(0, 5)).get(10,
TimeUnit.SECONDS);
assertEquals(S3Utils.getContentAsStringAndClose(object1), TEST_STRING
.substring(0, 6));
String key = "apples";
S3Object object2 = client.getObject(bucket, key,
range(5, TEST_STRING.length())).get(10, TimeUnit.SECONDS);
assertEquals(S3Utils.getContentAsStringAndClose(object2), TEST_STRING
.substring(5, TEST_STRING.length()));
addObjectAndValidateContent(bucketName, key);
S3Object object1 = client.getObject(bucketName, key, range(0, 5)).get(10,
TimeUnit.SECONDS);
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
void testGetTwoRanges() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
String bucket = bucketPrefix + "testGetTwoRanges".toLowerCase();
String key = "apples";
TimeoutException, IOException {
setUpBucket(bucket, key);
S3Object object = client.getObject(bucket, key,
range(0, 5).range(5, TEST_STRING.length())).get(10,
TimeUnit.SECONDS);
String key = "apples";
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
void testGetTail() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
String bucket = bucketPrefix + "testGetTail".toLowerCase();
String key = "apples";
TimeoutException, IOException {
setUpBucket(bucket, key);
S3Object object = client.getObject(bucket, key, tail(5)).get(10,
TimeUnit.SECONDS);
assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING
.substring(TEST_STRING.length() - 5));
assertEquals(object.getContentLength(), 5);
assertEquals(object.getMetadata().getSize(), TEST_STRING.length());
String key = "apples";
addObjectAndValidateContent(bucketName, key);
S3Object object = client.getObject(bucketName, key, tail(5)).get(10,
TimeUnit.SECONDS);
assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING
.substring(TEST_STRING.length() - 5));
assertEquals(object.getContentLength(), 5);
assertEquals(object.getMetadata().getSize(), TEST_STRING.length());
}
@Test
void testGetStartAt() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
String bucket = bucketPrefix + "testGetStartAt".toLowerCase();
String key = "apples";
TimeoutException, IOException {
setUpBucket(bucket, key);
S3Object object = client.getObject(bucket, key, startAt(5)).get(10,
TimeUnit.SECONDS);
assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING
.substring(5, TEST_STRING.length()));
assertEquals(object.getContentLength(), TEST_STRING.length() - 5);
assertEquals(object.getMetadata().getSize(), TEST_STRING.length());
String key = "apples";
addObjectAndValidateContent(bucketName, key);
S3Object object = client.getObject(bucketName, key, startAt(5)).get(10,
TimeUnit.SECONDS);
assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING
.substring(5, TEST_STRING.length()));
assertEquals(object.getContentLength(), TEST_STRING.length() - 5);
assertEquals(object.getMetadata().getSize(), TEST_STRING.length());
}
private void setUpBucket(String sourceBucket, String sourceKey)
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
createBucketAndEnsureEmpty(sourceBucket);
addObjectToBucket(sourceBucket, sourceKey);
validateContent(sourceBucket, sourceKey);
private void addObjectAndValidateContent(String sourcebucketName, String sourceKey)
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
addObjectToBucket(sourcebucketName, sourceKey);
validateContent(sourcebucketName, sourceKey);
}
}

View File

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

View File

@ -23,44 +23,43 @@
*/
package org.jclouds.aws.s3.commands;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.testng.annotations.Test;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Tests integrated functionality of all listOwnedBucket commands.
* <p/>
* Each test uses a different bucket name, so it should be perfectly fine to run
* in parallel.
*
*
* @author Adrian Cole
*
*/
@Test(groups = "integration", testName = "s3.ListOwnedBucketsIntegrationTest")
@Test(groups = {"integration", "live"}, testName = "s3.ListOwnedBucketsIntegrationTest")
public class ListOwnedBucketsIntegrationTest extends S3IntegrationTest {
@Test()
void bucketDoesntExist() throws Exception {
String bucketName = bucketPrefix + "shouldntexist";
List<S3Bucket.Metadata> list = client.listOwnedBuckets().get(10,
TimeUnit.SECONDS);
assert !list.contains(new S3Bucket(bucketName));
String bucketName = bucketPrefix + "shouldntexist";
List<S3Bucket.Metadata> list = client.listOwnedBuckets().get(10,
TimeUnit.SECONDS);
assert !list.contains(new S3Bucket(bucketName));
}
@Test()
void bucketExists() throws Exception {
String bucketName = bucketPrefix + "needstoexist";
assert client.putBucketIfNotExists(bucketName)
.get(10, TimeUnit.SECONDS);
List<S3Bucket.Metadata> list = client.listOwnedBuckets().get(10,
TimeUnit.SECONDS);
S3Bucket.Metadata firstBucket = list.get(0);
S3Bucket.Metadata toMatch = new S3Bucket.Metadata(bucketName);
toMatch.setOwner(firstBucket.getOwner());
String bucketName = bucketPrefix + "needstoexist";
assert client.putBucketIfNotExists(bucketName)
.get(10, TimeUnit.SECONDS);
List<S3Bucket.Metadata> list = client.listOwnedBuckets().get(10,
TimeUnit.SECONDS);
S3Bucket.Metadata firstBucket = list.get(0);
S3Bucket.Metadata toMatch = new S3Bucket.Metadata(bucketName);
toMatch.setOwner(firstBucket.getOwner());
assert list.contains(toMatch);
assert list.contains(toMatch);
}
}

View File

@ -23,64 +23,65 @@
*/
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.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.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.util.S3Utils;
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.
* <p/>
* Each test uses a different bucket name, so it should be perfectly fine to run
* in parallel.
*
*
* @author Adrian Cole
*
*/
@Test(groups = "integration", testName = "s3.PutBucketIntegrationTest")
public class PutBucketIntegrationTest extends S3IntegrationTest {
@Test(testName = "s3.PutBucketLiveTest")
public class PutBucketLiveTest extends S3IntegrationTest {
@Test()
/**
* overriding bucketName as we are changing access permissions
*/
@Test(groups = {"live"})
void testPublicReadAccessPolicy() throws Exception {
String bucketName = bucketPrefix + "public";
String bucketName = bucketPrefix + "public";
client.putBucketIfNotExists(bucketName,
withBucketAcl(CannedAccessPolicy.PUBLIC_READ)).get(10,
TimeUnit.SECONDS);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com",
bucketName));
S3Utils.toStringAndClose(url.openStream());
client.putBucketIfNotExists(bucketName,
withBucketAcl(CannedAccessPolicy.PUBLIC_READ)).get(10,
TimeUnit.SECONDS);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com",
bucketName));
S3Utils.toStringAndClose(url.openStream());
}
@Test(expectedExceptions = IOException.class)
@Test(expectedExceptions = IOException.class, groups = {"live"})
void testDefaultAccessPolicy() throws Exception {
String bucketName = bucketPrefix + "private";
client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com",
bucketName));
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 {
String bucketName = (bucketPrefix + "wow").toLowerCase();
client.putBucketIfNotExists(
bucketName,
createIn(LocationConstraint.EU).withBucketAcl(
CannedAccessPolicy.PUBLIC_READ)).get(10,
TimeUnit.SECONDS);
String bucketName = (bucketPrefix + "wow").toLowerCase();
client.putBucketIfNotExists(
bucketName,
createIn(LocationConstraint.EU).withBucketAcl(
CannedAccessPolicy.PUBLIC_READ)).get(10,
TimeUnit.SECONDS);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com",
bucketName));
S3Utils.toStringAndClose(url.openStream());
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com",
bucketName));
S3Utils.toStringAndClose(url.openStream());
}
}

View File

@ -23,9 +23,18 @@
*/
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.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.assertNotNull;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.File;
import java.io.FileInputStream;
@ -34,115 +43,85 @@ import java.io.InputStream;
import java.net.URL;
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.
* <p/>
* Each test uses a different bucket name, so it should be perfectly fine to run
* in parallel.
*
*
* @author Adrian Cole
*
*/
@Test(groups = "integration", testName = "s3.PutObjectIntegrationTest")
@Test(testName = "s3.PutObjectIntegrationTest")
public class PutObjectIntegrationTest extends S3IntegrationTest {
@DataProvider(name = "putTests")
public Object[][] createData1() throws IOException {
String realObject = IOUtils.toString(new FileInputStream("pom.xml"));
String realObject = IOUtils.toString(new FileInputStream("pom.xml"));
return new Object[][] {
{ "file", "text/xml", new File("pom.xml"), realObject },
{ "string", "text/xml", realObject, realObject },
{ "bytes", "application/octet-stream", realObject.getBytes(),
realObject } };
return new Object[][]{
{"file", "text/xml", new File("pom.xml"), realObject},
{"string", "text/xml", realObject, realObject},
{"bytes", "application/octet-stream", realObject.getBytes(),
realObject}};
}
@Test(dataProvider = "putTests")
@Test(dataProvider = "putTests", groups = {"integration", "live"})
void testPutObject(String key, String type, Object content,
Object realObject) throws Exception {
String bucketName = bucketPrefix + "tpo";
client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS);
context.createS3ObjectMap(bucketName).clear();
assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS)
.getContents().size(), 0);
S3Object object = new S3Object(key);
object.getMetadata().setContentType(type);
object.setData(content);
if (content instanceof InputStream) {
object.generateMd5();
}
assertNotNull(client.putObject(bucketName, object).get(10,
TimeUnit.SECONDS));
object = client.getObject(bucketName, object.getKey()).get(10,
TimeUnit.SECONDS);
String returnedString = S3Utils.getContentAsStringAndClose(object);
assertEquals(returnedString, realObject);
assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS)
.getContents().size(), 1);
Object realObject) throws Exception {
String bucketName = bucketPrefix + "tpo";
client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS);
context.createS3ObjectMap(bucketName).clear();
assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS)
.getContents().size(), 0);
S3Object object = new S3Object(key);
object.getMetadata().setContentType(type);
object.setData(content);
if (content instanceof InputStream) {
object.generateMd5();
}
assertNotNull(client.putObject(bucketName, object).get(10,
TimeUnit.SECONDS));
object = client.getObject(bucketName, object.getKey()).get(10,
TimeUnit.SECONDS);
String returnedString = S3Utils.getContentAsStringAndClose(object);
assertEquals(returnedString, realObject);
assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS)
.getContents().size(), 1);
}
@Test
@Test(groups = {"integration", "live"})
void testMetadata() throws Exception {
String bucketName = bucketPrefix + "tmd";
createBucketAndEnsureEmpty(bucketName);
String key = "hello";
String bucketName = bucketPrefix + "tmd";
createBucketAndEnsureEmpty(bucketName);
String key = "hello";
S3Object object = new S3Object(key, TEST_STRING);
object.getMetadata().setCacheControl("no-cache");
object.getMetadata().setContentType("text/plain");
object.getMetadata().setContentEncoding("x-compress");
object.getMetadata().setSize(TEST_STRING.length());
object.getMetadata().setContentDisposition(
"attachment; filename=hello.txt");
object.getMetadata().getUserMetadata().put(
S3Headers.USER_METADATA_PREFIX + "adrian", "powderpuff");
object.getMetadata().setMd5(S3Utils.md5(TEST_STRING.getBytes()));
S3Object object = new S3Object(key, TEST_STRING);
object.getMetadata().setCacheControl("no-cache");
object.getMetadata().setContentType("text/plain");
object.getMetadata().setContentEncoding("x-compress");
object.getMetadata().setSize(TEST_STRING.length());
object.getMetadata().setContentDisposition(
"attachment; filename=hello.txt");
object.getMetadata().getUserMetadata().put(
S3Headers.USER_METADATA_PREFIX + "adrian", "powderpuff");
object.getMetadata().setMd5(S3Utils.md5(TEST_STRING.getBytes()));
addObjectToBucket(bucketName, object);
S3Object newObject = validateContent(bucketName, key);
// TODO.. why does this come back as binary/octetstring
assertEquals(newObject.getMetadata().getContentType(),
"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());
addObjectToBucket(bucketName, object);
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()));
}
}

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;
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.Multimap;
import com.google.inject.Guice;
import com.google.inject.Injector;
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
*/
@Test
@Test(groups = {"unit"}, testName = "s3.S3CommandFactoryTest")
public class S3CommandFactoryTest {
Injector injector = 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
void setUpInjector() {
injector = Guice.createInjector(new S3CommandsModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Names.named("jclouds.http.address")).to("localhost");
super.configure();
}
});
commandFactory = injector.getInstance(S3CommandFactory.class);
injector = Guice.createInjector(new S3CommandsModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Names.named("jclouds.http.address")).to("localhost");
super.configure();
}
});
commandFactory = injector.getInstance(S3CommandFactory.class);
}
@AfterMethod
void tearDownInjector() {
commandFactory = null;
injector = null;
commandFactory = null;
injector = null;
}
@Test
void testCreateCopyObject() {
assert commandFactory.createCopyObject("sourcebucket", "sourceObject",
"destbucket", "destObject", CopyObjectOptions.NONE) != null;
assert commandFactory.createCopyObject("sourcebucket", "sourceObject",
"destbucket", "destObject", CopyObjectOptions.NONE) != null;
}
@Test
void testCreateCopyObjectOptions() {
assert commandFactory.createCopyObject("sourcebucket", "sourceObject",
"destbucket", "destObject", new CopyObjectOptions()) != null;
assert commandFactory.createCopyObject("sourcebucket", "sourceObject",
"destbucket", "destObject", new CopyObjectOptions()) != null;
}
@Test
void testCreateDeleteBucket() {
assert commandFactory.createDeleteBucket("test") != null;
assert commandFactory.createDeleteBucket("test") != null;
}
@Test
void testCreateDeleteObject() {
assert commandFactory.createDeleteObject("test", "blah") != null;
assert commandFactory.createDeleteObject("test", "blah") != null;
}
@Test
void testCreateHeadBucket() {
assert commandFactory.createHeadBucket("test") != null;
assert commandFactory.createHeadBucket("test") != null;
}
@Test
void testCreatePutBucket() {
assert commandFactory.createPutBucket("test", PutBucketOptions.NONE) != null;
assert commandFactory.createPutBucket("test", PutBucketOptions.NONE) != null;
}
@Test
void testCreatePutBucketOptions() {
assert commandFactory.createPutBucket("test", PutBucketOptions.Builder
.createIn(LocationConstraint.EU)) != null;
assert commandFactory.createPutBucket("test", PutBucketOptions.Builder
.createIn(LocationConstraint.EU)) != null;
}
@Test
void testCreatePutObject() {
S3Object.Metadata metadata = createMock(S3Object.Metadata.class);
S3Object object = new S3Object(metadata);
expect(metadata.getSize()).andReturn(4L).atLeastOnce();
expect(metadata.getKey()).andReturn("rawr");
expect(metadata.getContentType()).andReturn("text/xml").atLeastOnce();
expect(metadata.getCacheControl()).andReturn("no-cache").atLeastOnce();
expect(metadata.getContentDisposition()).andReturn("disposition")
.atLeastOnce();
expect(metadata.getContentEncoding()).andReturn("encoding")
.atLeastOnce();
expect(metadata.getMd5()).andReturn("encoding".getBytes())
.atLeastOnce();
Multimap<String, String> userMdata = HashMultimap.create();
expect(metadata.getUserMetadata()).andReturn(userMdata).atLeastOnce();
S3Object.Metadata metadata = createMock(S3Object.Metadata.class);
S3Object object = new S3Object(metadata);
expect(metadata.getSize()).andReturn(4L).atLeastOnce();
expect(metadata.getKey()).andReturn("rawr");
expect(metadata.getContentType()).andReturn("text/xml").atLeastOnce();
expect(metadata.getCacheControl()).andReturn("no-cache").atLeastOnce();
expect(metadata.getContentDisposition()).andReturn("disposition")
.atLeastOnce();
expect(metadata.getContentEncoding()).andReturn("encoding")
.atLeastOnce();
expect(metadata.getMd5()).andReturn("encoding".getBytes())
.atLeastOnce();
Multimap<String, String> userMdata = HashMultimap.create();
expect(metadata.getUserMetadata()).andReturn(userMdata).atLeastOnce();
replay(metadata);
object.setData("<a></a>");
replay(metadata);
object.setData("<a></a>");
assert commandFactory.createPutObject("test", object,
PutObjectOptions.NONE) != null;
assert commandFactory.createPutObject("test", object,
PutObjectOptions.NONE) != null;
}
@Test
void testCreateGetObject() {
assert commandFactory.createGetObject("test", "blah",
GetObjectOptions.NONE) != null;
assert commandFactory.createGetObject("test", "blah",
GetObjectOptions.NONE) != null;
}
@Test
void testCreateHeadMetadata() {
assert commandFactory.createHeadMetadata("test", "blah") != null;
assert commandFactory.createHeadMetadata("test", "blah") != null;
}
@Test
void testCreateListAllMyBuckets() {
assert commandFactory.createGetMetadataForOwnedBuckets() != null;
assert commandFactory.createGetMetadataForOwnedBuckets() != null;
}
@Test
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;
import static org.testng.Assert.assertEquals;
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 com.google.inject.Guice;
import com.google.inject.Injector;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.PerformanceTest;
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.commands.callables.xml.ParseSax;
import org.joda.time.DateTime;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.xml.sax.SAXException;
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;
/**
* Tests parsing of S3 responses
*
*
* @author Adrian Cole
*/
@Test(groups = "unit", sequential = true, testName = "s3.S3ParserTest")
@Test(groups = {"performance"}, testName = "s3.S3ParserTest")
public class S3ParserTest extends PerformanceTest {
Injector injector = null;
@ -69,136 +67,136 @@ public class S3ParserTest extends PerformanceTest {
@BeforeMethod
protected void setUpInjector() {
injector = Guice.createInjector(new S3ParserModule());
parserFactory = injector.getInstance(S3ParserFactory.class);
assert parserFactory != null;
injector = Guice.createInjector(new S3ParserModule());
parserFactory = injector.getInstance(S3ParserFactory.class);
assert parserFactory != null;
}
@AfterMethod
protected void tearDownInjector() {
parserFactory = null;
injector = null;
parserFactory = null;
injector = null;
}
@Test
void testParseListAllMyBucketsSerialResponseTime() throws HttpException {
for (int i = 0; i < LOOP_COUNT; i++)
runParseListAllMyBuckets();
for (int i = 0; i < LOOP_COUNT; i++)
runParseListAllMyBuckets();
}
private List<S3Bucket.Metadata> runParseListAllMyBuckets()
throws HttpException {
return parserFactory.createListBucketsParser().parse(
IOUtils.toInputStream(listAllMyBucketsResultOn200));
throws HttpException {
return parserFactory.createListBucketsParser().parse(
IOUtils.toInputStream(listAllMyBucketsResultOn200));
}
@Test
void testParseListAllMyBucketsParallelResponseTime()
throws InterruptedException, ExecutionException {
CompletionService<List<S3Bucket.Metadata>> completer = new ExecutorCompletionService<List<S3Bucket.Metadata>>(
exec);
for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<List<S3Bucket.Metadata>>() {
public List<S3Bucket.Metadata> call() throws IOException,
SAXException, HttpException {
return runParseListAllMyBuckets();
}
});
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get() != null;
throws InterruptedException, ExecutionException {
CompletionService<List<S3Bucket.Metadata>> completer = new ExecutorCompletionService<List<S3Bucket.Metadata>>(
exec);
for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<List<S3Bucket.Metadata>>() {
public List<S3Bucket.Metadata> call() throws IOException,
SAXException, HttpException {
return runParseListAllMyBuckets();
}
});
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get() != null;
}
@Test
public void testCanParseListAllMyBuckets() throws HttpException {
List<S3Bucket.Metadata> s3Buckets = runParseListAllMyBuckets();
S3Bucket.Metadata bucket1 = s3Buckets.get(0);
assert bucket1.getName().equals("adrianjbosstest");
DateTime expectedDate1 = new DateTime("2009-03-12T02:00:07.000Z");
DateTime date1 = bucket1.getCreationDate();
assert date1.equals(expectedDate1);
S3Bucket.Metadata bucket2 = s3Buckets.get(1);
assert bucket2.getName().equals("adrianjbosstest2");
DateTime expectedDate2 = new DateTime("2009-03-12T02:00:09.000Z");
DateTime date2 = bucket2.getCreationDate();
assert date2.equals(expectedDate2);
assert s3Buckets.size() == 2;
CanonicalUser owner = new CanonicalUser(
"e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
assert bucket1.getOwner().equals(owner);
assert bucket2.getOwner().equals(owner);
List<S3Bucket.Metadata> s3Buckets = runParseListAllMyBuckets();
S3Bucket.Metadata bucket1 = s3Buckets.get(0);
assert bucket1.getName().equals("adrianjbosstest");
DateTime expectedDate1 = new DateTime("2009-03-12T02:00:07.000Z");
DateTime date1 = bucket1.getCreationDate();
assert date1.equals(expectedDate1);
S3Bucket.Metadata bucket2 = s3Buckets.get(1);
assert bucket2.getName().equals("adrianjbosstest2");
DateTime expectedDate2 = new DateTime("2009-03-12T02:00:09.000Z");
DateTime date2 = bucket2.getCreationDate();
assert date2.equals(expectedDate2);
assert s3Buckets.size() == 2;
CanonicalUser owner = new CanonicalUser(
"e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
assert bucket1.getOwner().equals(owner);
assert bucket2.getOwner().equals(owner);
}
public static final String listBucketResult = "<ListBucketHandler xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>adrianjbosstest</Name><Prefix></Prefix><Marker></Marker><MaxKeys>1000</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>3366</Key><LastModified>2009-03-12T02:00:13.000Z</LastModified><ETag>&quot;9d7bb64e8e18ee34eec06dd2cf37b766&quot;</ETag><Size>136</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketHandler>";
public void testCanParseListBucketResult() throws HttpException,
UnsupportedEncodingException {
S3Bucket bucket = runParseListBucketResult();
assert bucket.isComplete();
assert bucket.getName().equals("adrianjbosstest");
assert bucket.getContents().size() == 1;
S3Object.Metadata object = bucket.getContents().iterator().next();
assert object.getKey().equals("3366");
DateTime expected = new DateTime("2009-03-12T02:00:13.000Z");
assert object.getLastModified().equals(expected) : String.format(
"expected %1$s, but got %1$s", expected, object
.getLastModified());
assertEquals(S3Utils.toHexString(object.getMd5()),
"9d7bb64e8e18ee34eec06dd2cf37b766");
assert object.getSize() == 136;
CanonicalUser owner = new CanonicalUser(
"e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
owner.setDisplayName("ferncam");
assert object.getOwner().equals(owner);
assert object.getStorageClass().equals("STANDARD");
UnsupportedEncodingException {
S3Bucket bucket = runParseListBucketResult();
assert !bucket.isTruncated();
assert bucket.getName().equals("adrianjbosstest");
assert bucket.getContents().size() == 1;
S3Object.Metadata object = bucket.getContents().iterator().next();
assert object.getKey().equals("3366");
DateTime expected = new DateTime("2009-03-12T02:00:13.000Z");
assert object.getLastModified().equals(expected) : String.format(
"expected %1$s, but got %1$s", expected, object
.getLastModified());
assertEquals(S3Utils.toHexString(object.getMd5()),
"9d7bb64e8e18ee34eec06dd2cf37b766");
assert object.getSize() == 136;
CanonicalUser owner = new CanonicalUser(
"e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
owner.setDisplayName("ferncam");
assert object.getOwner().equals(owner);
assert object.getStorageClass().equals("STANDARD");
}
private S3Bucket runParseListBucketResult() throws HttpException {
ParseSax<S3Bucket> parser = parserFactory.createListBucketParser();
ListBucketHandler handler = (ListBucketHandler) parser.getHandler();
handler.setBucketName("adrianjbosstest");
return parser.parse(IOUtils.toInputStream(listBucketResult));
ParseSax<S3Bucket> parser = parserFactory.createListBucketParser();
ListBucketHandler handler = (ListBucketHandler) parser.getHandler();
handler.setBucketName("adrianjbosstest");
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>";
private S3Object.Metadata runParseCopyObjectResult() throws HttpException {
ParseSax<S3Object.Metadata> parser = parserFactory
.createCopyObjectParser();
CopyObjectHandler handler = (CopyObjectHandler) parser.getHandler();
handler.setKey("adrianjbosstest");
return parser.parse(IOUtils.toInputStream(successfulCopyObject200));
ParseSax<S3Object.Metadata> parser = parserFactory
.createCopyObjectParser();
CopyObjectHandler handler = (CopyObjectHandler) parser.getHandler();
handler.setKey("adrianjbosstest");
return parser.parse(IOUtils.toInputStream(successfulCopyObject200));
}
public void testCanParseCopyObjectResult() throws HttpException,
UnsupportedEncodingException {
S3Object.Metadata metadata = runParseCopyObjectResult();
DateTime expected = new DateTime("2009-03-19T13:23:27.000Z");
assertEquals(metadata.getLastModified(), expected);
assertEquals(S3Utils.toHexString(metadata.getMd5()),
"92836a3ea45a6984d1b4d23a747d46bb");
assertEquals(metadata.getKey(), "adrianjbosstest");
UnsupportedEncodingException {
S3Object.Metadata metadata = runParseCopyObjectResult();
DateTime expected = new DateTime("2009-03-19T13:23:27.000Z");
assertEquals(metadata.getLastModified(), expected);
assertEquals(S3Utils.toHexString(metadata.getMd5()),
"92836a3ea45a6984d1b4d23a747d46bb");
assertEquals(metadata.getKey(), "adrianjbosstest");
}
@Test
void testParseListBucketResultSerialResponseTime() throws HttpException {
for (int i = 0; i < LOOP_COUNT; i++)
runParseListBucketResult();
for (int i = 0; i < LOOP_COUNT; i++)
runParseListBucketResult();
}
@Test
void testParseListBucketResultParallelResponseTime()
throws InterruptedException, ExecutionException {
CompletionService<S3Bucket> completer = new ExecutorCompletionService<S3Bucket>(
exec);
for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<S3Bucket>() {
public S3Bucket call() throws IOException, SAXException,
HttpException {
return runParseListBucketResult();
}
});
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get() != null;
throws InterruptedException, ExecutionException {
CompletionService<S3Bucket> completer = new ExecutorCompletionService<S3Bucket>(
exec);
for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<S3Bucket>() {
public S3Bucket call() throws IOException, SAXException,
HttpException {
return runParseListBucketResult();
}
});
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get() != null;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,8 +23,10 @@
*/
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.reference.S3Constants;
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.config.JavaUrlHttpFutureCommandClientModule;
import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Names;
/**
*
* @author Adrian Cole
*/
@Test
@Test(groups = "unit", testName = "s3.S3ContextModuleTest")
public class S3ContextModuleTest {
Injector injector = null;
@BeforeMethod
void setUpInjector() {
injector = Guice.createInjector(new S3ContextModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
"localhost");
bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY))
.to("localhost");
bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_HTTP_ADDRESS)).to(
"localhost");
bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_HTTP_PORT)).to("1000");
bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_HTTP_SECURE)).to(
"false");
super.configure();
}
}, new JavaUrlHttpFutureCommandClientModule());
injector = Guice.createInjector(new LiveS3ConnectionModule(), new S3ContextModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
"localhost");
bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY))
.to("localhost");
bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_HTTP_ADDRESS)).to(
"localhost");
bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_HTTP_PORT)).to("1000");
bindConstant().annotatedWith(
Names.named(S3Constants.PROPERTY_HTTP_SECURE)).to(
"false");
super.configure();
}
}, new JavaUrlHttpFutureCommandClientModule());
}
@AfterMethod
void tearDownInjector() {
injector = null;
injector = null;
}
private static class ClientErrorHandlerTest {
@Inject
@ClientErrorHandler
HttpResponseHandler errorHandler;
@Inject
@ClientErrorHandler
HttpResponseHandler errorHandler;
}
@Test
void testClientErrorHandler() {
ClientErrorHandlerTest error = injector
.getInstance(ClientErrorHandlerTest.class);
assertEquals(error.errorHandler.getClass(),
ParseS3ErrorFromXmlContent.class);
ClientErrorHandlerTest error = injector
.getInstance(ClientErrorHandlerTest.class);
assertEquals(error.errorHandler.getClass(),
ParseS3ErrorFromXmlContent.class);
}
private static class ServerErrorHandlerTest {
@Inject
@ServerErrorHandler
HttpResponseHandler errorHandler;
@Inject
@ServerErrorHandler
HttpResponseHandler errorHandler;
}
@Test
void testServerErrorHandler() {
ServerErrorHandlerTest error = injector
.getInstance(ServerErrorHandlerTest.class);
assertEquals(error.errorHandler.getClass(),
ParseS3ErrorFromXmlContent.class);
ServerErrorHandlerTest error = injector
.getInstance(ServerErrorHandlerTest.class);
assertEquals(error.errorHandler.getClass(),
ParseS3ErrorFromXmlContent.class);
}
private static class RedirectHandlerTest {
@Inject
@RedirectHandler
HttpResponseHandler errorHandler;
@Inject
@RedirectHandler
HttpResponseHandler errorHandler;
}
@Test
void testRedirectHandler() {
RedirectHandlerTest error = injector
.getInstance(RedirectHandlerTest.class);
assertEquals(error.errorHandler.getClass(),
CloseContentAndSetExceptionHandler.class);
RedirectHandlerTest error = injector
.getInstance(RedirectHandlerTest.class);
assertEquals(error.errorHandler.getClass(),
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;
import java.io.File;
import static org.testng.Assert.*;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.http.ContentTypes;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
@Test
import java.io.File;
@Test(groups = "unit", testName = "s3.S3ObjectTest")
public class S3ObjectTest {
@Test
void testSetNoContentType() {
S3Object object = new S3Object("test");
File file = new File("hello.txt");
object.setData(file);
assertEquals(object.getMetadata().getContentType(),
ContentTypes.BINARY);
S3Object object = new S3Object("test");
File file = new File("hello.txt");
object.setData(file);
assertEquals(object.getMetadata().getContentType(),
ContentTypes.BINARY);
}
}

View File

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

View File

@ -23,20 +23,19 @@
*/
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.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class BaseHandlerTest {
protected S3ParserFactory parserFactory = null;
private Injector injector;
public BaseHandlerTest() {
super();
super();
}
@BeforeMethod

View File

@ -23,43 +23,42 @@
*/
package org.jclouds.aws.s3.xml;
import static org.testng.Assert.assertEquals;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.domain.S3Error;
import org.jclouds.http.HttpException;
import org.jclouds.http.commands.callables.xml.ParseSax;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
@Test
@Test(groups = "unit", testName = "s3.ErrorHandlerTest")
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>";
@Test
public void testErrorFromAmazonIfYouDontRemoveTransferEncodingHeader()
throws HttpException {
ParseSax<S3Error> parser = parserFactory.createErrorParser();
S3Error error = parser
.parse(IOUtils
.toInputStream(errorFromAmazonIfYouDontRemoveTransferEncodingHeader));
assertEquals(error.getCode(), "NotImplemented");
assertEquals(error.getMessage(),
"A header you provided implies functionality that is not implemented");
assertEquals(error.getDetails().get("Header"), "Transfer-Encoding");
assertEquals(error.getRequestId(), "7C59925D75D15561");
assertEquals(error.getDetails().get("HostId"),
"fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb");
throws HttpException {
ParseSax<S3Error> parser = parserFactory.createErrorParser();
S3Error error = parser
.parse(IOUtils
.toInputStream(errorFromAmazonIfYouDontRemoveTransferEncodingHeader));
assertEquals(error.getCode(), "NotImplemented");
assertEquals(error.getMessage(),
"A header you provided implies functionality that is not implemented");
assertEquals(error.getDetails().get("Header"), "Transfer-Encoding");
assertEquals(error.getRequestId(), "7C59925D75D15561");
assertEquals(error.getDetails().get("HostId"),
"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 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"
+ "<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"
+ "Thu, 19 Mar 2009 17:48:01 GMT\n"
+ "/adriancole.s3.amazons3test.filetestsforadrian/file</StringToSign><AWSAccessKeyId>0101100101001001</AWSAccessKeyId></Error>";
+ "<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"
+ "Thu, 19 Mar 2009 17:48:01 GMT\n"
+ "/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>";
}

View File

@ -23,16 +23,15 @@
*/
package org.jclouds.aws.s3.xml;
import static org.testng.Assert.assertEquals;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.http.HttpException;
import org.jclouds.http.commands.callables.xml.ParseSax;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@Test
@Test(groups = "unit", testName = "s3.ListBucketHandlerTest")
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 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
void setUpParser() {
parser = parserFactory.createListBucketParser();
((ListBucketHandler) parser.getHandler()).setBucketName("test");
parser = parserFactory.createListBucketParser();
((ListBucketHandler) parser.getHandler()).setBucketName("test");
}
@Test
public void testListMyBucketsWithDelimiterSlashAndCommonPrefixesAppsSlash()
throws HttpException {
throws HttpException {
S3Bucket bucket = parser.parse(IOUtils
.toInputStream(listBucketWithSlashDelimiterAndCommonPrefixApps));
assertEquals(bucket.getCommonPrefixes().iterator().next(), "apps/");
assertEquals(bucket.getDelimiter(), "/");
assert bucket.getMarker() == null;
S3Bucket bucket = parser.parse(IOUtils
.toInputStream(listBucketWithSlashDelimiterAndCommonPrefixApps));
assertEquals(bucket.getCommonPrefixes().iterator().next(), "apps/");
assertEquals(bucket.getDelimiter(), "/");
assert bucket.getMarker() == null;
}
@Test
public void testListMyBucketsWithPrefixAppsSlash() throws HttpException {
S3Bucket bucket = parser.parse(IOUtils
.toInputStream(listBucketWithPrefixAppsSlash));
assertEquals(bucket.getPrefix(), "apps/");
assertEquals(bucket.getMaxKeys(), 1000);
assert bucket.getMarker() == null;
S3Bucket bucket = parser.parse(IOUtils
.toInputStream(listBucketWithPrefixAppsSlash));
assertEquals(bucket.getPrefix(), "apps/");
assertEquals(bucket.getMaxKeys(), 1000);
assert bucket.getMarker() == null;
}

View File

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