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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -25,12 +25,11 @@ package org.jclouds.aws.s3.commands.options;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import org.jclouds.http.options.BaseHttpRequestOptions;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Contains options supported in the REST API for the GET bucket operation. <h2>
* Usage</h2> The recommended way to instantiate a GetBucketOptions object is to
@ -39,17 +38,14 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
* <p/>
* <code>
* import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.*
*
* <p/>
* S3Connection connection = // get connection
* Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
* <code>
*
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html?"
* />
*
* @author Adrian Cole
*
*
*/
public class ListBucketOptions extends BaseHttpRequestOptions {
public static final ListBucketOptions NONE = new ListBucketOptions();
@ -122,7 +118,7 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
*
* @throws UnsupportedEncodingException
*/
public ListBucketOptions setDelimiter(String delimiter)
public ListBucketOptions delimiter(String delimiter)
throws UnsupportedEncodingException {
options.put("delimiter", URLEncoder.encode(checkNotNull(delimiter,
"delimiter"), "UTF-8"));
@ -130,7 +126,7 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
}
/**
* @see ListBucketOptions#setDelimiter(String)
* @see ListBucketOptions#delimiter(String)
*/
public String getDelimiter() {
return options.get("delimiter");
@ -173,7 +169,7 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
public static ListBucketOptions delimiter(String delimiter)
throws UnsupportedEncodingException {
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;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.http.options.BaseHttpRequestOptions;
import static com.google.common.base.Preconditions.*;
/**
* Contains options supported in the REST API for the PUT bucket operation. <h2>
* Usage</h2> The recommended way to instantiate a PutBucketOptions object is to
@ -40,16 +39,14 @@ import static com.google.common.base.Preconditions.*;
* import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.*
* import static org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint.*;
* import org.jclouds.aws.s3.S3Connection;
*
* <p/>
* S3Connection connection = // get connection
* Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
* <code>
*
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT.html?"
* />
*
* @author Adrian Cole
*
*/
public class PutBucketOptions extends BaseHttpRequestOptions {
public static final PutBucketOptions NONE = new PutBucketOptions();
@ -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() {
return constraint;
@ -98,7 +95,7 @@ public class PutBucketOptions extends BaseHttpRequestOptions {
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) {
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;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import com.google.inject.AbstractModule;
import com.google.inject.assistedinject.FactoryProvider;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.commands.config.S3CommandsModule;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.handlers.ParseS3ErrorFromXmlContent;
import org.jclouds.aws.s3.internal.GuiceS3Context;
import org.jclouds.aws.s3.internal.LiveS3Connection;
import org.jclouds.aws.s3.internal.LiveS3InputStreamMap;
import org.jclouds.aws.s3.internal.LiveS3ObjectMap;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponseHandler;
import org.jclouds.http.annotation.ClientErrorHandler;
import org.jclouds.http.annotation.RedirectHandler;
import org.jclouds.http.annotation.ServerErrorHandler;
import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import org.jclouds.logging.Logger;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.FactoryProvider;
import com.google.inject.name.Named;
/**
* Configures the S3 connection, including logging and http transport.
* Configures the {@link S3Context}; requires {@link S3Connection} bound.
*
* @author Adrian Cole
*/
public class S3ContextModule extends AbstractModule {
@Resource
protected Logger logger = Logger.NULL;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_ADDRESS)
String address;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_PORT)
int port;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_SECURE)
boolean isSecure;
@Override
protected void configure() {
this.requireBinding(S3Connection.class);
install(new S3CommandsModule());
bind(S3Connection.class).to(LiveS3Connection.class)
.in(Scopes.SINGLETON);
bind(GuiceS3Context.S3ObjectMapFactory.class).toProvider(
FactoryProvider.newFactory(
GuiceS3Context.S3ObjectMapFactory.class,
@ -87,25 +53,7 @@ public class S3ContextModule extends AbstractModule {
GuiceS3Context.S3InputStreamMapFactory.class,
LiveS3InputStreamMap.class));
bind(S3Context.class).to(GuiceS3Context.class);
bind(HttpResponseHandler.class).annotatedWith(RedirectHandler.class)
.to(CloseContentAndSetExceptionHandler.class).in(
Scopes.SINGLETON);
bind(HttpResponseHandler.class).annotatedWith(ClientErrorHandler.class)
.to(ParseS3ErrorFromXmlContent.class).in(Scopes.SINGLETON);
bind(HttpResponseHandler.class).annotatedWith(ServerErrorHandler.class)
.to(ParseS3ErrorFromXmlContent.class).in(Scopes.SINGLETON);
requestInjection(this);
logger.info("S3 Context = %1$s://%2$s:%3$s", (isSecure ? "https"
: "http"), address, port);
}
@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;
import static com.google.common.base.Preconditions.checkNotNull;
import org.joda.time.DateTime;
import java.util.HashSet;
import java.util.Set;
import org.joda.time.DateTime;
/**
* A container that provides namespace, access control and aggregation of
* {@link S3Object}s
*
* <p/>
* <p/>
* Every object stored in Amazon S3 is contained in a bucket. Buckets partition
* the namespace of objects stored in Amazon S3 at the top level. Within a
* bucket, you can use any names for your objects, but bucket names must be
* unique across all of Amazon S3.
*
* <p/>
* Buckets are similar to Internet domain names. Just as Amazon is the only
* owner of the domain name Amazon.com, only one person or organization can own
* a bucket within Amazon S3. Once you create a uniquely named bucket in Amazon
* S3, you can organize and name the objects within the bucket in any way you
* like and the bucket will remain yours for as long as you like and as long as
* you have the Amazon S3 account.
*
* <p/>
* The similarities between buckets and domain names is not a coincidenceÑthere
* is a direct mapping between Amazon S3 buckets and subdomains of
* s3.amazonaws.com. Objects stored in Amazon S3 are addressable using the REST
@ -65,7 +64,7 @@ public class S3Bucket {
final StringBuilder sb = new StringBuilder();
sb.append("S3Bucket");
sb.append("{metadata=").append(metadata);
sb.append(", isComplete=").append(isComplete);
sb.append(", isTruncated=").append(isTruncated);
sb.append('}');
return sb.toString();
}
@ -79,7 +78,7 @@ public class S3Bucket {
S3Bucket s3Bucket = (S3Bucket) o;
if (isComplete != s3Bucket.isComplete)
if (isTruncated != s3Bucket.isTruncated)
return false;
if (!metadata.equals(s3Bucket.metadata))
return false;
@ -94,7 +93,7 @@ public class S3Bucket {
public int hashCode() {
int result = objects != null ? objects.hashCode() : 0;
result = 31 * result + metadata.hashCode();
result = 31 * result + (isComplete ? 1 : 0);
result = 31 * result + (isTruncated ? 1 : 0);
return result;
}
@ -102,7 +101,6 @@ public class S3Bucket {
* System metadata of the S3Bucket
*
* @author Adrian Cole
*
*/
public static class Metadata {
@Override
@ -145,11 +143,10 @@ public class S3Bucket {
/**
* Location constraint of the bucket.
*
* @author Adrian Cole
* @see <a href=
* "http://docs.amazonwebservices.com/AmazonS3/latest/RESTBucketLocationGET.html"
* />
* @author Adrian Cole
*
*/
public static enum LocationConstraint {
EU
@ -168,16 +165,15 @@ public class S3Bucket {
/**
* To comply with Amazon S3 requirements, bucket names must:
*
* <p/>
* Contain lowercase letters, numbers, periods (.), underscores (_), and
* dashes (-)
*
* <p/>
* Start with a number or letter
*
* <p/>
* Be between 3 and 255 characters long
*
* <p/>
* Not be in an IP address style (e.g., "192.168.5.4")
*
*/
public String getName() {
return name;
@ -217,7 +213,7 @@ public class S3Bucket {
private long maxKeys;
private final Metadata metadata;
private boolean isComplete;
private boolean isTruncated;
public S3Bucket(String name) {
this.metadata = new Metadata(name);
@ -245,12 +241,12 @@ public class S3Bucket {
/**
* @return true, if the list contains all objects.
*/
public boolean isComplete() {
return isComplete;
public boolean isTruncated() {
return isTruncated;
}
public void setComplete(boolean complete) {
isComplete = complete;
public void setTruncated(boolean truncated) {
isTruncated = truncated;
}
public Metadata getMetadata() {
@ -263,14 +259,14 @@ public class S3Bucket {
/**
* Example:
* <p />
* <p/>
* if the following keys are in the bucket
*
* <p/>
* a/1/a<br/>
* a/1/b<br/>
* a/2/a<br/>
* a/2/b<br/>
* <p />
* <p/>
* and prefix is set to <code>a/</code> and delimiter is set to
* <code>/</code> then commonprefixes would return 1,2
*

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -22,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"/>
* @author Adrian Cole

View File

@ -25,17 +25,6 @@ package org.jclouds.aws.s3.util;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.bouncycastle.crypto.digests.MD5Digest;
@ -46,12 +35,17 @@ import org.bouncycastle.util.encoders.Base64;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.util.Utils;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.regex.Pattern;
/**
* Encryption, Hashing, and IO Utilities needed to sign and verify S3 requests
* and responses.
*
* @author Adrian Cole
*
*/
public class S3Utils extends Utils {
@ -62,21 +56,21 @@ public class S3Utils extends Utils {
public static String validateBucketName(String bucketName) {
checkNotNull(bucketName, "bucketName");
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(
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,
"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(),
"bucket name cannot be ip address style");
"bucketName name cannot be ip address style");
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) '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)
throws UnsupportedEncodingException {
@ -104,13 +98,13 @@ public class S3Utils extends Utils {
}
/**
*
* @throws IOException
*/
public static byte[] md5(Object data) throws IOException {
checkNotNull(data, "data must be set before calling generateMd5()");
byte[] md5 = null;
if (data == null || data instanceof byte[]) {
if (data == null) {
} else if (data instanceof byte[]) {
md5 = S3Utils.md5((byte[]) data);
} else if (data instanceof String) {
md5 = S3Utils.md5(((String) data).getBytes());
@ -210,6 +204,7 @@ public class S3Utils extends Utils {
}
} while (numRead != -1);
} finally {
out.close();
IOUtils.closeQuietly(toEncode);
}
md5.doFinal(resBuf, 0);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,27 +23,26 @@
*/
package org.jclouds.aws.s3;
import static org.testng.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import org.jclouds.aws.s3.config.LiveS3ConnectionModule;
import org.jclouds.http.config.HttpFutureCommandClientModule;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import java.util.ArrayList;
import java.util.List;
/**
* Tests behavior of modules configured in S3ContextFactory
*
* @author Adrian Cole
*
*/
@Test(groups = "unit", testName = "s3.S3ContextFactoryTest")
public class S3ContextFactoryTest {
@HttpFutureCommandClientModule
@ -60,7 +59,7 @@ public class S3ContextFactoryTest {
List<Module> modules = new ArrayList<Module>();
HttpModule module = new HttpModule();
modules.add(module);
S3ContextFactory.addHttpModuleIfNotPresent(modules);
S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.remove(0), module);
}
@ -82,7 +81,7 @@ public class S3ContextFactoryTest {
modules.add(loggingModule);
HttpModule httpModule = new HttpModule();
modules.add(httpModule);
S3ContextFactory.addHttpModuleIfNotPresent(modules);
S3ContextFactory.addHttpModuleIfNeededAndNotPresent(modules);
S3ContextFactory.addLoggingModuleIfNotPresent(modules);
assertEquals(modules.size(), 2);
assertEquals(modules.remove(0), loggingModule);
@ -90,11 +89,22 @@ public class S3ContextFactoryTest {
}
@Test
public void testAddBoth() {
public void testAddBothWhenNotLive() {
List<Module> modules = new ArrayList<Module>();
S3ContextFactory.addHttpModuleIfNotPresent(modules);
S3ContextFactory.addHttpModuleIfNeededAndNotPresent(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 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;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import com.google.inject.Module;
import org.jclouds.aws.s3.config.StubS3ConnectionModule;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
import org.testng.ITestContext;
import org.testng.annotations.*;
import com.google.inject.Module;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.*;
import java.util.logging.Formatter;
@Test
public class S3IntegrationTest {
protected static final String TEST_STRING = "<apples><apple name=\"fuji\"></apple> </apples>";
protected byte[] goodMd5;
protected byte[] badMd5;
protected String bucketName;
protected void createBucketAndEnsureEmpty(String sourceBucket)
throws InterruptedException, ExecutionException, TimeoutException {
@ -84,7 +69,6 @@ public class S3IntegrationTest {
protected void addObjectToBucket(String sourceBucket, S3Object object)
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
;
client.putObject(sourceBucket, object).get(10, TimeUnit.SECONDS);
}
@ -100,7 +84,7 @@ public class S3IntegrationTest {
return newObject;
}
@BeforeTest
@BeforeClass(groups = {"integration", "live"})
void enableDebug() {
if (debugEnabled()) {
Handler HANDLER = new ConsoleHandler() {
@ -139,29 +123,57 @@ public class S3IntegrationTest {
private static final String sysAWSSecretAccessKey = System
.getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
@BeforeTest
@Parameters( { S3Constants.PROPERTY_AWS_ACCESSKEYID,
S3Constants.PROPERTY_AWS_SECRETACCESSKEY })
protected void setUpClient(@Optional String AWSAccessKeyId,
@Optional String AWSSecretAccessKey) throws Exception {
context = createS3Context(AWSAccessKeyId != null ? AWSAccessKeyId
: sysAWSAccessKeyId,
AWSSecretAccessKey != null ? AWSSecretAccessKey
: sysAWSSecretAccessKey);
@BeforeClass(inheritGroups = false, groups = {"integration", "live"})
@Parameters({S3Constants.PROPERTY_AWS_ACCESSKEYID,
S3Constants.PROPERTY_AWS_SECRETACCESSKEY})
protected void setUpCredentials(@Optional String AWSAccessKeyId,
@Optional String AWSSecretAccessKey, ITestContext testContext) throws Exception {
AWSAccessKeyId = AWSAccessKeyId != null ? AWSAccessKeyId
: sysAWSAccessKeyId;
AWSSecretAccessKey = AWSSecretAccessKey != null ? AWSSecretAccessKey
: sysAWSSecretAccessKey;
if (AWSAccessKeyId != null)
testContext.setAttribute(S3Constants.PROPERTY_AWS_ACCESSKEYID, AWSAccessKeyId);
if (AWSSecretAccessKey != null)
testContext.setAttribute(S3Constants.PROPERTY_AWS_SECRETACCESSKEY, AWSSecretAccessKey);
}
@BeforeClass(dependsOnMethods = {"setUpCredentials"}, groups = {"integration", "live"})
protected void setUpClient(ITestContext testContext) throws Exception {
if (testContext.getAttribute(S3Constants.PROPERTY_AWS_ACCESSKEYID) != null) {
String AWSAccessKeyId = (String) testContext.getAttribute(S3Constants.PROPERTY_AWS_ACCESSKEYID);
String AWSSecretAccessKey = (String) testContext.getAttribute(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
context = S3ContextFactory.createS3Context(buildS3Properties(
checkNotNull(AWSAccessKeyId, "AWSAccessKeyId"),
checkNotNull(AWSSecretAccessKey, "AWSSecretAccessKey")),
createHttpModule());
} else {
Properties props = new Properties();
props.setProperty(S3Constants.PROPERTY_HTTP_ADDRESS, "stub");
context = S3ContextFactory.createS3Context(props, new StubS3ConnectionModule());
}
client = context.getConnection();
assert client != null;
deleteEverything();
goodMd5 = S3Utils.md5(TEST_STRING);
badMd5 = S3Utils.md5("alf");
}
protected boolean debugEnabled() {
return false;
@BeforeMethod(dependsOnMethods = "deleteBucket", groups = {"integration", "live"})
public void setUpBucket(Method method) throws TimeoutException, ExecutionException, InterruptedException {
bucketName = (bucketPrefix + method.getName()).toLowerCase();
createBucketAndEnsureEmpty(bucketName);
}
protected S3Context createS3Context(String AWSAccessKeyId,
String AWSSecretAccessKey) {
return S3ContextFactory.createS3Context(buildS3Properties(
AWSAccessKeyId, AWSSecretAccessKey), createHttpModule());
@BeforeMethod(groups = {"integration", "live"})
@AfterMethod(groups = {"integration", "live"})
public void deleteBucket() throws TimeoutException, ExecutionException, InterruptedException {
if (bucketName != null)
deleteBucket(bucketName);
}
protected boolean debugEnabled() {
return false;
}
protected Properties buildS3Properties(String AWSAccessKeyId,
@ -185,22 +197,9 @@ public class S3IntegrationTest {
try {
List<S3Bucket.Metadata> metadata = client.listOwnedBuckets().get(
10, TimeUnit.SECONDS);
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
for (S3Bucket.Metadata metaDatum : metadata) {
if (metaDatum.getName().startsWith(bucketPrefix.toLowerCase())) {
S3Bucket bucket = client.listBucket(metaDatum.getName())
.get(10, TimeUnit.SECONDS);
for (S3Object.Metadata objectMeta : bucket.getContents()) {
results.add(client.deleteObject(metaDatum.getName(),
objectMeta.getKey()));
}
Iterator<Future<Boolean>> iterator = results.iterator();
while (iterator.hasNext()) {
iterator.next().get(10, TimeUnit.SECONDS);
iterator.remove();
}
client.deleteBucketIfEmpty(metaDatum.getName()).get(10,
TimeUnit.SECONDS);
deleteBucket(metaDatum.getName());
}
}
@ -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 {
deleteEverything();
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.jclouds.aws.PerformanceTest;
import org.jclouds.aws.s3.util.S3Utils;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@ -38,14 +39,12 @@ import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import static org.testng.Assert.*;
/**
* This tests the performance of Digest commands.
*
* @author Adrian Cole
*/
@Test(groups = "unit", sequential = true, testName = "s3.PerformanceTest")
@Test(groups = "performance", sequential = true, testName = "s3.PerformanceTest")
public class S3UtilsTest extends PerformanceTest {
@Test(dataProvider = "hmacsha1")
@ -78,30 +77,31 @@ public class S3UtilsTest extends PerformanceTest {
public Object[][] createMD5Data() {
return base64MD5MessageDigest;
}
public final static Object[][] base64MD5MessageDigest = {
{ "apple", "1f3870be274f6c49b3e31a0c6728957f" },
{ "bear", "893b56e3cfe153fb770a120b83bac20c" },
{ "candy", "c48ba993d35c3abe0380f91738fe2a34" },
{ "dogma", "95eb470e4faee302e9cd3063b1923dab" },
{ "emma", "00a809937eddc44521da9521269e75c6" } };
{"apple", "1f3870be274f6c49b3e31a0c6728957f"},
{"bear", "893b56e3cfe153fb770a120b83bac20c"},
{"candy", "c48ba993d35c3abe0380f91738fe2a34"},
{"dogma", "95eb470e4faee302e9cd3063b1923dab"},
{"emma", "00a809937eddc44521da9521269e75c6"}};
public final static Object[][] base64KeyMessageDigest = {
{ Base64.decode("CwsLCwsLCwsLCwsLCwsLCwsLCws="), "Hi There",
"thcxhlUFcmTii8C2+zeMjvFGvgA=" },
{ Base64.decode("SmVmZQ=="), "what do ya want for nothing?",
"7/zfauXrL6LSdBbV8YTfnCWafHk=" },
{ Base64.decode("DAwMDAwMDAwMDAwMDAwMDAwMDAw="),
"Test With Truncation", "TBoDQktV4H/n8nvh1Yu5MkqaWgQ=" },
{Base64.decode("CwsLCwsLCwsLCwsLCwsLCwsLCws="), "Hi There",
"thcxhlUFcmTii8C2+zeMjvFGvgA="},
{Base64.decode("SmVmZQ=="), "what do ya want for nothing?",
"7/zfauXrL6LSdBbV8YTfnCWafHk="},
{Base64.decode("DAwMDAwMDAwMDAwMDAwMDAwMDAw="),
"Test With Truncation", "TBoDQktV4H/n8nvh1Yu5MkqaWgQ="},
{
Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key - Hash Key First",
"qkrl4VJy0A6VcFY3zoo7Ve1AIRI=" },
"qkrl4VJy0A6VcFY3zoo7Ve1AIRI="},
{
Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
"6OmdD0UjfXhta7qnllx4CLv/GpE=" } };
"6OmdD0UjfXhta7qnllx4CLv/GpE="}};
@DataProvider(name = "hmacsha1")
public Object[][] createData1() {
@ -121,7 +121,7 @@ public class S3UtilsTest extends PerformanceTest {
String base64Digest) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
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;
/**
* This performs the same test as {@link S3ConnectionTest}, except using SSL.
* This performs the same test as {@link S3ConnectionIntegrationTest}, except using SSL.
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "s3.SecureS3ConnectionTest")
public class SecureS3ConnectionTest extends S3ConnectionTest {
@Test(groups = {"live"}, testName = "s3.SecureS3ConnectionIntegrationTest")
public class SecureS3ConnectionIntegrationTest extends S3ConnectionIntegrationTest {
@Override
protected Properties buildS3Properties(String AWSAccessKeyId,
String AWSSecretAccessKey) {

View File

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

View File

@ -23,10 +23,11 @@
*/
package org.jclouds.aws.s3.commands;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import java.util.concurrent.TimeUnit;
/**
* Tests integrated functionality of all bucketExists commands.
@ -35,20 +36,19 @@ import org.testng.annotations.Test;
* in parallel.
*
* @author Adrian Cole
*
*/
@Test(groups = "integration", testName = "s3.BucketExistsIntegrationTest")
@Test(groups = {"integration", "live"}, testName = "s3.BucketExistsIntegrationTest")
public class BucketExistsIntegrationTest extends S3IntegrationTest {
@Test()
@Test
void bucketDoesntExist() throws Exception {
String bucketName = bucketPrefix + "shouldntexist";
String bucketName= bucketPrefix+"be";
assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
}
@Test()
@Test
void bucketExists() throws Exception {
String bucketName = bucketPrefix + "needstoexist";
String bucketName= bucketPrefix+"bde";
assert client.putBucketIfNotExists(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;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5DoesntMatch;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5Matches;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceModifiedSince;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceUnmodifiedSince;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideAcl;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideMetadataWith;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.*;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpResponseException;
import org.joda.time.DateTime;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Tests integrated functionality of all copyObject commands.
@ -57,79 +49,53 @@ import com.google.common.collect.Multimap;
* in parallel.
*
* @author Adrian Cole
*
*/
@Test(groups = "integration", testName = "s3.CopyObjectIntegrationTest")
@Test(testName = "s3.CopyObjectIntegrationTest")
public class CopyObjectIntegrationTest extends S3IntegrationTest {
String sourceKey = "apples";
String destinationKey = "pears";
@Test()
void testCannedAccessPolicyPublic() throws Exception {
String sourceBucket = bucketPrefix + "tcapp";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey);
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
destinationKey,overrideAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com/%2$s",
destinationBucket, destinationKey));
S3Utils.toStringAndClose(url.openStream());
}
@Test()
@Test(groups = {"integration","live"})
void testCopyObject() throws Exception {
String sourceBucket = bucketPrefix + "testcopyobject";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey);
String destinationBucket = bucketName + "dest";
addToBucketAndValidate(bucketName, sourceKey);
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey).get(10, TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
}
private void setupSourceBucket(String sourceBucket, String sourceKey)
private void addToBucketAndValidate(String bucketName, String sourceKey)
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
createBucketAndEnsureEmpty(sourceBucket);
addToBucketAndValidate(sourceBucket, sourceKey);
addObjectToBucket(bucketName, sourceKey);
validateContent(bucketName, sourceKey);
}
private void addToBucketAndValidate(String sourceBucket, String sourceKey)
throws InterruptedException, ExecutionException, TimeoutException,
IOException {
addObjectToBucket(sourceBucket, sourceKey);
validateContent(sourceBucket, sourceKey);
}
@Test
@Test(groups = {"integration","live"})
void testCopyIfModifiedSince() throws InterruptedException,
ExecutionException, TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcims";
String destinationBucket = sourceBucket + "dest";
String destinationBucket = bucketName + "dest";
DateTime before = new DateTime();
setupSourceBucket(sourceBucket, sourceKey);
addToBucketAndValidate(bucketName, sourceKey);
DateTime after = new DateTime().plusSeconds(1);
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(before)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
try {
client.copyObject(sourceBucket, sourceKey, destinationBucket,
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(after)).get(10,
TimeUnit.SECONDS);
} catch (ExecutionException e) {
@ -138,24 +104,24 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
}
}
@Test
@Test(groups = {"integration","live"})
void testCopyIfUnmodifiedSince() throws InterruptedException,
ExecutionException, TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcius";
String destinationBucket = sourceBucket + "dest";
String destinationBucket = bucketName + "dest";
DateTime before = new DateTime();
setupSourceBucket(sourceBucket, sourceKey);
addToBucketAndValidate(bucketName, sourceKey);
DateTime after = new DateTime().plusSeconds(1);
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceUnmodifiedSince(after)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
try {
client.copyObject(sourceBucket, sourceKey, destinationBucket,
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceModifiedSince(before)).get(10,
TimeUnit.SECONDS);
} catch (ExecutionException e) {
@ -164,23 +130,23 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
}
}
@Test
@Test(groups = {"integration","live"})
void testCopyIfMatch() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
String sourceBucket = bucketPrefix + "tcim";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey);
String destinationBucket = bucketName + "dest";
addToBucketAndValidate(bucketName, sourceKey);
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5Matches(goodMd5)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
try {
client.copyObject(sourceBucket, sourceKey, destinationBucket,
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5Matches(badMd5)).get(10,
TimeUnit.SECONDS);
} catch (ExecutionException e) {
@ -189,23 +155,23 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
}
}
@Test
@Test(groups = {"integration","live"})
void testCopyIfNoneMatch() throws IOException, InterruptedException,
ExecutionException, TimeoutException {
String sourceBucket = bucketPrefix + "tcinm";
String destinationBucket = sourceBucket + "dest";
setupSourceBucket(sourceBucket, sourceKey);
String destinationBucket = bucketName + "dest";
addToBucketAndValidate(bucketName, sourceKey);
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5DoesntMatch(badMd5)).get(10,
TimeUnit.SECONDS);
validateContent(destinationBucket, destinationKey);
try {
client.copyObject(sourceBucket, sourceKey, destinationBucket,
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, ifSourceMd5DoesntMatch(goodMd5)).get(10,
TimeUnit.SECONDS);
} catch (ExecutionException e) {
@ -214,19 +180,19 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
}
}
@Test
@Test(groups = {"integration","live"})
void testCopyWithMetadata() throws InterruptedException,
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();
metadata.put(S3Headers.USER_METADATA_PREFIX + "adrian", "cole");
createBucketAndEnsureEmpty(destinationBucket);
client.copyObject(sourceBucket, sourceKey, destinationBucket,
client.copyObject(bucketName, sourceKey, destinationBucket,
destinationKey, overrideMetadataWith(metadata)).get(10,
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;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.testng.annotations.Test;
import java.util.concurrent.TimeUnit;
/**
* Tests integrated functionality of all deleteBucket commands.
* <p/>
@ -35,12 +35,14 @@ import org.testng.annotations.Test;
* in parallel.
*
* @author Adrian Cole
*
*/
@Test(groups = "integration", testName = "s3.DeleteBucketIntegrationTest")
@Test(groups = {"integration", "live"}, testName = "s3.DeleteBucketIntegrationTest")
public class DeleteBucketIntegrationTest extends S3IntegrationTest {
@Test()
@Test
/**
* this method overrides bucketName to ensure it isn't found
*/
void deleteBucketIfEmptyNotFound() throws Exception {
String bucketName = bucketPrefix + "dbienf";
assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
@ -48,16 +50,12 @@ public class DeleteBucketIntegrationTest extends S3IntegrationTest {
@Test()
void deleteBucketIfEmptyButHasContents() throws Exception {
String bucketName = bucketPrefix + "dbiebhc";
createBucketAndEnsureEmpty(bucketName);
addObjectToBucket(bucketName,"test");
addObjectToBucket(bucketName, "test");
assert !client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
}
@Test()
void deleteBucketIfEmpty() throws Exception {
String bucketName = bucketPrefix + "dbie";
createBucketAndEnsureEmpty(bucketName);
assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,9 +23,18 @@
*/
package org.jclouds.aws.s3.commands;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl;
import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.withAcl;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.S3Utils;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.File;
import java.io.FileInputStream;
@ -34,16 +43,6 @@ import java.io.InputStream;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.S3IntegrationTest;
import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.*;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.S3Utils;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
* Tests integrated functionality of all PutObject commands.
@ -52,23 +51,22 @@ import org.testng.annotations.Test;
* in parallel.
*
* @author Adrian Cole
*
*/
@Test(groups = "integration", testName = "s3.PutObjectIntegrationTest")
@Test(testName = "s3.PutObjectIntegrationTest")
public class PutObjectIntegrationTest extends S3IntegrationTest {
@DataProvider(name = "putTests")
public Object[][] createData1() throws IOException {
String realObject = IOUtils.toString(new FileInputStream("pom.xml"));
return new Object[][] {
{ "file", "text/xml", new File("pom.xml"), realObject },
{ "string", "text/xml", realObject, realObject },
{ "bytes", "application/octet-stream", realObject.getBytes(),
realObject } };
return new Object[][]{
{"file", "text/xml", new File("pom.xml"), realObject},
{"string", "text/xml", realObject, realObject},
{"bytes", "application/octet-stream", realObject.getBytes(),
realObject}};
}
@Test(dataProvider = "putTests")
@Test(dataProvider = "putTests", groups = {"integration", "live"})
void testPutObject(String key, String type, Object content,
Object realObject) throws Exception {
String bucketName = bucketPrefix + "tpo";
@ -92,7 +90,7 @@ public class PutObjectIntegrationTest extends S3IntegrationTest {
.getContents().size(), 1);
}
@Test
@Test(groups = {"integration", "live"})
void testMetadata() throws Exception {
String bucketName = bucketPrefix + "tmd";
createBucketAndEnsureEmpty(bucketName);
@ -126,23 +124,4 @@ public class PutObjectIntegrationTest extends S3IntegrationTest {
.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;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import org.jclouds.aws.s3.commands.config.S3CommandsModule;
import org.jclouds.aws.s3.commands.options.CopyObjectOptions;
import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.commands.options.ListBucketOptions;
import org.jclouds.aws.s3.commands.options.PutBucketOptions;
import org.jclouds.aws.s3.commands.options.PutObjectOptions;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.name.Names;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import org.jclouds.aws.s3.commands.config.S3CommandsModule;
import org.jclouds.aws.s3.commands.options.*;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.jclouds.aws.s3.domain.S3Object;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test
@Test(groups = {"unit"}, testName = "s3.S3CommandFactoryTest")
public class S3CommandFactoryTest {
Injector injector = null;
S3CommandFactory commandFactory = null;
public static final String listAllMyBucketsResult = "<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/callables/\"><Owner ><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID></Owner><Buckets><Bucket><Name>adrianjbosstest</Name><CreationDate>2009-03-12T02:00:07.000Z</CreationDate></Bucket><Bucket><Name>adrianjbosstest2</Name><CreationDate>2009-03-12T02:00:09.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>";
@BeforeMethod
void setUpInjector() {
injector = Guice.createInjector(new S3CommandsModule() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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