mirror of https://github.com/apache/jclouds.git
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:
parent
40067b58f0
commit
69deb933e8
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
1
pom.xml
1
pom.xml
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
113
s3/pom.xml
113
s3/pom.xml
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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>"9d7bb64e8e18ee34eec06dd2cf37b766"</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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>";
|
||||
|
||||
}
|
||||
|
|
|
@ -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>"c82e6a0025c31c5de5947fda62ac51ab"</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>"944fab2c5a9a6bacf07db5e688310d7a"</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>"a227b8888045c8fd159fb495214000f0"</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>"c9caa76c3dec53e2a192608ce73eef03"</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>"1ce5d0dcc6154a647ea90c7bdf82a224"</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>"79433524d87462ee05708a8ef894ed55"</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>"dd00a060b28ddca8bc5a21a49e306f67"</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>"8cd06eca6e819a927b07a285d750b100"</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>"174495094d0633b92cbe46603eee6bad"</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>"cd8a19b26fea8a827276df0ad11c580d"</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;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue