separated out unit tests from integration tests and fixed javadoc

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

View File

@ -23,24 +23,18 @@
*/ */
package org.jclouds.http.internal; package org.jclouds.http.internal;
import java.net.URL; import com.google.inject.Inject;
import java.util.Collections; import org.jclouds.http.*;
import java.util.List;
import javax.annotation.Resource;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpFutureCommandClient;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseHandler;
import org.jclouds.http.annotation.ClientErrorHandler; import org.jclouds.http.annotation.ClientErrorHandler;
import org.jclouds.http.annotation.RedirectHandler; import org.jclouds.http.annotation.RedirectHandler;
import org.jclouds.http.annotation.ServerErrorHandler; import org.jclouds.http.annotation.ServerErrorHandler;
import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler; import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.inject.Inject; import javax.annotation.Resource;
import java.net.URL;
import java.util.Collections;
import java.util.List;
public abstract class BaseHttpFutureCommandClient implements HttpFutureCommandClient { public abstract class BaseHttpFutureCommandClient implements HttpFutureCommandClient {
@ -70,7 +64,7 @@ public abstract class BaseHttpFutureCommandClient implements HttpFutureCommandC
HttpResponse response) { HttpResponse response) {
int code = response.getStatusCode(); int code = response.getStatusCode();
if (command.getRequest().isReplayable() && code >= 500) { if (command.getRequest().isReplayable() && code >= 500) {
logger.info("resubmitting command: %1$s", command); logger.debug("resubmitting command: %1$s", command);
return true; return true;
} }
return false; return false;

View File

@ -23,44 +23,41 @@
*/ */
package org.jclouds.logging.config; package org.jclouds.logging.config;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Resource;
import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import static com.google.common.collect.Sets.filter;
import com.google.common.collect.Sets;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.ProvisionException; import com.google.inject.ProvisionException;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import com.google.inject.spi.InjectionListener; import com.google.inject.spi.InjectionListener;
import com.google.inject.spi.TypeEncounter; import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener; import com.google.inject.spi.TypeListener;
import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory;
import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/** /**
* TypeListener that will bind {@link org.jclouds.logging.Logger} to members annotated with * TypeListener that will bind {@link org.jclouds.logging.Logger} to members annotated with
* {@link javax.annotation.Resource} * {@link javax.annotation.Resource}
* * <p/>
* This class is a TypeListener so that it can create a logger whose category is * This class is a TypeListener so that it can create a logger whose category is
* the same as the name of the injected instance's class. * the same as the name of the injected instance's class.
* * <p/>
* Note that this occurs post-object construction through * Note that this occurs post-object construction through
* {@link com.google.inject.Binder#bindListener}. * {@link com.google.inject.Binder#bindListener}.
* * <p/>
* Here's an example usage: * Here's an example usage:
* <pre> * <pre>
* class A { * class A {
* @Resource private Logger logger = Logger.NULL; * @Resource private Logger logger = Logger.NULL;
* } * }
* * <p/>
* Injector i = Guice.createInjector(new AbstractModule() { * Injector i = Guice.createInjector(new AbstractModule() {
* @Override protected void configure() { * @Override protected void configure() {
* bindListener(any(), new * bindListener(any(), new
@ -68,13 +65,12 @@ import com.google.inject.spi.TypeListener;
* JDKLogger.JDKLoggerFactory())); * JDKLogger.JDKLoggerFactory()));
* } * }
* }); * });
* * <p/>
* A = i.getInstance(A.class); * A = i.getInstance(A.class);
* // A will now have a logger associated with it * // A will now have a logger associated with it
* </pre> * </pre>
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
public class BindLoggersAnnotatedWithResource implements TypeListener { public class BindLoggersAnnotatedWithResource implements TypeListener {
@ -98,13 +94,10 @@ public class BindLoggersAnnotatedWithResource implements TypeListener {
} }
static class LoggerFieldsAnnotatedWithResource implements static class LoggerFieldsAnnotatedWithResource implements
Function<Field, Field> { Predicate<Field> {
public Field apply(Field from) { public boolean apply(Field from) {
Annotation inject = from.getAnnotation(Resource.class); Annotation inject = from.getAnnotation(Resource.class);
if (inject != null && from.getType().isAssignableFrom(Logger.class)) { return (inject != null && from.getType().isAssignableFrom(Logger.class));
return from;
}
return null;
} }
} }
@ -138,9 +131,6 @@ public class BindLoggersAnnotatedWithResource implements TypeListener {
fields.addAll(Arrays.asList(type.getDeclaredFields())); fields.addAll(Arrays.asList(type.getDeclaredFields()));
type = type.getSuperclass(); type = type.getSuperclass();
} }
Set<Field> loggerFields = Sets.newHashSet(Iterables.transform(fields, return filter(fields, new LoggerFieldsAnnotatedWithResource());
new LoggerFieldsAnnotatedWithResource()));
loggerFields.remove(null);
return loggerFields;
} }
} }

View File

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

View File

@ -23,28 +23,26 @@
*/ */
package org.jclouds.logging.config; package org.jclouds.logging.config;
import static com.google.inject.matcher.Matchers.any;
import static org.easymock.classextension.EasyMock.createMock;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.lang.reflect.Field;
import java.util.Set;
import javax.annotation.Resource;
import org.jclouds.logging.Logger;
import org.jclouds.logging.config.BindLoggersAnnotatedWithResource.AssignLoggerToField;
import org.jclouds.logging.config.BindLoggersAnnotatedWithResource.LoggerFieldsAnnotatedWithResource;
import org.jclouds.logging.jdk.JDKLogger;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Injector; import com.google.inject.Injector;
import static com.google.inject.matcher.Matchers.any;
import static org.easymock.classextension.EasyMock.createMock;
import org.jclouds.logging.Logger;
import org.jclouds.logging.config.BindLoggersAnnotatedWithResource.AssignLoggerToField;
import org.jclouds.logging.config.BindLoggersAnnotatedWithResource.LoggerFieldsAnnotatedWithResource;
import org.jclouds.logging.jdk.JDKLogger;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.Set;
@Test
public class BindLoggersAnnotatedWithResourceTest { public class BindLoggersAnnotatedWithResourceTest {
private BindLoggersAnnotatedWithResource blawr; private BindLoggersAnnotatedWithResource blawr;
@ -100,9 +98,8 @@ public class BindLoggersAnnotatedWithResourceTest {
@Test @Test
public void testLoggerFieldsAnnotatedWithResource() public void testLoggerFieldsAnnotatedWithResource()
throws SecurityException, NoSuchFieldException { throws SecurityException, NoSuchFieldException {
LoggerFieldsAnnotatedWithResource function = new LoggerFieldsAnnotatedWithResource(); LoggerFieldsAnnotatedWithResource predicate = new LoggerFieldsAnnotatedWithResource();
assertEquals(function.apply(A.class.getDeclaredField("logger")), assert predicate.apply(A.class.getDeclaredField("logger"));
A.class.getDeclaredField("logger"));
} }
public static class C { public static class C {
@ -114,8 +111,8 @@ public class BindLoggersAnnotatedWithResourceTest {
@Test @Test
public void testLoggerFieldsAnnotatedWithInjectReturnsNull() public void testLoggerFieldsAnnotatedWithInjectReturnsNull()
throws SecurityException, NoSuchFieldException { throws SecurityException, NoSuchFieldException {
LoggerFieldsAnnotatedWithResource function = new LoggerFieldsAnnotatedWithResource(); LoggerFieldsAnnotatedWithResource predicate = new LoggerFieldsAnnotatedWithResource();
assertNull(function.apply(C.class.getDeclaredField("logger"))); assert ! predicate.apply(C.class.getDeclaredField("logger"));
} }
public static class D { public static class D {

View File

@ -24,32 +24,18 @@
package org.jclouds.gae; package org.jclouds.gae;
import static com.google.appengine.api.urlfetch.FetchOptions.Builder.disallowTruncate; import static com.google.appengine.api.urlfetch.FetchOptions.Builder.disallowTruncate;
import com.google.appengine.api.urlfetch.*;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import org.apache.commons.io.IOUtils;
import org.jclouds.http.*;
import org.jclouds.http.internal.BaseHttpFutureCommandClient;
import java.io.ByteArrayInputStream; import java.io.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import org.apache.commons.io.IOUtils;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpFutureCommandClient;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.internal.BaseHttpFutureCommandClient;
import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
/** /**
* Google App Engine version of {@link HttpFutureCommandClient} * Google App Engine version of {@link HttpFutureCommandClient}
* *
@ -73,7 +59,7 @@ public class URLFetchServiceClient extends BaseHttpFutureCommandClient {
filter.filter(request); filter.filter(request);
} }
HttpResponse response = null; HttpResponse response = null;
for (;;) { for (; ;) {
logger.trace("%1$s - converting request %2$s", target, request); logger.trace("%1$s - converting request %2$s", target, request);
HTTPRequest gaeRequest = convert(request); HTTPRequest gaeRequest = convert(request);
if (logger.isTraceEnabled()) if (logger.isTraceEnabled())

View File

@ -23,22 +23,17 @@
*/ */
package org.jclouds.http.httpnio.pool; package org.jclouds.http.httpnio.pool;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.http.nio.NHttpConnection;
import org.jclouds.command.pool.FutureCommandConnectionPoolClient;
import org.jclouds.http.*;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import org.apache.http.nio.NHttpConnection;
import org.jclouds.command.pool.FutureCommandConnectionPoolClient;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpFutureCommandClient;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/** /**
* // TODO: Adrian: Document this! * // TODO: Adrian: Document this!
* *

View File

@ -23,14 +23,8 @@
*/ */
package org.jclouds.http.httpnio.pool; package org.jclouds.http.httpnio.pool;
import java.io.IOException; import com.google.inject.Inject;
import java.net.InetSocketAddress; import com.google.inject.name.Named;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.apache.http.HttpException; import org.apache.http.HttpException;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor; import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.nio.NHttpConnection; import org.apache.http.nio.NHttpConnection;
@ -46,8 +40,9 @@ import org.jclouds.command.pool.FutureCommandConnectionPool;
import org.jclouds.command.pool.PoolConstants; import org.jclouds.command.pool.PoolConstants;
import org.jclouds.http.HttpFutureCommand; import org.jclouds.http.HttpFutureCommand;
import com.google.inject.Inject; import java.io.IOException;
import com.google.inject.name.Named; import java.net.InetSocketAddress;
import java.util.concurrent.*;
/** /**
* Connection Pool for HTTP requests that utilizes Apache HTTPNio * Connection Pool for HTTP requests that utilizes Apache HTTPNio

View File

@ -23,12 +23,7 @@
*/ */
package org.jclouds.http.httpnio.pool; package org.jclouds.http.httpnio.pool;
import java.io.IOException; import com.google.inject.Inject;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
@ -45,7 +40,10 @@ import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import org.jclouds.http.httpnio.util.HttpNioUtils; import org.jclouds.http.httpnio.util.HttpNioUtils;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.inject.Inject; import javax.annotation.Resource;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
/** /**
* // TODO: Adrian: Document this! * // TODO: Adrian: Document this!
@ -140,7 +138,7 @@ public class HttpNioFutureCommandExecutionHandler implements
protected boolean isRetryable(HttpFutureCommand<?> command) { protected boolean isRetryable(HttpFutureCommand<?> command) {
if (command.getRequest().isReplayable()) { if (command.getRequest().isReplayable()) {
logger.info("resubmitting command: %1$s", command); logger.debug("resubmitting command: %1$s", command);
return true; return true;
} }
return false; return false;

View File

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

View File

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

View File

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

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0" <metadata xsi:schemaLocation="http://maven.apache.org/METADATA/1.0.0 http://maven.apache.org/xsd/metadata-1.0.0.xsd" xmlns="http://maven.apache.org/METADATA/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>

View File

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

View File

@ -49,6 +49,9 @@
<properties> <properties>
<jclouds.aws.accesskeyid></jclouds.aws.accesskeyid> <jclouds.aws.accesskeyid></jclouds.aws.accesskeyid>
<jclouds.aws.secretaccesskey></jclouds.aws.secretaccesskey> <jclouds.aws.secretaccesskey></jclouds.aws.secretaccesskey>
<jclouds.s3.httpstream.url>http://apache.rediris.es/maven/binaries/apache-maven-2.1.0-bin.tar.bz2
</jclouds.s3.httpstream.url>
<jclouds.s3.httpstream.md5>9268c9de2cccfd0d8fbcdbcfaf517a87</jclouds.s3.httpstream.md5>
</properties> </properties>
<dependencies> <dependencies>
@ -67,13 +70,91 @@
<artifactId>bcprov-jdk15</artifactId> <artifactId>bcprov-jdk15</artifactId>
<version>140</version> <version>140</version>
</dependency> </dependency>
<dependency>
<groupId>xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.2</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration> <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>
<!-- 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> <systemProperties>
<property> <property>
<name>jclouds.aws.accesskeyid</name> <name>jclouds.aws.accesskeyid</name>
@ -83,9 +164,21 @@
<name>jclouds.aws.secretaccesskey</name> <name>jclouds.aws.secretaccesskey</name>
<value>${jclouds.aws.secretaccesskey}</value> <value>${jclouds.aws.secretaccesskey}</value>
</property> </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> </systemProperties>
</configuration> </configuration>
</execution>
</executions>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
</profile>
</profiles>
</project> </project>

View File

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

View File

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

View File

@ -23,28 +23,8 @@
*/ */
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_AWS_SECRETACCESSKEY;
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_IO_WORKER_THREADS;
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS;
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE;
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES;
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_REQUEST_INVOKER_THREADS;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_ADDRESS;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_PORT;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_SECURE;
import java.util.List;
import java.util.Properties;
import org.jclouds.aws.s3.config.S3ContextModule;
import org.jclouds.http.config.HttpFutureCommandClientModule;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -54,6 +34,21 @@ import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.name.Names; import com.google.inject.name.Names;
import org.jclouds.aws.s3.config.LiveS3ConnectionModule;
import org.jclouds.aws.s3.config.S3ConnectionModule;
import org.jclouds.aws.s3.config.S3ContextModule;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_AWS_SECRETACCESSKEY;
import org.jclouds.aws.s3.internal.LiveS3Connection;
import static org.jclouds.command.pool.PoolConstants.*;
import static org.jclouds.http.HttpConstants.*;
import org.jclouds.http.config.HttpFutureCommandClientModule;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import java.util.List;
import java.util.Properties;
/** /**
* Creates {@link S3Context} or {@link Injector} instances based on the most * Creates {@link S3Context} or {@link Injector} instances based on the most
@ -61,15 +56,15 @@ import com.google.inject.name.Names;
* <p/> * <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or * Note that Threadsafe objects will be bound as singletons to the Injector or
* Context provided. * Context provided.
* * <p/>
* <p/> * <p/>
* If no <code>Module</code>s are specified, the default * If no <code>Module</code>s are specified, the default
* {@link JDKLoggingModule logging} and * {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpFutureCommandClientModule http transports} will be * {@link JavaUrlHttpFutureCommandClientModule http transports} will be
* installed. * installed.
* *
* @see S3Context
* @author Adrian Cole * @author Adrian Cole
* @see S3Context
*/ */
public class S3ContextFactory { public class S3ContextFactory {
@ -177,11 +172,9 @@ public class S3ContextFactory {
* are specified, install the default {@link JDKLoggingModule} * are specified, install the default {@link JDKLoggingModule}
* {@link JavaUrlHttpFutureCommandClientModule} * {@link JavaUrlHttpFutureCommandClientModule}
* *
* @param properties * @param properties - contains constants used by jclouds
* - contains constants used by jclouds
* {@link #DEFAULT_PROPERTIES} * {@link #DEFAULT_PROPERTIES}
* @param configModules * @param configModules - alternative configuration modules
* - alternative configuration modules
*/ */
public static Injector createInjector(final Properties properties, public static Injector createInjector(final Properties properties,
Module... configModules) { Module... configModules) {
@ -189,7 +182,9 @@ public class S3ContextFactory {
addLoggingModuleIfNotPresent(modules); addLoggingModuleIfNotPresent(modules);
addHttpModuleIfNotPresent(modules); addHttpModuleIfNeededAndNotPresent(modules);
addS3ConnectionModuleIfNotPresent(modules);
return Guice.createInjector(new AbstractModule() { return Guice.createInjector(new AbstractModule() {
@Override @Override
@ -203,17 +198,36 @@ public class S3ContextFactory {
} }
@VisibleForTesting @VisibleForTesting
static void addHttpModuleIfNotPresent(final List<Module> modules) { static void addHttpModuleIfNeededAndNotPresent(final List<Module> modules) {
if (!Iterables.any(modules, new Predicate<Module>() { if (Iterables.any(modules, new Predicate<Module>() {
public boolean apply(Module input) {
return input instanceof LiveS3ConnectionModule;
}
}) && (!Iterables.any(modules, new Predicate<Module>() {
public boolean apply(Module input) { public boolean apply(Module input) {
return input.getClass().isAnnotationPresent( return input.getClass().isAnnotationPresent(
HttpFutureCommandClientModule.class); HttpFutureCommandClientModule.class);
} }
})) })))
modules.add(new JavaUrlHttpFutureCommandClientModule()); modules.add(new JavaUrlHttpFutureCommandClientModule());
} }
@VisibleForTesting
static void addS3ConnectionModuleIfNotPresent(final List<Module> modules) {
if (!Iterables.any(modules, new Predicate<Module>() {
public boolean apply(Module input) {
return input.getClass().isAnnotationPresent(
S3ConnectionModule
.class);
}
})){
modules.add(new LiveS3ConnectionModule());
}
}
@VisibleForTesting @VisibleForTesting
static void addLoggingModuleIfNotPresent(final List<Module> modules) { static void addLoggingModuleIfNotPresent(final List<Module> modules) {
if (!Iterables.any(modules, Predicates.instanceOf(LoggingModule.class))) if (!Iterables.any(modules, Predicates.instanceOf(LoggingModule.class)))

View File

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

View File

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

View File

@ -23,12 +23,10 @@
*/ */
package org.jclouds.aws.s3.commands.options; package org.jclouds.aws.s3.commands.options;
import static com.google.common.base.Preconditions.checkArgument; import com.google.common.base.Preconditions;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.*;
import static com.google.common.base.Preconditions.checkState; import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import java.io.UnsupportedEncodingException;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.DateService; import org.jclouds.aws.s3.util.DateService;
@ -36,9 +34,7 @@ import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.options.BaseHttpRequestOptions; import org.jclouds.http.options.BaseHttpRequestOptions;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import com.google.common.base.Preconditions; import java.io.UnsupportedEncodingException;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
/** /**
* Contains options supported in the REST API for the COPY object operation. * Contains options supported in the REST API for the COPY object operation.
@ -49,12 +45,12 @@ import com.google.common.collect.Multimap;
* <p/> * <p/>
* <code> * <code>
* import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.* * import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.*
* * <p/>
* S3Connection connection = // get connection * S3Connection connection = // get connection
* * <p/>
* Multimap<String,String> metadata = HashMultimap.create(); * Multimap<String,String> metadata = HashMultimap.create();
* metadata.put("x-amz-meta-adrian", "foo"); * metadata.put("x-amz-meta-adrian", "foo");
* * <p/>
* // this will copy the object, provided it wasn't modified since yesterday. * // this will copy the object, provided it wasn't modified since yesterday.
* // it will not use metadata from the source, and instead use what we pass in. * // it will not use metadata from the source, and instead use what we pass in.
* Future<S3Object.Metadata> object = connection.copyObject("sourceBucket", "objectName", * Future<S3Object.Metadata> object = connection.copyObject("sourceBucket", "objectName",
@ -64,11 +60,9 @@ import com.google.common.collect.Multimap;
* ); * );
* <code> * <code>
* *
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectCOPY.html?" * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectCOPY.html?"
* /> * />
* @author Adrian Cole
*
*
*/ */
public class CopyObjectOptions extends BaseHttpRequestOptions { public class CopyObjectOptions extends BaseHttpRequestOptions {
private final static DateService dateService = new DateService(); private final static DateService dateService = new DateService();
@ -100,15 +94,15 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
/** /**
* For use in the header x-amz-copy-source-if-unmodified-since * For use in the header x-amz-copy-source-if-unmodified-since
* <p /> * <p/>
* Copies the object if it hasn't been modified since the specified time; * Copies the object if it hasn't been modified since the specified time;
* otherwise returns a 412 (precondition failed). * otherwise returns a 412 (precondition failed).
* <p /> * <p/>
* This header can be used with x-amz-copy-source-if-match, but cannot be * This header can be used with x-amz-copy-source-if-match, but cannot be
* used with other conditional copy headers. * used with other conditional copy headers.
* *
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
* @return valid HTTP date * @return valid HTTP date
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
* @see CopyObjectOptions#ifSourceModifiedSince(DateTime) * @see CopyObjectOptions#ifSourceModifiedSince(DateTime)
*/ */
public String getIfModifiedSince() { public String getIfModifiedSince() {
@ -117,15 +111,15 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
/** /**
* For use in the header x-amz-copy-source-if-modified-since * For use in the header x-amz-copy-source-if-modified-since
* <p /> * <p/>
* Copies the object if it has been modified since the specified time; * Copies the object if it has been modified since the specified time;
* otherwise returns a 412 (failed condition). * otherwise returns a 412 (failed condition).
* <p/> * <p/>
* This header can be used with x-amz-copy-source-if-none-match, but cannot * This header can be used with x-amz-copy-source-if-none-match, but cannot
* be used with other conditional copy headers. * be used with other conditional copy headers.
* *
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
* @return valid HTTP date * @return valid HTTP date
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
* @see CopyObjectOptions#ifSourceUnmodifiedSince(DateTime) * @see CopyObjectOptions#ifSourceUnmodifiedSince(DateTime)
*/ */
public String getIfUnmodifiedSince() { public String getIfUnmodifiedSince() {
@ -134,7 +128,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
/** /**
* For use in the request header: x-amz-copy-source-if-match * For use in the request header: x-amz-copy-source-if-match
* <p /> * <p/>
* Copies the object if its entity tag (ETag) matches the specified tag; * Copies the object if its entity tag (ETag) matches the specified tag;
* otherwise return a 412 (precondition failed). * otherwise return a 412 (precondition failed).
* <p/> * <p/>
@ -149,7 +143,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
/** /**
* For use in the request header: x-amz-copy-source-if-none-match * For use in the request header: x-amz-copy-source-if-none-match
* <p /> * <p/>
* Copies the object if its entity tag (ETag) is different than the * Copies the object if its entity tag (ETag) is different than the
* specified Etag; otherwise returns a 412 (failed condition). * specified Etag; otherwise returns a 412 (failed condition).
* <p/> * <p/>
@ -175,7 +169,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
/** /**
* Only return the object if it has changed since this time. * Only return the object if it has changed since this time.
* <p /> * <p/>
* Not compatible with {@link #ifSourceMd5Matches(byte[])} or * Not compatible with {@link #ifSourceMd5Matches(byte[])} or
* {@link #ifSourceUnmodifiedSince(DateTime)} * {@link #ifSourceUnmodifiedSince(DateTime)}
*/ */
@ -192,7 +186,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
/** /**
* Only return the object if it hasn't changed since this time. * Only return the object if it hasn't changed since this time.
* <p /> * <p/>
* Not compatible with {@link #ifSourceMd5DoesntMatch(byte[])} or * Not compatible with {@link #ifSourceMd5DoesntMatch(byte[])} or
* {@link #ifSourceModifiedSince(DateTime)} * {@link #ifSourceModifiedSince(DateTime)}
*/ */
@ -209,15 +203,13 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
/** /**
* The object's md5 hash should match the parameter <code>md5</code>. * The object's md5 hash should match the parameter <code>md5</code>.
* * <p/>
* <p /> * <p/>
* Not compatible with {@link #ifSourceMd5DoesntMatch(byte[])} or * Not compatible with {@link #ifSourceMd5DoesntMatch(byte[])} or
* {@link #ifSourceModifiedSince(DateTime)} * {@link #ifSourceModifiedSince(DateTime)}
* *
* @param md5 * @param md5 hash representing the entity
* hash representing the entity * @throws UnsupportedEncodingException if there was a problem converting this into an S3 eTag string
* @throws UnsupportedEncodingException
* if there was a problem converting this into an S3 eTag string
*/ */
public CopyObjectOptions ifSourceMd5Matches(byte[] md5) public CopyObjectOptions ifSourceMd5Matches(byte[] md5)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
@ -233,14 +225,12 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
/** /**
* The object should not have a md5 hash corresponding with the parameter * The object should not have a md5 hash corresponding with the parameter
* <code>md5</code>. * <code>md5</code>.
* <p /> * <p/>
* Not compatible with {@link #ifSourceMd5Matches(byte[])} or * Not compatible with {@link #ifSourceMd5Matches(byte[])} or
* {@link #ifSourceUnmodifiedSince(DateTime)} * {@link #ifSourceUnmodifiedSince(DateTime)}
* *
* @param md5 * @param md5 hash representing the entity
* hash representing the entity * @throws UnsupportedEncodingException if there was a problem converting this into an S3 eTag string
* @throws UnsupportedEncodingException
* if there was a problem converting this into an S3 eTag string
*/ */
public CopyObjectOptions ifSourceMd5DoesntMatch(byte[] md5) public CopyObjectOptions ifSourceMd5DoesntMatch(byte[] md5)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {

View File

@ -25,12 +25,11 @@ package org.jclouds.aws.s3.commands.options;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import org.jclouds.http.options.BaseHttpRequestOptions;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import org.jclouds.http.options.BaseHttpRequestOptions;
/** /**
* Contains options supported in the REST API for the GET bucket operation. <h2> * Contains options supported in the REST API for the GET bucket operation. <h2>
* Usage</h2> The recommended way to instantiate a GetBucketOptions object is to * Usage</h2> The recommended way to instantiate a GetBucketOptions object is to
@ -39,17 +38,14 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
* <p/> * <p/>
* <code> * <code>
* import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.* * import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.*
* * <p/>
* S3Connection connection = // get connection * S3Connection connection = // get connection
* Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000)); * Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
* <code> * <code>
* *
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html?" * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html?"
* /> * />
*
* @author Adrian Cole
*
*
*/ */
public class ListBucketOptions extends BaseHttpRequestOptions { public class ListBucketOptions extends BaseHttpRequestOptions {
public static final ListBucketOptions NONE = new ListBucketOptions(); public static final ListBucketOptions NONE = new ListBucketOptions();
@ -122,7 +118,7 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
* *
* @throws UnsupportedEncodingException * @throws UnsupportedEncodingException
*/ */
public ListBucketOptions setDelimiter(String delimiter) public ListBucketOptions delimiter(String delimiter)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
options.put("delimiter", URLEncoder.encode(checkNotNull(delimiter, options.put("delimiter", URLEncoder.encode(checkNotNull(delimiter,
"delimiter"), "UTF-8")); "delimiter"), "UTF-8"));
@ -130,7 +126,7 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
} }
/** /**
* @see ListBucketOptions#setDelimiter(String) * @see ListBucketOptions#delimiter(String)
*/ */
public String getDelimiter() { public String getDelimiter() {
return options.get("delimiter"); return options.get("delimiter");
@ -173,7 +169,7 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
public static ListBucketOptions delimiter(String delimiter) public static ListBucketOptions delimiter(String delimiter)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions(); ListBucketOptions options = new ListBucketOptions();
return options.setDelimiter(delimiter); return options.delimiter(delimiter);
} }
} }

View File

@ -23,13 +23,12 @@
*/ */
package org.jclouds.aws.s3.commands.options; package org.jclouds.aws.s3.commands.options;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.http.options.BaseHttpRequestOptions; import org.jclouds.http.options.BaseHttpRequestOptions;
import static com.google.common.base.Preconditions.*;
/** /**
* Contains options supported in the REST API for the PUT bucket operation. <h2> * Contains options supported in the REST API for the PUT bucket operation. <h2>
* Usage</h2> The recommended way to instantiate a PutBucketOptions object is to * Usage</h2> The recommended way to instantiate a PutBucketOptions object is to
@ -40,16 +39,14 @@ import static com.google.common.base.Preconditions.*;
* import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.* * import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.*
* import static org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint.*; * import static org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint.*;
* import org.jclouds.aws.s3.S3Connection; * import org.jclouds.aws.s3.S3Connection;
* * <p/>
* S3Connection connection = // get connection * S3Connection connection = // get connection
* Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU)); * Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
* <code> * <code>
* *
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT.html?" * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT.html?"
* /> * />
*
* @author Adrian Cole
*
*/ */
public class PutBucketOptions extends BaseHttpRequestOptions { public class PutBucketOptions extends BaseHttpRequestOptions {
public static final PutBucketOptions NONE = new PutBucketOptions(); public static final PutBucketOptions NONE = new PutBucketOptions();
@ -90,7 +87,7 @@ public class PutBucketOptions extends BaseHttpRequestOptions {
} }
/** /**
* @see PutBucketOptions#createIn(LocationConstraint) * @see PutBucketOptions#createIn(org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint)
*/ */
public LocationConstraint getLocationConstraint() { public LocationConstraint getLocationConstraint() {
return constraint; return constraint;
@ -98,7 +95,7 @@ public class PutBucketOptions extends BaseHttpRequestOptions {
public static class Builder { public static class Builder {
/** /**
* @see PutBucketOptions#createIn(LocationConstraint) * @see PutBucketOptions#createIn(org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint)
*/ */
public static PutBucketOptions createIn(LocationConstraint constraint) { public static PutBucketOptions createIn(LocationConstraint constraint) {
PutBucketOptions options = new PutBucketOptions(); PutBucketOptions options = new PutBucketOptions();

View File

@ -0,0 +1,96 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.config;
import com.google.inject.*;
import com.google.inject.assistedinject.FactoryProvider;
import com.google.inject.name.Named;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.commands.config.S3CommandsModule;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.handlers.ParseS3ErrorFromXmlContent;
import org.jclouds.aws.s3.internal.GuiceS3Context;
import org.jclouds.aws.s3.internal.LiveS3Connection;
import org.jclouds.aws.s3.internal.LiveS3InputStreamMap;
import org.jclouds.aws.s3.internal.LiveS3ObjectMap;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponseHandler;
import org.jclouds.http.annotation.ClientErrorHandler;
import org.jclouds.http.annotation.RedirectHandler;
import org.jclouds.http.annotation.ServerErrorHandler;
import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import org.jclouds.logging.Logger;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* Configures the S3 connection, including logging and http transport.
*
* @author Adrian Cole
*/
@S3ConnectionModule
public class LiveS3ConnectionModule extends AbstractModule {
@Resource
protected Logger logger = Logger.NULL;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_ADDRESS)
String address;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_PORT)
int port;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_SECURE)
boolean isSecure;
@Override
protected void configure() {
bind(S3Connection.class).to(LiveS3Connection.class)
.in(Scopes.SINGLETON);
bind(HttpResponseHandler.class).annotatedWith(RedirectHandler.class)
.to(CloseContentAndSetExceptionHandler.class).in(
Scopes.SINGLETON);
bind(HttpResponseHandler.class).annotatedWith(ClientErrorHandler.class)
.to(ParseS3ErrorFromXmlContent.class).in(Scopes.SINGLETON);
bind(HttpResponseHandler.class).annotatedWith(ServerErrorHandler.class)
.to(ParseS3ErrorFromXmlContent.class).in(Scopes.SINGLETON);
requestInjection(this);
logger.info("S3 Context = %1$s://%2$s:%3$s", (isSecure ? "https"
: "http"), address, port);
}
@Provides
@Singleton
List<HttpRequestFilter> provideRequestFilters(
RequestAuthorizeSignature requestAuthorizeSignature) {
List<HttpRequestFilter> filters = new ArrayList<HttpRequestFilter>();
filters.add(requestAuthorizeSignature);
return filters;
}
}

View File

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

View File

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

View File

@ -24,29 +24,28 @@
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import org.joda.time.DateTime;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.joda.time.DateTime;
/** /**
* A container that provides namespace, access control and aggregation of * A container that provides namespace, access control and aggregation of
* {@link S3Object}s * {@link S3Object}s
* * <p/>
* <p/> * <p/>
* Every object stored in Amazon S3 is contained in a bucket. Buckets partition * Every object stored in Amazon S3 is contained in a bucket. Buckets partition
* the namespace of objects stored in Amazon S3 at the top level. Within a * the namespace of objects stored in Amazon S3 at the top level. Within a
* bucket, you can use any names for your objects, but bucket names must be * bucket, you can use any names for your objects, but bucket names must be
* unique across all of Amazon S3. * unique across all of Amazon S3.
* * <p/>
* Buckets are similar to Internet domain names. Just as Amazon is the only * Buckets are similar to Internet domain names. Just as Amazon is the only
* owner of the domain name Amazon.com, only one person or organization can own * owner of the domain name Amazon.com, only one person or organization can own
* a bucket within Amazon S3. Once you create a uniquely named bucket in Amazon * a bucket within Amazon S3. Once you create a uniquely named bucket in Amazon
* S3, you can organize and name the objects within the bucket in any way you * S3, you can organize and name the objects within the bucket in any way you
* like and the bucket will remain yours for as long as you like and as long as * like and the bucket will remain yours for as long as you like and as long as
* you have the Amazon S3 account. * you have the Amazon S3 account.
* * <p/>
* The similarities between buckets and domain names is not a coincidenceÑthere * The similarities between buckets and domain names is not a coincidenceÑthere
* is a direct mapping between Amazon S3 buckets and subdomains of * is a direct mapping between Amazon S3 buckets and subdomains of
* s3.amazonaws.com. Objects stored in Amazon S3 are addressable using the REST * s3.amazonaws.com. Objects stored in Amazon S3 are addressable using the REST
@ -65,7 +64,7 @@ public class S3Bucket {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("S3Bucket"); sb.append("S3Bucket");
sb.append("{metadata=").append(metadata); sb.append("{metadata=").append(metadata);
sb.append(", isComplete=").append(isComplete); sb.append(", isTruncated=").append(isTruncated);
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
@ -79,7 +78,7 @@ public class S3Bucket {
S3Bucket s3Bucket = (S3Bucket) o; S3Bucket s3Bucket = (S3Bucket) o;
if (isComplete != s3Bucket.isComplete) if (isTruncated != s3Bucket.isTruncated)
return false; return false;
if (!metadata.equals(s3Bucket.metadata)) if (!metadata.equals(s3Bucket.metadata))
return false; return false;
@ -94,7 +93,7 @@ public class S3Bucket {
public int hashCode() { public int hashCode() {
int result = objects != null ? objects.hashCode() : 0; int result = objects != null ? objects.hashCode() : 0;
result = 31 * result + metadata.hashCode(); result = 31 * result + metadata.hashCode();
result = 31 * result + (isComplete ? 1 : 0); result = 31 * result + (isTruncated ? 1 : 0);
return result; return result;
} }
@ -102,7 +101,6 @@ public class S3Bucket {
* System metadata of the S3Bucket * System metadata of the S3Bucket
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
public static class Metadata { public static class Metadata {
@Override @Override
@ -145,11 +143,10 @@ public class S3Bucket {
/** /**
* Location constraint of the bucket. * Location constraint of the bucket.
* *
* @author Adrian Cole
* @see <a href= * @see <a href=
* "http://docs.amazonwebservices.com/AmazonS3/latest/RESTBucketLocationGET.html" * "http://docs.amazonwebservices.com/AmazonS3/latest/RESTBucketLocationGET.html"
* /> * />
* @author Adrian Cole
*
*/ */
public static enum LocationConstraint { public static enum LocationConstraint {
EU EU
@ -168,16 +165,15 @@ public class S3Bucket {
/** /**
* To comply with Amazon S3 requirements, bucket names must: * To comply with Amazon S3 requirements, bucket names must:
* * <p/>
* Contain lowercase letters, numbers, periods (.), underscores (_), and * Contain lowercase letters, numbers, periods (.), underscores (_), and
* dashes (-) * dashes (-)
* * <p/>
* Start with a number or letter * Start with a number or letter
* * <p/>
* Be between 3 and 255 characters long * Be between 3 and 255 characters long
* * <p/>
* Not be in an IP address style (e.g., "192.168.5.4") * Not be in an IP address style (e.g., "192.168.5.4")
*
*/ */
public String getName() { public String getName() {
return name; return name;
@ -217,7 +213,7 @@ public class S3Bucket {
private long maxKeys; private long maxKeys;
private final Metadata metadata; private final Metadata metadata;
private boolean isComplete; private boolean isTruncated;
public S3Bucket(String name) { public S3Bucket(String name) {
this.metadata = new Metadata(name); this.metadata = new Metadata(name);
@ -245,12 +241,12 @@ public class S3Bucket {
/** /**
* @return true, if the list contains all objects. * @return true, if the list contains all objects.
*/ */
public boolean isComplete() { public boolean isTruncated() {
return isComplete; return isTruncated;
} }
public void setComplete(boolean complete) { public void setTruncated(boolean truncated) {
isComplete = complete; isTruncated = truncated;
} }
public Metadata getMetadata() { public Metadata getMetadata() {
@ -263,14 +259,14 @@ public class S3Bucket {
/** /**
* Example: * Example:
* <p /> * <p/>
* if the following keys are in the bucket * if the following keys are in the bucket
* * <p/>
* a/1/a<br/> * a/1/a<br/>
* a/1/b<br/> * a/1/b<br/>
* a/2/a<br/> * a/2/a<br/>
* a/2/b<br/> * a/2/b<br/>
* <p /> * <p/>
* and prefix is set to <code>a/</code> and delimiter is set to * and prefix is set to <code>a/</code> and delimiter is set to
* <code>/</code> then commonprefixes would return 1,2 * <code>/</code> then commonprefixes would return 1,2
* *

View File

@ -23,32 +23,28 @@
*/ */
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.*;
import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.collect.HashMultimap;
import static com.google.common.base.Preconditions.checkState; import com.google.common.collect.Multimap;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import org.jclouds.aws.s3.commands.options.GetObjectOptions; import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.aws.s3.util.S3Utils.Md5InputStreamResult; import org.jclouds.aws.s3.util.S3Utils.Md5InputStreamResult;
import org.jclouds.http.ContentTypes; import org.jclouds.http.ContentTypes;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import com.google.common.collect.HashMultimap; import java.io.IOException;
import com.google.common.collect.Multimap; import java.io.InputStream;
import java.util.Arrays;
/** /**
* Amazon S3 is designed to store objects. Objects are stored in * Amazon S3 is designed to store objects. Objects are stored in
* {@link S3Bucket buckets} and consist of a {@link S3Object#getValue() value}, * {@link S3Bucket buckets} and consist of a {@link org.jclouds.aws.s3.domain.S3Object#getData() value},
* a {@link S3Object#getKey key}, {@link S3Object.Metadata#getUserMetadata() * a {@link S3Object#getKey key}, {@link S3Object.Metadata#getUserMetadata()
* metadata}, and an access control policy. * metadata}, and an access control policy.
* *
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html" * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html"
* /> * />
* @author Adrian Cole
*/ */
public class S3Object { public class S3Object {
public static final S3Object NOT_FOUND = new S3Object(Metadata.NOT_FOUND); public static final S3Object NOT_FOUND = new S3Object(Metadata.NOT_FOUND);
@ -79,13 +75,12 @@ public class S3Object {
/** /**
* System and user Metadata for the {@link S3Object}. * System and user Metadata for the {@link S3Object}.
* *
* @author Adrian Cole
* @see <a href= * @see <a href=
* "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingMetadata.html" * "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingMetadata.html"
* /> * />
* @author Adrian Cole
*
*/ */
public static class Metadata { public static class Metadata implements Comparable<Metadata> {
public static final Metadata NOT_FOUND = new Metadata("NOT_FOUND"); public static final Metadata NOT_FOUND = new Metadata("NOT_FOUND");
// parsed during list, head, or get // parsed during list, head, or get
@ -107,8 +102,8 @@ public class S3Object {
private String storageClass = null; private String storageClass = null;
/** /**
* @see #getKey()
* @param key * @param key
* @see #getKey()
*/ */
public Metadata(String key) { public Metadata(String key) {
checkNotNull(key, "key"); checkNotNull(key, "key");
@ -196,8 +191,6 @@ public class S3Object {
* @see <a href= * @see <a href=
* "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.13." * "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.13."
* /> * />
*
* @return
*/ */
public long getSize() { public long getSize() {
return size; return size;
@ -210,12 +203,9 @@ public class S3Object {
/** /**
* A standard MIME type describing the format of the contents. If none * A standard MIME type describing the format of the contents. If none
* is provided, the default is binary/octet-stream. * is provided, the default is binary/octet-stream.
*
* @see <a href= * @see <a href=
* "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.17." * "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.17."
* /> * />
*
* @return
*/ */
public String getContentType() { public String getContentType() {
return dataType; return dataType;
@ -226,14 +216,14 @@ public class S3Object {
} }
public void setMd5(byte[] md5) { public void setMd5(byte[] md5) {
this.md5 = md5; this.md5 = Arrays.copyOf(md5, md5.length);
} }
/** /**
* @return the md5 value stored in the Etag header returned by S3. * @return the md5 value stored in the Etag header returned by S3.
*/ */
public byte[] getMd5() { public byte[] getMd5() {
return md5; return (md5 == null) ? null : Arrays.copyOf(md5, md5.length);
} }
public void setUserMetadata(Multimap<String, String> userMetadata) { public void setUserMetadata(Multimap<String, String> userMetadata) {
@ -241,12 +231,10 @@ public class S3Object {
} }
/** /**
*
* Any header starting with <code>x-amz-meta-</code> is considered user * Any header starting with <code>x-amz-meta-</code> is considered user
* metadata. It will be stored with the object and returned when you * metadata. It will be stored with the object and returned when you
* retrieve the object. The total size of the HTTP request, not * retrieve the object. The total size of the HTTP request, not
* including the body, must be less than 8 KB. * including the body, must be less than 8 KB.
*
*/ */
public Multimap<String, String> getUserMetadata() { public Multimap<String, String> getUserMetadata() {
return userMetadata; return userMetadata;
@ -326,12 +314,15 @@ public class S3Object {
} }
/** /**
*
* @return all http response headers associated with this S3Object * @return all http response headers associated with this S3Object
*/ */
public Multimap<String, String> getAllHeaders() { public Multimap<String, String> getAllHeaders() {
return allHeaders; return allHeaders;
} }
public int compareTo(Metadata o) {
return (this == o) ? 0 : getKey().compareTo(o.getKey());
}
} }
/** /**
@ -345,8 +336,7 @@ public class S3Object {
* Sets payload for the request or the content from the response. If size * Sets payload for the request or the content from the response. If size
* isn't set, this will attempt to discover it. * isn't set, this will attempt to discover it.
* *
* @param data * @param data typically InputStream for downloads, or File, byte [], String,
* typically InputStream for downloads, or File, byte [], String,
* or InputStream for uploads. * or InputStream for uploads.
*/ */
public void setData(Object data) { public void setData(Object data) {
@ -357,13 +347,12 @@ public class S3Object {
/** /**
* generate an MD5 Hash for the current data. * generate an MD5 Hash for the current data.
* * <p/>
* <h2>Note</h2> * <h2>Note</h2>
* <p/> * <p/>
* If this is an InputStream, it will be converted to a byte array first. * If this is an InputStream, it will be converted to a byte array first.
* *
* @throws IOException * @throws IOException if there is a problem generating the hash.
* if there is a problem generating the hash.
*/ */
public void generateMd5() throws IOException { public void generateMd5() throws IOException {
checkState(data != null, "data"); checkState(data != null, "data");
@ -379,7 +368,6 @@ public class S3Object {
} }
/** /**
*
* @return InputStream, if downloading, or whatever was set during * @return InputStream, if downloading, or whatever was set during
* {@link #setData(Object)} * {@link #setData(Object)}
*/ */
@ -392,7 +380,6 @@ public class S3Object {
} }
/** /**
*
* @return System and User metadata relevant to this object. * @return System and User metadata relevant to this object.
*/ */
public Metadata getMetadata() { public Metadata getMetadata() {
@ -444,11 +431,10 @@ public class S3Object {
* {@link org.jclouds.aws.s3.S3Connection#getObject(String, String, org.jclouds.aws.s3.commands.options.GetObjectOptions) } * {@link org.jclouds.aws.s3.S3Connection#getObject(String, String, org.jclouds.aws.s3.commands.options.GetObjectOptions) }
* is called with options like tail, range, or startAt. * is called with options like tail, range, or startAt.
* *
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
* @see GetObjectOptions
* @return the length in bytes that can be be obtained from * @return the length in bytes that can be be obtained from
* {@link #getData()} * {@link #getData()}
* * @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
* @see GetObjectOptions
*/ */
public long getContentLength() { public long getContentLength() {
return contentLength; return contentLength;

View File

@ -24,19 +24,9 @@
package org.jclouds.aws.s3.internal; package org.jclouds.aws.s3.internal;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.Inject;
import java.io.FileNotFoundException; import com.google.inject.assistedinject.Assisted;
import java.io.IOException; import com.google.inject.name.Named;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Map; import org.jclouds.aws.s3.S3Map;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
@ -44,9 +34,13 @@ import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.inject.Inject; import java.io.FileNotFoundException;
import com.google.inject.assistedinject.Assisted; import java.io.IOException;
import com.google.inject.name.Named; import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/** /**
* Implements core Map functionality with an {@link S3Connection} * Implements core Map functionality with an {@link S3Connection}
@ -55,7 +49,6 @@ import com.google.inject.name.Named;
* complete before throwing an exception. * complete before throwing an exception.
* *
* @author Adrian Cole * @author Adrian Cole
*
* @param <V> * @param <V>
* value of the map * value of the map
*/ */
@ -74,7 +67,7 @@ public abstract class BaseS3Map<V> implements S3Map<String, V> {
@Inject @Inject
public BaseS3Map(S3Connection connection, @Assisted String bucket) { public BaseS3Map(S3Connection connection, @Assisted String bucket) {
this.connection = checkNotNull(connection, "connection"); this.connection = checkNotNull(connection, "connection");
this.bucket = checkNotNull(bucket, "bucket"); this.bucket = checkNotNull(bucket, "bucketName");
} }
/** /**
@ -90,8 +83,8 @@ public abstract class BaseS3Map<V> implements S3Map<String, V> {
Set<S3Object.Metadata> contents = bucket.getContents(); Set<S3Object.Metadata> contents = bucket.getContents();
return contents.size(); return contents.size();
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error getting size of bucket" throw new S3RuntimeException("Error getting size of bucketName"
+ bucket, e); + bucket, e);
} }
} }
@ -136,10 +129,9 @@ public abstract class BaseS3Map<V> implements S3Map<String, V> {
object = futureObject.get(requestTimeoutMilliseconds, object = futureObject.get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format( throw new S3RuntimeException(String.format(
"Error getting value from bucket %1$s:%2$s", bucket, "Error getting value from bucket %1$s", bucket), e);
object != null ? object.getKey() : "unknown"), e);
} }
if (object != S3Object.NOT_FOUND) if (object != S3Object.NOT_FOUND)
objects.add(object); objects.add(object);
@ -149,19 +141,19 @@ public abstract class BaseS3Map<V> implements S3Map<String, V> {
/** /**
* {@inheritDoc} * {@inheritDoc}
* * <p/>
* Note that if value is an instance of InputStream, it will be read and * Note that if value is an instance of InputStream, it will be read and
* closed following this method. To reuse data from InputStreams, pass * closed following this method. To reuse data from InputStreams, pass
* {@link InputStream}s inside {@link S3Object}s * {@link java.io.InputStream}s inside {@link S3Object}s
*/ */
public boolean containsValue(Object value) { public boolean containsValue(Object value) {
try { try {
byte[] md5 = getMd5(value); byte[] md5 = getMd5(value);
return containsMd5(md5); return containsMd5(md5);
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format( throw new S3RuntimeException(String.format(
"Error searching for ETAG of value: [%2$s] in bucket:%1$s", "Error searching for ETAG of value: [%2$s] in bucketName:%1$s",
bucket, value), e); bucket, value), e);
} }
} }
@ -190,8 +182,8 @@ public abstract class BaseS3Map<V> implements S3Map<String, V> {
throw new S3RuntimeException("failed to delete entry"); throw new S3RuntimeException("failed to delete entry");
} }
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error clearing bucket" + bucket, e); throw new S3RuntimeException("Error clearing bucketName" + bucket, e);
} }
} }
@ -200,7 +192,7 @@ public abstract class BaseS3Map<V> implements S3Map<String, V> {
S3Bucket currentBucket = connection.listBucket(bucket).get( S3Bucket currentBucket = connection.listBucket(bucket).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
if (currentBucket == S3Bucket.NOT_FOUND) if (currentBucket == S3Bucket.NOT_FOUND)
throw new S3RuntimeException("bucket not found: " + bucket); throw new S3RuntimeException("bucketName not found: " + bucket);
else else
return currentBucket; return currentBucket;
} }
@ -212,8 +204,8 @@ public abstract class BaseS3Map<V> implements S3Map<String, V> {
keys.add(object.getKey()); keys.add(object.getKey());
return keys; return keys;
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error getting keys in bucket: " throw new S3RuntimeException("Error getting keys in bucketName: "
+ bucket, e); + bucket, e);
} }
} }
@ -223,7 +215,7 @@ public abstract class BaseS3Map<V> implements S3Map<String, V> {
return connection.headObject(bucket, key.toString()).get( return connection.headObject(bucket, key.toString()).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS) != S3Object.Metadata.NOT_FOUND; requestTimeoutMilliseconds, TimeUnit.MILLISECONDS) != S3Object.Metadata.NOT_FOUND;
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format( throw new S3RuntimeException(String.format(
"Error searching for %1$s:%2$s", bucket, key), e); "Error searching for %1$s:%2$s", bucket, key), e);
} }
@ -237,8 +229,8 @@ public abstract class BaseS3Map<V> implements S3Map<String, V> {
try { try {
return refreshBucket(); return refreshBucket();
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error getting bucket" + bucket, e); throw new S3RuntimeException("Error getting bucketName" + bucket, e);
} }
} }
} }

View File

@ -23,10 +23,8 @@
*/ */
package org.jclouds.aws.s3.internal; package org.jclouds.aws.s3.internal;
import java.io.IOException; import com.google.inject.Inject;
import com.google.inject.Injector;
import javax.annotation.Resource;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Context; import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.S3InputStreamMap; import org.jclouds.aws.s3.S3InputStreamMap;
@ -34,14 +32,14 @@ import org.jclouds.aws.s3.S3ObjectMap;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.inject.Inject; import javax.annotation.Resource;
import com.google.inject.Injector; import java.io.IOException;
/** /**
* Uses a Guice Injector to configure the objects served by S3Context methods. * Uses a Guice Injector to configure the objects served by S3Context methods.
* *
* @see Injector
* @author Adrian Cole * @author Adrian Cole
* @see Injector
*/ */
public class GuiceS3Context implements S3Context { public class GuiceS3Context implements S3Context {
public interface S3ObjectMapFactory { public interface S3ObjectMapFactory {

View File

@ -23,35 +23,28 @@
*/ */
package org.jclouds.aws.s3.internal; package org.jclouds.aws.s3.internal;
import java.io.File; import com.google.common.annotations.VisibleForTesting;
import java.io.InputStream; import com.google.inject.Inject;
import java.util.ArrayList; import com.google.inject.assistedinject.Assisted;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3InputStreamMap; import org.jclouds.aws.s3.S3InputStreamMap;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting; import java.io.File;
import com.google.inject.Inject; import java.io.InputStream;
import com.google.inject.assistedinject.Assisted; import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/** /**
* Map representation of a live connection to S3. All put operations will result * Map representation of a live connection to S3. All put operations will result
* in Md5 calculation. If this is not desired, use {@link LiveS3ObjectMap} * in Md5 calculation. If this is not desired, use {@link LiveS3ObjectMap}
* instead. * instead.
* *
* @author Adrian Cole
* @see S3Connection * @see S3Connection
* @see BaseS3Map * @see BaseS3Map
* @author Adrian Cole
*/ */
public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
S3InputStreamMap { S3InputStreamMap {
@ -72,7 +65,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)) .get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS))
.getData(); .getData();
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format( throw new S3RuntimeException(String.format(
"Error geting object %1$s:%2$s", bucket, o), e); "Error geting object %1$s:%2$s", bucket, o), e);
} }
@ -89,7 +82,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
connection.deleteObject(bucket, o.toString()).get( connection.deleteObject(bucket, o.toString()).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format( throw new S3RuntimeException(String.format(
"Error removing object %1$s:%2$s", bucket, o), e); "Error removing object %1$s:%2$s", bucket, o), e);
} }
@ -124,9 +117,6 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
return entrySet; return entrySet;
} }
/**
* {@inheritDoc}
*/
public class Entry implements java.util.Map.Entry<String, InputStream> { public class Entry implements java.util.Map.Entry<String, InputStream> {
private InputStream value; private InputStream value;
@ -203,9 +193,9 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
void putAllInternal(Map<? extends String, ? extends Object> map) { void putAllInternal(Map<? extends String, ? extends Object> map) {
try { try {
List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>(); List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>();
for (String key : map.keySet()) { for (Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
S3Object object = new S3Object(key); S3Object object = new S3Object(entry.getKey());
object.setData(map.get(key)); object.setData(entry.getValue());
object.generateMd5(); object.generateMd5();
puts.add(connection.putObject(bucket, object)); puts.add(connection.putObject(bucket, object));
} }
@ -213,8 +203,8 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
// this will throw an exception if there was a problem // this will throw an exception if there was a problem
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error putting into bucket" + bucket, throw new S3RuntimeException("Error putting into bucketName" + bucket,
e); e);
} }
} }
@ -256,7 +246,6 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
} }
/** /**
*
* calculates md5 before adding the object to s3. As a side-effect of this, * calculates md5 before adding the object to s3. As a side-effect of this,
* the content will be copied into a byte []. * * the content will be copied into a byte []. *
* *
@ -273,7 +262,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
return returnVal; return returnVal;
} catch (Exception e) { } catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format( throw new S3RuntimeException(String.format(
"Error adding object %1$s:%2$s", bucket, object), e); "Error adding object %1$s:%2$s", bucket, object), e);
} }

View File

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

View File

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

View File

@ -25,17 +25,6 @@ package org.jclouds.aws.s3.util;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.io.output.ByteArrayOutputStream;
import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.crypto.digests.MD5Digest;
@ -46,12 +35,17 @@ import org.bouncycastle.util.encoders.Base64;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.regex.Pattern;
/** /**
* Encryption, Hashing, and IO Utilities needed to sign and verify S3 requests * Encryption, Hashing, and IO Utilities needed to sign and verify S3 requests
* and responses. * and responses.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
public class S3Utils extends Utils { public class S3Utils extends Utils {
@ -62,21 +56,21 @@ public class S3Utils extends Utils {
public static String validateBucketName(String bucketName) { public static String validateBucketName(String bucketName) {
checkNotNull(bucketName, "bucketName"); checkNotNull(bucketName, "bucketName");
checkArgument(bucketName.matches("^[a-z0-9].*"), checkArgument(bucketName.matches("^[a-z0-9].*"),
"bucket name must start with a number or letter"); "bucketName name must start with a number or letter");
checkArgument( checkArgument(
bucketName.matches("^[-_.a-z0-9]+"), bucketName.matches("^[-_.a-z0-9]+"),
"bucket name can only contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)"); "bucketName name can only contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)");
checkArgument(bucketName.length() > 2 && bucketName.length() < 256, checkArgument(bucketName.length() > 2 && bucketName.length() < 256,
"bucket name must be between 3 and 255 characters long"); "bucketName name must be between 3 and 255 characters long");
checkArgument(!IP_PATTERN.matcher(bucketName).matches(), checkArgument(!IP_PATTERN.matcher(bucketName).matches(),
"bucket name cannot be ip address style"); "bucketName name cannot be ip address style");
return bucketName; return bucketName;
} }
static final byte[] HEX_CHAR_TABLE = { (byte) '0', (byte) '1', (byte) '2', static final byte[] HEX_CHAR_TABLE = {(byte) '0', (byte) '1', (byte) '2',
(byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
(byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c',
(byte) 'd', (byte) 'e', (byte) 'f' }; (byte) 'd', (byte) 'e', (byte) 'f'};
public static String toHexString(byte[] raw) public static String toHexString(byte[] raw)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
@ -104,13 +98,13 @@ public class S3Utils extends Utils {
} }
/** /**
*
* @throws IOException * @throws IOException
*/ */
public static byte[] md5(Object data) throws IOException { public static byte[] md5(Object data) throws IOException {
checkNotNull(data, "data must be set before calling generateMd5()"); checkNotNull(data, "data must be set before calling generateMd5()");
byte[] md5 = null; byte[] md5 = null;
if (data == null || data instanceof byte[]) { if (data == null) {
} else if (data instanceof byte[]) {
md5 = S3Utils.md5((byte[]) data); md5 = S3Utils.md5((byte[]) data);
} else if (data instanceof String) { } else if (data instanceof String) {
md5 = S3Utils.md5(((String) data).getBytes()); md5 = S3Utils.md5(((String) data).getBytes());
@ -210,6 +204,7 @@ public class S3Utils extends Utils {
} }
} while (numRead != -1); } while (numRead != -1);
} finally { } finally {
out.close();
IOUtils.closeQuietly(toEncode); IOUtils.closeQuietly(toEncode);
} }
md5.doFinal(resBuf, 0); md5.doFinal(resBuf, 0);

View File

@ -24,7 +24,7 @@
package org.jclouds.aws.s3.xml; package org.jclouds.aws.s3.xml;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.Inject;
import org.jclouds.aws.s3.domain.CanonicalUser; import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
@ -33,16 +33,14 @@ import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import com.google.inject.Inject;
/** /**
* Parses the following XML document: * Parses the following XML document:
* <p/> * <p/>
* ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01" * ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01"
* *
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html" * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html"
* /> * />
* @author Adrian Cole
*/ */
public class ListBucketHandler extends ParseSax.HandlerWithResult<S3Bucket> { public class ListBucketHandler extends ParseSax.HandlerWithResult<S3Bucket> {
private S3Bucket s3Bucket; private S3Bucket s3Bucket;
@ -97,7 +95,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<S3Bucket> {
currentObjectMetadata.setStorageClass(currentText.toString()); currentObjectMetadata.setStorageClass(currentText.toString());
} else if (qName.equals("Contents")) { } else if (qName.equals("Contents")) {
s3Bucket.getContents().add(currentObjectMetadata); s3Bucket.getContents().add(currentObjectMetadata);
} else if (qName.equals("Name")) {// bucket stuff last, as least likely } else if (qName.equals("Name")) {// bucketName stuff last, as least likely
} else if (qName.equals("Prefix")) { } else if (qName.equals("Prefix")) {
String prefix = currentText.toString().trim(); String prefix = currentText.toString().trim();
if (inCommonPrefixes) if (inCommonPrefixes)
@ -114,7 +112,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<S3Bucket> {
s3Bucket.setMaxKeys(Long.parseLong(currentText.toString())); s3Bucket.setMaxKeys(Long.parseLong(currentText.toString()));
} else if (qName.equals("IsTruncated")) { } else if (qName.equals("IsTruncated")) {
boolean isTruncated = Boolean.parseBoolean(currentText.toString()); boolean isTruncated = Boolean.parseBoolean(currentText.toString());
s3Bucket.setComplete(!isTruncated); s3Bucket.setTruncated(isTruncated);
} }
currentText = new StringBuilder(); currentText = new StringBuilder();
} }

View File

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

View File

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

View File

@ -0,0 +1,141 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.internal.BaseS3Map;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.io.*;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
@Test
public abstract class BaseS3MapIntegrationTest<T> extends S3IntegrationTest {
public abstract void testPutAll();
public abstract void testEntrySet() throws IOException;
public abstract void testValues() throws IOException;
protected BaseS3Map<T> map;
protected Map<String, String> fiveStrings = ImmutableMap.of("one", "apple",
"two", "bear", "three", "candy", "four", "dogma", "five", "emma");
protected Map<String, byte[]> fiveBytes = ImmutableMap.of("one", "apple"
.getBytes(), "two", "bear".getBytes(), "three", "candy".getBytes(),
"four", "dogma".getBytes(), "five", "emma".getBytes());
protected Map<String, InputStream> fiveInputs;
protected Map<String, File> fiveFiles;
String tmpDirectory;
@BeforeMethod(dependsOnMethods = "setUpBucket", groups = {"integration", "live"})
@Parameters({"basedir"})
protected void setUpTempDir(String basedir) throws InterruptedException,
ExecutionException, FileNotFoundException, IOException,
TimeoutException {
tmpDirectory = basedir + File.separator + "target" + File.separator
+ "testFiles" + File.separator + getClass().getSimpleName();
new File(tmpDirectory).mkdirs();
fiveFiles = ImmutableMap.of("one", new File(tmpDirectory, "apple"),
"two", new File(tmpDirectory, "bear"), "three", new File(
tmpDirectory, "candy"), "four", new File(tmpDirectory,
"dogma"), "five", new File(tmpDirectory, "emma"));
for (File file : fiveFiles.values()) {
IOUtils.write(file.getName(), new FileOutputStream(file));
}
fiveInputs = ImmutableMap.of("one", IOUtils.toInputStream("apple"),
"two", IOUtils.toInputStream("bear"), "three", IOUtils
.toInputStream("candy"), "four", IOUtils
.toInputStream("dogma"), "five", IOUtils
.toInputStream("emma"));
map = createMap(context, bucketName);
map.clear();
}
protected abstract BaseS3Map<T> createMap(S3Context context, String bucket);
@Test(groups = {"integration", "live"})
public void testClear() {
map.clear();
assertEquals(map.size(), 0);
putString("one", "apple");
assertEquals(map.size(), 1);
map.clear();
assertEquals(map.size(), 0);
}
@Test(groups = {"integration", "live"})
public abstract void testRemove() throws IOException;
@Test(groups = {"integration", "live"})
public void testKeySet() {
assertEquals(map.keySet().size(), 0);
putString("one", "two");
assertEquals(map.keySet(), ImmutableSet.of("one"));
}
@Test(groups = {"integration", "live"})
public void testContainsKey() {
assert !map.containsKey("one");
putString("one", "apple");
assert map.containsKey("one");
}
@Test(groups = {"integration", "live"})
public void testIsEmpty() {
assert map.isEmpty();
putString("one", "apple");
assert !map.isEmpty();
}
abstract protected void putString(String key, String value);
protected void fourLeftRemovingOne() {
map.remove("one");
assertEquals(map.size(), 4);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
ImmutableSet.of("two", "three", "four", "five")));
}
@Test(groups = {"integration", "live"})
public abstract void testPut() throws IOException;
@Test(groups = {"integration", "live"})
public void testGetBucket() {
assertEquals(map.getBucket().getName(), bucketName);
}
}

View File

@ -1,156 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3;
import static org.testng.Assert.assertEquals;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.internal.BaseS3Map;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
public abstract class BaseS3MapTest<T> extends S3IntegrationTest {
public abstract void testPutAll();
public abstract void testEntrySet() throws IOException;
public abstract void testValues() throws IOException;
protected BaseS3Map<T> map;
protected Map<String, String> fiveStrings = ImmutableMap.of("one", "apple",
"two", "bear", "three", "candy", "four", "dogma", "five", "emma");
protected Map<String, byte[]> fiveBytes = ImmutableMap.of("one", "apple"
.getBytes(), "two", "bear".getBytes(), "three", "candy".getBytes(),
"four", "dogma".getBytes(), "five", "emma".getBytes());
protected Map<String, InputStream> fiveInputs;
protected Map<String, File> fiveFiles;
String tmpDirectory;
private String bucket;
@BeforeMethod
@Parameters( { "basedir" })
protected void setUpTempDir(String basedir) throws InterruptedException,
ExecutionException, FileNotFoundException, IOException,
TimeoutException {
tmpDirectory = basedir + File.separator + "target" + File.separator
+ "testFiles" + File.separator + getClass().getSimpleName();
new File(tmpDirectory).mkdirs();
fiveFiles = ImmutableMap.of("one", new File(tmpDirectory, "apple"),
"two", new File(tmpDirectory, "bear"), "three", new File(
tmpDirectory, "candy"), "four", new File(tmpDirectory,
"dogma"), "five", new File(tmpDirectory, "emma"));
for (File file : fiveFiles.values()) {
IOUtils.write(file.getName(), new FileOutputStream(file));
}
fiveInputs = ImmutableMap.of("one", IOUtils.toInputStream("apple"),
"two", IOUtils.toInputStream("bear"), "three", IOUtils
.toInputStream("candy"), "four", IOUtils
.toInputStream("dogma"), "five", IOUtils
.toInputStream("emma"));
bucket = (bucketPrefix + ".mimi").toLowerCase();
client.putBucketIfNotExists(bucket).get(10, TimeUnit.SECONDS);
map = createMap(context, bucket);
map.clear();
}
protected abstract BaseS3Map<T> createMap(S3Context context, String bucket);
@AfterMethod
public void tearDown() {
map.clear();
map = null;
}
@Test
public void testClear() {
map.clear();
assertEquals(map.size(), 0);
putString("one", "apple");
assertEquals(map.size(), 1);
map.clear();
assertEquals(map.size(), 0);
}
@Test()
public abstract void testRemove() throws IOException;
@Test()
public void testKeySet() {
assertEquals(map.keySet().size(), 0);
putString("one", "two");
assertEquals(map.keySet(), ImmutableSet.of("one"));
}
@Test()
public void testContainsKey() {
assert !map.containsKey("one");
putString("one", "apple");
assert map.containsKey("one");
}
@Test()
public void testIsEmpty() {
assert map.isEmpty();
putString("one", "apple");
assert !map.isEmpty();
}
abstract protected void putString(String key, String value);
protected void fourLeftRemovingOne() {
map.remove("one");
assertEquals(map.size(), 4);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
ImmutableSet.of("two", "three", "four", "five")));
}
@Test
public abstract void testPut() throws IOException;
@Test()
public void testGetBucket() {
assertEquals(map.getBucket().getName(), bucket);
}
}

View File

@ -0,0 +1,94 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.util.S3Utils;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Tests connection by listing all the buckets and their size
*
* @author Adrian Cole
*/
@Test(testName = "s3.S3ConnectionIntegrationTest")
public class S3ConnectionIntegrationTest extends S3IntegrationTest {
@Test(groups = {"integration"})
void testListBuckets() throws Exception {
List<S3Bucket.Metadata> myBuckets = client.listOwnedBuckets().get(10,
TimeUnit.SECONDS);
for (S3Bucket.Metadata bucket : myBuckets) {
context.createInputStreamMap(bucket.getName()).size();
}
}
private static final String sysHttpStreamUrl = System
.getProperty("jclouds.s3.httpstream.url");
private static final String sysHttpStreamMd5 = System
.getProperty("jclouds.s3.httpstream.md5");
@Test(groups = {"integration"})
@Parameters({"jclouds.s3.httpstream.url", "jclouds.s3.httpstream.md5"})
public void testCopyUrl(@Optional String httpStreamUrl,
@Optional String httpStreamMd5) throws Exception {
httpStreamUrl = checkNotNull(httpStreamUrl != null ? httpStreamUrl
: sysHttpStreamUrl, "httpStreamUrl");
httpStreamMd5 = checkNotNull(httpStreamMd5 != null ? httpStreamMd5
: sysHttpStreamMd5, "httpStreamMd5");
String bucketName = bucketPrefix + "tcu";
createBucketAndEnsureEmpty(bucketName);
String key = "hello";
URL url = new URL(httpStreamUrl);
byte[] md5 = S3Utils
.fromHexString(httpStreamMd5);
URLConnection connection = url.openConnection();
int length = connection.getContentLength();
InputStream input = connection.getInputStream();
S3Object object = new S3Object(key, input);
object.setContentLength(length);
object.getMetadata().setMd5(md5);
object.getMetadata().setSize(length);
byte[] newMd5 = client.putObject(bucketName, object).get(30,
TimeUnit.SECONDS);
assertEquals(newMd5, md5);
}
}

View File

@ -1,50 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.testng.annotations.Test;
/**
* Tests connection by listing all the buckets and their size
*
* @author Adrian Cole
*
*/
@Test(groups = "unit", testName = "s3.S3ConnectionTest")
public class S3ConnectionTest extends S3IntegrationTest {
@Test
void testListBuckets() throws Exception {
List<S3Bucket.Metadata> myBuckets = client.listOwnedBuckets().get(10,
TimeUnit.SECONDS);
for (S3Bucket.Metadata bucket : myBuckets) {
context.createInputStreamMap(bucket.getName()).size();
}
}
}

View File

@ -23,27 +23,26 @@
*/ */
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import static org.testng.Assert.assertEquals; import com.google.inject.AbstractModule;
import com.google.inject.Module;
import java.util.ArrayList; import org.jclouds.aws.s3.config.LiveS3ConnectionModule;
import java.util.List;
import org.jclouds.http.config.HttpFutureCommandClientModule; import org.jclouds.http.config.HttpFutureCommandClientModule;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule; import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.jclouds.logging.config.LoggingModule; import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.config.NullLoggingModule; import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule; import org.jclouds.logging.jdk.config.JDKLoggingModule;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.inject.AbstractModule; import java.util.ArrayList;
import com.google.inject.Module; import java.util.List;
/** /**
* Tests behavior of modules configured in S3ContextFactory * Tests behavior of modules configured in S3ContextFactory
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "unit", testName = "s3.S3ContextFactoryTest")
public class S3ContextFactoryTest { public class S3ContextFactoryTest {
@HttpFutureCommandClientModule @HttpFutureCommandClientModule
@ -60,7 +59,7 @@ public class S3ContextFactoryTest {
List<Module> modules = new ArrayList<Module>(); List<Module> modules = new ArrayList<Module>();
HttpModule module = new HttpModule(); HttpModule module = new HttpModule();
modules.add(module); modules.add(module);
S3ContextFactory.addHttpModuleIfNotPresent(modules); S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules);
assertEquals(modules.size(), 1); assertEquals(modules.size(), 1);
assertEquals(modules.remove(0), module); assertEquals(modules.remove(0), module);
} }
@ -82,7 +81,7 @@ public class S3ContextFactoryTest {
modules.add(loggingModule); modules.add(loggingModule);
HttpModule httpModule = new HttpModule(); HttpModule httpModule = new HttpModule();
modules.add(httpModule); modules.add(httpModule);
S3ContextFactory.addHttpModuleIfNotPresent(modules); S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules);
S3ContextFactory.addLoggingModuleIfNotPresent(modules); S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 2); assertEquals(modules.size(), 2);
assertEquals(modules.remove(0), loggingModule); assertEquals(modules.remove(0), loggingModule);
@ -90,11 +89,22 @@ public class S3ContextFactoryTest {
} }
@Test @Test
public void testAddBoth() { public void testAddBothWhenNotLive() {
List<Module> modules = new ArrayList<Module>(); List<Module> modules = new ArrayList<Module>();
S3ContextFactory.addHttpModuleIfNotPresent(modules); S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules);
S3ContextFactory.addLoggingModuleIfNotPresent(modules); S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 2); assertEquals(modules.size(), 1);
assert modules.remove(0) instanceof 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 JavaUrlHttpFutureCommandClientModule;
assert modules.remove(0) instanceof JDKLoggingModule; assert modules.remove(0) instanceof JDKLoggingModule;
} }

View File

@ -0,0 +1,210 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.internal.BaseS3Map;
import org.jclouds.util.Utils;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
/**
* Tests to cover @{link LiveS3ObjectMap}
*
* @author Adrian Cole
*/
@Test(testName = "s3.S3InputStreamMapIntegrationTest")
public class S3InputStreamMapIntegrationTest extends BaseS3MapIntegrationTest<InputStream> {
S3InputStreamMap map = null;
@SuppressWarnings("unchecked")
protected BaseS3Map<InputStream> createMap(S3Context context, String bucket) {
map = context.createInputStreamMap(bucket);
return (BaseS3Map<InputStream>) map;
}
@Override
@Test(groups = {"integration", "live"})
public void testValues() throws IOException {
map.putAll(this.fiveInputs);
Collection<InputStream> values = map.values();
assertEquals(values.size(), 5);
Set<String> valuesAsString = new HashSet<String>();
for (InputStream stream : values) {
valuesAsString.add(Utils.toStringAndClose(stream));
}
valuesAsString.removeAll(fiveStrings.values());
assert valuesAsString.size() == 0;
}
@Test(groups = {"integration", "live"})
public void testRemove() throws IOException {
putString("one", "two");
InputStream old = map.remove("one");
assertEquals(Utils.toStringAndClose(old), "two");
old = map.remove("one");
assert old == null;
old = map.get("one");
assert old == null;
assertEquals(map.keySet().size(), 0);
}
@Override
@Test(groups = {"integration", "live"})
public void testEntrySet() throws IOException {
map.putAllStrings(this.fiveStrings);
Set<Entry<String, InputStream>> entries = map.entrySet();
assertEquals(entries.size(), 5);
for (Entry<String, InputStream> entry : entries) {
assertEquals(IOUtils.toString(entry.getValue()), fiveStrings
.get(entry.getKey()));
entry.setValue(IOUtils.toInputStream(""));
}
assertEquals(map.size(), 5);
for (InputStream value : map.values()) {
assertEquals(IOUtils.toString(value), "");
}
}
@Test(groups = {"integration", "live"})
public void testContainsStringValue() {
map.putString("one", "apple");
assert map.containsValue(fiveStrings.get("one"));
}
@Test(groups = {"integration", "live"})
public void testContainsFileValue() {
map.putString("one", "apple");
assert map.containsValue(fiveFiles.get("one"));
}
@Test(groups = {"integration", "live"})
public void testContainsInputStreamValue() {
map.putString("one", "apple");
assert map.containsValue(this.fiveInputs.get("one"));
}
@Test(groups = {"integration", "live"})
public void testContainsBytesValue() {
map.putString("one", "apple");
assert map.containsValue(this.fiveBytes.get("one"));
}
@Override
@Test(groups = {"integration", "live"})
public void testPutAll() {
map.putAll(this.fiveInputs);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveInputs.keySet()));
fourLeftRemovingOne();
}
@Test(groups = {"integration", "live"})
public void testPutAllBytes() {
map.putAllBytes(this.fiveBytes);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveBytes.keySet()));
fourLeftRemovingOne();
}
@Test(groups = {"integration", "live"})
public void testPutAllFiles() {
map.putAllFiles(this.fiveFiles);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveFiles.keySet()));
fourLeftRemovingOne();
}
@Test(groups = {"integration", "live"})
public void testPutAllStrings() {
map.putAllStrings(this.fiveStrings);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveStrings.keySet()));
fourLeftRemovingOne();
}
@Test(groups = {"integration", "live"})
public void testPutString() throws IOException {
InputStream old = map.putString("one", "apple");
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.putString("one", "bear");
getOneReturnsBearAndOldValueIsApple(apple);
}
void getOneReturnsAppleAndOldValueIsNull(InputStream old)
throws IOException {
assert old == null;
assertEquals(Utils.toStringAndClose(map.get("one")), "apple");
assertEquals(map.size(), 1);
}
void getOneReturnsBearAndOldValueIsApple(InputStream oldValue)
throws IOException {
assertEquals(Utils.toStringAndClose(map.get("one")), "bear");
assertEquals(Utils.toStringAndClose(oldValue), "apple");
assertEquals(map.size(), 1);
}
@Test(groups = {"integration", "live"})
public void testPutFile() throws IOException {
InputStream old = map.putFile("one", fiveFiles.get("one"));
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.putFile("one", fiveFiles.get("two"));
getOneReturnsBearAndOldValueIsApple(apple);
}
@Test(groups = {"integration", "live"})
public void testPutBytes() throws IOException {
InputStream old = map.putBytes("one", "apple".getBytes());
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.putBytes("one", "bear".getBytes());
getOneReturnsBearAndOldValueIsApple(apple);
}
@Test(groups = {"integration", "live"})
public void testPut() throws IOException {
InputStream old = map.put("one", IOUtils.toInputStream("apple"));
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.put("one", IOUtils.toInputStream("bear"));
getOneReturnsBearAndOldValueIsApple(apple);
}
@Override
protected void putString(String key, String value) {
map.putString(key, value);
}
}

View File

@ -1,211 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.Map.Entry;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.internal.BaseS3Map;
import org.jclouds.util.Utils;
import org.testng.annotations.Test;
/**
* Tests to cover @{link LiveS3ObjectMap}
*
* @author Adrian Cole
*/
@Test(groups = "unit", sequential = true, testName = "s3.S3InputStreamMapTest")
public class S3InputStreamMapTest extends BaseS3MapTest<InputStream> {
S3InputStreamMap map = null;
@SuppressWarnings("unchecked")
protected BaseS3Map<InputStream> createMap(S3Context context, String bucket) {
map = context.createInputStreamMap(bucket);
return (BaseS3Map<InputStream>) map;
}
@Override
@Test()
public void testValues() throws IOException {
map.putAll(this.fiveInputs);
Collection<InputStream> values = map.values();
assertEquals(values.size(), 5);
Set<String> valuesAsString = new HashSet<String>();
for (InputStream stream : values) {
valuesAsString.add(Utils.toStringAndClose(stream));
}
valuesAsString.removeAll(fiveStrings.values());
assert valuesAsString.size() == 0;
}
@Test()
public void testRemove() throws IOException {
putString("one", "two");
InputStream old = map.remove("one");
assertEquals(Utils.toStringAndClose(old), "two");
old = map.remove("one");
assert old == null;
old = map.get("one");
assert old == null;
assertEquals(map.keySet().size(), 0);
}
@Override
@Test()
public void testEntrySet() throws IOException {
map.putAllStrings(this.fiveStrings);
Set<Entry<String, InputStream>> entries = map.entrySet();
assertEquals(entries.size(), 5);
for (Entry<String, InputStream> entry : entries) {
assertEquals(IOUtils.toString(entry.getValue()), fiveStrings
.get(entry.getKey()));
entry.setValue(IOUtils.toInputStream(""));
}
assertEquals(map.size(), 5);
for (InputStream value : map.values()) {
assertEquals(IOUtils.toString(value), "");
}
}
@Test()
public void testContainsStringValue() {
map.putString("one", "apple");
assert map.containsValue(fiveStrings.get("one"));
}
@Test()
public void testContainsFileValue() {
map.putString("one", "apple");
assert map.containsValue(fiveFiles.get("one"));
}
@Test()
public void testContainsInputStreamValue() {
map.putString("one", "apple");
assert map.containsValue(this.fiveInputs.get("one"));
}
@Test()
public void testContainsBytesValue() {
map.putString("one", "apple");
assert map.containsValue(this.fiveBytes.get("one"));
}
@Override
@Test()
public void testPutAll() {
map.putAll(this.fiveInputs);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveInputs.keySet()));
fourLeftRemovingOne();
}
@Test()
public void testPutAllBytes() {
map.putAllBytes(this.fiveBytes);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveBytes.keySet()));
fourLeftRemovingOne();
}
@Test
public void testPutAllFiles() {
map.putAllFiles(this.fiveFiles);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveFiles.keySet()));
fourLeftRemovingOne();
}
@Test()
public void testPutAllStrings() {
map.putAllStrings(this.fiveStrings);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveStrings.keySet()));
fourLeftRemovingOne();
}
@Test()
public void testPutString() throws IOException {
InputStream old = map.putString("one", "apple");
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.putString("one", "bear");
getOneReturnsBearAndOldValueIsApple(apple);
}
void getOneReturnsAppleAndOldValueIsNull(InputStream old)
throws IOException {
assert old == null;
assertEquals(Utils.toStringAndClose(map.get("one")), "apple");
assertEquals(map.size(), 1);
}
void getOneReturnsBearAndOldValueIsApple(InputStream oldValue)
throws IOException {
assertEquals(Utils.toStringAndClose(map.get("one")), "bear");
assertEquals(Utils.toStringAndClose(oldValue), "apple");
assertEquals(map.size(), 1);
}
@Test()
public void testPutFile() throws IOException {
InputStream old = map.putFile("one", fiveFiles.get("one"));
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.putFile("one", fiveFiles.get("two"));
getOneReturnsBearAndOldValueIsApple(apple);
}
@Test()
public void testPutBytes() throws IOException {
InputStream old = map.putBytes("one", "apple".getBytes());
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.putBytes("one", "bear".getBytes());
getOneReturnsBearAndOldValueIsApple(apple);
}
@Test()
public void testPut() throws IOException {
InputStream old = map.put("one", IOUtils.toInputStream("apple"));
getOneReturnsAppleAndOldValueIsNull(old);
InputStream apple = map.put("one", IOUtils.toInputStream("bear"));
getOneReturnsBearAndOldValueIsApple(apple);
}
@Override
protected void putString(String key, String value) {
map.putString(key, value);
}
}

View File

@ -24,46 +24,31 @@
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals; import com.google.inject.Module;
import org.jclouds.aws.s3.config.StubS3ConnectionModule;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpConstants; import org.jclouds.http.HttpConstants;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule; import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.testng.annotations.AfterTest; import static org.testng.Assert.assertEquals;
import org.testng.annotations.BeforeTest; import org.testng.ITestContext;
import org.testng.annotations.Optional; import org.testng.annotations.*;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import com.google.inject.Module; import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.*;
import java.util.logging.Formatter;
@Test
public class S3IntegrationTest { public class S3IntegrationTest {
protected static final String TEST_STRING = "<apples><apple name=\"fuji\"></apple> </apples>"; protected static final String TEST_STRING = "<apples><apple name=\"fuji\"></apple> </apples>";
protected byte[] goodMd5; protected byte[] goodMd5;
protected byte[] badMd5; protected byte[] badMd5;
protected String bucketName;
protected void createBucketAndEnsureEmpty(String sourceBucket) protected void createBucketAndEnsureEmpty(String sourceBucket)
throws InterruptedException, ExecutionException, TimeoutException { throws InterruptedException, ExecutionException, TimeoutException {
@ -84,7 +69,6 @@ public class S3IntegrationTest {
protected void addObjectToBucket(String sourceBucket, S3Object object) protected void addObjectToBucket(String sourceBucket, S3Object object)
throws InterruptedException, ExecutionException, TimeoutException, throws InterruptedException, ExecutionException, TimeoutException,
IOException { IOException {
;
client.putObject(sourceBucket, object).get(10, TimeUnit.SECONDS); client.putObject(sourceBucket, object).get(10, TimeUnit.SECONDS);
} }
@ -100,7 +84,7 @@ public class S3IntegrationTest {
return newObject; return newObject;
} }
@BeforeTest @BeforeClass(groups = {"integration", "live"})
void enableDebug() { void enableDebug() {
if (debugEnabled()) { if (debugEnabled()) {
Handler HANDLER = new ConsoleHandler() { Handler HANDLER = new ConsoleHandler() {
@ -139,29 +123,57 @@ public class S3IntegrationTest {
private static final String sysAWSSecretAccessKey = System private static final String sysAWSSecretAccessKey = System
.getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY); .getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
@BeforeTest @BeforeClass(inheritGroups = false, groups = {"integration", "live"})
@Parameters( { S3Constants.PROPERTY_AWS_ACCESSKEYID, @Parameters({S3Constants.PROPERTY_AWS_ACCESSKEYID,
S3Constants.PROPERTY_AWS_SECRETACCESSKEY }) S3Constants.PROPERTY_AWS_SECRETACCESSKEY})
protected void setUpClient(@Optional String AWSAccessKeyId, protected void setUpCredentials(@Optional String AWSAccessKeyId,
@Optional String AWSSecretAccessKey) throws Exception { @Optional String AWSSecretAccessKey, ITestContext testContext) throws Exception {
context = createS3Context(AWSAccessKeyId != null ? AWSAccessKeyId AWSAccessKeyId = AWSAccessKeyId != null ? AWSAccessKeyId
: sysAWSAccessKeyId, : sysAWSAccessKeyId;
AWSSecretAccessKey != null ? AWSSecretAccessKey AWSSecretAccessKey = AWSSecretAccessKey != null ? AWSSecretAccessKey
: sysAWSSecretAccessKey); : sysAWSSecretAccessKey;
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(); client = context.getConnection();
assert client != null;
deleteEverything(); deleteEverything();
goodMd5 = S3Utils.md5(TEST_STRING); goodMd5 = S3Utils.md5(TEST_STRING);
badMd5 = S3Utils.md5("alf"); badMd5 = S3Utils.md5("alf");
} }
protected boolean debugEnabled() { @BeforeMethod(dependsOnMethods = "deleteBucket", groups = {"integration", "live"})
return false; public void setUpBucket(Method method) throws TimeoutException, ExecutionException, InterruptedException {
bucketName = (bucketPrefix + method.getName()).toLowerCase();
createBucketAndEnsureEmpty(bucketName);
} }
protected S3Context createS3Context(String AWSAccessKeyId, @BeforeMethod(groups = {"integration", "live"})
String AWSSecretAccessKey) { @AfterMethod(groups = {"integration", "live"})
return S3ContextFactory.createS3Context(buildS3Properties( public void deleteBucket() throws TimeoutException, ExecutionException, InterruptedException {
AWSAccessKeyId, AWSSecretAccessKey), createHttpModule()); if (bucketName != null)
deleteBucket(bucketName);
}
protected boolean debugEnabled() {
return false;
} }
protected Properties buildS3Properties(String AWSAccessKeyId, protected Properties buildS3Properties(String AWSAccessKeyId,
@ -185,22 +197,9 @@ public class S3IntegrationTest {
try { try {
List<S3Bucket.Metadata> metadata = client.listOwnedBuckets().get( List<S3Bucket.Metadata> metadata = client.listOwnedBuckets().get(
10, TimeUnit.SECONDS); 10, TimeUnit.SECONDS);
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
for (S3Bucket.Metadata metaDatum : metadata) { for (S3Bucket.Metadata metaDatum : metadata) {
if (metaDatum.getName().startsWith(bucketPrefix.toLowerCase())) { if (metaDatum.getName().startsWith(bucketPrefix.toLowerCase())) {
S3Bucket bucket = client.listBucket(metaDatum.getName()) deleteBucket(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);
} }
} }
@ -209,7 +208,27 @@ public class S3IntegrationTest {
} }
} }
@AfterTest private void deleteBucket(String name) throws InterruptedException, ExecutionException, TimeoutException {
if (client.bucketExists(name).get(10, TimeUnit.SECONDS)) {
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
S3Bucket bucket = client.listBucket(name)
.get(10, TimeUnit.SECONDS);
for (S3Object.Metadata objectMeta : bucket.getContents()) {
results.add(client.deleteObject(name,
objectMeta.getKey()));
}
Iterator<Future<Boolean>> iterator = results.iterator();
while (iterator.hasNext()) {
iterator.next().get(10, TimeUnit.SECONDS);
iterator.remove();
}
client.deleteBucketIfEmpty(name).get(10,
TimeUnit.SECONDS);
}
}
@AfterClass
protected void tearDownClient() throws Exception { protected void tearDownClient() throws Exception {
deleteEverything(); deleteEverything();
context.close(); context.close();

View File

@ -0,0 +1,166 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.internal.BaseS3Map;
import org.jclouds.aws.s3.util.S3Utils;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
/**
* Tests to cover @{link LiveS3ObjectMap}
*
* @author Adrian Cole
*/
@Test(testName = "s3.S3ObjectMapIntegrationTest")
public class S3ObjectMapIntegrationTest extends BaseS3MapIntegrationTest<S3Object> {
S3ObjectMap map = null;
@SuppressWarnings("unchecked")
protected BaseS3Map<S3Object> createMap(S3Context context, String bucket) {
map = context.createS3ObjectMap(bucket);
return (BaseS3Map<S3Object>) map;
}
@Override
@Test(groups = {"integration", "live"})
public void testValues() throws IOException {
putFiveStrings();
Collection<S3Object> values = map.values();
assertEquals(values.size(), 5);
Set<String> valuesAsString = new HashSet<String>();
for (S3Object object : values) {
valuesAsString.add(S3Utils.getContentAsStringAndClose(object));
}
valuesAsString.removeAll(fiveStrings.values());
assert valuesAsString.size() == 0;
}
@Test(groups = {"integration", "live"})
public void testRemove() throws IOException {
putString("one", "two");
S3Object old = map.remove("one");
assertEquals(S3Utils.getContentAsStringAndClose(old), "two");
old = map.remove("one");
assert old == S3Object.NOT_FOUND;
old = map.get("one");
assert old == S3Object.NOT_FOUND;
assertEquals(map.keySet().size(), 0);
}
@Override
@Test(groups = {"integration", "live"})
public void testEntrySet() throws IOException {
putFiveStrings();
Set<Entry<String, S3Object>> entries = map.entrySet();
assertEquals(entries.size(), 5);
for (Entry<String, S3Object> entry : entries) {
assertEquals(S3Utils.getContentAsStringAndClose(entry.getValue()),
fiveStrings.get(entry.getKey()));
S3Object value = entry.getValue();
value.setData("");
value.generateMd5();
entry.setValue(value);
}
assertEquals(map.size(), 5);
for (S3Object value : map.values()) {
assertEquals(S3Utils.getContentAsStringAndClose(value), "");
}
}
@Test(groups = {"integration", "live"})
public void testContains() {
putString("one", "apple");
S3Object object = new S3Object("one");
object.setData("apple");
assert map.containsValue(object);
}
void getOneReturnsAppleAndOldValueIsNull(S3Object old) throws IOException {
assert old == S3Object.NOT_FOUND;
assertEquals(S3Utils.getContentAsStringAndClose(map.get("one")),
"apple");
assert map.size() == 1;
}
void getOneReturnsBearAndOldValueIsApple(S3Object oldValue)
throws IOException {
assertEquals(S3Utils.getContentAsStringAndClose(map.get("one")), "bear");
assertEquals(S3Utils.getContentAsStringAndClose(oldValue), "apple");
assert map.size() == 1;
}
@Test(groups = {"integration", "live"})
public void testPut() throws IOException {
S3Object object = new S3Object("one");
object.setData(IOUtils.toInputStream("apple"));
object.generateMd5();
S3Object old = map.put(object.getKey(), object);
getOneReturnsAppleAndOldValueIsNull(old);
object.setData(IOUtils.toInputStream("bear"));
object.generateMd5();
S3Object apple = map.put(object.getKey(), object);
getOneReturnsBearAndOldValueIsApple(apple);
}
@Test(groups = {"integration", "live"})
public void testPutAll() {
Map<String, S3Object> newMap = new HashMap<String, S3Object>();
for (String key : fiveInputs.keySet()) {
S3Object object = new S3Object(key);
object.setData(fiveInputs.get(key));
object.getMetadata().setSize(fiveBytes.get(key).length);
newMap.put(key, object);
}
map.putAll(newMap);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveInputs.keySet()));
fourLeftRemovingOne();
}
@Override
protected void putString(String key, String value) {
S3Object object = new S3Object(key);
object.setData(value);
map.put(key, object);
}
protected void putFiveStrings() {
Map<String, S3Object> newMap = new HashMap<String, S3Object>();
for (Map.Entry<String, String> entry : fiveStrings.entrySet()) {
S3Object object = new S3Object(entry.getKey());
object.setData(entry.getValue());
newMap.put(entry.getKey(), object);
}
map.putAll(newMap);
}
}

View File

@ -1,172 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.Map.Entry;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.internal.BaseS3Map;
import org.jclouds.aws.s3.util.S3Utils;
import org.testng.annotations.Test;
/**
* Tests to cover @{link LiveS3ObjectMap}
*
* @author Adrian Cole
*/
@Test(groups = "unit", sequential = true, testName = "s3.S3ObjectMapTest")
public class S3ObjectMapTest extends BaseS3MapTest<S3Object> {
S3ObjectMap map = null;
@SuppressWarnings("unchecked")
protected BaseS3Map<S3Object> createMap(S3Context context, String bucket) {
map = context.createS3ObjectMap(bucket);
return (BaseS3Map<S3Object>) map;
}
@Override
@Test()
public void testValues() throws IOException {
putFiveStrings();
Collection<S3Object> values = map.values();
assertEquals(values.size(), 5);
Set<String> valuesAsString = new HashSet<String>();
for (S3Object object : values) {
valuesAsString.add(S3Utils.getContentAsStringAndClose(object));
}
valuesAsString.removeAll(fiveStrings.values());
assert valuesAsString.size() == 0;
}
@Test()
public void testRemove() throws IOException {
putString("one", "two");
S3Object old = map.remove("one");
assertEquals(S3Utils.getContentAsStringAndClose(old), "two");
old = map.remove("one");
assert old == S3Object.NOT_FOUND;
old = map.get("one");
assert old == S3Object.NOT_FOUND;
assertEquals(map.keySet().size(), 0);
}
@Override
@Test()
public void testEntrySet() throws IOException {
putFiveStrings();
Set<Entry<String, S3Object>> entries = map.entrySet();
assertEquals(entries.size(), 5);
for (Entry<String, S3Object> entry : entries) {
assertEquals(S3Utils.getContentAsStringAndClose(entry.getValue()),
fiveStrings.get(entry.getKey()));
S3Object value = entry.getValue();
value.setData("");
value.generateMd5();
entry.setValue(value);
}
assertEquals(map.size(), 5);
for (S3Object value : map.values()) {
assertEquals(S3Utils.getContentAsStringAndClose(value), "");
}
}
@Test()
public void testContains() {
putString("one", "apple");
S3Object object = new S3Object("one");
object.setData("apple");
assert map.containsValue(object);
}
void getOneReturnsAppleAndOldValueIsNull(S3Object old) throws IOException {
assert old == S3Object.NOT_FOUND;
assertEquals(S3Utils.getContentAsStringAndClose(map.get("one")),
"apple");
assert map.size() == 1;
}
void getOneReturnsBearAndOldValueIsApple(S3Object oldValue)
throws IOException {
assertEquals(S3Utils.getContentAsStringAndClose(map.get("one")), "bear");
assertEquals(S3Utils.getContentAsStringAndClose(oldValue), "apple");
assert map.size() == 1;
}
@Test
public void testPut() throws IOException {
S3Object object = new S3Object("one");
object.setData(IOUtils.toInputStream("apple"));
object.generateMd5();
S3Object old = map.put(object.getKey(), object);
getOneReturnsAppleAndOldValueIsNull(old);
object.setData(IOUtils.toInputStream("bear"));
object.generateMd5();
S3Object apple = map.put(object.getKey(), object);
getOneReturnsBearAndOldValueIsApple(apple);
}
@Test
public void testPutAll() {
Map<String, S3Object> newMap = new HashMap<String, S3Object>();
for (String key : fiveInputs.keySet()) {
S3Object object = new S3Object(key);
object.setData(fiveInputs.get(key));
object.getMetadata().setSize(fiveBytes.get(key).length);
newMap.put(key, object);
}
map.putAll(newMap);
assertEquals(map.size(), 5);
assertEquals(new TreeSet<String>(map.keySet()), new TreeSet<String>(
fiveInputs.keySet()));
fourLeftRemovingOne();
}
@Override
protected void putString(String key, String value) {
S3Object object = new S3Object(key);
object.setData(value);
map.put(key, object);
}
protected void putFiveStrings() {
Map<String, S3Object> newMap = new HashMap<String, S3Object>();
for (Map.Entry<String, String> entry : fiveStrings.entrySet()) {
S3Object object = new S3Object(entry.getKey());
object.setData(entry.getValue());
newMap.put(entry.getKey(), object);
}
map.putAll(newMap);
}
}

View File

@ -26,6 +26,7 @@ package org.jclouds.aws.s3;
import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Base64;
import org.jclouds.aws.PerformanceTest; import org.jclouds.aws.PerformanceTest;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -38,14 +39,12 @@ import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorCompletionService;
import static org.testng.Assert.*;
/** /**
* This tests the performance of Digest commands. * This tests the performance of Digest commands.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", sequential = true, testName = "s3.PerformanceTest") @Test(groups = "performance", sequential = true, testName = "s3.PerformanceTest")
public class S3UtilsTest extends PerformanceTest { public class S3UtilsTest extends PerformanceTest {
@Test(dataProvider = "hmacsha1") @Test(dataProvider = "hmacsha1")
@ -78,30 +77,31 @@ public class S3UtilsTest extends PerformanceTest {
public Object[][] createMD5Data() { public Object[][] createMD5Data() {
return base64MD5MessageDigest; return base64MD5MessageDigest;
} }
public final static Object[][] base64MD5MessageDigest = { public final static Object[][] base64MD5MessageDigest = {
{ "apple", "1f3870be274f6c49b3e31a0c6728957f" }, {"apple", "1f3870be274f6c49b3e31a0c6728957f"},
{ "bear", "893b56e3cfe153fb770a120b83bac20c" }, {"bear", "893b56e3cfe153fb770a120b83bac20c"},
{ "candy", "c48ba993d35c3abe0380f91738fe2a34" }, {"candy", "c48ba993d35c3abe0380f91738fe2a34"},
{ "dogma", "95eb470e4faee302e9cd3063b1923dab" }, {"dogma", "95eb470e4faee302e9cd3063b1923dab"},
{ "emma", "00a809937eddc44521da9521269e75c6" } }; {"emma", "00a809937eddc44521da9521269e75c6"}};
public final static Object[][] base64KeyMessageDigest = { public final static Object[][] base64KeyMessageDigest = {
{ Base64.decode("CwsLCwsLCwsLCwsLCwsLCwsLCws="), "Hi There", {Base64.decode("CwsLCwsLCwsLCwsLCwsLCwsLCws="), "Hi There",
"thcxhlUFcmTii8C2+zeMjvFGvgA=" }, "thcxhlUFcmTii8C2+zeMjvFGvgA="},
{ Base64.decode("SmVmZQ=="), "what do ya want for nothing?", {Base64.decode("SmVmZQ=="), "what do ya want for nothing?",
"7/zfauXrL6LSdBbV8YTfnCWafHk=" }, "7/zfauXrL6LSdBbV8YTfnCWafHk="},
{ Base64.decode("DAwMDAwMDAwMDAwMDAwMDAwMDAw="), {Base64.decode("DAwMDAwMDAwMDAwMDAwMDAwMDAw="),
"Test With Truncation", "TBoDQktV4H/n8nvh1Yu5MkqaWgQ=" }, "Test With Truncation", "TBoDQktV4H/n8nvh1Yu5MkqaWgQ="},
{ {
Base64 Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="), .decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key - Hash Key First", "Test Using Larger Than Block-Size Key - Hash Key First",
"qkrl4VJy0A6VcFY3zoo7Ve1AIRI=" }, "qkrl4VJy0A6VcFY3zoo7Ve1AIRI="},
{ {
Base64 Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="), .decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
"6OmdD0UjfXhta7qnllx4CLv/GpE=" } }; "6OmdD0UjfXhta7qnllx4CLv/GpE="}};
@DataProvider(name = "hmacsha1") @DataProvider(name = "hmacsha1")
public Object[][] createData1() { public Object[][] createData1() {
@ -121,7 +121,7 @@ public class S3UtilsTest extends PerformanceTest {
String base64Digest) throws NoSuchProviderException, String base64Digest) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException { NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
String b64 = S3Utils.md5Hex(message.getBytes()); String b64 = S3Utils.md5Hex(message.getBytes());
assertEquals(base64Digest,b64); assertEquals(base64Digest, b64);
} }
} }

View File

@ -28,12 +28,12 @@ import org.testng.annotations.Test;
import java.util.Properties; import java.util.Properties;
/** /**
* This performs the same test as {@link S3ConnectionTest}, except using SSL. * This performs the same test as {@link S3ConnectionIntegrationTest}, except using SSL.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "s3.SecureS3ConnectionTest") @Test(groups = {"live"}, testName = "s3.SecureS3ConnectionIntegrationTest")
public class SecureS3ConnectionTest extends S3ConnectionTest { public class SecureS3ConnectionIntegrationTest extends S3ConnectionIntegrationTest {
@Override @Override
protected Properties buildS3Properties(String AWSAccessKeyId, protected Properties buildS3Properties(String AWSAccessKeyId,
String AWSSecretAccessKey) { String AWSSecretAccessKey) {

View File

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

View File

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

View File

@ -23,32 +23,24 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5DoesntMatch; import com.google.common.collect.HashMultimap;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5Matches; import com.google.common.collect.Multimap;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceModifiedSince;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceUnmodifiedSince;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideAcl;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideMetadataWith;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.S3IntegrationTest; import org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.*;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.IOException;
import com.google.common.collect.HashMultimap; import java.net.URL;
import com.google.common.collect.Multimap; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/** /**
* Tests integrated functionality of all copyObject commands. * Tests integrated functionality of all copyObject commands.
@ -57,79 +49,53 @@ import com.google.common.collect.Multimap;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.CopyObjectIntegrationTest") @Test(testName = "s3.CopyObjectIntegrationTest")
public class CopyObjectIntegrationTest extends S3IntegrationTest { public class CopyObjectIntegrationTest extends S3IntegrationTest {
String sourceKey = "apples"; String sourceKey = "apples";
String destinationKey = "pears"; String destinationKey = "pears";
@Test(groups = {"integration","live"})
@Test()
void testCannedAccessPolicyPublic() throws Exception {
String sourceBucket = bucketPrefix + "tcapp";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey);
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey,overrideAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com/%2$s",
destinationBucket, destinationKey));
S3Utils.toStringAndClose(url.openStream());
}
@Test()
void testCopyObject() throws Exception { void testCopyObject() throws Exception {
String sourceBucket = bucketPrefix + "testcopyobject";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey); String destinationBucket = bucketName + "dest";
addToBucketAndValidate(bucketName, sourceKey);
createBucketAndEnsureEmpty(destinationBucket); createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey).get(10, TimeUnit.SECONDS); destinationKey).get(10, TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey); validateContent(destinationBucket, destinationKey);
} }
private void setupSourceBucket(String sourceBucket, String sourceKey)
private void addToBucketAndValidate(String bucketName, String sourceKey)
throws InterruptedException, ExecutionException, TimeoutException, throws InterruptedException, ExecutionException, TimeoutException,
IOException { IOException {
createBucketAndEnsureEmpty(sourceBucket); addObjectToBucket(bucketName, sourceKey);
addToBucketAndValidate(sourceBucket, sourceKey); validateContent(bucketName, sourceKey);
} }
private void addToBucketAndValidate(String sourceBucket, String sourceKey) @Test(groups = {"integration","live"})
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
addObjectToBucket(sourceBucket, sourceKey);
validateContent(sourceBucket, sourceKey);
}
@Test
void testCopyIfModifiedSince() throws InterruptedException, void testCopyIfModifiedSince() throws InterruptedException,
ExecutionException, TimeoutException, IOException { ExecutionException, TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcims";
String destinationBucket = sourceBucket + "dest"; String destinationBucket = bucketName + "dest";
DateTime before = new DateTime(); DateTime before = new DateTime();
setupSourceBucket(sourceBucket, sourceKey); addToBucketAndValidate(bucketName, sourceKey);
DateTime after = new DateTime().plusSeconds(1); DateTime after = new DateTime().plusSeconds(1);
createBucketAndEnsureEmpty(destinationBucket); createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(before)).get(10, destinationKey, ifSourceModifiedSince(before)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey); validateContent(destinationBucket, destinationKey);
try { try {
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(after)).get(10, destinationKey, ifSourceModifiedSince(after)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
} catch (ExecutionException e) { } catch (ExecutionException e) {
@ -138,24 +104,24 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
} }
} }
@Test @Test(groups = {"integration","live"})
void testCopyIfUnmodifiedSince() throws InterruptedException, void testCopyIfUnmodifiedSince() throws InterruptedException,
ExecutionException, TimeoutException, IOException { ExecutionException, TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcius";
String destinationBucket = sourceBucket + "dest"; String destinationBucket = bucketName + "dest";
DateTime before = new DateTime(); DateTime before = new DateTime();
setupSourceBucket(sourceBucket, sourceKey); addToBucketAndValidate(bucketName, sourceKey);
DateTime after = new DateTime().plusSeconds(1); DateTime after = new DateTime().plusSeconds(1);
createBucketAndEnsureEmpty(destinationBucket); createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceUnmodifiedSince(after)).get(10, destinationKey, ifSourceUnmodifiedSince(after)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey); validateContent(destinationBucket, destinationKey);
try { try {
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(before)).get(10, destinationKey, ifSourceModifiedSince(before)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
} catch (ExecutionException e) { } catch (ExecutionException e) {
@ -164,23 +130,23 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
} }
} }
@Test @Test(groups = {"integration","live"})
void testCopyIfMatch() throws InterruptedException, ExecutionException, void testCopyIfMatch() throws InterruptedException, ExecutionException,
TimeoutException, IOException { TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcim";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey); String destinationBucket = bucketName + "dest";
addToBucketAndValidate(bucketName, sourceKey);
createBucketAndEnsureEmpty(destinationBucket); createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5Matches(goodMd5)).get(10, destinationKey, ifSourceMd5Matches(goodMd5)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey); validateContent(destinationBucket, destinationKey);
try { try {
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5Matches(badMd5)).get(10, destinationKey, ifSourceMd5Matches(badMd5)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
} catch (ExecutionException e) { } catch (ExecutionException e) {
@ -189,23 +155,23 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
} }
} }
@Test @Test(groups = {"integration","live"})
void testCopyIfNoneMatch() throws IOException, InterruptedException, void testCopyIfNoneMatch() throws IOException, InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
String sourceBucket = bucketPrefix + "tcinm";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey); String destinationBucket = bucketName + "dest";
addToBucketAndValidate(bucketName, sourceKey);
createBucketAndEnsureEmpty(destinationBucket); createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5DoesntMatch(badMd5)).get(10, destinationKey, ifSourceMd5DoesntMatch(badMd5)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey); validateContent(destinationBucket, destinationKey);
try { try {
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5DoesntMatch(goodMd5)).get(10, destinationKey, ifSourceMd5DoesntMatch(goodMd5)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
} catch (ExecutionException e) { } catch (ExecutionException e) {
@ -214,19 +180,19 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
} }
} }
@Test @Test(groups = {"integration","live"})
void testCopyWithMetadata() throws InterruptedException, void testCopyWithMetadata() throws InterruptedException,
ExecutionException, TimeoutException, IOException { ExecutionException, TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcwm";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey); String destinationBucket = bucketName + "dest";
addToBucketAndValidate(bucketName, sourceKey);
Multimap<String, String> metadata = HashMultimap.create(); Multimap<String, String> metadata = HashMultimap.create();
metadata.put(S3Headers.USER_METADATA_PREFIX + "adrian", "cole"); metadata.put(S3Headers.USER_METADATA_PREFIX + "adrian", "cole");
createBucketAndEnsureEmpty(destinationBucket); createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket, client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, overrideMetadataWith(metadata)).get(10, destinationKey, overrideMetadataWith(metadata)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);

View File

@ -0,0 +1,68 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.commands;
import org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideAcl;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.util.S3Utils;
import org.testng.annotations.Test;
import java.net.URL;
import java.util.concurrent.TimeUnit;
/**
* Tests integrated functionality of all copyObject commands.
* <p/>
* Each test uses a different bucket name, so it should be perfectly fine to run
* in parallel.
*
* @author Adrian Cole
*/
@Test(testName = "s3.CopyObjectLiveTest")
public class CopyObjectLiveTest extends S3IntegrationTest {
String sourceKey = "apples";
String destinationKey = "pears";
@Test(groups = "live")
void testCannedAccessPolicyPublic() throws Exception {
String destinationBucket = bucketName + "dest";
addObjectToBucket(bucketName, sourceKey);
validateContent(bucketName, sourceKey);
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, overrideAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com/%2$s",
destinationBucket, destinationKey));
S3Utils.toStringAndClose(url.openStream());
}
}

View File

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

View File

@ -23,14 +23,14 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3IntegrationTest; import org.jclouds.aws.s3.S3IntegrationTest;
import org.jclouds.aws.s3.S3ResponseException; import org.jclouds.aws.s3.S3ResponseException;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/** /**
* Tests integrated functionality of all deleteObject commands. * Tests integrated functionality of all deleteObject commands.
@ -39,9 +39,8 @@ import static org.testng.Assert.assertEquals;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.DeleteObjectIntegrationTest") @Test(groups = {"integration", "live"}, testName = "s3.DeleteObjectIntegrationTest")
public class DeleteObjectIntegrationTest extends S3IntegrationTest { public class DeleteObjectIntegrationTest extends S3IntegrationTest {
@Test() @Test()

View File

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

View File

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

View File

@ -23,13 +23,13 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3IntegrationTest; import org.jclouds.aws.s3.S3IntegrationTest;
import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Bucket;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.List;
import java.util.concurrent.TimeUnit;
/** /**
* Tests integrated functionality of all listOwnedBucket commands. * Tests integrated functionality of all listOwnedBucket commands.
* <p/> * <p/>
@ -37,9 +37,8 @@ import org.testng.annotations.Test;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.ListOwnedBucketsIntegrationTest") @Test(groups = {"integration", "live"}, testName = "s3.ListOwnedBucketsIntegrationTest")
public class ListOwnedBucketsIntegrationTest extends S3IntegrationTest { public class ListOwnedBucketsIntegrationTest extends S3IntegrationTest {
@Test() @Test()

View File

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

View File

@ -23,9 +23,18 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl; import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl;
import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.withAcl;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.S3Utils;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -34,16 +43,6 @@ import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.*;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.S3Utils;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/** /**
* Tests integrated functionality of all PutObject commands. * Tests integrated functionality of all PutObject commands.
@ -52,23 +51,22 @@ import org.testng.annotations.Test;
* in parallel. * in parallel.
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test(groups = "integration", testName = "s3.PutObjectIntegrationTest") @Test(testName = "s3.PutObjectIntegrationTest")
public class PutObjectIntegrationTest extends S3IntegrationTest { public class PutObjectIntegrationTest extends S3IntegrationTest {
@DataProvider(name = "putTests") @DataProvider(name = "putTests")
public Object[][] createData1() throws IOException { public Object[][] createData1() throws IOException {
String realObject = IOUtils.toString(new FileInputStream("pom.xml")); String realObject = IOUtils.toString(new FileInputStream("pom.xml"));
return new Object[][] { return new Object[][]{
{ "file", "text/xml", new File("pom.xml"), realObject }, {"file", "text/xml", new File("pom.xml"), realObject},
{ "string", "text/xml", realObject, realObject }, {"string", "text/xml", realObject, realObject},
{ "bytes", "application/octet-stream", realObject.getBytes(), {"bytes", "application/octet-stream", realObject.getBytes(),
realObject } }; realObject}};
} }
@Test(dataProvider = "putTests") @Test(dataProvider = "putTests", groups = {"integration", "live"})
void testPutObject(String key, String type, Object content, void testPutObject(String key, String type, Object content,
Object realObject) throws Exception { Object realObject) throws Exception {
String bucketName = bucketPrefix + "tpo"; String bucketName = bucketPrefix + "tpo";
@ -92,7 +90,7 @@ public class PutObjectIntegrationTest extends S3IntegrationTest {
.getContents().size(), 1); .getContents().size(), 1);
} }
@Test @Test(groups = {"integration", "live"})
void testMetadata() throws Exception { void testMetadata() throws Exception {
String bucketName = bucketPrefix + "tmd"; String bucketName = bucketPrefix + "tmd";
createBucketAndEnsureEmpty(bucketName); createBucketAndEnsureEmpty(bucketName);
@ -126,23 +124,4 @@ public class PutObjectIntegrationTest extends S3IntegrationTest {
.getBytes())); .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());
}
} }

View File

@ -0,0 +1,69 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.commands;
import org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl;
import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.withAcl;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.util.S3Utils;
import org.testng.annotations.Test;
import java.net.URL;
import java.util.concurrent.TimeUnit;
/**
* Tests integrated functionality of all PutObject commands.
* <p/>
* Each test uses a different bucket name, so it should be perfectly fine to run
* in parallel.
*
* @author Adrian Cole
*/
@Test(testName = "s3.PutObjectLiveTest")
public class PutObjectLiveTest extends S3IntegrationTest {
@Test(groups = {"live"})
void testCannedAccessPolicyPublic() throws Exception {
String bucketName = bucketPrefix + "tcapp";
createBucketAndEnsureEmpty(bucketName);
String key = "hello";
client.putBucketIfNotExists(bucketName,
withBucketAcl(CannedAccessPolicy.PUBLIC_READ)).get(10,
TimeUnit.SECONDS);
client.putObject(bucketName, new S3Object(key, TEST_STRING),
withAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com/%2$s",
bucketName, key));
S3Utils.toStringAndClose(url.openStream());
}
}

View File

@ -23,40 +23,31 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import org.jclouds.aws.s3.commands.config.S3CommandsModule;
import org.jclouds.aws.s3.commands.options.CopyObjectOptions;
import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.commands.options.ListBucketOptions;
import org.jclouds.aws.s3.commands.options.PutBucketOptions;
import org.jclouds.aws.s3.commands.options.PutObjectOptions;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.name.Names; import com.google.inject.name.Names;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import org.jclouds.aws.s3.commands.config.S3CommandsModule;
import org.jclouds.aws.s3.commands.options.*;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.jclouds.aws.s3.domain.S3Object;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test @Test(groups = {"unit"}, testName = "s3.S3CommandFactoryTest")
public class S3CommandFactoryTest { public class S3CommandFactoryTest {
Injector injector = null; Injector injector = null;
S3CommandFactory commandFactory = null; S3CommandFactory commandFactory = null;
public static final String listAllMyBucketsResult = "<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/callables/\"><Owner ><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID></Owner><Buckets><Bucket><Name>adrianjbosstest</Name><CreationDate>2009-03-12T02:00:07.000Z</CreationDate></Bucket><Bucket><Name>adrianjbosstest2</Name><CreationDate>2009-03-12T02:00:09.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>";
@BeforeMethod @BeforeMethod
void setUpInjector() { void setUpInjector() {
injector = Guice.createInjector(new S3CommandsModule() { injector = Guice.createInjector(new S3CommandsModule() {

View File

@ -23,16 +23,8 @@
*/ */
package org.jclouds.aws.s3.commands; package org.jclouds.aws.s3.commands;
import static org.testng.Assert.assertEquals; import com.google.inject.Guice;
import com.google.inject.Injector;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.aws.PerformanceTest; import org.jclouds.aws.PerformanceTest;
import org.jclouds.aws.s3.domain.CanonicalUser; import org.jclouds.aws.s3.domain.CanonicalUser;
@ -46,20 +38,26 @@ import org.jclouds.aws.s3.xml.config.S3ParserModule;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import com.google.inject.Guice; import java.io.IOException;
import com.google.inject.Injector; import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
/** /**
* Tests parsing of S3 responses * Tests parsing of S3 responses
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", sequential = true, testName = "s3.S3ParserTest") @Test(groups = {"performance"}, testName = "s3.S3ParserTest")
public class S3ParserTest extends PerformanceTest { public class S3ParserTest extends PerformanceTest {
Injector injector = null; Injector injector = null;
@ -133,7 +131,7 @@ public class S3ParserTest extends PerformanceTest {
public void testCanParseListBucketResult() throws HttpException, public void testCanParseListBucketResult() throws HttpException,
UnsupportedEncodingException { UnsupportedEncodingException {
S3Bucket bucket = runParseListBucketResult(); S3Bucket bucket = runParseListBucketResult();
assert bucket.isComplete(); assert !bucket.isTruncated();
assert bucket.getName().equals("adrianjbosstest"); assert bucket.getName().equals("adrianjbosstest");
assert bucket.getContents().size() == 1; assert bucket.getContents().size() == 1;
S3Object.Metadata object = bucket.getContents().iterator().next(); S3Object.Metadata object = bucket.getContents().iterator().next();

View File

@ -23,25 +23,22 @@
*/ */
package org.jclouds.aws.s3.commands.callables; package org.jclouds.aws.s3.commands.callables;
import static org.testng.Assert.*;
import static org.easymock.classextension.EasyMock.*;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import static org.easymock.classextension.EasyMock.*;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.S3Object.Metadata; import org.jclouds.aws.s3.domain.S3Object.Metadata;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpHeaders; import org.jclouds.http.HttpHeaders;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*
*/ */
@Test @Test(groups = "unit", testName = "s3.ParseObjectFromHeadersAndHttpContentTest")
public class ParseObjectFromHeadersAndHttpContentTest { public class ParseObjectFromHeadersAndHttpContentTest {
ParseObjectFromHeadersAndHttpContent callable; ParseObjectFromHeadersAndHttpContent callable;
ParseMetadataFromHeaders metadataParser; ParseMetadataFromHeaders metadataParser;

View File

@ -23,34 +23,26 @@
*/ */
package org.jclouds.aws.s3.commands.options; package org.jclouds.aws.s3.commands.options;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5DoesntMatch; import com.google.common.collect.HashMultimap;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5Matches; import com.google.common.collect.Multimap;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceModifiedSince; import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.*;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceUnmodifiedSince;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideAcl;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideMetadataWith;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.DateService; import org.jclouds.aws.s3.util.DateService;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import static org.testng.Assert.*;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.HashMultimap; import java.io.UnsupportedEncodingException;
import com.google.common.collect.Multimap;
/** /**
* Tests possible uses of CopyObjectOptions and CopyObjectOptions.Builder.* * Tests possible uses of CopyObjectOptions and CopyObjectOptions.Builder.*
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "s3.CopyObjectOptionsTest")
public class CopyObjectOptionsTest { public class CopyObjectOptionsTest {
private byte[] testBytes; private byte[] testBytes;
@ -68,7 +60,7 @@ public class CopyObjectOptionsTest {
now = new DateTime(); now = new DateTime();
nowExpected = new DateService().toHeaderString(now); nowExpected = new DateService().toHeaderString(now);
testBytes = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; testBytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
} }
@Test @Test
@ -95,7 +87,7 @@ public class CopyObjectOptionsTest {
private void assertGoodMeta(CopyObjectOptions options) { private void assertGoodMeta(CopyObjectOptions options) {
assert options != null; assert options != null;
assert options.getMetadata() != null; assert options.getMetadata() != null;
Multimap<String,String> headers = options.buildRequestHeaders(); Multimap<String, String> headers = options.buildRequestHeaders();
assertEquals(headers.size(), 2); assertEquals(headers.size(), 2);
assertEquals(headers.get( assertEquals(headers.get(
"x-amz-metadata-directive").iterator().next(), "x-amz-metadata-directive").iterator().next(),

View File

@ -23,29 +23,23 @@
*/ */
package org.jclouds.aws.s3.commands.options; package org.jclouds.aws.s3.commands.options;
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.startAt; import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.*;
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.tail;
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.ifMd5DoesntMatch;
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.ifMd5Matches;
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.ifModifiedSince;
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.ifUnmodifiedSince;
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.range;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.io.UnsupportedEncodingException;
import org.jclouds.aws.s3.util.DateService; import org.jclouds.aws.s3.util.DateService;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.UnsupportedEncodingException;
/** /**
* Tests possible uses of GetObjectOptions and GetObjectOptions.Builder.* * Tests possible uses of GetObjectOptions and GetObjectOptions.Builder.*
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "s3.GetObjectOptionsTest")
public class GetObjectOptionsTest { public class GetObjectOptionsTest {
private byte[] testBytes; private byte[] testBytes;
@ -56,7 +50,7 @@ public class GetObjectOptionsTest {
void setUp() { void setUp() {
now = new DateTime(); now = new DateTime();
nowExpected = new DateService().toHeaderString(now); nowExpected = new DateService().toHeaderString(now);
testBytes = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; testBytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
} }
@Test @Test
@ -115,7 +109,7 @@ public class GetObjectOptionsTest {
GetObjectOptions options = new GetObjectOptions(); GetObjectOptions options = new GetObjectOptions();
options.ifModifiedSince(now); options.ifModifiedSince(now);
options.range(0, 1024); options.range(0, 1024);
isNowExpected(options); assertEquals(options.getIfModifiedSince(), nowExpected);
bytes1to1024(options); bytes1to1024(options);
} }

View File

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

View File

@ -23,26 +23,24 @@
*/ */
package org.jclouds.aws.s3.commands.options; package org.jclouds.aws.s3.commands.options;
import com.google.common.collect.Multimap;
import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.createIn; import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.createIn;
import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl; import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.io.UnsupportedEncodingException;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.UnsupportedEncodingException;
import com.google.common.collect.Multimap;
/** /**
* Tests possible uses of PutBucketOptions and PutBucketOptions.Builder.* * Tests possible uses of PutBucketOptions and PutBucketOptions.Builder.*
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "s3.PutBucketOptionsTest")
public class PutBucketOptionsTest { public class PutBucketOptionsTest {
@Test @Test

View File

@ -23,23 +23,21 @@
*/ */
package org.jclouds.aws.s3.commands.options; package org.jclouds.aws.s3.commands.options;
import com.google.common.collect.Multimap;
import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.withAcl; import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.withAcl;
import static org.testng.Assert.assertEquals;
import java.io.UnsupportedEncodingException;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.UnsupportedEncodingException;
import com.google.common.collect.Multimap;
/** /**
* Tests possible uses of PutObjectOptions and PutObjectOptions.Builder.* * Tests possible uses of PutObjectOptions and PutObjectOptions.Builder.*
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "s3.PutObjectOptionsTest")
public class PutObjectOptionsTest { public class PutObjectOptionsTest {
@Test @Test

View File

@ -23,8 +23,10 @@
*/ */
package org.jclouds.aws.s3.config; package org.jclouds.aws.s3.config;
import static org.testng.Assert.assertEquals; import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Names;
import org.jclouds.aws.s3.handlers.ParseS3ErrorFromXmlContent; import org.jclouds.aws.s3.handlers.ParseS3ErrorFromXmlContent;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.http.HttpResponseHandler; import org.jclouds.http.HttpResponseHandler;
@ -33,28 +35,22 @@ import org.jclouds.http.annotation.RedirectHandler;
import org.jclouds.http.annotation.ServerErrorHandler; import org.jclouds.http.annotation.ServerErrorHandler;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule; import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler; import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Names;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test @Test(groups = "unit", testName = "s3.S3ContextModuleTest")
public class S3ContextModuleTest { public class S3ContextModuleTest {
Injector injector = null; Injector injector = null;
@BeforeMethod @BeforeMethod
void setUpInjector() { void setUpInjector() {
injector = Guice.createInjector(new S3ContextModule() { injector = Guice.createInjector(new LiveS3ConnectionModule(), new S3ContextModule() {
@Override @Override
protected void configure() { protected void configure() {
bindConstant().annotatedWith( bindConstant().annotatedWith(

View File

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

View File

@ -23,15 +23,13 @@
*/ */
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
import java.io.File;
import static org.testng.Assert.*;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.http.ContentTypes; import org.jclouds.http.ContentTypes;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@Test import java.io.File;
@Test(groups = "unit", testName = "s3.S3ObjectTest")
public class S3ObjectTest { public class S3ObjectTest {
@Test @Test

View File

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

View File

@ -23,13 +23,12 @@
*/ */
package org.jclouds.aws.s3.xml; package org.jclouds.aws.s3.xml;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.jclouds.aws.s3.xml.config.S3ParserModule; import org.jclouds.aws.s3.xml.config.S3ParserModule;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class BaseHandlerTest { public class BaseHandlerTest {
protected S3ParserFactory parserFactory = null; protected S3ParserFactory parserFactory = null;

View File

@ -23,15 +23,14 @@
*/ */
package org.jclouds.aws.s3.xml; package org.jclouds.aws.s3.xml;
import static org.testng.Assert.assertEquals;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.domain.S3Error; import org.jclouds.aws.s3.domain.S3Error;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.commands.callables.xml.ParseSax; import org.jclouds.http.commands.callables.xml.ParseSax;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@Test @Test(groups = "unit", testName = "s3.ErrorHandlerTest")
public class ErrorHandlerTest extends BaseHandlerTest { public class ErrorHandlerTest extends BaseHandlerTest {
public static final String errorFromAmazonIfYouDontRemoveTransferEncodingHeader = "<Error><Code>NotImplemented</Code><Message>A header you provided implies functionality that is not implemented</Message><Header>Transfer-Encoding</Header><RequestId>7C59925D75D15561</RequestId><HostId>fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb</HostId></Error>"; public static final String errorFromAmazonIfYouDontRemoveTransferEncodingHeader = "<Error><Code>NotImplemented</Code><Message>A header you provided implies functionality that is not implemented</Message><Header>Transfer-Encoding</Header><RequestId>7C59925D75D15561</RequestId><HostId>fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb</HostId></Error>";
@ -53,7 +52,7 @@ public class ErrorHandlerTest extends BaseHandlerTest {
public static final String badRequestWhenSourceIsDestBucketOnCopy400 = "<Error><Code>InvalidRequest</Code><Message>The Source and Destination may not be the same when the MetadataDirective is Copy.</Message><RequestId>54C77CAF4D42474B</RequestId><HostId>SJecknEUUUx88/65VAKbCdKSOCkpuVTeu7ZG9in9x9NTNglGnoxdbALCfS4k/DUZ</HostId></Error>"; public static final String badRequestWhenSourceIsDestBucketOnCopy400 = "<Error><Code>InvalidRequest</Code><Message>The Source and Destination may not be the same when the MetadataDirective is Copy.</Message><RequestId>54C77CAF4D42474B</RequestId><HostId>SJecknEUUUx88/65VAKbCdKSOCkpuVTeu7ZG9in9x9NTNglGnoxdbALCfS4k/DUZ</HostId></Error>";
public static final String noSuchSourceKeyOrBucketOnCopy404 = "<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>null</Key><RequestId>9CCDF1DACA78B36F</RequestId><HostId>63cqk9YsTFBVfBfks840JVGsepPEdQM42mU+r7HN35sF4Nk5xAcWDEUPaQpK2eFU</HostId></Error>"; public static final String noSuchSourceKeyOrBucketOnCopy404 = "<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>null</Key><RequestId>9CCDF1DACA78B36F</RequestId><HostId>63cqk9YsTFBVfBfks840JVGsepPEdQM42mU+r7HN35sF4Nk5xAcWDEUPaQpK2eFU</HostId></Error>";
public static final String noSuchDestinationBucketOnCopy404 = "<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>copydestination</BucketName><RequestId>4F0CF319C5535975</RequestId><HostId>hdZyHOm7VK+JI2UCdye3d6TVkKhRBIoWflldXVDTKbgipYlamy8HgPBzHrUAVQNJ</HostId></Error>"; public static final String noSuchDestinationBucketOnCopy404 = "<Error><Code>NoSuchBucket</Code><Message>The specified bucketName does not exist</Message><BucketName>copydestination</BucketName><RequestId>4F0CF319C5535975</RequestId><HostId>hdZyHOm7VK+JI2UCdye3d6TVkKhRBIoWflldXVDTKbgipYlamy8HgPBzHrUAVQNJ</HostId></Error>";
public static final String badSign403 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" public static final String badSign403 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<Error><Code>SignatureDoesNotMatch</Code><Message>The operation signature we calculated does not match the signature you provided. Check your key and signing method.</Message><StringToSignBytes>47 45 54 0a 0a 0a 54 68 75 2c 20 31 39 20 4d 61 72 20 32 30 30 39 20 31 37 3a 34 38 3a 30 31 20 47 4d 54 0a 2f 61 64 72 69 61 6e 63 6f 6c 65 2e 73 33 2e 61 6d 61 7a 6f 6e 73 33 74 65 73 74 2e 66 69 6c 65 74 65 73 74 73 66 6f 72 61 64 72 69 61 6e 2f 66 69 6c 65</StringToSignBytes><RequestId>514AA22EB75A6E42</RequestId><HostId>H5nqnZkGjuKvB+seutvx5hnp1P+WAuC9c3Y7MdQCcYDr1TGwNX/mt+FHstK0pVld</HostId><SignatureProvided>Qm6Wss7e5e/eNXV50AxChH+xkLI=</SignatureProvided><StringToSign>GET\n" + "<Error><Code>SignatureDoesNotMatch</Code><Message>The operation signature we calculated does not match the signature you provided. Check your key and signing method.</Message><StringToSignBytes>47 45 54 0a 0a 0a 54 68 75 2c 20 31 39 20 4d 61 72 20 32 30 30 39 20 31 37 3a 34 38 3a 30 31 20 47 4d 54 0a 2f 61 64 72 69 61 6e 63 6f 6c 65 2e 73 33 2e 61 6d 61 7a 6f 6e 73 33 74 65 73 74 2e 66 69 6c 65 74 65 73 74 73 66 6f 72 61 64 72 69 61 6e 2f 66 69 6c 65</StringToSignBytes><RequestId>514AA22EB75A6E42</RequestId><HostId>H5nqnZkGjuKvB+seutvx5hnp1P+WAuC9c3Y7MdQCcYDr1TGwNX/mt+FHstK0pVld</HostId><SignatureProvided>Qm6Wss7e5e/eNXV50AxChH+xkLI=</SignatureProvided><StringToSign>GET\n"
+ "\n" + "\n"

View File

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

View File

@ -23,19 +23,17 @@
*/ */
package org.jclouds.aws.s3.xml; package org.jclouds.aws.s3.xml;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.jclouds.aws.s3.xml.config.S3ParserModule; import org.jclouds.aws.s3.xml.config.S3ParserModule;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test @Test(groups = "unit", testName = "s3.S3ParserFactoryTest")
public class S3ParserFactoryTest { public class S3ParserFactoryTest {
Injector injector = null; Injector injector = null;