Issue 73, 130, 150: overhauled context builders, blobstore javadocs, setup http connection limiter, and otherwise readied the code for consumption

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2729 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2010-01-25 09:41:37 +00:00
parent 99f201f0f8
commit 70aa7e4ef3
324 changed files with 5532 additions and 5165 deletions

View File

@ -89,12 +89,12 @@
<appender-ref ref="ASYNC" />
</category>
<category name="jclouds.http.headers">
<category name="jclouds.headers">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category><!--
<category name="jclouds.http.wire">
<category name="jclouds.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>

View File

@ -45,10 +45,10 @@ import org.jclouds.atmosonline.saas.functions.ReturnEndpointIfAlreadyExists;
import org.jclouds.atmosonline.saas.options.ListOptions;
import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.attr.ConsistencyModels;
import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.options.GetOptions;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Endpoint;
@ -183,7 +183,7 @@ public interface AtmosStorageAsyncClient {
* @see AtmosStorageClient#pathExists
*/
@HEAD
@ExceptionParser(ReturnFalseOn404.class)
@ExceptionParser(ReturnFalseOnKeyNotFound.class)
@Path("/rest/namespace/{path}")
@Consumes(MediaType.WILDCARD)
ListenableFuture<Boolean> pathExists(@PathParam("path") String path);

View File

@ -20,21 +20,32 @@ package org.jclouds.atmosonline.saas;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import org.jclouds.atmosonline.saas.config.AtmosStorageContextModule;
import org.jclouds.atmosonline.saas.blobstore.config.AtmosBlobStoreContextModule;
import org.jclouds.atmosonline.saas.config.AtmosStorageRestClientModule;
import org.jclouds.rest.RestContextBuilder;
import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Creates {@link AtmosBlobStoreContext} or {@link Injector} instances based on the most commonly
* requested arguments.
* <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 JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole
* @author Adrian Cole, Andrew Newdigate
* @see AtmosBlobStoreContext
*/
public class AtmosStorageContextBuilder extends
RestContextBuilder<AtmosStorageAsyncClient, AtmosStorageClient> {
BlobStoreContextBuilder<AtmosStorageAsyncClient, AtmosStorageClient> {
public AtmosStorageContextBuilder(Properties props) {
super(new TypeLiteral<AtmosStorageAsyncClient>() {
@ -42,24 +53,13 @@ public class AtmosStorageContextBuilder extends
}, props);
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new AtmosBlobStoreContextModule());
}
@Override
protected void addClientModule(List<Module> modules) {
modules.add(new AtmosStorageRestClientModule());
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new AtmosStorageContextModule());
}
@Override
public AtmosStorageContextBuilder withExecutorService(ExecutorService service) {
return (AtmosStorageContextBuilder) super.withExecutorService(service);
}
@Override
public AtmosStorageContextBuilder withModules(Module... modules) {
return (AtmosStorageContextBuilder) super.withModules(modules);
}
}

View File

@ -16,12 +16,11 @@
* limitations under the License.
* ====================================================================
*/
package org.jclouds.atmosonline.saas.blobstore;
package org.jclouds.atmosonline.saas;
import java.net.URI;
import java.util.Properties;
import org.jclouds.atmosonline.saas.AtmosStoragePropertiesBuilder;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
@ -40,20 +39,20 @@ import com.google.inject.Module;
* @author Adrian Cole
* @see AtmosBlobStoreContext
*/
public class AtmosBlobStoreContextFactory {
public class AtmosStorageContextFactory {
public static BlobStoreContext createContext(Properties properties, Module... modules) {
return new AtmosBlobStoreContextBuilder(new AtmosStoragePropertiesBuilder(properties).build())
return new AtmosStorageContextBuilder(new AtmosStoragePropertiesBuilder(properties).build())
.withModules(modules).buildBlobStoreContext();
}
public static BlobStoreContext createContext(String uid, String key, Module... modules) {
return new AtmosBlobStoreContextBuilder(new AtmosStoragePropertiesBuilder(uid, key).build())
return new AtmosStorageContextBuilder(new AtmosStoragePropertiesBuilder(uid, key).build())
.withModules(modules).buildBlobStoreContext();
}
public static BlobStoreContext createContext(URI endpoint, String uid, String key,
Module... modules) {
return new AtmosBlobStoreContextBuilder(new AtmosStoragePropertiesBuilder(uid, key)
return new AtmosStorageContextBuilder(new AtmosStoragePropertiesBuilder(uid, key)
.withEndpoint(endpoint).build()).withModules(modules).buildBlobStoreContext();
}
}

View File

@ -23,15 +23,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Properties;
import org.jclouds.PropertiesBuilder;
import org.jclouds.atmosonline.saas.reference.AtmosStorageConstants;
import org.jclouds.http.HttpPropertiesBuilder;
/**
* Builds properties used in AtmosStorage Connections
*
* @author Adrian Cole
*/
public class AtmosStoragePropertiesBuilder extends HttpPropertiesBuilder {
public class AtmosStoragePropertiesBuilder extends PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();

View File

@ -28,7 +28,9 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
import org.jclouds.atmosonline.saas.AtmosStorageClient;
import org.jclouds.atmosonline.saas.blobstore.functions.BlobStoreListOptionsToListOptions;
@ -40,6 +42,7 @@ import org.jclouds.atmosonline.saas.blobstore.internal.BaseAtmosBlobStore;
import org.jclouds.atmosonline.saas.domain.AtmosObject;
import org.jclouds.atmosonline.saas.options.ListOptions;
import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
@ -48,6 +51,7 @@ import org.jclouds.blobstore.domain.ListResponse;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.strategy.ClearListStrategy;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.options.GetOptions;
@ -72,7 +76,8 @@ public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlob
BlobStoreListOptionsToListOptions container2ContainerListOptions,
BlobToHttpGetOptions blob2ObjectGetOptions,
DirectoryEntryListToResourceMetadataList container2ResourceList,
ExecutorService service, EncryptionService encryptionService) {
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
EncryptionService encryptionService) {
super(async, sync, blobFactory, logFactory, clearContainerStrategy, object2BlobMd,
object2Blob, blob2Object, container2ContainerListOptions, blob2ObjectGetOptions,
container2ResourceList, service);
@ -80,8 +85,9 @@ public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlob
}
/**
* This implementation uses the AtmosStorage HEAD Object command to return the result
* This implementation invokes {@link AtmosStorageAsyncClient#headFile}
*/
@Override
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return compose(convertExceptionToValue(async.headFile(container + "/" + key),
KeyNotFoundException.class, null), new Function<AtmosObject, BlobMetadata>() {
@ -92,6 +98,11 @@ public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlob
}, service);
}
/**
* This implementation invokes {@link ClearListStrategy#execute} with the
* {@link ListContainerOptions#recursive} option.
*/
@Override
public ListenableFuture<Void> clearContainer(final String container) {
return makeListenable(service.submit(new Callable<Void>() {
@ -104,18 +115,25 @@ public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlob
}
/**
* Note that location is currently ignored.
* This implementation invokes {@link AtmosStorageAsyncClient#createDirectory}
* <p/>
* Note location is ignored
*/
@Override
public ListenableFuture<Boolean> createContainerInLocation(String location, String container) {
return compose(async.createDirectory(container), new Function<URI, Boolean>() {
public Boolean apply(URI from) {
return true;// no etag
return true;
}
});
}
/**
* This implementation invokes {@link AtmosStorageAsyncClient#createDirectory}
*/
@Override
public ListenableFuture<Void> createDirectory(String container, String directory) {
return compose(async.createDirectory(container + "/" + directory), new Function<URI, Void>() {
@ -126,17 +144,23 @@ public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlob
});
}
/**
* This implementation invokes {@link ClearListStrategy#execute} with the
* {@link ListContainerOptions#recursive} option. Then, it blocks until
* {@link AtmosStorageAsyncClient#pathExists} fails.
*/
@Override
public ListenableFuture<Void> deleteContainer(final String container) {
return makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
clearContainerStrategy.execute(container, recursive());
async.deletePath(container).get();
sync.deletePath(container);
if (!Utils.enventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
return !sync.pathExists(container);
}
}, requestTimeoutMilliseconds)) {
}, 300)) {
throw new IllegalStateException(container + " still exists after deleting!");
}
return null;
@ -145,43 +169,92 @@ public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlob
}), service);
}
/**
* This implementation invokes {@link AtmosStorageAsyncClient#pathExists}
*/
@Override
public ListenableFuture<Boolean> containerExists(String container) {
return async.pathExists(container);
return convertExceptionToValue(async.pathExists(container), ContainerNotFoundException.class,
false);
}
/**
* This implementation invokes {@link AtmosStorageAsyncClient#pathExists}
*/
@Override
public ListenableFuture<Boolean> directoryExists(String container, String directory) {
return async.pathExists(container + "/" + directory);
}
/**
* This implementation invokes {@link AtmosStorageAsyncClient#pathExists}
*
* @param container
* container
* @param key
* file name
*/
@Override
public ListenableFuture<Boolean> blobExists(String container, String key) {
return async.pathExists(container + "/" + key);
}
/**
* This implementation invokes
* {@link #getBlob(String,String,org.jclouds.blobstore.options.GetOptions)}
*/
@Override
public ListenableFuture<Blob> getBlob(String container, String key) {
return this.getBlob(container, key, org.jclouds.blobstore.options.GetOptions.NONE);
}
/**
* This implementation invokes {@link AtmosStorageAsyncClient#readFile}
*/
@Override
public ListenableFuture<Blob> getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions... optionsList) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList);
org.jclouds.blobstore.options.GetOptions options) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
ListenableFuture<AtmosObject> returnVal = async.readFile(container + "/" + key, httpOptions);
return compose(convertExceptionToValue(returnVal, KeyNotFoundException.class, null),
object2Blob, service);
}
/**
* This implementation invokes {@link AtmosStorageAsyncClient#listDirectories}
*/
@Override
public ListenableFuture<? extends ListResponse<? extends StorageMetadata>> list() {
return compose(async.listDirectories(), container2ResourceList, service);
}
/**
* This implementation invokes
* {@link #list(String,org.jclouds.blobstore.options.ListContainerOptions)}
*/
@Override
public ListenableFuture<? extends ListContainerResponse<? extends StorageMetadata>> list(
String container, org.jclouds.blobstore.options.ListContainerOptions... optionsList) {
if (optionsList.length == 1) {
if (optionsList[0].isRecursive()) {
throw new UnsupportedOperationException("recursive not currently supported in emcsaas");
}
if (optionsList[0].getDir() != null) {
container = container + "/" + optionsList[0].getDir();
}
}
ListOptions nativeOptions = container2ContainerListOptions.apply(optionsList);
String container) {
return this.list(container, org.jclouds.blobstore.options.ListContainerOptions.NONE);
}
/**
* This implementation invokes {@link AtmosStorageAsyncClient#listDirectory}
*/
@Override
public ListenableFuture<? extends ListContainerResponse<? extends StorageMetadata>> list(
String container, org.jclouds.blobstore.options.ListContainerOptions options) {
container = adjustContainerIfDirOptionPresent(container, options);
ListOptions nativeOptions = container2ContainerListOptions.apply(options);
return compose(async.listDirectory(container, nativeOptions), container2ResourceList, service);
}
/**
* This implementation invokes {@link AtmosStorageAsyncClient#createFile}
* <p/>
* Since there is no etag support in atmos, we just return the path.
*/
@Override
public ListenableFuture<String> putBlob(final String container, final Blob blob) {
final String path = container + "/" + blob.getMetadata().getName();
return compose(async.deletePath(path), new Function<Void, String>() {
@ -192,7 +265,7 @@ public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlob
public Boolean get() {
return !sync.pathExists(path);
}
}, requestTimeoutMilliseconds)) {
}, 300)) {
throw new IllegalStateException(path + " still exists after deleting!");
}
if (blob.getMetadata().getContentMD5() != null)
@ -209,6 +282,10 @@ public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlob
}
/**
* This implementation invokes {@link AtmosStorageAsyncClient#deletePath}
*/
@Override
public ListenableFuture<Void> removeBlob(String container, String key) {
return async.deletePath(container + "/" + key);
}

View File

@ -19,12 +19,14 @@
package org.jclouds.atmosonline.saas.blobstore;
import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
import static org.jclouds.blobstore.util.BlobStoreUtils.returnNullOnKeyNotFoundOrPropagate;
import static org.jclouds.blobstore.util.BlobStoreUtils.keyNotFoundToNullOrPropagate;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
import org.jclouds.atmosonline.saas.AtmosStorageClient;
import org.jclouds.atmosonline.saas.blobstore.functions.BlobStoreListOptionsToListOptions;
@ -35,6 +37,7 @@ import org.jclouds.atmosonline.saas.blobstore.functions.ObjectToBlobMetadata;
import org.jclouds.atmosonline.saas.blobstore.internal.BaseAtmosBlobStore;
import org.jclouds.atmosonline.saas.options.ListOptions;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ListContainerResponse;
@ -42,6 +45,7 @@ import org.jclouds.blobstore.domain.ListResponse;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.strategy.ClearListStrategy;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.options.GetOptions;
@ -61,7 +65,8 @@ public class AtmosBlobStore extends BaseAtmosBlobStore implements BlobStore {
BlobStoreListOptionsToListOptions container2ContainerListOptions,
BlobToHttpGetOptions blob2ObjectGetOptions,
DirectoryEntryListToResourceMetadataList container2ResourceList,
ExecutorService service, EncryptionService encryptionService) {
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
EncryptionService encryptionService) {
super(async, sync, blobFactory, logFactory, clearContainerStrategy, object2BlobMd,
object2Blob, blob2Object, container2ContainerListOptions, blob2ObjectGetOptions,
container2ResourceList, service);
@ -69,38 +74,46 @@ public class AtmosBlobStore extends BaseAtmosBlobStore implements BlobStore {
}
/**
* This implementation uses the AtmosStorage HEAD Object command to return the result
* This implementation invokes {@link AtmosStorageClient#headFile}
*/
@Override
public BlobMetadata blobMetadata(String container, String key) {
try {
return object2BlobMd.apply(sync.headFile(container + "/" + key));
} catch (Exception e) {
return returnNullOnKeyNotFoundOrPropagate(e);
return keyNotFoundToNullOrPropagate(e);
}
}
/**
* This implementation invokes {@link ClearListStrategy#execute} with the
* {@link ListContainerOptions#recursive} option.
*/
@Override
public void clearContainer(final String container) {
clearContainerStrategy.execute(container, recursive());
}
/**
* Note that location is currently ignored.
* This implementation invokes {@link ClearListStrategy#execute} with the
* {@link ListContainerOptions#recursive} option. Then, it invokes
* {@link #deleteAndEnsurePathGone}
*/
public boolean createContainerInLocation(String location, String container) {
sync.createDirectory(container);
return true;// no etag
}
public void createDirectory(String container, String directory) {
sync.createDirectory(container + "/" + directory);
}
@Override
public void deleteContainer(final String container) {
clearContainerStrategy.execute(container, recursive());
deleteAndEnsurePathGone(container);
try {
clearContainerStrategy.execute(container, recursive());
deleteAndEnsurePathGone(container);
} catch (ContainerNotFoundException e) {
}
}
private void deleteAndEnsurePathGone(final String path) {
/**
* This implementation invokes {@link AtmosStorageClient#deleteAndEnsurePathGone} then blocks
* until {@link AtmosStorageClient#pathExists} returns false.
*/
public void deleteAndEnsurePathGone(final String path) {
sync.deletePath(path);
try {
if (!Utils.enventuallyTrue(new Supplier<Boolean>() {
@ -115,49 +128,126 @@ public class AtmosBlobStore extends BaseAtmosBlobStore implements BlobStore {
}
}
public boolean containerExists(String container) {
return sync.pathExists(container);
/**
* This implementation invokes {@link AtmosStorageClient#createDirectory}
*
* @param location
* currently ignored
* @param container
* directory name
*/
@Override
public boolean createContainerInLocation(String location, String container) {
sync.createDirectory(container);
return true;
}
/**
* This implementation invokes {@link AtmosStorageClient#createDirectory}
*
* @param container
* directory name
*/
@Override
public void createDirectory(String container, String directory) {
sync.createDirectory(container + "/" + directory);
}
/**
* This implementation invokes {@link AtmosStorageClient#pathExists}
*/
@Override
public boolean containerExists(String container) {
try {
return sync.pathExists(container);
} catch (ContainerNotFoundException e) {
return false;
}
}
/**
* This implementation invokes {@link AtmosStorageClient#pathExists}
*/
@Override
public boolean directoryExists(String container, String directory) {
try {
return sync.pathExists(container + "/" + directory);
} catch (Exception e) {
return (Boolean)returnNullOnKeyNotFoundOrPropagate(e);
keyNotFoundToNullOrPropagate(e);
return false;
}
}
/**
* This implementation invokes {@link AtmosStorageClient#pathExists}
*
* @param container
* container
* @param key
* file name
*/
@Override
public boolean blobExists(String container, String key) {
return sync.pathExists(container + "/" + key);
}
/**
* This implementation invokes
* {@link #getBlob(String,String,org.jclouds.blobstore.options.GetOptions)}
*/
@Override
public Blob getBlob(String container, String key) {
return this.getBlob(container, key, org.jclouds.blobstore.options.GetOptions.NONE);
}
/**
* This implementation invokes {@link AtmosStorageClient#readFile}
*/
@Override
public Blob getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions... optionsList) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList);
org.jclouds.blobstore.options.GetOptions options) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
try {
return object2Blob.apply(sync.readFile(container + "/" + key, httpOptions));
} catch (Exception e) {
return returnNullOnKeyNotFoundOrPropagate(e);
return keyNotFoundToNullOrPropagate(e);
}
}
/**
* This implementation invokes {@link AtmosStorageClient#listDirectories}
*/
@Override
public ListResponse<? extends StorageMetadata> list() {
return container2ResourceList.apply(sync.listDirectories());
}
/**
* This implementation invokes
* {@link #list(String,org.jclouds.blobstore.options.ListContainerOptions)}
*/
@Override
public ListContainerResponse<? extends StorageMetadata> list(String container) {
return this.list(container, org.jclouds.blobstore.options.ListContainerOptions.NONE);
}
/**
* This implementation invokes {@link AtmosStorageClient#listDirectory}
*/
@Override
public ListContainerResponse<? extends StorageMetadata> list(String container,
org.jclouds.blobstore.options.ListContainerOptions... optionsList) {
if (optionsList.length == 1) {
if (optionsList[0].isRecursive()) {
throw new UnsupportedOperationException("recursive not currently supported in emcsaas");
}
if (optionsList[0].getDir() != null) {
container = container + "/" + optionsList[0].getDir();
}
}
ListOptions nativeOptions = container2ContainerListOptions.apply(optionsList);
org.jclouds.blobstore.options.ListContainerOptions options) {
container = adjustContainerIfDirOptionPresent(container, options);
ListOptions nativeOptions = container2ContainerListOptions.apply(options);
return container2ResourceList.apply(sync.listDirectory(container, nativeOptions));
}
/**
* This implementation invokes {@link AtmosStorageClient#createFile}
* <p/>
* Since there is no etag support in atmos, we just return the path.
*/
@Override
public String putBlob(final String container, final Blob blob) {
final String path = container + "/" + blob.getMetadata().getName();
deleteAndEnsurePathGone(path);
@ -168,6 +258,10 @@ public class AtmosBlobStore extends BaseAtmosBlobStore implements BlobStore {
return path;
}
/**
* This implementation invokes {@link AtmosStorageClient#deletePath}
*/
@Override
public void removeBlob(String container, String key) {
sync.deletePath(container + "/" + key);
}

View File

@ -1,95 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.atmosonline.saas.blobstore;
import static org.jclouds.atmosonline.saas.reference.AtmosStorageConstants.PROPERTY_EMCSAAS_RETRY;
import static org.jclouds.atmosonline.saas.reference.AtmosStorageConstants.PROPERTY_EMCSAAS_TIMEOUT;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_BLOBSTORE_RETRY;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import java.util.List;
import java.util.Properties;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
import org.jclouds.atmosonline.saas.AtmosStorageClient;
import org.jclouds.atmosonline.saas.blobstore.config.AtmosBlobStoreContextModule;
import org.jclouds.atmosonline.saas.config.AtmosStorageRestClientModule;
import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Creates {@link AtmosBlobStoreContext} or {@link Injector} instances based on the most commonly
* requested arguments.
* <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 JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole, Andrew Newdigate
* @see AtmosBlobStoreContext
*/
public class AtmosBlobStoreContextBuilder extends
BlobStoreContextBuilder<AtmosStorageAsyncClient, AtmosStorageClient> {
public AtmosBlobStoreContextBuilder(Properties props) {
super(new TypeLiteral<AtmosStorageAsyncClient>() {
}, new TypeLiteral<AtmosStorageClient>() {
}, convert(props));
}
private static Properties convert(Properties props) {
for (Entry<String, String> entry : ImmutableMap.of(PROPERTY_EMCSAAS_RETRY,
PROPERTY_BLOBSTORE_RETRY, PROPERTY_EMCSAAS_TIMEOUT, PROPERTY_USER_METADATA_PREFIX)
.entrySet()) {
if (props.containsKey(entry.getKey()))
props.setProperty(entry.getValue(), props.getProperty(entry.getKey()));
}
return props;
}
@Override
public AtmosBlobStoreContextBuilder withExecutorService(ExecutorService service) {
return (AtmosBlobStoreContextBuilder) super.withExecutorService(service);
}
@Override
public AtmosBlobStoreContextBuilder withModules(Module... modules) {
return (AtmosBlobStoreContextBuilder) super.withModules(modules);
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new AtmosBlobStoreContextModule());
}
@Override
protected void addClientModule(List<Module> modules) {
modules.add(new AtmosStorageRestClientModule());
}
}

View File

@ -28,15 +28,17 @@ import com.google.common.base.Function;
* @author Adrian Cole
*/
@Singleton
public class BlobStoreListOptionsToListOptions implements Function<ListContainerOptions[], org.jclouds.atmosonline.saas.options.ListOptions> {
public org.jclouds.atmosonline.saas.options.ListOptions apply(ListContainerOptions[] optionsList) {
public class BlobStoreListOptionsToListOptions implements
Function<ListContainerOptions, org.jclouds.atmosonline.saas.options.ListOptions> {
@Override
public org.jclouds.atmosonline.saas.options.ListOptions apply(ListContainerOptions from) {
org.jclouds.atmosonline.saas.options.ListOptions httpOptions = new org.jclouds.atmosonline.saas.options.ListOptions();
if (optionsList.length != 0) {
if (optionsList[0].getMarker() != null) {
httpOptions.token(optionsList[0].getMarker());
if (from != null && from != ListContainerOptions.NONE) {
if (from.getMarker() != null) {
httpOptions.token(from.getMarker());
}
if (optionsList[0].getMaxResults() != null) {
httpOptions.limit(optionsList[0].getMaxResults());
if (from.getMaxResults() != null) {
httpOptions.limit(from.getMaxResults());
}
}
return httpOptions;

View File

@ -47,7 +47,8 @@ public class ObjectToBlob implements Function<AtmosObject, Blob> {
Blob blob = blobFactory.create(object2BlobMd.apply(from));
if (from.getContentMetadata().getContentLength() != null)
blob.setContentLength(from.getContentMetadata().getContentLength());
blob.setPayload(from.getPayload());
if (from.getPayload() != null)
blob.setPayload(from.getPayload());
blob.setAllHeaders(from.getAllHeaders());
return blob;
}

View File

@ -22,8 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.concurrent.ExecutorService;
import javax.inject.Named;
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
import org.jclouds.atmosonline.saas.AtmosStorageClient;
import org.jclouds.atmosonline.saas.blobstore.functions.BlobStoreListOptionsToListOptions;
@ -33,7 +31,6 @@ import org.jclouds.atmosonline.saas.blobstore.functions.ObjectToBlob;
import org.jclouds.atmosonline.saas.blobstore.functions.ObjectToBlobMetadata;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.blobstore.strategy.ClearListStrategy;
import org.jclouds.logging.Logger.LoggerFactory;
@ -53,10 +50,6 @@ public class BaseAtmosBlobStore {
protected final DirectoryEntryListToResourceMetadataList container2ResourceList;
protected final ExecutorService service;
@Inject(optional = true)
@Named(BlobStoreConstants.PROPERTY_BLOBSTORE_TIMEOUT)
protected long requestTimeoutMilliseconds = 30000;
@Inject
protected BaseAtmosBlobStore(AtmosStorageAsyncClient async, AtmosStorageClient sync,
Blob.Factory blobFactory, LoggerFactory logFactory,
@ -86,4 +79,17 @@ public class BaseAtmosBlobStore {
return blob;
}
protected String adjustContainerIfDirOptionPresent(String container,
org.jclouds.blobstore.options.ListContainerOptions options) {
if (options != org.jclouds.blobstore.options.ListContainerOptions.NONE) {
if (options.isRecursive()) {
throw new UnsupportedOperationException("recursive not currently supported in emcsaas");
}
if (options.getDir() != null) {
container = container + "/" + options.getDir();
}
}
return container;
}
}

View File

@ -19,20 +19,33 @@
package org.jclouds.atmosonline.saas.blobstore.strategy;
import java.util.Arrays;
import java.util.SortedSet;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.atmosonline.saas.AtmosStorageClient;
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
import org.jclouds.Constants;
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
import org.jclouds.atmosonline.saas.domain.AtmosObject;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.functions.ObjectMD5;
import org.jclouds.blobstore.internal.BlobRuntimeException;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
import org.jclouds.blobstore.strategy.ListBlobMetadataStrategy;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject;
/**
* Searches Content-MD5 tag for the value associated with the value
@ -41,34 +54,75 @@ import com.google.common.base.Throwables;
*/
@Singleton
public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
@Resource
protected Logger logger = Logger.NULL;
protected final ObjectMD5 objectMD5;
protected final ListBlobMetadataStrategy getAllBlobMetadata;
private final AtmosStorageClient client;
private final AtmosStorageAsyncClient client;
private final ExecutorService userExecutor;
/**
* maximum duration of an blob Request
*/
@Inject(optional = true)
@Named(Constants.PROPERTY_HTTP_REQUEST_TIMEOUT)
protected Long maxTime;
@Inject
private FindMD5InUserMetadata(ObjectMD5 objectMD5, ListBlobMetadataStrategy getAllBlobMetadata,
AtmosStorageClient client) {
private FindMD5InUserMetadata(
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
ObjectMD5 objectMD5, ListBlobMetadataStrategy getAllBlobMetadata,
AtmosStorageAsyncClient client) {
this.objectMD5 = objectMD5;
this.getAllBlobMetadata = getAllBlobMetadata;
this.client = client;
this.userExecutor = userExecutor;
}
public boolean execute(String containerName, Object value, ListContainerOptions options) {
public boolean execute(final String containerName, Object value, ListContainerOptions options) {
final byte[] toSearch = objectMD5.apply(value);
final BlockingQueue<Boolean> queue = new SynchronousQueue<Boolean>();
SortedSet<? extends BlobMetadata> allMd = getAllBlobMetadata.execute(containerName, options);
final CountDownLatch doneSignal = new CountDownLatch(allMd.size());
for (final ListenableFuture<AtmosObject> future : Iterables.transform(getAllBlobMetadata
.execute(containerName, options),
new Function<BlobMetadata, ListenableFuture<AtmosObject>>() {
@Override
public ListenableFuture<AtmosObject> apply(BlobMetadata from) {
return client.headFile(containerName + "/" + from.getName());
}
})) {
future.addListener(new Runnable() {
public void run() {
try {
future.get();
doneSignal.countDown();
if (Arrays.equals(toSearch, future.get().getContentMetadata().getContentMD5())) {
queue.put(true);
}
} catch (Exception e) {
doneSignal.countDown();
}
}
}, userExecutor);
}
try {
byte[] toSearch = objectMD5.apply(value);
for (BlobMetadata metadata : getAllBlobMetadata.execute(containerName, options)) {
MutableContentMetadata contentMd = client.headFile(
containerName + "/" + metadata.getName()).getContentMetadata();
if (Arrays.equals(toSearch, contentMd.getContentMD5()))
return true;
if (maxTime != null) {
return queue.poll(maxTime, TimeUnit.MILLISECONDS);
} else {
doneSignal.await();
return queue.poll(1, TimeUnit.MICROSECONDS);
}
} catch (InterruptedException e) {
return false;
} catch (Exception e) {
Throwables.propagateIfPossible(e, BlobRuntimeException.class);
throw new BlobRuntimeException(String.format(
"Error searching for ETAG of value: [%2$s] in container:%1$s", containerName,
value), e);
"Error searching for ETAG of value: [%s] in container:%s", value, containerName),
e);
}
}
}
}

View File

@ -18,22 +18,21 @@
*/
package org.jclouds.atmosonline.saas.blobstore.strategy;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
import org.jclouds.atmosonline.saas.AtmosStorageClient;
import org.jclouds.atmosonline.saas.domain.DirectoryEntry;
import org.jclouds.atmosonline.saas.domain.FileType;
import org.jclouds.blobstore.internal.BlobRuntimeException;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.blobstore.strategy.ClearContainerStrategy;
import org.jclouds.blobstore.strategy.ClearListStrategy;
import org.jclouds.logging.Logger;
@ -41,7 +40,6 @@ import org.jclouds.util.Utils;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@ -58,18 +56,21 @@ public class RecursiveRemove implements ClearListStrategy, ClearContainerStrateg
* maximum duration of an blob Request
*/
@Inject(optional = true)
@Named(BlobStoreConstants.PROPERTY_BLOBSTORE_TIMEOUT)
protected long requestTimeoutMilliseconds = 30000;
@Named(Constants.PROPERTY_HTTP_REQUEST_TIMEOUT)
protected Long maxTime;
protected final AtmosStorageAsyncClient async;
protected final AtmosStorageClient sync;
private final ExecutorService userExecutor;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public RecursiveRemove(AtmosStorageAsyncClient connection, AtmosStorageClient sync) {
public RecursiveRemove(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
AtmosStorageAsyncClient connection, AtmosStorageClient sync) {
this.async = connection;
this.sync = sync;
this.userExecutor = userExecutor;
}
public void execute(String containerName) {
@ -78,57 +79,45 @@ public class RecursiveRemove implements ClearListStrategy, ClearContainerStrateg
logger.trace("cleared container " + containerName);
}
private ListenableFuture<Void> rm(final String fullPath, FileType type, boolean recursive)
throws InterruptedException, ExecutionException, TimeoutException {
Set<ListenableFuture<Void>> deletes = Sets.newHashSet();
private ListenableFuture<Void> rm(final String fullPath, FileType type, boolean recursive) {
Set<ListenableFuture<Void>> responses = Sets.newHashSet();
if ((type == FileType.DIRECTORY) && recursive) {
for (DirectoryEntry child : async.listDirectory(fullPath).get(10, TimeUnit.SECONDS)) {
deletes.add(rm(fullPath + "/" + child.getObjectName(), child.getType(), true));
for (DirectoryEntry child : sync.listDirectory(fullPath)) {
responses.add(rm(fullPath + "/" + child.getObjectName(), child.getType(), true));
}
}
for (ListenableFuture<Void> isdeleted : deletes) {
isdeleted.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
}
return Futures.compose(async.deletePath(fullPath),
new Function<Void, Void>() {
awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
"deleting from path: %s", fullPath));
public Void apply(Void from) {
try {
if (!Utils.enventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
return !sync.pathExists(fullPath);
}
}, requestTimeoutMilliseconds)) {
throw new IllegalStateException(fullPath
+ " still exists after deleting!");
}
return null;
} catch (InterruptedException e) {
throw new IllegalStateException(fullPath + " still exists after deleting!",
e);
}
return Futures.compose(async.deletePath(fullPath), new Function<Void, Void>() {
public Void apply(Void from) {
try {
if (!Utils.enventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
return !sync.pathExists(fullPath);
}
}, maxTime != null ? maxTime : 1000)) {
throw new IllegalStateException(fullPath + " still exists after deleting!");
}
return null;
} catch (InterruptedException e) {
throw new IllegalStateException(fullPath + " still exists after deleting!", e);
}
}
});
});
}
public void execute(final String containerName, ListContainerOptions options) {
String path = containerName;
public void execute(String path, ListContainerOptions options) {
if (options.getDir() != null)
path += "/" + options.getDir();
Set<ListenableFuture<Void>> deletes = Sets.newHashSet();
try {
for (DirectoryEntry md : async.listDirectory(path).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS)) {
deletes.add(rm(path + "/" + md.getObjectName(), md.getType(), options.isRecursive()));
}
for (ListenableFuture<Void> isdeleted : deletes) {
isdeleted.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
}
} catch (Exception e) {
Throwables.propagateIfPossible(e, BlobRuntimeException.class);
throw new BlobRuntimeException("Error deleting path: " + path, e);
Set<ListenableFuture<Void>> responses = Sets.newHashSet();
for (DirectoryEntry md : sync.listDirectory(path)) {
responses.add(rm(path + "/" + md.getObjectName(), md.getType(), options.isRecursive()));
}
awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
"deleting from path: %s", path));
}
}

View File

@ -33,11 +33,11 @@ import javax.inject.Provider;
import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.Constants;
import org.jclouds.atmosonline.saas.reference.AtmosStorageConstants;
import org.jclouds.atmosonline.saas.reference.AtmosStorageHeaders;
import org.jclouds.date.TimeStamp;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
@ -67,7 +67,7 @@ public class SignRequest implements HttpRequestFilter {
Logger logger = Logger.NULL;
@Resource
@Named(HttpConstants.LOGGER_SIGNATURE)
@Named(Constants.LOGGER_SIGNATURE)
Logger signatureLog = Logger.NULL;
@Inject
@ -83,12 +83,17 @@ public class SignRequest implements HttpRequestFilter {
}
public void filter(HttpRequest request) throws HttpException {
String toSign = replaceUIDHeader(request).replaceDateHeader(request).createStringToSign(
request);
String toSign = replaceUIDHeader(request).removeOldSignature(request).replaceDateHeader(
request).createStringToSign(request);
calculateAndReplaceAuthHeader(request, toSign);
HttpUtils.logRequest(signatureLog, request, "<<");
}
private SignRequest removeOldSignature(HttpRequest request) {
request.getHeaders().removeAll(AtmosStorageHeaders.SIGNATURE);
return this;
}
public String createStringToSign(HttpRequest request) {
HttpUtils.logRequest(signatureLog, request, ">>");
StringBuilder buffer = new StringBuilder();

View File

@ -62,7 +62,8 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
AtmosObject object = objectProvider.create(systemMetadataParser.apply(from),
userMetadataParser.apply(from));
addAllHeadersTo(from, object);
object.setPayload(from.getContent());
if (from.getContent() != null)
object.setPayload(from.getContent());
String contentLength = from.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH);
if (contentLength != null) {
object.getContentMetadata().setContentLength(Long.parseLong(contentLength));

View File

@ -21,11 +21,15 @@ package org.jclouds.atmosonline.saas.handlers;
import javax.annotation.Resource;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.atmosonline.saas.domain.AtmosStorageError;
import org.jclouds.atmosonline.saas.util.AtmosStorageUtils;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.logging.Logger;
import com.google.inject.Inject;
@ -36,25 +40,41 @@ import com.google.inject.Inject;
* @author Adrian Cole
*/
public class AtmosStorageClientErrorRetryHandler implements HttpRetryHandler {
private final AtmosStorageUtils utils;
private final BackoffLimitedRetryHandler backoffHandler;
@Inject
public AtmosStorageClientErrorRetryHandler(BackoffLimitedRetryHandler backoffHandler,
AtmosStorageUtils utils) {
this.backoffHandler = backoffHandler;
this.utils = utils;
}
@Inject(optional = true)
@Named(HttpConstants.PROPERTY_HTTP_MAX_RETRIES)
@Named(Constants.PROPERTY_MAX_RETRIES)
private int retryCountLimit = 5;
@Resource
protected Logger logger = Logger.NULL;
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
HttpUtils.closeClientButKeepContentStream(response);
command.incrementFailureCount();
if (!command.isReplayable()) {
logger.warn("Cannot retry after server error, command is not replayable: %1$s", command);
if (command.getFailureCount() > retryCountLimit)
return false;
} else if (command.getFailureCount() > retryCountLimit) {
logger.warn(
"Cannot retry after server error, command has exceeded retry limit %1$d: %2$s",
retryCountLimit, command);
return false;
} else if (response.getStatusCode() == 409) {
if (response.getStatusCode() == 404 && command.getRequest().getMethod().equals("DELETE")) {
command.incrementFailureCount();
return true;
} else if (response.getStatusCode() == 409 || response.getStatusCode() == 400) {
byte[] content = HttpUtils.closeClientButKeepContentStream(response);
try {
AtmosStorageError error = utils.parseAtmosStorageErrorFromContent(command, response,
new String(content));
if (error.getCode() == 1016) {
return backoffHandler.shouldRetryRequest(command, response);
}
// don't increment count before here, since backoff handler does already
command.incrementFailureCount();
} catch (HttpException e) {
logger.warn(e, "error parsing response: %s", new String(content));
}
return true;
}
return false;

View File

@ -19,6 +19,9 @@
package org.jclouds.atmosonline.saas.handlers;
import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -26,15 +29,18 @@ import javax.inject.Inject;
import org.jclouds.atmosonline.saas.AtmosStorageResponseException;
import org.jclouds.atmosonline.saas.domain.AtmosStorageError;
import org.jclouds.atmosonline.saas.util.AtmosStorageUtils;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyAlreadyExistsException;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.util.Utils;
import com.google.common.base.Throwables;
import com.google.common.io.Closeables;
/**
* This will parse and set an appropriate exception on the command object.
@ -54,39 +60,55 @@ public class ParseAtmosStorageErrorFromXmlContent implements HttpErrorHandler {
this.utils = utils;
}
public static final Pattern CONTAINER_PATH = Pattern.compile("^/rest/namespace/?([^/]+)[/]?$");
public static final Pattern CONTAINER_KEY_PATH = Pattern
.compile("^/rest/namespace/?([^/]+)/(.*)");
public void handleError(HttpCommand command, HttpResponse response) {
String content;
Exception exception = new HttpResponseException(command, response);
try {
content = response.getContent() != null ? Utils.toStringAndClose(response.getContent())
: null;
if (content != null) {
try {
if (content.indexOf('<') >= 0) {
AtmosStorageError error = utils.parseAtmosStorageErrorFromContent(command,
response, content);
AtmosStorageResponseException exception = new AtmosStorageResponseException(
command, response, error);
if (error.getCode() == 1016) {
File file = new File(command.getRequest().getEndpoint().getPath());
command.setException(new KeyAlreadyExistsException(file.getParentFile()
.getAbsolutePath(), file.getName(), exception));
switch (response.getStatusCode()) {
case 401:
exception = new AuthorizationException(command.getRequest().getRequestLine());
break;
case 404:
if (!command.getRequest().getMethod().equals("DELETE")) {
String path = command.getRequest().getEndpoint().getPath();
Matcher matcher = CONTAINER_PATH.matcher(path);
if (matcher.find()) {
exception = new ContainerNotFoundException(matcher.group(1));
} else {
command.setException(exception);
matcher = CONTAINER_KEY_PATH.matcher(path);
if (matcher.find()) {
exception = new KeyNotFoundException(matcher.group(1), matcher.group(2));
}
}
}
break;
default:
if (response.getContent() != null) {
try {
String content = Utils.toStringAndClose(response.getContent());
if (content.indexOf('<') >= 0) {
AtmosStorageError error = utils.parseAtmosStorageErrorFromContent(command,
response, content);
if (error.getCode() == 1016) {
File file = new File(command.getRequest().getEndpoint().getPath());
exception = new KeyAlreadyExistsException(file.getParentFile()
.getAbsolutePath(), file.getName());
} else {
exception = new AtmosStorageResponseException(command, response, error);
}
}
} catch (IOException e) {
logger.warn(e, "exception reading error from response", response);
exception = new HttpResponseException(command, response);
}
} else {
command.setException(new HttpResponseException(command, response, content));
}
} catch (Exception he) {
command.setException(new HttpResponseException(command, response, content));
Throwables.propagateIfPossible(he);
}
} else {
command.setException(new HttpResponseException(command, response));
}
} catch (Exception e) {
command.setException(new HttpResponseException(command, response));
Throwables.propagateIfPossible(e);
} finally {
Closeables.closeQuietly(response.getContent());
command.setException(exception);
}
}
}

View File

@ -28,16 +28,9 @@ public interface AtmosStorageConstants {
public static final String PROPERTY_EMCSAAS_UID = "jclouds.emcsaas.uid";
public static final String PROPERTY_EMCSAAS_KEY = "jclouds.emcsaas.key";
/**
* how long do we wait before obtaining a new timestamp for requests. Clocks must be within 5m of Atmos.
* how long do we wait before obtaining a new timestamp for requests. Clocks must be within 5m of
* Atmos.
*/
public static final String PROPERTY_EMCSAAS_SESSIONINTERVAL = "jclouds.emcsaas.sessioninterval";
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public static final String PROPERTY_EMCSAAS_TIMEOUT = "jclouds.emcsaas.timeout";
/**
* time to pause before retrying a transient failure
*/
public static final String PROPERTY_EMCSAAS_RETRY = "jclouds.emcsaas.retry";
}

View File

@ -26,6 +26,8 @@ import java.lang.reflect.UndeclaredThrowableException;
import java.net.URI;
import java.security.SecureRandom;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeoutException;
import org.jclouds.atmosonline.saas.blobstore.strategy.RecursiveRemove;
@ -35,6 +37,7 @@ import org.jclouds.atmosonline.saas.domain.DirectoryEntry;
import org.jclouds.atmosonline.saas.domain.FileType;
import org.jclouds.atmosonline.saas.domain.SystemMetadata;
import org.jclouds.atmosonline.saas.options.ListOptions;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyAlreadyExistsException;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
@ -49,6 +52,7 @@ import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
/**
* Tests behavior of {@code AtmosStorageClient}
@ -103,7 +107,7 @@ public class AtmosStorageClientLiveTest {
private static final int INCONSISTENCY_WINDOW = 5000;
protected AtmosStorageClient connection;
private String containerPrefix = BaseBlobStoreIntegrationTest.CONTAINER_PREFIX;
private String containerPrefix = BaseBlobStoreIntegrationTest.CONTAINER_PREFIX+"live";
URI container1;
URI container2;
@ -116,12 +120,19 @@ public class AtmosStorageClientLiveTest {
RestContext<AtmosStorageAsyncClient, AtmosStorageClient> context = new AtmosStorageContextBuilder(
new AtmosStoragePropertiesBuilder(uid, key).build()).withModules(
new Log4JLoggingModule()).buildContext();
ExecutorService service = Executors.newCachedThreadPool();
connection = context.getApi();
ClearContainerStrategy clearer = new RecursiveRemove(context.getAsyncApi(), connection);
ClearContainerStrategy clearer = new RecursiveRemove(service, context.getAsyncApi(),
connection);
for (DirectoryEntry entry : connection.listDirectories()) {
if (entry.getObjectName().startsWith(containerPrefix)) {
clearer.execute(entry.getObjectName());
deleteConfirmed(entry.getObjectName());
try {
if (entry.getObjectName().startsWith(containerPrefix)) {
clearer.execute(entry.getObjectName());
deleteConfirmed(entry.getObjectName());
}
} catch (ContainerNotFoundException e) {
if (entry.getType() != FileType.DIRECTORY)
throw e;
}
}
}
@ -152,8 +163,7 @@ public class AtmosStorageClientLiveTest {
}
BoundedSet<? extends DirectoryEntry> response = connection.listDirectories();
for (DirectoryEntry id : response) {
BoundedSet<? extends DirectoryEntry> r2 = connection.listDirectory(id
.getObjectName());
BoundedSet<? extends DirectoryEntry> r2 = connection.listDirectory(id.getObjectName());
assert r2 != null;
}
}
@ -182,10 +192,13 @@ public class AtmosStorageClientLiveTest {
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testListOptions" })
public void testFileOperations() throws Exception {
// create the object
System.err.printf("creating%n");
createOrReplaceObject("object", "here is my data!", "meta-value1");
assertEventuallyObjectMatches("object", "here is my data!", "meta-value1");
assertEventuallyHeadMatches("object", "meta-value1");
// try overwriting the object
System.err.printf("overwriting%n");
createOrReplaceObject("object", "here is my data?", "meta-value?");
assertEventuallyObjectMatches("object", "here is my data?", "meta-value?");
@ -324,8 +337,7 @@ public class AtmosStorageClientLiveTest {
.currentTimeMillis()
- time);
} catch (Exception e) {
String message = (e.getCause().getCause() != null) ? e.getCause().getCause().getMessage()
: e.getCause().getMessage();
String message = Throwables.getRootCause(e).getMessage();
System.err.printf("failure %s %s; %dms: [%s]%n", "creating",
object.getPayload() instanceof InputStreamPayload ? "stream" : "string", System
.currentTimeMillis()
@ -337,17 +349,21 @@ public class AtmosStorageClientLiveTest {
private void deleteConfirmed(final String path) throws InterruptedException, ExecutionException,
TimeoutException {
long time = System.currentTimeMillis();
deleteImmediateAndVerifyWithHead(path);
deleteConsistencyAware(path);
System.err.printf("confirmed deletion after %dms%n", System.currentTimeMillis() - time);
}
private void deleteImmediateAndVerifyWithHead(final String path) throws InterruptedException,
protected void deleteImmediateAndVerifyWithHead(final String path) throws InterruptedException,
ExecutionException, TimeoutException {
try {
connection.deletePath(path);
} catch (KeyNotFoundException ex) {
}
assert !connection.pathExists(path);
System.err.printf("path %s doesn't exist%n", path);
assert !connection.pathExists(path);
System.err.printf("path %s doesn't exist%n", path);
}
protected void deleteConsistencyAware(final String path) throws InterruptedException,
@ -402,8 +418,7 @@ public class AtmosStorageClientLiveTest {
.currentTimeMillis()
- time);
} catch (Exception e) {
String message = (e.getCause().getCause() != null) ? e.getCause().getCause().getMessage()
: e.getCause().getMessage();
String message = Throwables.getRootCause(e).getMessage();
System.err.printf("failure %s %s; %dms: [%s]%n", update ? "updating" : "creating", object
.getPayload() instanceof InputStreamPayload ? "stream" : "string", System
.currentTimeMillis()

View File

@ -16,8 +16,9 @@
* limitations under the License.
* ====================================================================
*/
package org.jclouds.atmosonline.saas.blobstore;
package org.jclouds.atmosonline.saas;
import static com.google.common.util.concurrent.Executors.sameThreadExecutor;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.testng.Assert.assertEquals;
@ -25,8 +26,11 @@ import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.jclouds.atmosonline.saas.AtmosStorageContextBuilder;
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
import org.jclouds.atmosonline.saas.AtmosStorageClient;
import org.jclouds.atmosonline.saas.AtmosStoragePropertiesBuilder;
import org.jclouds.atmosonline.saas.blobstore.AtmosAsyncBlobStore;
import org.jclouds.atmosonline.saas.blobstore.config.AtmosBlobStoreContextModule;
import org.jclouds.atmosonline.saas.config.AtmosStorageRestClientModule;
import org.jclouds.atmosonline.saas.config.AtmosStorageStubClientModule;
@ -35,9 +39,11 @@ import org.jclouds.atmosonline.saas.domain.internal.AtmosObjectImpl;
import org.jclouds.atmosonline.saas.internal.StubAtmosStorageAsyncClient;
import org.jclouds.atmosonline.saas.reference.AtmosStorageConstants;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.internal.BlobImpl;
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.testng.annotations.Test;
import com.google.inject.Injector;
@ -49,10 +55,10 @@ import com.google.inject.Module;
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "emcsaas.AtmosStorageContextBuilderTest")
public class AtmosBlobStoreContextBuilderTest {
public class AtmosStorageContextBuilderTest {
public void testNewBuilder() {
AtmosBlobStoreContextBuilder builder = newBuilder();
BlobStoreContextBuilder<AtmosStorageAsyncClient, AtmosStorageClient> builder = newBuilder();
assertEquals(builder.getProperties().getProperty(PROPERTY_USER_METADATA_PREFIX), null);
assertEquals(builder.getProperties().getProperty(AtmosStorageConstants.PROPERTY_EMCSAAS_UID),
"id");
@ -60,9 +66,10 @@ public class AtmosBlobStoreContextBuilderTest {
"secret");
}
private AtmosBlobStoreContextBuilder newBuilder() {
return new AtmosBlobStoreContextBuilder(new AtmosStoragePropertiesBuilder("id", "secret")
.build()).withModules(new AtmosStorageStubClientModule());
private BlobStoreContextBuilder<AtmosStorageAsyncClient, AtmosStorageClient> newBuilder() {
return new AtmosStorageContextBuilder(new AtmosStoragePropertiesBuilder("id", "secret")
.build()).withModules(new AtmosStorageStubClientModule(), new ExecutorServiceModule(
sameThreadExecutor(), sameThreadExecutor()));
}
public void testBuildContext() {
@ -71,8 +78,8 @@ public class AtmosBlobStoreContextBuilderTest {
assertEquals(context.getProviderSpecificContext().getAsyncApi().getClass(),
StubAtmosStorageAsyncClient.class);
assertEquals(context.getAsyncBlobStore().getClass(), AtmosAsyncBlobStore.class);
assertEquals(((AtmosStorageAsyncClient)context.getProviderSpecificContext().getAsyncApi()).newObject().getClass(),
AtmosObjectImpl.class);
assertEquals(((AtmosStorageAsyncClient) context.getProviderSpecificContext().getAsyncApi())
.newObject().getClass(), AtmosObjectImpl.class);
assertEquals(context.getAsyncBlobStore().newBlob(null).getClass(), BlobImpl.class);
assertEquals(context.getProviderSpecificContext().getAccount(), "id");
assertEquals(context.getProviderSpecificContext().getEndPoint(), URI
@ -88,7 +95,7 @@ public class AtmosBlobStoreContextBuilderTest {
protected void testAddContextModule() {
List<Module> modules = new ArrayList<Module>();
AtmosBlobStoreContextBuilder builder = newBuilder();
AtmosStorageContextBuilder builder = (AtmosStorageContextBuilder) newBuilder();
builder.addContextModule(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), AtmosBlobStoreContextModule.class);
@ -96,7 +103,7 @@ public class AtmosBlobStoreContextBuilderTest {
protected void addClientModule() {
List<Module> modules = new ArrayList<Module>();
AtmosBlobStoreContextBuilder builder = newBuilder();
AtmosStorageContextBuilder builder = (AtmosStorageContextBuilder) newBuilder();
builder.addClientModule(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), AtmosStorageRestClientModule.class);

View File

@ -21,6 +21,7 @@ package org.jclouds.atmosonline.saas.blobstore.config;
import static com.google.common.util.concurrent.Executors.sameThreadExecutor;
import static org.testng.Assert.assertEquals;
import org.jclouds.Constants;
import org.jclouds.atmosonline.saas.blobstore.strategy.FindMD5InUserMetadata;
import org.jclouds.atmosonline.saas.config.AtmosStorageStubClientModule;
import org.jclouds.atmosonline.saas.reference.AtmosStorageConstants;
@ -42,8 +43,8 @@ import com.google.inject.Injector;
public class AtmosBlobStoreModuleTest {
Injector createInjector() {
return Guice.createInjector(new ExecutorServiceModule(sameThreadExecutor()),
new JDKLoggingModule(), new AtmosStorageStubClientModule(),
return Guice.createInjector(new ExecutorServiceModule(sameThreadExecutor(),
sameThreadExecutor()), new JDKLoggingModule(), new AtmosStorageStubClientModule(),
new AtmosBlobStoreContextModule() {
@Override
protected void configure() {
@ -54,6 +55,14 @@ public class AtmosBlobStoreModuleTest {
bindConstant().annotatedWith(
Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_ENDPOINT)).to(
"http://localhost");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_IO_WORKER_THREADS)).to("1");
bindConstant().annotatedWith(Jsr330.named(Constants.PROPERTY_USER_THREADS))
.to("1");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_MAX_CONNECTIONS_PER_CONTEXT)).to("0");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST)).to("1");
super.configure();
}
});

View File

@ -21,7 +21,7 @@ package org.jclouds.atmosonline.saas.blobstore.integration;
import java.io.IOException;
import java.util.Properties;
import org.jclouds.atmosonline.saas.blobstore.AtmosBlobStoreContextFactory;
import org.jclouds.atmosonline.saas.AtmosStorageContextFactory;
import org.jclouds.atmosonline.saas.config.AtmosStorageStubClientModule;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextFactory;
@ -46,7 +46,7 @@ public class AtmosStorageTestInitializer extends BaseTestInitializer {
@Override
protected BlobStoreContext createStubContext() {
return AtmosBlobStoreContextFactory.createContext("user", "pass",
return AtmosStorageContextFactory.createContext("user", "pass",
new AtmosStorageStubClientModule());
}

View File

@ -22,6 +22,7 @@ import static com.google.common.util.concurrent.Executors.sameThreadExecutor;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import org.jclouds.Constants;
import org.jclouds.atmosonline.saas.handlers.AtmosStorageClientErrorRetryHandler;
import org.jclouds.atmosonline.saas.handlers.ParseAtmosStorageErrorFromXmlContent;
import org.jclouds.atmosonline.saas.reference.AtmosStorageConstants;
@ -48,20 +49,31 @@ public class AtmosStorageRestClientModuleTest {
Injector createInjector() {
return Guice.createInjector(new AtmosStorageRestClientModule(), new ExecutorServiceModule(
sameThreadExecutor()), new ParserModule(), new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_ENDPOINT)).to(
"http://localhost");
bindConstant().annotatedWith(Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_UID))
.to("uid");
bindConstant().annotatedWith(Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_KEY))
.to(new String(Base64.encodeBytes("key".getBytes())));
bindConstant().annotatedWith(
Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_SESSIONINTERVAL)).to("2");
}
});
sameThreadExecutor(), sameThreadExecutor()), new ParserModule(),
new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_ENDPOINT)).to(
"http://localhost");
bindConstant().annotatedWith(
Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_UID)).to("uid");
bindConstant().annotatedWith(
Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_KEY)).to(
new String(Base64.encodeBytes("key".getBytes())));
bindConstant().annotatedWith(
Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_SESSIONINTERVAL))
.to("2");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_IO_WORKER_THREADS)).to("1");
bindConstant().annotatedWith(Jsr330.named(Constants.PROPERTY_USER_THREADS))
.to("1");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_MAX_CONNECTIONS_PER_CONTEXT)).to("0");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST)).to("1");
}
});
}
@Test

View File

@ -29,6 +29,7 @@ import java.security.NoSuchAlgorithmException;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import org.jclouds.Constants;
import org.jclouds.atmosonline.saas.reference.AtmosStorageConstants;
import org.jclouds.atmosonline.saas.reference.AtmosStorageHeaders;
import org.jclouds.concurrent.config.ExecutorServiceModule;
@ -79,23 +80,26 @@ public class SignRequestTest {
@BeforeClass
protected void createFilter() {
injector = Guice.createInjector(new ExecutorServiceModule(sameThreadExecutor()),
new AbstractModule() {
injector = Guice.createInjector(new ExecutorServiceModule(sameThreadExecutor(),
sameThreadExecutor()), new AbstractModule() {
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_UID)).to("user");
bindConstant().annotatedWith(
Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_KEY)).to(KEY);
}
protected void configure() {
bindConstant().annotatedWith(Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_UID))
.to("user");
bindConstant().annotatedWith(Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_KEY))
.to(KEY);
bindConstant().annotatedWith(Jsr330.named(Constants.PROPERTY_IO_WORKER_THREADS))
.to("1");
bindConstant().annotatedWith(Jsr330.named(Constants.PROPERTY_USER_THREADS)).to("1");
}
@SuppressWarnings("unused")
@Provides
@TimeStamp
String getDate() {
return "Thu, 05 Jun 2008 16:38:19 GMT";
}
});
@SuppressWarnings("unused")
@Provides
@TimeStamp
String getDate() {
return "Thu, 05 Jun 2008 16:38:19 GMT";
}
});
filter = injector.getInstance(SignRequest.class);
}

View File

@ -1,21 +1,116 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<!-- A time/date based rolling appender -->
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-wire.log" />
<param name="Append" value="true" />
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
====================================================================
Licensed 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
<param name="Threshold" value="TRACE" />
http://www.apache.org/licenses/LICENSE-2.0
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
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.
====================================================================
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
-->
<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="COMPUTEFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-compute.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
%m%n"/>
-->
</layout>
</appender>
<appender name="ASYNCCOMPUTE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="COMPUTEFILE" />
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="WIREFILE" />
</appender>
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
<category name="org.jclouds">
<priority value="DEBUG" />
<appender-ref ref="ASYNC" />
</category>
<category name="jclouds.headers">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="jclouds.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category><!--
<category name="jclouds.signature">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
--><!-- ================ -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="WARN" />
</root>
</log4j:configuration>

View File

@ -18,41 +18,54 @@
*/
package org.jclouds.aws.ec2;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
import java.util.List;
import java.util.Properties;
import org.jclouds.aws.ec2.config.EC2ContextModule;
import org.jclouds.aws.ec2.compute.config.EC2ComputeServiceContextModule;
import org.jclouds.aws.ec2.config.EC2RestClientModule;
import org.jclouds.rest.RestContextBuilder;
import org.jclouds.compute.ComputeServiceContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Creates {@link EC2ComputeServiceContext} or {@link Injector} instances based on the most commonly
* requested arguments.
* <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 JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole
* @see EC2ComputeServiceContext
*/
public class EC2ContextBuilder extends RestContextBuilder<EC2AsyncClient, EC2Client> {
public class EC2ContextBuilder extends
ComputeServiceContextBuilder<EC2AsyncClient, EC2Client> {
public EC2ContextBuilder(Properties props) {
super(new TypeLiteral<EC2AsyncClient>() {
}, new TypeLiteral<EC2Client>() {
}, props);
checkNotNull(properties.getProperty(PROPERTY_AWS_ACCESSKEYID));
checkNotNull(properties.getProperty(PROPERTY_AWS_SECRETACCESSKEY));
}
protected void addClientModule(List<Module> modules) {
modules.add(new EC2RestClientModule());
@Override
public EC2ContextBuilder withModules(Module... modules) {
return (EC2ContextBuilder) super.withModules(modules);
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new EC2ContextModule());
modules.add(new EC2ComputeServiceContextModule());
}
@Override
protected void addClientModule(List<Module> modules) {
modules.add(new EC2RestClientModule());
}
}

View File

@ -21,15 +21,15 @@ package org.jclouds.aws.ec2;
import java.net.URI;
import java.util.Properties;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.RestContext;
import com.google.inject.Module;
/**
* Creates {@link RestContext} instances bound with generic type {@link EC2AsyncClient} based on the
* most commonly requested arguments.
* Creates {@link EC2ComputeServiceContext} instances based on the most commonly requested
* arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
@ -38,31 +38,31 @@ import com.google.inject.Module;
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole
* @see RestContext
* @see EC2ComputeServiceContext
*/
public class EC2ContextFactory {
public static RestContext<EC2AsyncClient, EC2Client> createContext(Properties properties,
Module... modules) {
return new EC2ContextBuilder(new EC2PropertiesBuilder(properties).build()).withModules(
modules).buildContext();
public static ComputeServiceContext createContext(Properties properties, Module... modules) {
return new EC2ContextBuilder(new EC2PropertiesBuilder(properties).build())
.withModules(modules).buildComputeServiceContext();
}
public static RestContext<EC2AsyncClient, EC2Client> createContext(Properties properties,
String awsAccessKeyId, String awsSecretAccessKey, Module... modules) {
return new EC2ContextBuilder(new EC2PropertiesBuilder(properties).withCredentials(
awsAccessKeyId, awsSecretAccessKey).build()).withModules(modules).buildContext();
}
public static RestContext<EC2AsyncClient, EC2Client> createContext(String awsAccessKeyId,
public static ComputeServiceContext createContext(String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new EC2ContextBuilder(new EC2PropertiesBuilder(awsAccessKeyId, awsSecretAccessKey)
.build()).withModules(modules).buildContext();
return new EC2ContextBuilder(new EC2PropertiesBuilder(awsAccessKeyId,
awsSecretAccessKey).build()).withModules(modules).buildComputeServiceContext();
}
public static RestContext<EC2AsyncClient, EC2Client> createContext(URI endpoint,
String awsAccessKeyId, String awsSecretAccessKey, Module... modules) {
return new EC2ContextBuilder(new EC2PropertiesBuilder(awsAccessKeyId, awsSecretAccessKey)
.withEndpoint(endpoint).build()).withModules(modules).buildContext();
public static ComputeServiceContext createContext(Properties properties, String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new EC2ContextBuilder(new EC2PropertiesBuilder(properties)
.withCredentials(awsAccessKeyId, awsSecretAccessKey).build()).withModules(modules)
.buildComputeServiceContext();
}
public static ComputeServiceContext createContext(URI endpoint, String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new EC2ContextBuilder(new EC2PropertiesBuilder(awsAccessKeyId,
awsSecretAccessKey).withEndpoint(endpoint).build()).withModules(modules)
.buildComputeServiceContext();
}
}

View File

@ -27,14 +27,14 @@ import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKE
import java.net.URI;
import java.util.Properties;
import org.jclouds.http.HttpPropertiesBuilder;
import org.jclouds.PropertiesBuilder;
/**
* Builds properties used in EC2 Clients
*
* @author Adrian Cole
*/
public class EC2PropertiesBuilder extends HttpPropertiesBuilder {
public class EC2PropertiesBuilder extends PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();

View File

@ -1,79 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.ec2.compute;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.compute.config.EC2ComputeServiceContextModule;
import org.jclouds.aws.ec2.config.EC2RestClientModule;
import org.jclouds.compute.ComputeServiceContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Creates {@link EC2ComputeServiceContext} or {@link Injector} instances based on the most commonly
* requested arguments.
* <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 JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole
* @see EC2ComputeServiceContext
*/
public class EC2ComputeServiceContextBuilder extends
ComputeServiceContextBuilder<EC2AsyncClient, EC2Client> {
public EC2ComputeServiceContextBuilder(Properties props) {
super(new TypeLiteral<EC2AsyncClient>() {
}, new TypeLiteral<EC2Client>() {
}, props);
}
@Override
public EC2ComputeServiceContextBuilder withExecutorService(ExecutorService service) {
return (EC2ComputeServiceContextBuilder) super.withExecutorService(service);
}
@Override
public EC2ComputeServiceContextBuilder withModules(Module... modules) {
return (EC2ComputeServiceContextBuilder) super.withModules(modules);
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new EC2ComputeServiceContextModule());
}
@Override
protected void addClientModule(List<Module> modules) {
modules.add(new EC2RestClientModule());
}
}

View File

@ -1,69 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.ec2.compute;
import java.net.URI;
import java.util.Properties;
import org.jclouds.aws.ec2.EC2PropertiesBuilder;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.inject.Module;
/**
* Creates {@link EC2ComputeServiceContext} instances based on the most commonly requested
* arguments.
* <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 JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole
* @see EC2ComputeServiceContext
*/
public class EC2ComputeServiceContextFactory {
public static ComputeServiceContext createContext(Properties properties, Module... modules) {
return new EC2ComputeServiceContextBuilder(new EC2PropertiesBuilder(properties).build())
.withModules(modules).buildComputeServiceContext();
}
public static ComputeServiceContext createContext(String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new EC2ComputeServiceContextBuilder(new EC2PropertiesBuilder(awsAccessKeyId,
awsSecretAccessKey).build()).withModules(modules).buildComputeServiceContext();
}
public static ComputeServiceContext createContext(Properties properties, String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new EC2ComputeServiceContextBuilder(new EC2PropertiesBuilder(properties)
.withCredentials(awsAccessKeyId, awsSecretAccessKey).build()).withModules(modules)
.buildComputeServiceContext();
}
public static ComputeServiceContext createContext(URI endpoint, String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new EC2ComputeServiceContextBuilder(new EC2PropertiesBuilder(awsAccessKeyId,
awsSecretAccessKey).withEndpoint(endpoint).build()).withModules(modules)
.buildComputeServiceContext();
}
}

View File

@ -40,11 +40,11 @@ import javax.inject.Provider;
import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.Constants;
import org.jclouds.aws.reference.AWSConstants;
import org.jclouds.aws.util.RequestSigner;
import org.jclouds.date.TimeStamp;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
@ -78,7 +78,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
private final Provider<String> dateService;
private final EncryptionService encryptionService;
@Resource
@Named(HttpConstants.LOGGER_SIGNATURE)
@Named(Constants.LOGGER_SIGNATURE)
private Logger signatureLog = Logger.NULL;
@Inject

View File

@ -21,10 +21,10 @@ package org.jclouds.aws.handlers;
import javax.annotation.Resource;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler;
@ -41,7 +41,7 @@ import com.google.inject.Inject;
public class AWSClientErrorRetryHandler implements HttpRetryHandler {
@Inject(optional = true)
@Named(HttpConstants.PROPERTY_HTTP_MAX_RETRIES)
@Named(Constants.PROPERTY_MAX_RETRIES)
private int retryCountLimit = 5;
private final AWSUtils utils;

View File

@ -18,20 +18,25 @@
*/
package org.jclouds.aws.handlers;
import java.io.IOException;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.util.Utils;
import com.google.common.base.Throwables;
import com.google.common.io.Closeables;
/**
* This will parse and set an appropriate exception on the command object.
@ -52,28 +57,38 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
}
public void handleError(HttpCommand command, HttpResponse response) {
String content;
Exception exception = null;
try {
content = response.getContent() != null ? Utils.toStringAndClose(response.getContent())
: null;
if (content != null) {
try {
if (content.indexOf('<') >= 0) {
AWSError error = utils.parseAWSErrorFromContent(command, response, content);
command.setException(new AWSResponseException(command, response, error));
} else {
command.setException(new HttpResponseException(command, response, content));
switch (response.getStatusCode()) {
case 401:
exception = new AuthorizationException(command.getRequest().getRequestLine());
break;
case 404:
String container = command.getRequest().getEndpoint().getHost();
String key = command.getRequest().getEndpoint().getPath();
if (key == null || key.equals("/"))
exception = new ContainerNotFoundException(container);
else
exception = new KeyNotFoundException(container, key);
break;
default:
if (response.getContent() != null) {
try {
String content = Utils.toStringAndClose(response.getContent());
if (content.indexOf('<') >= 0) {
AWSError error = utils.parseAWSErrorFromContent(command, response, content);
exception = new AWSResponseException(command, response, error);
} else {
exception = new HttpResponseException(command, response, content);
}
} catch (IOException e) {
logger.warn(e, "exception reading error from response", response);
}
}
} catch (Exception he) {
command.setException(new HttpResponseException(command, response, content));
Throwables.propagateIfPossible(he);
}
} else if (response.getStatusCode() == 404) {
command.setException(new HttpResponseException(command, response));
}
} catch (Exception e) {
command.setException(new HttpResponseException(command, response));
Throwables.propagateIfPossible(e);
} finally {
Closeables.closeQuietly(response.getContent());
command.setException(exception);
}
}
}

View File

@ -18,15 +18,14 @@
*/
package org.jclouds.aws.reference;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.pool.PoolConstants;
import org.jclouds.Constants;
/**
* Configuration properties and constants used in AWS connections.
*
* @author Adrian Cole
*/
public interface AWSConstants extends HttpConstants, PoolConstants {
public interface AWSConstants extends Constants {
public static final String ENDPOINT = "Endpoint";
public static final String PROPERTY_AWS_SECRETACCESSKEY = "jclouds.aws.secretaccesskey";
public static final String PROPERTY_AWS_ACCESSKEYID = "jclouds.aws.accesskeyid";

View File

@ -49,7 +49,7 @@ import org.jclouds.aws.s3.functions.ObjectKey;
import org.jclouds.aws.s3.functions.ParseObjectFromHeadersAndHttpContent;
import org.jclouds.aws.s3.functions.ParseObjectMetadataFromHeaders;
import org.jclouds.aws.s3.functions.ReturnTrueIfBucketAlreadyOwnedByYou;
import org.jclouds.aws.s3.functions.ReturnTrueOn404FalseIfNotEmpty;
import org.jclouds.aws.s3.functions.ReturnTrueOn404OrNotFoundFalseIfNotEmpty;
import org.jclouds.aws.s3.options.CopyObjectOptions;
import org.jclouds.aws.s3.options.ListBucketOptions;
import org.jclouds.aws.s3.options.PutBucketOptions;
@ -64,11 +64,12 @@ import org.jclouds.aws.s3.xml.PayerHandler;
import org.jclouds.blobstore.attr.BlobScope;
import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.attr.ConsistencyModels;
import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound;
import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.options.GetOptions;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Endpoint;
@ -130,6 +131,15 @@ public interface S3AsyncClient {
ListenableFuture<ObjectMetadata> headObject(@HostPrefixParam String bucketName,
@PathParam("key") String key);
/**
* @see S3Client#objectExists
*/
@HEAD
@Path("{key}")
@ExceptionParser(ReturnFalseOnKeyNotFound.class)
ListenableFuture<Boolean> objectExists(@HostPrefixParam String bucketName,
@PathParam("key") String key);
/**
* @see S3Client#deleteObject
*/
@ -166,7 +176,7 @@ public interface S3AsyncClient {
*/
@DELETE
@Path("/")
@ExceptionParser(ReturnTrueOn404FalseIfNotEmpty.class)
@ExceptionParser(ReturnTrueOn404OrNotFoundFalseIfNotEmpty.class)
ListenableFuture<Boolean> deleteBucketIfEmpty(@HostPrefixParam String bucketName);
/**
@ -175,7 +185,7 @@ public interface S3AsyncClient {
@HEAD
@Path("/")
@QueryParams(keys = "max-keys", values = "0")
@ExceptionParser(ReturnFalseOn404.class)
@ExceptionParser(ReturnFalseOnContainerNotFound.class)
ListenableFuture<Boolean> bucketExists(@HostPrefixParam String bucketName);
/**

View File

@ -50,7 +50,7 @@ import com.google.common.util.concurrent.ListenableFuture;
* @author James Murty
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAPI.html" />
*/
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
@Timeout(duration = 90, timeUnit = TimeUnit.SECONDS)
public interface S3Client {
/**
@ -75,6 +75,11 @@ public interface S3Client {
* <li>{@link GetObjectOptions#tail}</li>
* </ul>
*
* <h3>Timeout</h3>
* The maximum size of an object in S3 is 5GB. We've set the timeout according to a rate of
* 512kb/s for the maximum size. If you wish a shorter timeout, please use the
* {@link S3AsyncClient} interface}.
*
* @param bucketName
* namespace of the object you are retrieving
* @param key
@ -87,7 +92,7 @@ public interface S3Client {
* @see #getObject(String, String)
* @see GetObjectOptions
*/
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
@Timeout(duration = 5 * 1024 * 1024 / 512, timeUnit = TimeUnit.SECONDS)
S3Object getObject(String bucketName, String key, GetOptions... options);
/**
@ -116,6 +121,8 @@ public interface S3Client {
*/
ObjectMetadata headObject(String bucketName, String key);
boolean objectExists(String bucketName, String key);
/**
* Removes the object and metadata associated with the key.
* <p/>
@ -143,6 +150,10 @@ public interface S3Client {
* <p/>
* This returns a byte[] of the eTag hash of what Amazon S3 received
* <p />
* <h3>Timeout</h3>
* The maximum size of an object in S3 is 5GB. We've set the timeout according to a rate of
* 128kb/s for the maximum size. If you wish a shorter timeout, please use the
* {@link S3AsyncClient} interface}.
*
* @param bucketName
* namespace of the object you are storing
@ -158,7 +169,7 @@ public interface S3Client {
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT.html"
* />
*/
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
@Timeout(duration = 5 * 1024 * 1024 / 128, timeUnit = TimeUnit.SECONDS)
String putObject(String bucketName, S3Object object, PutObjectOptions... options);
/**

View File

@ -18,24 +18,15 @@
*/
package org.jclouds.aws.s3;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_METADATA_PREFIX;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_RETRY;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_TIMEOUT;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_BLOBSTORE_RETRY;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import java.util.List;
import java.util.Properties;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import org.jclouds.aws.s3.config.S3ContextModule;
import org.jclouds.aws.s3.blobstore.config.S3BlobStoreContextModule;
import org.jclouds.aws.s3.config.S3RestClientModule;
import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.RestContextBuilder;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
@ -53,42 +44,21 @@ import com.google.inject.TypeLiteral;
* @author Adrian Cole, Andrew Newdigate
* @see S3Context
*/
public class S3ContextBuilder extends RestContextBuilder<S3AsyncClient, S3Client> {
public class S3ContextBuilder extends BlobStoreContextBuilder<S3AsyncClient, S3Client> {
public S3ContextBuilder(Properties props) {
super(new TypeLiteral<S3AsyncClient>() {
}, new TypeLiteral<S3Client>() {
}, convert(props));
}
private static Properties convert(Properties props) {
for (Entry<String, String> entry : ImmutableMap.of(PROPERTY_S3_METADATA_PREFIX,
PROPERTY_USER_METADATA_PREFIX, PROPERTY_S3_RETRY, PROPERTY_BLOBSTORE_RETRY,
PROPERTY_S3_TIMEOUT, PROPERTY_USER_METADATA_PREFIX).entrySet()) {
if (props.containsKey(entry.getKey()))
props.setProperty(entry.getValue(), props.getProperty(entry.getKey()));
}
return props;
}, props);
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new S3ContextModule());
modules.add(new S3BlobStoreContextModule());
}
@Override
protected void addClientModule(List<Module> modules) {
modules.add(new S3RestClientModule());
}
@Override
public S3ContextBuilder withExecutorService(ExecutorService service) {
return (S3ContextBuilder) super.withExecutorService(service);
}
@Override
public S3ContextBuilder withModules(Module... modules) {
return (S3ContextBuilder) super.withModules(modules);
}
}
}

View File

@ -21,9 +21,9 @@ package org.jclouds.aws.s3;
import java.net.URI;
import java.util.Properties;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.RestContext;
import com.google.inject.Module;
@ -41,27 +41,27 @@ import com.google.inject.Module;
*/
public class S3ContextFactory {
public static RestContext<S3AsyncClient, S3Client> createContext(Properties properties,
public static BlobStoreContext createContext(Properties properties,
Module... modules) {
return new S3ContextBuilder(new S3PropertiesBuilder(properties).build()).withModules(modules)
.buildContext();
.buildBlobStoreContext();
}
public static RestContext<S3AsyncClient, S3Client> createContext(Properties properties,
public static BlobStoreContext createContext(Properties properties,
String awsAccessKeyId, String awsSecretAccessKey, Module... modules) {
return new S3ContextBuilder(new S3PropertiesBuilder(properties).withCredentials(
awsAccessKeyId, awsSecretAccessKey).build()).withModules(modules).buildContext();
awsAccessKeyId, awsSecretAccessKey).build()).withModules(modules).buildBlobStoreContext();
}
public static RestContext<S3AsyncClient, S3Client> createContext(String awsAccessKeyId,
public static BlobStoreContext createContext(String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new S3ContextBuilder(new S3PropertiesBuilder(awsAccessKeyId, awsSecretAccessKey)
.build()).withModules(modules).buildContext();
.build()).withModules(modules).buildBlobStoreContext();
}
public static RestContext<S3AsyncClient, S3Client> createContext(URI endpoint,
public static BlobStoreContext createContext(URI endpoint,
String awsAccessKeyId, String awsSecretAccessKey, Module... modules) {
return new S3ContextBuilder(new S3PropertiesBuilder(awsAccessKeyId, awsSecretAccessKey)
.withEndpoint(endpoint).build()).withModules(modules).buildContext();
.withEndpoint(endpoint).build()).withModules(modules).buildBlobStoreContext();
}
}

View File

@ -19,35 +19,33 @@
package org.jclouds.aws.s3;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.Constants.PROPERTY_RELAX_HOSTNAME;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_ENDPOINT;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_METADATA_PREFIX;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_RETRY;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SESSIONINTERVAL;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_TIMEOUT;
import static org.jclouds.blobstore.reference.BlobStoreConstants.DIRECTORY_SUFFIX_FOLDER;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_BLOBSTORE_DIRECTORY_SUFFIX;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_RELAX_HOSTNAME;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import java.net.URI;
import java.util.Properties;
import org.jclouds.PropertiesBuilder;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.http.HttpPropertiesBuilder;
/**
* Builds properties used in S3 Connections
*
* @author Adrian Cole
*/
public class S3PropertiesBuilder extends HttpPropertiesBuilder {
public class S3PropertiesBuilder extends PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_HTTP_RELAX_HOSTNAME, "true");
properties.setProperty(PROPERTY_RELAX_HOSTNAME, "true");
properties.setProperty(PROPERTY_S3_ENDPOINT, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_S3_METADATA_PREFIX, "x-amz-meta-");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "x-amz-meta-");
properties.setProperty(PROPERTY_S3_SESSIONINTERVAL, "60");
properties.setProperty(PROPERTY_BLOBSTORE_DIRECTORY_SUFFIX, DIRECTORY_SUFFIX_FOLDER);
return properties;
@ -81,24 +79,8 @@ public class S3PropertiesBuilder extends HttpPropertiesBuilder {
return this;
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public S3PropertiesBuilder withRequestTimeout(long milliseconds) {
properties.setProperty(PROPERTY_S3_TIMEOUT, Long.toString(milliseconds));
return this;
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public S3PropertiesBuilder withMaxRetries(int retries) {
properties.setProperty(PROPERTY_S3_RETRY, Integer.toString(retries));
return this;
}
protected S3PropertiesBuilder withMetaPrefix(String prefix) {
properties.setProperty(PROPERTY_S3_METADATA_PREFIX, prefix);
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, prefix);
return this;
}
}

View File

@ -28,12 +28,13 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.s3.S3AsyncClient;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.blobstore.functions.BlobToObject;
import org.jclouds.aws.s3.blobstore.functions.BlobToObjectGetOptions;
import org.jclouds.aws.s3.blobstore.functions.BucketToResourceList;
import org.jclouds.aws.s3.blobstore.functions.BucketToResourceMetadata;
import org.jclouds.aws.s3.blobstore.functions.ContainerToBucketListOptions;
@ -53,6 +54,7 @@ import org.jclouds.blobstore.domain.ListResponse;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.blobstore.domain.internal.ListResponseImpl;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.strategy.ClearListStrategy;
import org.jclouds.blobstore.strategy.GetDirectoryStrategy;
@ -75,94 +77,19 @@ public class S3AsyncBlobStore extends BaseS3BlobStore implements AsyncBlobStore
LoggerFactory logFactory, ClearListStrategy clearContainerStrategy,
ObjectToBlobMetadata object2BlobMd, ObjectToBlob object2Blob, BlobToObject blob2Object,
ContainerToBucketListOptions container2BucketListOptions,
BlobToObjectGetOptions blob2ObjectGetOptions,
GetDirectoryStrategy getDirectoryStrategy, MkdirStrategy mkdirStrategy,
BucketToResourceMetadata bucket2ResourceMd, BucketToResourceList bucket2ResourceList,
ExecutorService service) {
BlobToHttpGetOptions blob2ObjectGetOptions, GetDirectoryStrategy getDirectoryStrategy,
MkdirStrategy mkdirStrategy, BucketToResourceMetadata bucket2ResourceMd,
BucketToResourceList bucket2ResourceList,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service) {
super(async, sync, blobFactory, logFactory, clearContainerStrategy, object2BlobMd,
object2Blob, blob2Object, container2BucketListOptions, blob2ObjectGetOptions,
getDirectoryStrategy, mkdirStrategy, bucket2ResourceMd, bucket2ResourceList, service);
}
/**
* This implementation uses the S3 HEAD Object command to return the result
* This implementation invokes {@link S3AsyncClient#listOwnedBuckets}
*/
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return compose(convertExceptionToValue(async.headObject(container, key),
KeyNotFoundException.class, null), new Function<ObjectMetadata, BlobMetadata>() {
@Override
public BlobMetadata apply(ObjectMetadata from) {
return object2BlobMd.apply(from);
}
}, service);
}
public ListenableFuture<Void> clearContainer(final String container) {
return makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
clearContainerStrategy.execute(container, recursive());
return null;
}
}), service);
}
public ListenableFuture<Void> deleteContainer(final String container) {
return makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
clearContainerStrategy.execute(container, recursive());
async.deleteBucketIfEmpty(container).get();
return null;
}
}), service);
}
public ListenableFuture<Boolean> createContainerInLocation(String location, String container) {
return async.putBucketInRegion(Region.DEFAULT, container);// TODO
}
public ListenableFuture<Boolean> containerExists(String container) {
return async.bucketExists(container);
}
public ListenableFuture<Void> createDirectory(final String container, final String directory) {
return makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
mkdirStrategy.execute(S3AsyncBlobStore.this, container, directory);
return null;
}
}), service);
}
public ListenableFuture<Boolean> directoryExists(final String container, final String directory) {
return makeListenable(service.submit(new Callable<Boolean>() {
public Boolean call() throws Exception {
try {
getDirectoryStrategy.execute(S3AsyncBlobStore.this, container, directory);
return true;
} catch (KeyNotFoundException e) {
return false;
}
}
}), service);
}
public ListenableFuture<Blob> getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions... optionsList) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList);
return compose(convertExceptionToValue(async.getObject(container, key, httpOptions),
KeyNotFoundException.class, null), object2Blob, service);
}
@Override
public ListenableFuture<? extends ListResponse<? extends StorageMetadata>> list() {
return compose(
async.listOwnedBuckets(),
@ -175,17 +102,227 @@ public class S3AsyncBlobStore extends BaseS3BlobStore implements AsyncBlobStore
}, service);
}
/**
* This implementation invokes {@link S3AsyncClient#bucketExists}
*
* @param container
* bucket name
*/
@Override
public ListenableFuture<Boolean> containerExists(String container) {
return async.bucketExists(container);
}
/**
* This implementation invokes {@link S3AsyncClient#putBucketInRegion}
*
* @param location
* corresponds to {@link Region#fromValue}
* @param container
* bucket name
*/
@Override
public ListenableFuture<Boolean> createContainerInLocation(String location, String container) {
return async.putBucketInRegion(Region.fromValue(location), container);
}
/**
* This implementation invokes
* {@link #list(String,org.jclouds.blobstore.options.ListContainerOptions)}
*
* @param container
* bucket name
*/
@Override
public ListenableFuture<? extends ListContainerResponse<? extends StorageMetadata>> list(
String container, ListContainerOptions... optionsList) {
ListBucketOptions httpOptions = container2BucketListOptions.apply(optionsList);
String container) {
return this.list(container, org.jclouds.blobstore.options.ListContainerOptions.NONE);
}
/**
* This implementation invokes {@link S3AsyncClient#listBucket}
*
* @param container
* bucket name
*/
@Override
public ListenableFuture<? extends ListContainerResponse<? extends StorageMetadata>> list(
String container, ListContainerOptions options) {
ListBucketOptions httpOptions = container2BucketListOptions.apply(options);
ListenableFuture<ListBucketResponse> returnVal = async.listBucket(container, httpOptions);
return compose(returnVal, bucket2ResourceList, service);
}
/**
* This implementation invokes {@link ClearListStrategy#execute} with the
* {@link ListContainerOptions#recursive} option.
*
* @param container
* bucket name
*/
@Override
public ListenableFuture<Void> clearContainer(final String container) {
return makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
clearContainerStrategy.execute(container, recursive());
return null;
}
}), service);
}
/**
* This implementation invokes {@link ClearListStrategy#execute} with the
* {@link ListContainerOptions#recursive} option. Then, it invokes
* {@link S3AsyncClient#deleteBucketIfEmpty}
*
* @param container
* bucket name
*/
@Override
public ListenableFuture<Void> deleteContainer(final String container) {
return makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
clearContainerStrategy.execute(container, recursive());
async.deleteBucketIfEmpty(container).get();
return null;
}
}), service);
}
/**
* This implementation invokes {@link GetDirectoryStrategy#execute}
*
* @param container
* bucket name
* @param directory
* virtual path
*/
@Override
public ListenableFuture<Boolean> directoryExists(final String container, final String directory) {
return makeListenable(service.submit(new Callable<Boolean>() {
public Boolean call() throws Exception {
try {
getDirectoryStrategy.execute(container, directory);
return true;
} catch (KeyNotFoundException e) {
return false;
}
}
}), service);
}
/**
* This implementation invokes {@link MkdirStrategy#execute}
*
* @param container
* bucket name
* @param directory
* virtual path
*/
@Override
public ListenableFuture<Void> createDirectory(final String container, final String directory) {
return makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
mkdirStrategy.execute(container, directory);
return null;
}
}), service);
}
/**
* This implementation invokes {@link S3AsyncClient#objectExists}
*
* @param container
* bucket name
* @param key
* object key
*/
@Override
public ListenableFuture<Boolean> blobExists(String container, String key) {
return async.objectExists(container, key);
}
/**
* This implementation invokes {@link S3AsyncClient#headObject}
*
* @param container
* bucket name
* @param key
* object key
*/
@Override
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return compose(convertExceptionToValue(async.headObject(container, key),
KeyNotFoundException.class, null), new Function<ObjectMetadata, BlobMetadata>() {
@Override
public BlobMetadata apply(ObjectMetadata from) {
return object2BlobMd.apply(from);
}
}, service);
}
/**
* This implementation invokes
* {@link #getBlob(String,String,org.jclouds.blobstore.options.GetOptions)}
*
* @param container
* bucket name
* @param key
* object key
*/
@Override
public ListenableFuture<Blob> getBlob(String container, String key) {
return getBlob(container, key, org.jclouds.blobstore.options.GetOptions.NONE);
}
/**
* This implementation invokes {@link S3AsyncClient#getObject}
*
* @param container
* bucket name
* @param key
* object key
*/
@Override
public ListenableFuture<Blob> getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions options) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
return compose(convertExceptionToValue(async.getObject(container, key, httpOptions),
KeyNotFoundException.class, null), object2Blob, service);
}
/**
* This implementation invokes {@link S3AsyncClient#putObject}
*
* @param container
* bucket name
* @param blob
* object
*/
@Override
public ListenableFuture<String> putBlob(String container, Blob blob) {
return async.putObject(container, blob2Object.apply(blob));
}
/**
* This implementation invokes {@link S3AsyncClient#deleteObject}
*
* @param container
* bucket name
* @param key
* object key
*/
@Override
public ListenableFuture<Void> removeBlob(String container, String key) {
return async.deleteObject(container, key);
}

View File

@ -19,18 +19,19 @@
package org.jclouds.aws.s3.blobstore;
import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
import static org.jclouds.blobstore.util.BlobStoreUtils.returnNullOnKeyNotFoundOrPropagate;
import static org.jclouds.blobstore.util.BlobStoreUtils.keyNotFoundToNullOrPropagate;
import java.util.SortedSet;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.s3.S3AsyncClient;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.blobstore.functions.BlobToObject;
import org.jclouds.aws.s3.blobstore.functions.BlobToObjectGetOptions;
import org.jclouds.aws.s3.blobstore.functions.BucketToResourceList;
import org.jclouds.aws.s3.blobstore.functions.BucketToResourceMetadata;
import org.jclouds.aws.s3.blobstore.functions.ContainerToBucketListOptions;
@ -48,6 +49,7 @@ import org.jclouds.blobstore.domain.ListResponse;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.blobstore.domain.internal.ListResponseImpl;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.strategy.ClearListStrategy;
import org.jclouds.blobstore.strategy.GetDirectoryStrategy;
@ -59,75 +61,25 @@ import com.google.common.base.Function;
import com.google.common.collect.Iterables;
public class S3BlobStore extends BaseS3BlobStore implements BlobStore {
private final S3AsyncBlobStore aBlobStore;
@Inject
public S3BlobStore(S3AsyncBlobStore aBlobStore, S3AsyncClient async, S3Client sync,
Factory blobFactory, LoggerFactory logFactory,
ClearListStrategy clearContainerStrategy, ObjectToBlobMetadata object2BlobMd,
ObjectToBlob object2Blob, BlobToObject blob2Object,
public S3BlobStore(S3AsyncClient async, S3Client sync, Factory blobFactory,
LoggerFactory logFactory, ClearListStrategy clearContainerStrategy,
ObjectToBlobMetadata object2BlobMd, ObjectToBlob object2Blob, BlobToObject blob2Object,
ContainerToBucketListOptions container2BucketListOptions,
BlobToObjectGetOptions blob2ObjectGetOptions,
GetDirectoryStrategy getDirectoryStrategy, MkdirStrategy mkdirStrategy,
BucketToResourceMetadata bucket2ResourceMd, BucketToResourceList bucket2ResourceList,
ExecutorService service) {
BlobToHttpGetOptions blob2ObjectGetOptions, GetDirectoryStrategy getDirectoryStrategy,
MkdirStrategy mkdirStrategy, BucketToResourceMetadata bucket2ResourceMd,
BucketToResourceList bucket2ResourceList,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service) {
super(async, sync, blobFactory, logFactory, clearContainerStrategy, object2BlobMd,
object2Blob, blob2Object, container2BucketListOptions, blob2ObjectGetOptions,
getDirectoryStrategy, mkdirStrategy, bucket2ResourceMd, bucket2ResourceList, service);
this.aBlobStore = aBlobStore;
}
/**
* This implementation uses the S3 HEAD Object command to return the result
* This implementation invokes {@link S3Client#listOwnedBuckets}
*/
public BlobMetadata blobMetadata(String container, String key) {
try {
return object2BlobMd.apply(sync.headObject(container, key));
} catch (Exception e) {
return returnNullOnKeyNotFoundOrPropagate(e);
}
}
public void clearContainer(String container) {
clearContainerStrategy.execute(container, recursive());
}
public boolean containerExists(String container) {
return sync.bucketExists(container);
}
public boolean createContainerInLocation(String location, String container) {
return sync.putBucketInRegion(Region.DEFAULT, container);// TODO parameterize
}
public void deleteContainer(String container) {
clearContainer(container);
sync.deleteBucketIfEmpty(container);
}
public boolean directoryExists(String containerName, String directory) {
try {
getDirectoryStrategy.execute(aBlobStore, containerName, directory);
return true;
} catch (KeyNotFoundException e) {
return false;
}
}
public void createDirectory(String containerName, String directory) {
mkdirStrategy.execute(aBlobStore, containerName, directory);
}
public Blob getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions... optionsList) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList);
try {
return object2Blob.apply(sync.getObject(container, key, httpOptions));
} catch (Exception e) {
return returnNullOnKeyNotFoundOrPropagate(e);
}
}
@Override
public ListResponse<? extends StorageMetadata> list() {
return new Function<SortedSet<BucketMetadata>, org.jclouds.blobstore.domain.ListResponse<? extends StorageMetadata>>() {
public org.jclouds.blobstore.domain.ListResponse<? extends StorageMetadata> apply(
@ -138,16 +90,197 @@ public class S3BlobStore extends BaseS3BlobStore implements BlobStore {
}.apply(sync.listOwnedBuckets());
}
/**
* This implementation invokes {@link S3Client#bucketExists}
*
* @param container
* bucket name
*/
@Override
public boolean containerExists(String container) {
return sync.bucketExists(container);
}
/**
* This implementation invokes {@link S3Client#putBucketInRegion}
*
* @param location
* corresponds to {@link Region#fromValue}
* @param container
* bucket name
*/
@Override
public boolean createContainerInLocation(String location, String container) {
return sync.putBucketInRegion(Region.DEFAULT, container);// TODO parameterize
}
/**
* This implementation invokes
* {@link #list(String,org.jclouds.blobstore.options.ListContainerOptions)}
*
* @param container
* bucket name
*/
@Override
public ListContainerResponse<? extends StorageMetadata> list(String container) {
return this.list(container, org.jclouds.blobstore.options.ListContainerOptions.NONE);
}
/**
* This implementation invokes {@link S3Client#listBucket}
*
* @param container
* bucket name
*/
@Override
public ListContainerResponse<? extends StorageMetadata> list(String container,
ListContainerOptions... optionsList) {
ListContainerOptions optionsList) {
ListBucketOptions httpOptions = container2BucketListOptions.apply(optionsList);
return bucket2ResourceList.apply(sync.listBucket(container, httpOptions));
}
/**
* This implementation invokes {@link ClearListStrategy#execute} with the
* {@link ListContainerOptions#recursive} option.
*
* @param container
* bucket name
*/
@Override
public void clearContainer(String container) {
clearContainerStrategy.execute(container, recursive());
}
/**
* This implementation invokes {@link ClearListStrategy#execute} with the
* {@link ListContainerOptions#recursive} option. Then, it invokes
* {@link S3Client#deleteBucketIfEmpty}
*
* @param container
* bucket name
*/
@Override
public void deleteContainer(String container) {
clearContainer(container);
sync.deleteBucketIfEmpty(container);
}
/**
* This implementation invokes {@link GetDirectoryStrategy#execute}
*
* @param container
* bucket name
* @param directory
* virtual path
*/
@Override
public boolean directoryExists(String containerName, String directory) {
try {
getDirectoryStrategy.execute(containerName, directory);
return true;
} catch (KeyNotFoundException e) {
return false;
}
}
/**
* This implementation invokes {@link MkdirStrategy#execute}
*
* @param container
* bucket name
* @param directory
* virtual path
*/
@Override
public void createDirectory(String containerName, String directory) {
mkdirStrategy.execute(containerName, directory);
}
/**
* This implementation invokes {@link S3Client#objectExists}
*
* @param container
* bucket name
* @param key
* object key
*/
@Override
public boolean blobExists(String container, String key) {
return sync.objectExists(container, key);
}
/**
* This implementation invokes {@link S3Client#headObject}
*
* @param container
* bucket name
* @param key
* object key
*/
@Override
public BlobMetadata blobMetadata(String container, String key) {
try {
return object2BlobMd.apply(sync.headObject(container, key));
} catch (Exception e) {
return keyNotFoundToNullOrPropagate(e);
}
}
/**
* This implementation invokes
* {@link #getBlob(String,String,org.jclouds.blobstore.options.GetOptions)}
*
* @param container
* bucket name
* @param key
* object key
*/
@Override
public Blob getBlob(String container, String key) {
return getBlob(container, key, org.jclouds.blobstore.options.GetOptions.NONE);
}
/**
* This implementation invokes {@link S3Client#getObject}
*
* @param container
* bucket name
* @param key
* object key
*/
@Override
public Blob getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions optionsList) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList);
try {
return object2Blob.apply(sync.getObject(container, key, httpOptions));
} catch (Exception e) {
return keyNotFoundToNullOrPropagate(e);
}
}
/**
* This implementation invokes {@link S3Client#putObject}
*
* @param container
* bucket name
* @param blob
* object
*/
@Override
public String putBlob(String container, Blob blob) {
return sync.putObject(container, blob2Object.apply(blob));
}
/**
* This implementation invokes {@link S3Client#deleteObject}
*
* @param container
* bucket name
* @param key
* object key
*/
@Override
public void removeBlob(String container, String key) {
sync.deleteObject(container, key);
}

View File

@ -1,95 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.blobstore;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_METADATA_PREFIX;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_RETRY;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_TIMEOUT;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_BLOBSTORE_RETRY;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import java.util.List;
import java.util.Properties;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import org.jclouds.aws.s3.S3AsyncClient;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.blobstore.config.S3BlobStoreContextModule;
import org.jclouds.aws.s3.config.S3RestClientModule;
import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Creates {@link S3BlobStoreContext} or {@link Injector} instances based on the most commonly
* requested arguments.
* <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 JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole, Andrew Newdigate
* @see S3BlobStoreContext
*/
public class S3BlobStoreContextBuilder extends BlobStoreContextBuilder<S3AsyncClient, S3Client> {
public S3BlobStoreContextBuilder(Properties props) {
super(new TypeLiteral<S3AsyncClient>() {
}, new TypeLiteral<S3Client>() {
}, convert(props));
}
private static Properties convert(Properties props) {
for (Entry<String, String> entry : ImmutableMap.of(PROPERTY_S3_METADATA_PREFIX,
PROPERTY_USER_METADATA_PREFIX, PROPERTY_S3_RETRY, PROPERTY_BLOBSTORE_RETRY,
PROPERTY_S3_TIMEOUT, PROPERTY_USER_METADATA_PREFIX).entrySet()) {
if (props.containsKey(entry.getKey()))
props.setProperty(entry.getValue(), props.getProperty(entry.getKey()));
}
return props;
}
@Override
public S3BlobStoreContextBuilder withExecutorService(ExecutorService service) {
return (S3BlobStoreContextBuilder) super.withExecutorService(service);
}
@Override
public S3BlobStoreContextBuilder withModules(Module... modules) {
return (S3BlobStoreContextBuilder) super.withModules(modules);
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new S3BlobStoreContextModule());
}
@Override
protected void addClientModule(List<Module> modules) {
modules.add(new S3RestClientModule());
}
}

View File

@ -1,68 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.blobstore;
import java.net.URI;
import java.util.Properties;
import org.jclouds.aws.s3.S3PropertiesBuilder;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.inject.Module;
/**
* Creates {@link S3BlobStoreContext} instances based on the most commonly requested arguments.
* <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 JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole, Andrew Newdigate
* @see S3BlobStoreContext
*/
public class S3BlobStoreContextFactory {
public static BlobStoreContext createContext(Properties properties, Module... modules) {
return new S3BlobStoreContextBuilder(new S3PropertiesBuilder(properties).build())
.withModules(modules).buildBlobStoreContext();
}
public static BlobStoreContext createContext(String awsAccessKeyId, String awsSecretAccessKey,
Module... modules) {
return new S3BlobStoreContextBuilder(new S3PropertiesBuilder(awsAccessKeyId,
awsSecretAccessKey).build()).withModules(modules).buildBlobStoreContext();
}
public static BlobStoreContext createContext(Properties properties, String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new S3BlobStoreContextBuilder(new S3PropertiesBuilder(properties).withCredentials(
awsAccessKeyId, awsSecretAccessKey).build()).withModules(modules)
.buildBlobStoreContext();
}
public static BlobStoreContext createContext(URI endpoint, String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new S3BlobStoreContextBuilder(new S3PropertiesBuilder(awsAccessKeyId,
awsSecretAccessKey).withEndpoint(endpoint).build()).withModules(modules)
.buildBlobStoreContext();
}
}

View File

@ -56,7 +56,7 @@ public class S3BlobStoreContextModule extends S3ContextModule {
@Singleton
BlobStoreContext provideContext(BlobMap.Factory blobMapFactory,
InputStreamMap.Factory inputStreamMapFactory, Closer closer,
AsyncBlobStore asynchBlobStore, BlobStore blobStore,
S3AsyncBlobStore asynchBlobStore, S3BlobStore blobStore,
RestContext<S3AsyncClient, S3Client> context) {
return new BlobStoreContextImpl<S3AsyncClient, S3Client>(blobMapFactory,
inputStreamMapFactory, asynchBlobStore, blobStore, context);

View File

@ -1,60 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.http.options.GetOptions;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class BlobToObjectGetOptions implements
Function<org.jclouds.blobstore.options.GetOptions[], GetOptions> {
public GetOptions apply(org.jclouds.blobstore.options.GetOptions[] from) {
GetOptions httpOptions = new GetOptions();
if (from.length != 0) {
if (from[0].getIfMatch() != null) {
httpOptions.ifETagMatches(from[0].getIfMatch());
}
if (from[0].getIfModifiedSince() != null) {
httpOptions.ifModifiedSince(from[0].getIfModifiedSince());
}
if (from[0].getIfNoneMatch() != null) {
httpOptions.ifETagDoesntMatch(from[0].getIfNoneMatch());
}
if (from[0].getIfUnmodifiedSince() != null) {
httpOptions.ifUnmodifiedSince(from[0].getIfUnmodifiedSince());
}
for (String range : from[0].getRanges()) {
String[] firstLast = range.split("\\-");
if (firstLast.length == 2)
httpOptions.range(Long.parseLong(firstLast[0]), Long.parseLong(firstLast[1]));
else if (range.startsWith("-"))
httpOptions.tail(Long.parseLong(firstLast[0]));
else
httpOptions.startAt(Long.parseLong(firstLast[0]));
}
}
return httpOptions;
}
}

View File

@ -30,24 +30,24 @@ import com.google.common.base.Function;
*/
@Singleton
public class ContainerToBucketListOptions implements
Function<ListContainerOptions[], ListBucketOptions> {
public ListBucketOptions apply(ListContainerOptions[] optionsList) {
Function<ListContainerOptions, ListBucketOptions> {
public ListBucketOptions apply(ListContainerOptions from) {
ListBucketOptions httpOptions = new ListBucketOptions();
if (optionsList.length != 0) {
if (!optionsList[0].isRecursive()) {
if (from != null && from != ListContainerOptions.NONE) {
if (!from.isRecursive()) {
httpOptions.delimiter("/");
}
if (optionsList[0].getDir() != null) {// TODO unit test
String path = optionsList[0].getDir();
if (from.getDir() != null) {// TODO unit test
String path = from.getDir();
if (!path.endsWith("/"))
path = path + "/";
httpOptions.withPrefix(path);
}
if (optionsList[0].getMarker() != null) {
httpOptions.afterMarker(optionsList[0].getMarker());
if (from.getMarker() != null) {
httpOptions.afterMarker(from.getMarker());
}
if (optionsList[0].getMaxResults() != null) {
httpOptions.maxResults(optionsList[0].getMaxResults());
if (from.getMaxResults() != null) {
httpOptions.maxResults(from.getMaxResults());
}
}
return httpOptions;

View File

@ -47,7 +47,8 @@ public class ObjectToBlob implements Function<S3Object, Blob> {
Blob blob = blobFactory.create(object2BlobMd.apply(from.getMetadata()));
if (from.getContentLength() != null)
blob.setContentLength(from.getContentLength());
blob.setPayload(from.getPayload());
if (from.getPayload() != null)
blob.setPayload(from.getPayload());
blob.setAllHeaders(from.getAllHeaders());
return blob;
}

View File

@ -27,13 +27,13 @@ import javax.inject.Inject;
import org.jclouds.aws.s3.S3AsyncClient;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.blobstore.functions.BlobToObject;
import org.jclouds.aws.s3.blobstore.functions.BlobToObjectGetOptions;
import org.jclouds.aws.s3.blobstore.functions.BucketToResourceList;
import org.jclouds.aws.s3.blobstore.functions.BucketToResourceMetadata;
import org.jclouds.aws.s3.blobstore.functions.ContainerToBucketListOptions;
import org.jclouds.aws.s3.blobstore.functions.ObjectToBlob;
import org.jclouds.aws.s3.blobstore.functions.ObjectToBlobMetadata;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.blobstore.strategy.ClearListStrategy;
import org.jclouds.blobstore.strategy.GetDirectoryStrategy;
import org.jclouds.blobstore.strategy.MkdirStrategy;
@ -49,7 +49,7 @@ public class BaseS3BlobStore {
protected final ObjectToBlob object2Blob;
protected final BlobToObject blob2Object;
protected final ContainerToBucketListOptions container2BucketListOptions;
protected final BlobToObjectGetOptions blob2ObjectGetOptions;
protected final BlobToHttpGetOptions blob2ObjectGetOptions;
protected final BucketToResourceMetadata bucket2ResourceMd;
protected final BucketToResourceList bucket2ResourceList;
protected final ExecutorService service;
@ -61,7 +61,7 @@ public class BaseS3BlobStore {
LoggerFactory logFactory, ClearListStrategy clearContainerStrategy,
ObjectToBlobMetadata object2BlobMd, ObjectToBlob object2Blob, BlobToObject blob2Object,
ContainerToBucketListOptions container2BucketListOptions,
BlobToObjectGetOptions blob2ObjectGetOptions,
BlobToHttpGetOptions blob2ObjectGetOptions,
GetDirectoryStrategy getDirectoryStrategy, MkdirStrategy mkdirStrategy,
BucketToResourceMetadata bucket2ResourceMd, BucketToResourceList bucket2ResourceList,
ExecutorService service) {

View File

@ -33,11 +33,11 @@ import javax.inject.Provider;
import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.Constants;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.util.RequestSigner;
import org.jclouds.date.TimeStamp;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
@ -70,7 +70,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
private final EncryptionService encryptionService;
@Resource
@Named(HttpConstants.LOGGER_SIGNATURE)
@Named(Constants.LOGGER_SIGNATURE)
Logger signatureLog = Logger.NULL;
@Inject

View File

@ -61,7 +61,8 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
public S3Object apply(HttpResponse from) {
S3Object object = objectProvider.create(metadataParser.apply(from));
addAllHeadersTo(from, object);
object.setPayload(from.getContent());
if (from.getContent() != null)
object.setPayload(from.getContent());
attemptToParseSizeAndRangeFromHeaders(from, object);
return object;
}

View File

@ -23,14 +23,17 @@ import static org.jclouds.util.Utils.propagateOrNull;
import javax.inject.Singleton;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.blobstore.ContainerNotFoundException;
import com.google.common.base.Function;
@Singleton
public class ReturnTrueOn404FalseIfNotEmpty implements Function<Exception, Boolean> {
public class ReturnTrueOn404OrNotFoundFalseIfNotEmpty implements Function<Exception, Boolean> {
public Boolean apply(Exception from) {
if (from instanceof AWSResponseException) {
if (from instanceof ContainerNotFoundException) {
return true;
} else if (from instanceof AWSResponseException) {
AWSResponseException responseException = (AWSResponseException) from;
if (responseException.getResponse().getStatusCode() == 404) {
return true;

View File

@ -41,18 +41,4 @@ public interface S3Constants extends AWSConstants, S3Headers {
*/
public static final String PROPERTY_S3_SESSIONINTERVAL = "jclouds.s3.sessioninterval";
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public static final String PROPERTY_S3_TIMEOUT = "jclouds.s3.timeout";
/**
* time to pause before retrying a transient failure
*/
public static final String PROPERTY_S3_RETRY = "jclouds.s3.retry";
/**
* Any header starting with this prefix is considered user metadata. It will be stored with the
* object and returned when you retrieve the object/
*/
public static final String PROPERTY_S3_METADATA_PREFIX = "jclouds.s3.metaprefix";
}

View File

@ -20,7 +20,6 @@ package org.jclouds.aws.sqs;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import org.jclouds.aws.sqs.config.SQSContextModule;
import org.jclouds.aws.sqs.config.SQSRestClientModule;
@ -63,11 +62,6 @@ public class SQSContextBuilder extends RestContextBuilder<SQSAsyncClient, SQSCli
modules.add(new SQSRestClientModule());
}
@Override
public SQSContextBuilder withExecutorService(ExecutorService service) {
return (SQSContextBuilder) super.withExecutorService(service);
}
@Override
public SQSContextBuilder withModules(Module... modules) {
return (SQSContextBuilder) super.withModules(modules);

View File

@ -29,14 +29,14 @@ import static org.jclouds.aws.sqs.reference.SQSConstants.PROPERTY_SQS_ENDPOINT_U
import java.net.URI;
import java.util.Properties;
import org.jclouds.http.HttpPropertiesBuilder;
import org.jclouds.PropertiesBuilder;
/**
* Builds properties used in SQS Clients
*
* @author Adrian Cole
*/
public class SQSPropertiesBuilder extends HttpPropertiesBuilder {
public class SQSPropertiesBuilder extends PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();

View File

@ -27,7 +27,6 @@ import javax.inject.Provider;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.xml.ErrorHandler;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseSax;
@ -48,7 +47,7 @@ public class AWSUtils {
Provider<ErrorHandler> errorHandlerProvider;
public AWSError parseAWSErrorFromContent(HttpCommand command, HttpResponse response,
InputStream content) throws HttpException {
InputStream content) {
AWSError error = (AWSError) factory.create(errorHandlerProvider.get()).parse(content);
if ("SignatureDoesNotMatch".equals(error.getCode())) {
error.setStringSigned(signer.createStringToSign(command.getRequest()));
@ -58,7 +57,7 @@ public class AWSUtils {
}
public AWSError parseAWSErrorFromContent(HttpCommand command, HttpResponse response,
String content) throws HttpException {
String content) {
return parseAWSErrorFromContent(command, response, new ByteArrayInputStream(content
.getBytes()));
}

View File

@ -28,12 +28,10 @@ import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
*
* Generally disabled, as it incurs higher fees.
*
* @author Adrian Cole
*/
@Test(groups = "live", enabled = true, sequential = true, testName = "ec2.EC2ComputeServiceLiveTest")
@Test(groups = "live", sequential = true, testName = "ec2.EC2ComputeServiceLiveTest")
public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@BeforeClass
@Override

View File

@ -23,6 +23,7 @@ import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Properties;
import org.jclouds.aws.ec2.EC2ContextBuilder;
import org.jclouds.aws.ec2.EC2PropertiesBuilder;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
@ -45,7 +46,7 @@ public class PropertiesTest {
public void testProperties() {
assertEquals(properties.getProperty("ec2.contextbuilder"),
EC2ComputeServiceContextBuilder.class.getName());
EC2ContextBuilder.class.getName());
assertEquals(properties.getProperty("ec2.propertiesbuilder"),
EC2PropertiesBuilder.class.getName());
}

View File

@ -21,6 +21,7 @@ package org.jclouds.aws.ec2.config;
import static com.google.common.util.concurrent.Executors.sameThreadExecutor;
import static org.testng.Assert.assertEquals;
import org.jclouds.Constants;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.reference.EC2Constants;
@ -45,8 +46,8 @@ import com.google.inject.TypeLiteral;
public class EC2ContextModuleTest {
Injector createInjector() {
return Guice.createInjector(new ExecutorServiceModule(sameThreadExecutor()),
new EC2RestClientModule(), new RestModule(),
return Guice.createInjector(new ExecutorServiceModule(sameThreadExecutor(),
sameThreadExecutor()), new EC2RestClientModule(), new RestModule(),
new JavaUrlHttpCommandExecutorServiceModule(), new JDKLoggingModule(),
new EC2ContextModule() {
@Override
@ -57,6 +58,14 @@ public class EC2ContextModuleTest {
Jsr330.named(EC2Constants.PROPERTY_AWS_SECRETACCESSKEY)).to("key");
bindConstant().annotatedWith(Jsr330.named(EC2Constants.PROPERTY_EC2_ENDPOINT))
.to("http://localhost");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_IO_WORKER_THREADS)).to("1");
bindConstant().annotatedWith(Jsr330.named(Constants.PROPERTY_USER_THREADS))
.to("1");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_MAX_CONNECTIONS_PER_CONTEXT)).to("0");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST)).to("1");
bindConstant().annotatedWith(
Jsr330.named(EC2Constants.PROPERTY_AWS_EXPIREINTERVAL)).to(30);
super.configure();

View File

@ -21,6 +21,7 @@ package org.jclouds.aws.ec2.config;
import static com.google.common.util.concurrent.Executors.sameThreadExecutor;
import static org.testng.Assert.assertEquals;
import org.jclouds.Constants;
import org.jclouds.aws.ec2.reference.EC2Constants;
import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.handlers.AWSRedirectionRetryHandler;
@ -44,19 +45,24 @@ public class EC2RestClientModuleTest {
Injector createInjector() {
return Guice.createInjector(new EC2RestClientModule(), new ExecutorServiceModule(
sameThreadExecutor()), new ParserModule(), new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Jsr330.named(EC2Constants.PROPERTY_AWS_ACCESSKEYID)).to(
"user");
bindConstant().annotatedWith(Jsr330.named(EC2Constants.PROPERTY_AWS_SECRETACCESSKEY))
.to("key");
bindConstant().annotatedWith(Jsr330.named(EC2Constants.PROPERTY_EC2_ENDPOINT)).to(
"http://localhost");
bindConstant().annotatedWith(Jsr330.named(EC2Constants.PROPERTY_AWS_EXPIREINTERVAL))
.to(30);
}
});
sameThreadExecutor(), sameThreadExecutor()), new ParserModule(),
new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(EC2Constants.PROPERTY_AWS_ACCESSKEYID)).to("user");
bindConstant().annotatedWith(
Jsr330.named(EC2Constants.PROPERTY_AWS_SECRETACCESSKEY)).to("key");
bindConstant().annotatedWith(Jsr330.named(EC2Constants.PROPERTY_EC2_ENDPOINT))
.to("http://localhost");
bindConstant().annotatedWith(
Jsr330.named(EC2Constants.PROPERTY_AWS_EXPIREINTERVAL)).to(30);
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_IO_WORKER_THREADS)).to("1");
bindConstant().annotatedWith(Jsr330.named(Constants.PROPERTY_USER_THREADS))
.to("1");
}
});
}
@Test

View File

@ -69,7 +69,8 @@ public class AMIClientLiveTest {
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule());
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule())
.getProviderSpecificContext();
client = context.getApi().getAMIServices();
}
@ -92,6 +93,7 @@ public class AMIClientLiveTest {
}
}
@Test(enabled = false)
public void testRegisterImageFromManifest() {
String imageRegisteredId = client.registerImageFromManifestInRegion(Region.DEFAULT,
"jcloudstest1", DEFAULT_MANIFEST);
@ -105,6 +107,7 @@ public class AMIClientLiveTest {
assertEquals(imageRegisteredFromManifest.getRootDeviceName(), "/dev/sda1");
}
@Test(enabled = false)
public void testRegisterImageFromManifestOptions() {
String imageRegisteredWithOptionsId = client.registerImageFromManifestInRegion(
Region.DEFAULT, "jcloudstest2", DEFAULT_MANIFEST, withDescription("adrian"));
@ -137,9 +140,9 @@ public class AMIClientLiveTest {
@Test(enabled = false)
// awaiting EBS functionality to be added to jclouds
public void testRegisterImageBackedByEBSOptions() {
String imageRegisteredWithOptionsId = client.registerUnixImageBackedByEbsInRegion(Region.DEFAULT,
"jcloudstest2", DEFAULT_SNAPSHOT, addNewBlockDevice("/dev/sda2", "myvirtual", 1)
.withDescription("adrian"));
String imageRegisteredWithOptionsId = client.registerUnixImageBackedByEbsInRegion(
Region.DEFAULT, "jcloudstest2", DEFAULT_SNAPSHOT, addNewBlockDevice("/dev/sda2",
"myvirtual", 1).withDescription("adrian"));
imagesToDeregister.add(imageRegisteredWithOptionsId);
Image imageRegisteredWithOptions = Iterables.getOnlyElement(client.describeImagesInRegion(
Region.DEFAULT, imageIds(imageRegisteredWithOptionsId)));
@ -162,7 +165,7 @@ public class AMIClientLiveTest {
public void testAddProductCodesToImage() {
// TODO client.addProductCodesToImageInRegion(Region.DEFAULT, productCodes, imageId);
}
@Test(enabled = false)
public void testAddLaunchPermissionsToImage() {
// TODO client.addLaunchPermissionsToImageInRegion(Region.DEFAULT, userIds, userGroups,

View File

@ -62,7 +62,8 @@ public class AvailabilityZoneAndRegionClientLiveTest {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule());
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule())
.getProviderSpecificContext();
client = context.getApi().getAvailabilityZoneAndRegionServices();
}

View File

@ -65,7 +65,8 @@ public class ElasticBlockStoreClientLiveTest {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule());
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule())
.getProviderSpecificContext();
client = context.getApi().getElasticBlockStoreServices();
}

View File

@ -54,7 +54,8 @@ public class ElasticIPAddressClientLiveTest {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule());
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule())
.getProviderSpecificContext();
client = context.getApi().getElasticIPAddressServices();
}

View File

@ -24,9 +24,13 @@ import static org.testng.Assert.assertNotNull;
import java.util.Set;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.EC2ContextFactory;
import org.jclouds.aws.ec2.domain.Reservation;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@ -43,14 +47,16 @@ public class InstanceClientLiveTest {
private InstanceClient client;
private String user;
private RestContext<EC2AsyncClient, EC2Client> context;
@BeforeGroups(groups = { "live" })
public void setupClient() {
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule())
.getProviderSpecificContext();
client = context.getApi().getInstanceServices();
client = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule()).getApi()
.getInstanceServices();
}
@Test
@ -62,4 +68,9 @@ public class InstanceClientLiveTest {
assert allResults.size() >= 0 : allResults.size();
}
}
@AfterTest
public void shutdown() {
context.close();
}
}

View File

@ -54,7 +54,8 @@ public class KeyPairClientLiveTest {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule());
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule())
.getProviderSpecificContext();
client = context.getApi().getKeyPairServices();
}

View File

@ -50,7 +50,8 @@ public class MonitoringClientLiveTest {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule());
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule())
.getProviderSpecificContext();
client = context.getApi().getMonitoringServices();
}

View File

@ -62,7 +62,8 @@ public class SecurityGroupClientLiveTest {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule());
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule())
.getProviderSpecificContext();
client = context.getApi().getSecurityGroupServices();
}

View File

@ -18,12 +18,14 @@
*/
package org.jclouds.aws.filters;
import static com.google.common.util.concurrent.Executors.sameThreadExecutor;
import static org.testng.Assert.assertEquals;
import java.util.Date;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.aws.reference.AWSConstants;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.date.DateService;
@ -64,7 +66,7 @@ public class FormSignerTest {
@BeforeClass
protected void createFilter() {
injector = Guice.createInjector(new ParserModule(), new ExecutorServiceModule(Executors
.sameThreadExecutor()), new AbstractModule() {
.sameThreadExecutor(), sameThreadExecutor()), new AbstractModule() {
protected void configure() {
bindConstant().annotatedWith(Jsr330.named(AWSConstants.PROPERTY_AWS_ACCESSKEYID)).to(
@ -73,6 +75,9 @@ public class FormSignerTest {
.to("bar");
bindConstant().annotatedWith(Jsr330.named(AWSConstants.PROPERTY_AWS_EXPIREINTERVAL))
.to(30);
bindConstant().annotatedWith(Jsr330.named(Constants.PROPERTY_IO_WORKER_THREADS))
.to("1");
bindConstant().annotatedWith(Jsr330.named(Constants.PROPERTY_USER_THREADS)).to("1");
}
@SuppressWarnings("unused")

View File

@ -40,7 +40,7 @@ import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.functions.ParseObjectFromHeadersAndHttpContent;
import org.jclouds.aws.s3.functions.ParseObjectMetadataFromHeaders;
import org.jclouds.aws.s3.functions.ReturnTrueIfBucketAlreadyOwnedByYou;
import org.jclouds.aws.s3.functions.ReturnTrueOn404FalseIfNotEmpty;
import org.jclouds.aws.s3.functions.ReturnTrueOn404OrNotFoundFalseIfNotEmpty;
import org.jclouds.aws.s3.options.CopyObjectOptions;
import org.jclouds.aws.s3.options.ListBucketOptions;
import org.jclouds.aws.s3.options.PutBucketOptions;
@ -55,16 +55,17 @@ import org.jclouds.aws.s3.xml.LocationConstraintHandler;
import org.jclouds.aws.s3.xml.PayerHandler;
import org.jclouds.blobstore.binders.BindBlobToMultipartFormTest;
import org.jclouds.blobstore.config.BlobStoreObjectModule;
import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound;
import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.functions.CloseContentAndReturn;
import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.CloseContentAndReturn;
import org.jclouds.http.options.GetOptions;
import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory;
@ -186,7 +187,7 @@ public class S3AsyncClientTest extends RestClientTest<S3AsyncClient> {
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnFalseOn404.class);
assertExceptionParserClassEquals(method, ReturnFalseOnContainerNotFound.class);
checkFilters(httpMethod);
}
@ -223,7 +224,7 @@ public class S3AsyncClientTest extends RestClientTest<S3AsyncClient> {
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnTrueOn404FalseIfNotEmpty.class);
assertExceptionParserClassEquals(method, ReturnTrueOn404OrNotFoundFalseIfNotEmpty.class);
checkFilters(httpMethod);
}
@ -296,6 +297,23 @@ public class S3AsyncClientTest extends RestClientTest<S3AsyncClient> {
checkFilters(httpMethod);
}
public void testObjectExists() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3AsyncClient.class.getMethod("objectExists", String.class, String.class);
GeneratedHttpRequest<S3AsyncClient> httpMethod = processor.createRequest(method, "bucket",
"object");
assertRequestLineEquals(httpMethod, "HEAD http://bucket.stub:8080/object HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnFalseOnKeyNotFound.class);
checkFilters(httpMethod);
}
public void testHeadObject() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3AsyncClient.class.getMethod("headObject", String.class, String.class);

View File

@ -446,7 +446,6 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest {
} finally {
returnContainer(containerName);
returnContainer(destinationContainer);
}
}

View File

@ -1,100 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.jclouds.aws.s3.config.S3ContextModule;
import org.jclouds.aws.s3.config.S3RestClientModule;
import org.jclouds.aws.s3.config.S3StubClientModule;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.internal.S3ObjectImpl;
import org.jclouds.aws.s3.internal.StubS3AsyncClient;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl;
import org.testng.annotations.Test;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of modules configured in S3ContextBuilder
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "s3.S3ContextBuilderTest")
public class S3ContextBuilderTest {
public void testNewBuilder() {
S3ContextBuilder builder = new S3ContextBuilder(new S3PropertiesBuilder("id", "secret")
.build());
assertEquals(builder.getProperties().getProperty(S3Constants.PROPERTY_S3_METADATA_PREFIX),
"x-amz-meta-");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_ACCESSKEYID), "id");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_SECRETACCESSKEY), "secret");
}
public void testBuildContext() {
RestContext<S3AsyncClient, S3Client> context = new S3ContextBuilder(new S3PropertiesBuilder(
"id", "secret").build()).withModules(new S3StubClientModule()).buildContext();
assertEquals(context.getClass(), RestContextImpl.class);
assertEquals(context.getAsyncApi().getClass(), StubS3AsyncClient.class);
assertEquals(context.getAsyncApi().newS3Object().getClass(), S3ObjectImpl.class);
assertEquals(context.getAccount(), "id");
assertEquals(context.getEndPoint(), URI.create("https://localhost/s3stub"));
}
public void testBuildInjector() {
Injector i = new S3ContextBuilder(new S3PropertiesBuilder("id", "secret").build())
.withModules(new S3StubClientModule()).buildInjector();
assert i.getInstance(Key.get(new TypeLiteral<RestContext<S3AsyncClient, S3Client>>() {
})) != null;
assert i.getInstance(S3Object.class) != null;
assert i.getInstance(Blob.class) != null;
}
protected void testAddContextModule() {
List<Module> modules = new ArrayList<Module>();
S3ContextBuilder builder = new S3ContextBuilder(new S3PropertiesBuilder("id", "secret")
.build());
builder.addContextModule(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), S3ContextModule.class);
}
protected void addClientModule() {
List<Module> modules = new ArrayList<Module>();
S3ContextBuilder builder = new S3ContextBuilder(new S3PropertiesBuilder("id", "secret")
.build());
builder.addClientModule(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), S3RestClientModule.class);
}
}

View File

@ -1,105 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.blobstore;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.jclouds.aws.s3.S3AsyncClient;
import org.jclouds.aws.s3.S3PropertiesBuilder;
import org.jclouds.aws.s3.blobstore.config.S3BlobStoreContextModule;
import org.jclouds.aws.s3.config.S3RestClientModule;
import org.jclouds.aws.s3.config.S3StubClientModule;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.internal.S3ObjectImpl;
import org.jclouds.aws.s3.internal.StubS3AsyncClient;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.internal.BlobImpl;
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
import org.testng.annotations.Test;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
* Tests behavior of modules configured in S3ContextBuilder
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "s3.S3ContextBuilderTest")
public class S3BlobStoreContextBuilderTest {
public void testNewBuilder() {
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(new S3PropertiesBuilder(
"id", "secret").build());
assertEquals(builder.getProperties().getProperty(PROPERTY_USER_METADATA_PREFIX),
"x-amz-meta-");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_ACCESSKEYID), "id");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_SECRETACCESSKEY), "secret");
}
public void testBuildContext() {
BlobStoreContext context = new S3BlobStoreContextBuilder(new S3PropertiesBuilder("id",
"secret").build()).withModules(new S3StubClientModule()).buildBlobStoreContext();
assertEquals(context.getClass(), BlobStoreContextImpl.class);
assertEquals(context.getProviderSpecificContext().getAsyncApi().getClass(),
StubS3AsyncClient.class);
assertEquals(context.getAsyncBlobStore().getClass(), S3AsyncBlobStore.class);
assertEquals(((S3AsyncClient) context.getProviderSpecificContext().getAsyncApi())
.newS3Object().getClass(), S3ObjectImpl.class);
assertEquals(context.getAsyncBlobStore().newBlob(null).getClass(), BlobImpl.class);
assertEquals(context.getProviderSpecificContext().getAccount(), "id");
assertEquals(context.getProviderSpecificContext().getEndPoint(), URI
.create("https://localhost/s3stub"));
}
public void testBuildInjector() {
Injector i = new S3BlobStoreContextBuilder(new S3PropertiesBuilder("id", "secret").build())
.withModules(new S3StubClientModule()).buildInjector();
assert i.getInstance(BlobStoreContext.class) != null;
assert i.getInstance(S3Object.class) != null;
assert i.getInstance(Blob.class) != null;
}
protected void testAddContextModule() {
List<Module> modules = new ArrayList<Module>();
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(new S3PropertiesBuilder(
"id", "secret").build());
builder.addContextModule(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), S3BlobStoreContextModule.class);
}
protected void addClientModule() {
List<Module> modules = new ArrayList<Module>();
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(new S3PropertiesBuilder(
"id", "secret").build());
builder.addClientModule(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), S3RestClientModule.class);
}
}

View File

@ -21,6 +21,7 @@ package org.jclouds.aws.s3.blobstore.config;
import static com.google.common.util.concurrent.Executors.sameThreadExecutor;
import static org.testng.Assert.assertEquals;
import org.jclouds.Constants;
import org.jclouds.aws.s3.config.S3StubClientModule;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.blobstore.BlobStoreContext;
@ -40,8 +41,9 @@ import com.google.inject.Injector;
public class S3BlobStoreModuleTest {
Injector createInjector() {
return Guice.createInjector(new ExecutorServiceModule(sameThreadExecutor()),
new JDKLoggingModule(), new S3StubClientModule(), new S3BlobStoreContextModule() {
return Guice.createInjector(new ExecutorServiceModule(sameThreadExecutor(),
sameThreadExecutor()), new JDKLoggingModule(), new S3StubClientModule(),
new S3BlobStoreContextModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
@ -50,6 +52,12 @@ public class S3BlobStoreModuleTest {
Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)).to("key");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT))
.to("http://localhost");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_IO_WORKER_THREADS)).to("1");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST)).to("1");
bindConstant().annotatedWith(Jsr330.named(Constants.PROPERTY_USER_THREADS))
.to("1");
super.configure();
}
});

View File

@ -21,13 +21,13 @@ package org.jclouds.aws.s3.blobstore.integration;
import java.io.IOException;
import java.util.Properties;
import org.jclouds.aws.s3.blobstore.S3BlobStoreContextFactory;
import org.jclouds.aws.s3.S3ContextFactory;
import org.jclouds.aws.s3.config.S3StubClientModule;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextFactory;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.blobstore.integration.internal.BaseTestInitializer;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.logging.config.ConsoleLoggingModule;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
@ -43,12 +43,12 @@ public class S3TestInitializer extends BaseTestInitializer {
String account, String key) throws IOException {
BaseBlobStoreIntegrationTest.SANITY_CHECK_RETURNED_BUCKET_NAME = true;
return new BlobStoreContextFactory().createContext("s3", account, key, ImmutableSet.of(
configurationModule, new Log4JLoggingModule()), new Properties());
configurationModule, new ConsoleLoggingModule()), new Properties());
}
@Override
protected BlobStoreContext createStubContext() {
return S3BlobStoreContextFactory.createContext("user", "pass", new S3StubClientModule());
return S3ContextFactory.createContext("user", "pass", new S3StubClientModule());
}
}

View File

@ -1,69 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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 static com.google.common.util.concurrent.Executors.sameThreadExecutor;
import static org.testng.Assert.assertEquals;
import org.jclouds.aws.s3.S3AsyncClient;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl;
import org.jclouds.util.Jsr330;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "s3.S3ContextModuleTest")
public class S3ContextModuleTest {
Injector createInjector() {
return Guice.createInjector(new ExecutorServiceModule(sameThreadExecutor()),
new S3StubClientModule(), new JDKLoggingModule(), new S3ContextModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to("user");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)).to("key");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT))
.to("http://localhost");
super.configure();
}
});
}
@Test
void testContextImpl() {
RestContext<S3AsyncClient, S3Client> handler = createInjector().getInstance(
Key.get(new TypeLiteral<RestContext<S3AsyncClient, S3Client>>() {
}));
assertEquals(handler.getClass(), RestContextImpl.class);
}
}

View File

@ -22,6 +22,7 @@ import static com.google.common.util.concurrent.Executors.sameThreadExecutor;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import org.jclouds.Constants;
import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.handlers.AWSRedirectionRetryHandler;
import org.jclouds.aws.handlers.ParseAWSErrorFromXmlContent;
@ -47,19 +48,24 @@ public class S3RestClientModuleTest {
Injector createInjector() {
return Guice.createInjector(new S3RestClientModule(), new ExecutorServiceModule(
sameThreadExecutor()), new ParserModule(), new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
"user");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY))
.to("key");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT)).to(
"http://localhost");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_SESSIONINTERVAL)).to(
"2");
}
});
sameThreadExecutor(), sameThreadExecutor()), new ParserModule(),
new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to("user");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)).to("key");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT))
.to("http://localhost");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_S3_SESSIONINTERVAL)).to("2");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_IO_WORKER_THREADS)).to("1");
bindConstant().annotatedWith(Jsr330.named(Constants.PROPERTY_USER_THREADS))
.to("1");
}
});
}
@Test

View File

@ -26,6 +26,7 @@ import java.net.URI;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.Constants;
import org.jclouds.aws.s3.config.S3RestClientModule;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.concurrent.config.ExecutorServiceModule;
@ -137,19 +138,24 @@ public class RequestAuthorizeSignatureTest {
@BeforeClass
protected void createFilter() {
injector = Guice.createInjector(new S3RestClientModule(), new ExecutorServiceModule(
sameThreadExecutor()), new ParserModule(), new AbstractModule() {
sameThreadExecutor(), sameThreadExecutor()), new ParserModule(),
new AbstractModule() {
protected void configure() {
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
"foo");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY))
.to("bar");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_SESSIONINTERVAL)).to(
"2");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT)).to(
"https://s3.amazonaws.com");
}
});
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to("foo");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)).to("bar");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_S3_SESSIONINTERVAL)).to("2");
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_IO_WORKER_THREADS)).to("1");
bindConstant().annotatedWith(Jsr330.named(Constants.PROPERTY_USER_THREADS))
.to("1");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT))
.to("https://s3.amazonaws.com");
}
});
filter = injector.getInstance(RequestAuthorizeSignature.class);
}

View File

@ -31,7 +31,9 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.s3.S3AsyncClient;
import org.jclouds.aws.s3.blobstore.S3AsyncBlobStore;
@ -55,6 +57,7 @@ import org.jclouds.aws.s3.options.CopyObjectOptions;
import org.jclouds.aws.s3.options.ListBucketOptions;
import org.jclouds.aws.s3.options.PutBucketOptions;
import org.jclouds.aws.s3.options.PutObjectOptions;
import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.attr.ConsistencyModels;
@ -83,7 +86,7 @@ import com.google.common.util.concurrent.ListenableFuture;
public class StubS3AsyncClient implements S3AsyncClient {
private final DateService dateService;
private final HttpGetOptionsListToGetOptions httpGetOptionsConverter;
private final StubAsyncBlobStore blobStore;
private final AsyncBlobStore blobStore;
private final S3Object.Factory objectProvider;
private final Blob.Factory blobProvider;
private final ObjectToBlob object2Blob;
@ -92,6 +95,7 @@ public class StubS3AsyncClient implements S3AsyncClient {
private final BucketToContainerListOptions bucket2ContainerListOptions;
private final ResourceToBucketList resource2BucketList;
private final ExecutorService executorService;
private final ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs;
@Inject
private StubS3AsyncClient(StubAsyncBlobStore blobStore,
@ -100,7 +104,9 @@ public class StubS3AsyncClient implements S3AsyncClient {
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob,
BlobToObject blob2Object, BlobToObjectMetadata blob2ObjectMetadata,
BucketToContainerListOptions bucket2ContainerListOptions,
ResourceToBucketList resource2BucketList, ExecutorService executorService) {
ResourceToBucketList resource2BucketList,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executorService) {
this.containerToBlobs = containerToBlobs;
this.blobStore = blobStore;
this.objectProvider = objectProvider;
this.blobProvider = blobProvider;
@ -147,31 +153,32 @@ public class StubS3AsyncClient implements S3AsyncClient {
final String destinationObject, CopyObjectOptions... nullableOptions) {
final CopyObjectOptions options = (nullableOptions.length == 0) ? new CopyObjectOptions()
: nullableOptions[0];
ConcurrentMap<String, Blob> source = blobStore.getContainerToBlobs().get(sourceBucket);
ConcurrentMap<String, Blob> dest = blobStore.getContainerToBlobs().get(destinationBucket);
ConcurrentMap<String, Blob> source = containerToBlobs.get(sourceBucket);
ConcurrentMap<String, Blob> dest = containerToBlobs.get(destinationBucket);
if (source.containsKey(sourceObject)) {
Blob object = source.get(sourceObject);
if (options.getIfMatch() != null) {
if (!object.getMetadata().getETag().equals(options.getIfMatch()))
return immediateFailedFuture(blobStore.returnResponseException(412));
return immediateFailedFuture(StubAsyncBlobStore.returnResponseException(412));
}
if (options.getIfNoneMatch() != null) {
if (object.getMetadata().getETag().equals(options.getIfNoneMatch()))
return immediateFailedFuture(blobStore.returnResponseException(412));
return immediateFailedFuture(StubAsyncBlobStore.returnResponseException(412));
}
if (options.getIfModifiedSince() != null) {
Date modifiedSince = dateService.rfc822DateParse(options.getIfModifiedSince());
if (modifiedSince.after(object.getMetadata().getLastModified()))
return immediateFailedFuture(blobStore.returnResponseException(412));
return immediateFailedFuture(StubAsyncBlobStore.returnResponseException(412));
}
if (options.getIfUnmodifiedSince() != null) {
Date unmodifiedSince = dateService.rfc822DateParse(options.getIfUnmodifiedSince());
if (unmodifiedSince.before(object.getMetadata().getLastModified()))
return immediateFailedFuture(blobStore.returnResponseException(412));
return immediateFailedFuture(StubAsyncBlobStore.returnResponseException(412));
}
Blob sourceS3 = source.get(sourceObject);
MutableBlobMetadata newMd = blobStore.copy(sourceS3.getMetadata(), destinationObject);
MutableBlobMetadata newMd = StubAsyncBlobStore.copy(sourceS3.getMetadata(),
destinationObject);
if (options.getAcl() != null)
keyToAcl.put(destinationBucket + "/" + destinationObject, options.getAcl());
@ -179,7 +186,8 @@ public class StubS3AsyncClient implements S3AsyncClient {
Blob newBlob = blobProvider.create(newMd);
newBlob.setPayload(sourceS3.getContent());
dest.put(destinationObject, newBlob);
return immediateFuture((ObjectMetadata) blob2ObjectMetadata.apply(blobStore.copy(newMd)));
return immediateFuture((ObjectMetadata) blob2ObjectMetadata.apply(StubAsyncBlobStore
.copy(newMd)));
}
return immediateFailedFuture(new KeyNotFoundException(sourceBucket, sourceObject));
}
@ -253,11 +261,18 @@ public class StubS3AsyncClient implements S3AsyncClient {
}
public ListenableFuture<Boolean> bucketExists(final String bucketName) {
return immediateFuture(blobStore.getContainerToBlobs().containsKey(bucketName));
return immediateFuture(containerToBlobs.containsKey(bucketName));
}
public ListenableFuture<Boolean> deleteBucketIfEmpty(String bucketName) {
return blobStore.deleteContainerImpl(bucketName);
Boolean returnVal = true;
if (containerToBlobs.containsKey(bucketName)) {
if (containerToBlobs.get(bucketName).size() == 0)
containerToBlobs.remove(bucketName);
else
returnVal = false;
}
return immediateFuture(returnVal);
}
public ListenableFuture<Void> deleteObject(String bucketName, String key) {
@ -281,13 +296,13 @@ public class StubS3AsyncClient implements S3AsyncClient {
}
public ListenableFuture<? extends SortedSet<BucketMetadata>> listOwnedBuckets() {
return immediateFuture(Sets.newTreeSet(Iterables.transform(blobStore.getContainerToBlobs()
.keySet(), new Function<String, BucketMetadata>() {
public BucketMetadata apply(String name) {
return new BucketMetadata(name, null, null);
}
return immediateFuture(Sets.newTreeSet(Iterables.transform(containerToBlobs.keySet(),
new Function<String, BucketMetadata>() {
public BucketMetadata apply(String name) {
return new BucketMetadata(name, null, null);
}
})));
})));
}
public S3Object newS3Object() {
@ -325,4 +340,9 @@ public class StubS3AsyncClient implements S3AsyncClient {
return immediateFuture(null);
}
@Override
public ListenableFuture<Boolean> objectExists(String bucketName, String key) {
return immediateFuture(containerToBlobs.get(bucketName).containsKey(key));
}
}

View File

@ -25,6 +25,7 @@ import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Map;
import org.jclouds.Constants;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.handlers.AWSRedirectionRetryHandler;
@ -51,26 +52,31 @@ public class SQSRestClientModuleTest {
Injector createInjector() {
return Guice.createInjector(new SQSRestClientModule(), new ExecutorServiceModule(
sameThreadExecutor()), new ParserModule(), new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Jsr330.named(SQSConstants.PROPERTY_AWS_ACCESSKEYID)).to(
"user");
bindConstant().annotatedWith(Jsr330.named(SQSConstants.PROPERTY_AWS_SECRETACCESSKEY))
.to("key");
bindConstant()
.annotatedWith(Jsr330.named(SQSConstants.PROPERTY_SQS_ENDPOINT_US_EAST_1)).to(
sameThreadExecutor(), sameThreadExecutor()), new ParserModule(),
new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(SQSConstants.PROPERTY_AWS_ACCESSKEYID)).to("user");
bindConstant().annotatedWith(
Jsr330.named(SQSConstants.PROPERTY_AWS_SECRETACCESSKEY)).to("key");
bindConstant().annotatedWith(
Jsr330.named(SQSConstants.PROPERTY_SQS_ENDPOINT_US_EAST_1)).to(
"http://default");
bindConstant()
.annotatedWith(Jsr330.named(SQSConstants.PROPERTY_SQS_ENDPOINT_US_WEST_1)).to(
bindConstant().annotatedWith(
Jsr330.named(SQSConstants.PROPERTY_SQS_ENDPOINT_US_WEST_1)).to(
"http://uswest");
bindConstant()
.annotatedWith(Jsr330.named(SQSConstants.PROPERTY_SQS_ENDPOINT_EU_WEST_1)).to(
bindConstant().annotatedWith(
Jsr330.named(SQSConstants.PROPERTY_SQS_ENDPOINT_EU_WEST_1)).to(
"http://euwest");
bindConstant().annotatedWith(Jsr330.named(SQSConstants.PROPERTY_AWS_EXPIREINTERVAL))
.to(30);
}
});
bindConstant().annotatedWith(
Jsr330.named(SQSConstants.PROPERTY_AWS_EXPIREINTERVAL)).to(30);
bindConstant().annotatedWith(
Jsr330.named(Constants.PROPERTY_IO_WORKER_THREADS)).to("1");
bindConstant().annotatedWith(Jsr330.named(Constants.PROPERTY_USER_THREADS))
.to("1");
}
});
}
@Test

View File

@ -126,7 +126,7 @@ public class ListQueuesResponseHandlerTest extends PerformanceTest {
}
}
@Test()
@Test(enabled=false)
void testRegexSerialResponseTime() throws IOException {
long now = System.currentTimeMillis();
for (int i = 0; i < LOOP_COUNT; i++)
@ -134,7 +134,7 @@ public class ListQueuesResponseHandlerTest extends PerformanceTest {
System.out.println("testRegex serial: " + (System.currentTimeMillis() - now) + "");
}
@Test()
@Test(enabled=false)
void testRegexParallelResponseTime() throws Throwable {
List<Runnable> tasks = ImmutableList.<Runnable> of(new Runnable() {
public void run() {
@ -144,7 +144,7 @@ public class ListQueuesResponseHandlerTest extends PerformanceTest {
executeMultiThreadedPerformanceTest("testRegexParallelResponseTime", tasks);
}
@Test()
@Test(enabled=false)
void testSaxSerialResponseTime() throws IOException {
long now = System.currentTimeMillis();
for (int i = 0; i < LOOP_COUNT; i++)
@ -152,7 +152,7 @@ public class ListQueuesResponseHandlerTest extends PerformanceTest {
System.out.println("testSax serial: " + (System.currentTimeMillis() - now) + "");
}
@Test()
@Test(enabled=false)
void testSaxParallelResponseTime() throws Throwable {
List<Runnable> tasks = ImmutableList.<Runnable> of(new Runnable() {
public void run() {

View File

@ -89,12 +89,12 @@
<appender-ref ref="ASYNC" />
</category>
<category name="jclouds.http.headers">
<category name="jclouds.headers">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="jclouds.http.wire">
<category name="jclouds.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>

View File

@ -74,7 +74,7 @@ public class MainApp {
// Init
RestContext<EC2AsyncClient, EC2Client> context = EC2ContextFactory.createContext(accesskeyid,
secretkey);
secretkey).getProviderSpecificContext();
// Get a synchronous client
EC2Client client = context.getApi();

View File

@ -30,7 +30,6 @@ import javax.servlet.ServletContextEvent;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.gae.config.GoogleAppEngineConfigurationModule;
import org.jclouds.samples.googleappengine.GetAllContainersController;
@ -50,6 +49,8 @@ import com.google.inject.servlet.ServletModule;
*/
public class GuiceServletConfig extends GuiceServletContextListener {
public static final String PROPERTY_BLOBSTORE_CONTEXTS = "blobstore.contexts";
private Map<String, BlobStoreContext> contexts;
@SuppressWarnings("unchecked")
@ -57,8 +58,8 @@ public class GuiceServletConfig extends GuiceServletContextListener {
public void contextInitialized(ServletContextEvent servletContextEvent) {
Properties props = loadJCloudsProperties(servletContextEvent);
ImmutableList<String> list = ImmutableList.<String> of(checkNotNull(
props.getProperty(BlobStoreConstants.PROPERTY_BLOBSTORE_CONTEXTS),
BlobStoreConstants.PROPERTY_BLOBSTORE_CONTEXTS).split(","));
props.getProperty(PROPERTY_BLOBSTORE_CONTEXTS), PROPERTY_BLOBSTORE_CONTEXTS).split(
","));
contexts = Maps.newHashMap();
for (String className : list) {
try {

View File

@ -23,7 +23,6 @@ import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT;
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_BLOBSTORE_CONTEXTS;
import static org.jclouds.rackspace.reference.RackspaceConstants.PROPERTY_RACKSPACE_KEY;
import static org.jclouds.rackspace.reference.RackspaceConstants.PROPERTY_RACKSPACE_USER;
@ -32,12 +31,13 @@ import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import org.jclouds.aws.s3.S3ContextBuilder;
import org.jclouds.aws.s3.S3PropertiesBuilder;
import org.jclouds.aws.s3.blobstore.S3BlobStoreContextBuilder;
import org.jclouds.azure.storage.blob.AzureBlobPropertiesBuilder;
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStoreContextBuilder;
import org.jclouds.azure.storage.blob.AzureBlobContextBuilder;
import org.jclouds.rackspace.cloudfiles.CloudFilesContextBuilder;
import org.jclouds.rackspace.cloudfiles.CloudFilesPropertiesBuilder;
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextBuilder;
import org.jclouds.samples.googleappengine.config.GuiceServletConfig;
import org.jclouds.util.Utils;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Parameters;
@ -62,9 +62,9 @@ public class GoogleAppEngineLiveTest {
url = new URL(String.format("http://%s:%s", address, port));
Properties props = new Properties();
props.setProperty(PROPERTY_BLOBSTORE_CONTEXTS, String.format("%s,%s,%s",
S3BlobStoreContextBuilder.class.getName(), CloudFilesBlobStoreContextBuilder.class
.getName(), AzureBlobStoreContextBuilder.class.getName()));
props.setProperty(GuiceServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, String.format("%s,%s,%s",
S3ContextBuilder.class.getName(), CloudFilesContextBuilder.class.getName(),
AzureBlobContextBuilder.class.getName()));
props = new S3PropertiesBuilder(props)
.withCredentials(

View File

@ -62,10 +62,9 @@ public class SpeedTest {
int messageCount = Integer.parseInt(args[3]);
RestContext<SQSAsyncClient, SQSClient> context = isEnterprise ? SQSContextFactory
.createContext(System.getProperties(), accesskeyid, secretkey,
new NullLoggingModule(), new EnterpriseConfigurationModule())
: SQSContextFactory.createContext(System.getProperties(), accesskeyid, secretkey,
new NullLoggingModule());
.createContext(accesskeyid, secretkey, new NullLoggingModule(),
new EnterpriseConfigurationModule()) : SQSContextFactory.createContext(
accesskeyid, secretkey, new NullLoggingModule());
try {
Set<Queue> queues = Sets.newHashSet();

View File

@ -27,7 +27,6 @@ import java.util.Map;
import java.util.SortedSet;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.s3.S3AsyncClient;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.S3ContextFactory;
import org.jclouds.aws.s3.blobstore.S3AsyncBlobStore;
@ -36,8 +35,8 @@ import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.options.CopyObjectOptions;
import org.jclouds.aws.s3.options.ListBucketOptions;
import org.jclouds.aws.s3.options.PutObjectOptions;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.http.options.GetOptions;
import org.jclouds.rest.RestContext;
import org.jets3t.service.S3ObjectsChunk;
import org.jets3t.service.S3Service;
import org.jets3t.service.S3ServiceException;
@ -60,7 +59,7 @@ public class JCloudsS3Service extends S3Service {
private static final long serialVersionUID = 1L;
private final RestContext<S3AsyncClient, S3Client> context;
private final BlobStoreContext context;
private final S3Client connection;
/**
@ -78,7 +77,7 @@ public class JCloudsS3Service extends S3Service {
super(awsCredentials);
context = S3ContextFactory.createContext(awsCredentials.getAccessKey(), awsCredentials
.getSecretKey(), modules);
connection = context.getApi();
connection = (S3Client) context.getProviderSpecificContext().getApi();
}
@Override

View File

@ -24,7 +24,9 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.jets3t.service.S3ServiceException;
import org.testng.ITestContext;
@ -88,30 +90,34 @@ public class AmazonPerformanceLiveTest extends BasePerformanceLiveTest {
throw new UnsupportedOperationException();
}
@SuppressWarnings("unchecked")
@Override
protected boolean putByteArray(String bucket, String key, byte[] data, String contentType)
throws Exception {
com.amazon.s3.S3Object object = new com.amazon.s3.S3Object(data, null);
Map<String, List<String>> headers = new TreeMap<String, List<String>>();
protected Future<?> putByteArray(final String bucket, final String key, byte[] data,
String contentType) {
final com.amazon.s3.S3Object object = new com.amazon.s3.S3Object(data, null);
final Map<String, List<String>> headers = new TreeMap<String, List<String>>();
headers.put("Content-Type", Arrays.asList(new String[] { contentType }));
return amzClient.put(bucket, key, object, headers).connection.getResponseMessage() != null;
return exec.submit(new Callable() {
@Override
public Object call() throws Exception {
return amzClient.put(bucket, key, object, headers).connection.getResponseMessage();
}
});
}
@Override
protected boolean putFile(String bucket, String key, File data, String contentType)
throws Exception {
protected Future<?> putFile(String bucket, String key, File data, String contentType) {
throw new UnsupportedOperationException();
}
@Override
protected boolean putInputStream(String bucket, String key, InputStream data, String contentType)
throws Exception {
protected Future<?> putInputStream(String bucket, String key, InputStream data,
String contentType) {
throw new UnsupportedOperationException();
}
@Override
protected boolean putString(String bucket, String key, String data, String contentType)
throws Exception {
protected Future<?> putString(String bucket, String key, String data, String contentType) {
throw new UnsupportedOperationException();
}

View File

@ -18,11 +18,20 @@
*/
package org.jclouds.aws.s3;
import static org.jclouds.Constants.*;
import static org.jclouds.Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.concurrent.Future;
import org.jclouds.aws.s3.domain.S3Object;
import com.google.appengine.repackaged.com.google.common.base.Throwables;
/**
* // TODO: Adrian: Document this!
*
@ -46,23 +55,32 @@ public abstract class BaseJCloudsPerformanceLiveTest extends BasePerformanceLive
// S3Object.NOT_FOUND;
// }
@Override
protected boolean putByteArray(String bucket, String key, byte[] data, String contentType)
throws Exception {
S3Object object = newObject(key);
object.getMetadata().setContentType(contentType);
object.setPayload(data);
return getApi().putObject(bucket, object) != null;
protected void overrideWithSysPropertiesAndPrint(Properties overrides, String contextName) {
overrides.putAll(System.getProperties());
System.out.printf(
"%s: loopCount(%s), perContext(%s), perHost(%s),ioWorkers(%s), userThreads(%s)%n",
contextName, loopCount, overrides.getProperty(PROPERTY_MAX_CONNECTIONS_PER_CONTEXT),
overrides.getProperty(PROPERTY_MAX_CONNECTIONS_PER_HOST), overrides
.getProperty(PROPERTY_IO_WORKER_THREADS), overrides
.getProperty(PROPERTY_USER_THREADS));
}
@Override
protected boolean putFile(String bucket, String key, File data, String contentType)
throws Exception {
protected Future<?> putByteArray(String bucket, String key, byte[] data, String contentType) {
S3Object object = newObject(key);
object.getMetadata().setContentType(contentType);
object.setPayload(data);
return getApi().putObject(bucket, object) != null;
return getApi().putObject(bucket, object);
}
public abstract S3AsyncClient getApi();
@Override
protected Future<?> putFile(String bucket, String key, File data, String contentType) {
S3Object object = newObject(key);
object.getMetadata().setContentType(contentType);
object.setPayload(data);
return getApi().putObject(bucket, object);
}
private S3Object newObject(String key) {
@ -72,21 +90,24 @@ public abstract class BaseJCloudsPerformanceLiveTest extends BasePerformanceLive
}
@Override
protected boolean putInputStream(String bucket, String key, InputStream data, String contentType)
throws Exception {
protected Future<?> putInputStream(String bucket, String key, InputStream data,
String contentType) {
S3Object object = newObject(key);
object.getMetadata().setContentType(contentType);
object.setPayload(data);
object.setContentLength(new Long(data.available()));
return getApi().putObject(bucket, object) != null;
try {
object.setContentLength(new Long(data.available()));
} catch (IOException e) {
Throwables.propagate(e);
}
return getApi().putObject(bucket, object);
}
@Override
protected boolean putString(String bucket, String key, String data, String contentType)
throws Exception {
protected Future<?> putString(String bucket, String key, String data, String contentType) {
S3Object object = newObject(key);
object.getMetadata().setContentType(contentType);
object.setPayload(data);
return getApi().putObject(bucket, object) != null;
return getApi().putObject(bucket, object);
}
}

View File

@ -18,27 +18,28 @@
*/
package org.jclouds.aws.s3;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import javax.inject.Provider;
import org.jclouds.aws.domain.Region;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.jclouds.logging.Logger;
import org.testng.annotations.Test;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Tests relative performance of S3 functions.
*
@ -49,68 +50,15 @@ public abstract class BasePerformanceLiveTest extends BaseBlobStoreIntegrationTe
containerCount = 1;
}
protected int timeoutSeconds = 15;
protected int loopCount = 100;
protected int loopCount = 1000;
protected ExecutorService exec;
protected CompletionService<Boolean> completer;
protected Logger logger = Logger.NULL;;
@BeforeClass(groups = { "live" }, dependsOnMethods = "setUpResourcesOnThisThread")
public void setUpCallables() throws InterruptedException, ExecutionException, TimeoutException {
exec = Executors.newCachedThreadPool();
completer = new ExecutorCompletionService<Boolean>(exec);
}
@AfterClass(groups = { "live" })
public void tearDownExecutor() throws Exception {
exec.shutdownNow();
exec = null;
}
// too slow...
@Test(enabled = false)
public void testPutBytesSerialEU() throws Exception {
String euContainerName = createScratchContainerInEU();
try {
doSerial(new PutBytesCallable(euContainerName), loopCount);
} finally {
destroyContainer(euContainerName);
}
}
public S3Client getApi() {
return (S3Client) context.getProviderSpecificContext().getApi();
}
/**
* using scratch containerName as we are changing location
*
* @throws TimeoutException
* @throws ExecutionException
* @throws InterruptedException
*/
protected String createScratchContainerInEU() throws InterruptedException, ExecutionException,
TimeoutException {
String containerName = getScratchContainerName();
getApi().putBucketInRegion(Region.EU_WEST_1, containerName);
return containerName;
}
// too slow...
@Test(enabled = false)
public void testPutBytesParallelEU() throws InterruptedException, ExecutionException,
TimeoutException {
String euContainerName = createScratchContainerInEU();
try {
doParallel(new PutBytesCallable(euContainerName), loopCount);
} finally {
destroyContainer(euContainerName);
}
}
@Test
public void testPutBytesSerial() throws Exception {
String bucketName = getContainerName();
try {
doSerial(new PutBytesCallable(bucketName), loopCount / 10);
doSerial(new PutBytesFuture(bucketName), loopCount / 10);
} finally {
returnContainer(bucketName);
}
@ -121,17 +69,17 @@ public abstract class BasePerformanceLiveTest extends BaseBlobStoreIntegrationTe
TimeoutException {
String bucketName = getContainerName();
try {
doParallel(new PutBytesCallable(bucketName), loopCount);
doParallel(new PutBytesFuture(bucketName), loopCount, bucketName);
} finally {
returnContainer(bucketName);
}
}
@Test
@Test(enabled = false)
public void testPutFileSerial() throws Exception {
String bucketName = getContainerName();
try {
doSerial(new PutFileCallable(bucketName), loopCount / 10);
doSerial(new PutFileFuture(bucketName), loopCount / 10);
} finally {
returnContainer(bucketName);
}
@ -142,17 +90,17 @@ public abstract class BasePerformanceLiveTest extends BaseBlobStoreIntegrationTe
TimeoutException {
String bucketName = getContainerName();
try {
doParallel(new PutFileCallable(bucketName), loopCount);
doParallel(new PutFileFuture(bucketName), loopCount, bucketName);
} finally {
returnContainer(bucketName);
}
}
@Test
@Test(enabled = false)
public void testPutInputStreamSerial() throws Exception {
String bucketName = getContainerName();
try {
doSerial(new PutInputStreamCallable(bucketName), loopCount / 10);
doSerial(new PutInputStreamFuture(bucketName), loopCount / 10);
} finally {
returnContainer(bucketName);
}
@ -163,17 +111,17 @@ public abstract class BasePerformanceLiveTest extends BaseBlobStoreIntegrationTe
TimeoutException {
String bucketName = getContainerName();
try {
doParallel(new PutInputStreamCallable(bucketName), loopCount);
doParallel(new PutInputStreamFuture(bucketName), loopCount, bucketName);
} finally {
returnContainer(bucketName);
}
}
@Test
@Test(enabled = false)
public void testPutStringSerial() throws Exception {
String bucketName = getContainerName();
try {
doSerial(new PutStringCallable(bucketName), loopCount / 10);
doSerial(new PutStringFuture(bucketName), loopCount / 10);
} finally {
returnContainer(bucketName);
}
@ -184,116 +132,98 @@ public abstract class BasePerformanceLiveTest extends BaseBlobStoreIntegrationTe
TimeoutException {
String bucketName = getContainerName();
try {
doParallel(new PutStringCallable(bucketName), loopCount);
doParallel(new PutStringFuture(bucketName), loopCount, bucketName);
} finally {
returnContainer(bucketName);
}
}
private void doSerial(Provider<Callable<Boolean>> provider, int loopCount) throws Exception,
private void doSerial(Provider<ListenableFuture<?>> provider, int loopCount) throws Exception,
ExecutionException {
for (int i = 0; i < loopCount; i++)
assert provider.get().call();
assert provider.get().get() != null;
}
private void doParallel(Provider<Callable<Boolean>> provider, int loopCount)
throws InterruptedException, ExecutionException, TimeoutException {
private void doParallel(Provider<ListenableFuture<?>> provider, int loopCount,
String containerName) throws InterruptedException, ExecutionException, TimeoutException {
Set<ListenableFuture<?>> responses = Sets.newHashSet();
for (int i = 0; i < loopCount; i++)
completer.submit(provider.get());
for (int i = 0; i < loopCount; i++)
assert completer.take().get(timeoutSeconds, TimeUnit.SECONDS);
responses.add(provider.get());
awaitCompletion(responses, exec, null, logger, String.format(
"putting into containerName: %s", containerName));
}
class PutBytesCallable implements Provider<Callable<Boolean>> {
class PutBytesFuture implements Provider<ListenableFuture<?>> {
final AtomicInteger key = new AtomicInteger(0);
protected byte[] test = new byte[1024 * 2];
private final String bucketName;
public PutBytesCallable(String bucketName) {
public PutBytesFuture(String bucketName) {
this.bucketName = bucketName;
}
public Callable<Boolean> get() {
return new Callable<Boolean>() {
public Boolean call() throws Exception {
String bucketName2 = bucketName;
return putByteArray(bucketName2, key.getAndIncrement() + "", test,
"application/octetstring");
}
};
public ListenableFuture<?> get() {
return Futures.makeListenable(putByteArray(bucketName, key.getAndIncrement() + "", test,
"application/octetstring"));
}
}
class PutFileCallable implements Provider<Callable<Boolean>> {
class PutFileFuture implements Provider<ListenableFuture<?>> {
final AtomicInteger key = new AtomicInteger(0);
protected File file = new File("pom.xml");
private final String bucketName;
public PutFileCallable(String bucketName) {
public PutFileFuture(String bucketName) {
this.bucketName = bucketName;
}
public Callable<Boolean> get() {
return new Callable<Boolean>() {
public Boolean call() throws Exception {
return putFile(bucketName, key.getAndIncrement() + "", file, "text/xml");
}
};
public ListenableFuture<?> get() {
return Futures.makeListenable(putFile(bucketName, key.getAndIncrement() + "", file,
"text/xml"));
}
}
class PutInputStreamCallable extends PutBytesCallable {
class PutInputStreamFuture extends PutBytesFuture {
final AtomicInteger key = new AtomicInteger(0);
private final String bucketName;
public PutInputStreamCallable(String bucketName) {
public PutInputStreamFuture(String bucketName) {
super(bucketName);
this.bucketName = bucketName;
}
@Override
public Callable<Boolean> get() {
return new Callable<Boolean>() {
public Boolean call() throws Exception {
return putInputStream(bucketName, key.getAndIncrement() + "",
new ByteArrayInputStream(test), "application/octetstring");
}
};
public ListenableFuture<?> get() {
return Futures.makeListenable(putInputStream(bucketName, key.getAndIncrement() + "",
new ByteArrayInputStream(test), "application/octetstring"));
}
}
class PutStringCallable implements Provider<Callable<Boolean>> {
class PutStringFuture implements Provider<ListenableFuture<?>> {
final AtomicInteger key = new AtomicInteger(0);
protected String testString = "hello world!";
private final String bucketName;
public PutStringCallable(String bucketName) {
public PutStringFuture(String bucketName) {
this.bucketName = bucketName;
}
public Callable<Boolean> get() {
return new Callable<Boolean>() {
public Boolean call() throws Exception {
return putString(bucketName, key.getAndIncrement() + "", testString, "text/plain");
}
};
public ListenableFuture<?> get() {
return Futures.makeListenable(putString(bucketName, key.getAndIncrement() + "",
testString, "text/plain"));
}
}
protected abstract boolean putByteArray(String bucket, String key, byte[] data,
String contentType) throws Exception;
protected abstract Future<?> putByteArray(String bucket, String key, byte[] data,
String contentType);
protected abstract boolean putFile(String bucket, String key, File data, String contentType)
throws Exception;
protected abstract Future<?> putFile(String bucket, String key, File data, String contentType);
protected abstract boolean putInputStream(String bucket, String key, InputStream data,
String contentType) throws Exception;
protected abstract Future<?> putInputStream(String bucket, String key, InputStream data,
String contentType);
protected abstract boolean putString(String bucket, String key, String data, String contentType)
throws Exception;
protected abstract Future<?> putString(String bucket, String key, String data, String contentType);
}

View File

@ -21,17 +21,23 @@ package org.jclouds.aws.s3;
import java.io.File;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.enterprise.config.EnterpriseConfigurationModule;
import org.jclouds.gae.config.GoogleAppEngineConfigurationModule;
import org.jclouds.logging.config.NullLoggingModule;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.testng.v6.Maps;
import com.google.appengine.tools.development.ApiProxyLocalImpl;
import com.google.apphosting.api.ApiProxy;
import com.google.inject.Module;
/**
*
@ -49,25 +55,12 @@ public class JCloudsGaePerformanceLiveTest extends BaseJCloudsPerformanceLiveTes
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutBytesParallelEU() throws InterruptedException, ExecutionException,
TimeoutException {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutBytesSerial() throws Exception {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutBytesSerialEU() throws Exception {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutFileParallel() throws InterruptedException, ExecutionException,
@ -116,29 +109,26 @@ public class JCloudsGaePerformanceLiveTest extends BaseJCloudsPerformanceLiveTes
}
@Override
protected boolean putByteArray(String bucket, String key, byte[] data, String contentType)
throws Exception {
protected Future<?> putByteArray(String bucket, String key, byte[] data, String contentType) {
setupApiProxy();
return super.putByteArray(bucket, key, data, contentType);
}
@Override
protected boolean putFile(String bucket, String key, File data, String contentType)
throws Exception {
protected Future<?> putFile(String bucket, String key, File data, String contentType) {
setupApiProxy();
return super.putFile(bucket, key, data, contentType);
}
@Override
protected boolean putInputStream(String bucket, String key, InputStream data, String contentType)
throws Exception {
protected Future<?> putInputStream(String bucket, String key, InputStream data,
String contentType) {
setupApiProxy();
return super.putInputStream(bucket, key, data, contentType);
}
@Override
protected boolean putString(String bucket, String key, String data, String contentType)
throws Exception {
protected Future<?> putString(String bucket, String key, String data, String contentType) {
setupApiProxy();
return super.putString(bucket, key, data, contentType);
}
@ -191,8 +181,28 @@ public class JCloudsGaePerformanceLiveTest extends BaseJCloudsPerformanceLiveTes
}
}
private BlobStoreContext perfContext;
@BeforeClass(groups = { "live" })
void setup() {
String accesskeyid = System.getProperty("jclouds.test.user");
String secretkey = System.getProperty("jclouds.test.key");
Properties overrides = new Properties();
String contextName = "gae";
overrideWithSysPropertiesAndPrint(overrides, contextName);
this.perfContext = S3ContextFactory.createContext(overrides, accesskeyid, secretkey,
new NullLoggingModule(), new EnterpriseConfigurationModule(),
new GoogleAppEngineConfigurationModule());
}
@AfterClass(groups = { "live" })
void tearDown() {
if (perfContext != null)
perfContext.close();
}
@Override
protected Module createHttpModule() {
return new GoogleAppEngineConfigurationModule();
public S3AsyncClient getApi() {
return (S3AsyncClient) perfContext.getProviderSpecificContext().getAsyncApi();
}
}

View File

@ -18,27 +18,44 @@
*/
package org.jclouds.aws.s3;
import org.jclouds.date.joda.config.JodaDateServiceModule;
import org.jclouds.encryption.bouncycastle.config.BouncyCastleEncryptionServiceModule;
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
import static org.jclouds.Constants.PROPERTY_MAX_CONNECTIONS_PER_CONTEXT;
import static org.jclouds.Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import java.util.Properties;
import java.util.concurrent.Executors;
import org.jclouds.enterprise.config.EnterpriseConfigurationModule;
import org.jclouds.http.httpnio.config.NioTransformingHttpCommandExecutorServiceModule;
import org.jclouds.logging.config.NullLoggingModule;
import org.testng.ITestContext;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@Test(sequential = true, testName = "perftest.JCloudsNioPerformanceLiveTest", groups = { "live" })
public class JCloudsNioPerformanceLiveTest extends BaseJCloudsPerformanceLiveTest {
@ConfiguresHttpCommandExecutorService
private static final class Module extends NioTransformingHttpCommandExecutorServiceModule {
@Override
protected void configure() {
super.configure();
install(new JodaDateServiceModule());
install(new BouncyCastleEncryptionServiceModule());
}
@Override
@BeforeClass(groups = { "integration", "live" })
public void setUpResourcesOnThisThread(ITestContext testContext) throws Exception {
exec = Executors.newCachedThreadPool();
String accesskeyid = System.getProperty("jclouds.test.user");
String secretkey = System.getProperty("jclouds.test.key");
Properties overrides = new Properties();
overrides.setProperty(PROPERTY_MAX_CONNECTIONS_PER_CONTEXT, 20 + "");
overrides.setProperty(PROPERTY_IO_WORKER_THREADS, 3 + "");
overrides.setProperty(PROPERTY_MAX_CONNECTIONS_PER_HOST, 12 + "");
overrides.setProperty(PROPERTY_USER_THREADS, 0 + "");
String contextName = "nio";
overrideWithSysPropertiesAndPrint(overrides, contextName);
context = S3ContextFactory.createContext(overrides, accesskeyid, secretkey,
new NullLoggingModule(), new EnterpriseConfigurationModule(),
new NioTransformingHttpCommandExecutorServiceModule());
}
@Override
protected Module createHttpModule() {
return new Module();
public S3AsyncClient getApi() {
return (S3AsyncClient) context.getProviderSpecificContext().getAsyncApi();
}
}
}

View File

@ -18,10 +18,18 @@
*/
package org.jclouds.aws.s3;
import org.jclouds.date.joda.config.JodaDateServiceModule;
import org.jclouds.encryption.bouncycastle.config.BouncyCastleEncryptionServiceModule;
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
import static org.jclouds.Constants.PROPERTY_MAX_CONNECTIONS_PER_CONTEXT;
import static org.jclouds.Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import java.util.Properties;
import java.util.concurrent.Executors;
import org.jclouds.enterprise.config.EnterpriseConfigurationModule;
import org.jclouds.logging.config.NullLoggingModule;
import org.testng.ITestContext;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
@ -32,18 +40,26 @@ import org.testng.annotations.Test;
*/
@Test(sequential = true, timeOut = 2 * 60 * 1000, testName = "perftest.JCloudsPerformanceLiveTest", groups = { "live" })
public class JCloudsPerformanceLiveTest extends BaseJCloudsPerformanceLiveTest {
@ConfiguresHttpCommandExecutorService
private static final class Module extends JavaUrlHttpCommandExecutorServiceModule {
@Override
protected void configure() {
super.configure();
install(new JodaDateServiceModule());
install(new BouncyCastleEncryptionServiceModule());
}
@Override
@BeforeClass(groups = { "integration", "live" })
public void setUpResourcesOnThisThread(ITestContext testContext) throws Exception {
exec = Executors.newCachedThreadPool();
String accesskeyid = System.getProperty("jclouds.test.user");
String secretkey = System.getProperty("jclouds.test.key");
Properties overrides = new Properties();
overrides.setProperty(PROPERTY_MAX_CONNECTIONS_PER_CONTEXT, 50 + "");
overrides.setProperty(PROPERTY_MAX_CONNECTIONS_PER_HOST, 30 + "");
overrides.setProperty(PROPERTY_IO_WORKER_THREADS, 50 + "");
overrides.setProperty(PROPERTY_USER_THREADS, 0 + "");
String contextName = "standard";
overrideWithSysPropertiesAndPrint(overrides, contextName);
context = S3ContextFactory.createContext(overrides, accesskeyid, secretkey,
new NullLoggingModule(), new EnterpriseConfigurationModule());
}
@Override
protected Module createHttpModule() {
return new Module();
public S3AsyncClient getApi() {
return (S3AsyncClient) context.getProviderSpecificContext().getAsyncApi();
}
}

View File

@ -42,9 +42,11 @@ package org.jclouds.aws.s3;
* ====================================================================
*/
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.Future;
import org.jets3t.service.S3Service;
import org.jets3t.service.S3ServiceException;
@ -54,6 +56,8 @@ import org.testng.ITestContext;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.appengine.repackaged.com.google.common.base.Throwables;
/**
* Runs operations that jets3t is capable of performing.
*
@ -93,19 +97,6 @@ public class Jets3tPerformanceLiveTest extends BasePerformanceLiveTest {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutBytesParallelEU() throws InterruptedException, ExecutionException,
TimeoutException {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutBytesSerialEU() throws Exception {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutBytesParallel() throws InterruptedException, ExecutionException {
@ -126,35 +117,49 @@ public class Jets3tPerformanceLiveTest extends BasePerformanceLiveTest {
@Override
@Test(enabled = false)
protected boolean putByteArray(String bucket, String key, byte[] data, String contentType)
throws Exception {
protected Future<?> putByteArray(String bucket, String key, byte[] data, String contentType) {
throw new UnsupportedOperationException();
}
@SuppressWarnings("unchecked")
@Override
protected boolean putFile(String bucket, String key, File data, String contentType)
throws Exception {
org.jets3t.service.model.S3Object object = new org.jets3t.service.model.S3Object(key);
protected Future<?> putFile(final String bucket, String key, File data, String contentType) {
final org.jets3t.service.model.S3Object object = new org.jets3t.service.model.S3Object(key);
object.setContentType(contentType);
object.setDataInputFile(data);
object.setContentLength(data.length());
return jetClient.putObject(bucket, object) != null;
return exec.submit(new Callable() {
@Override
public Object call() throws Exception {
return jetClient.putObject(bucket, object);
}
});
}
@SuppressWarnings("unchecked")
@Override
protected boolean putInputStream(String bucket, String key, InputStream data, String contentType)
throws Exception {
org.jets3t.service.model.S3Object object = new org.jets3t.service.model.S3Object(key);
protected Future<?> putInputStream(final String bucket, String key, InputStream data,
String contentType) {
final org.jets3t.service.model.S3Object object = new org.jets3t.service.model.S3Object(key);
object.setContentType(contentType);
object.setDataInputStream(data);
object.setContentLength(data.available());
return jetClient.putObject(bucket, object) != null;
try {
object.setContentLength(data.available());
} catch (IOException e) {
Throwables.propagate(e);
}
return exec.submit(new Callable() {
@Override
public Object call() throws Exception {
return jetClient.putObject(bucket, object);
}
});
}
@Override
protected boolean putString(String bucket, String key, String data, String contentType)
throws Exception {
protected Future<?> putString(String bucket, String key, String data, String contentType) {
throw new UnsupportedOperationException();
}

View File

@ -49,10 +49,11 @@ import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.attr.ConsistencyModels;
import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound;
import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.functions.ReturnTrueOn404;
import org.jclouds.http.options.GetOptions;
import org.jclouds.rest.annotations.BinderParam;
@ -124,7 +125,7 @@ public interface AzureBlobAsyncClient {
@HEAD
@Path("{container}")
@QueryParams(keys = "restype", values = "container")
@ExceptionParser(ReturnFalseOn404.class)
@ExceptionParser(ReturnFalseOnContainerNotFound.class)
ListenableFuture<Boolean> containerExists(@PathParam("container") String container);
/**
@ -213,6 +214,15 @@ public interface AzureBlobAsyncClient {
ListenableFuture<BlobProperties> getBlobProperties(@PathParam("container") String container,
@PathParam("name") String name);
/**
* @see AzureBlobClient#blobExists
*/
@HEAD
@ExceptionParser(ReturnFalseOnKeyNotFound.class)
@Path("{container}/{name}")
ListenableFuture<Boolean> blobExists(@PathParam("container") String container,
@PathParam("name") String name);
/**
* @see AzureBlobClient#setBlobMetadata
*/

View File

@ -29,6 +29,7 @@ import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.concurrent.Timeout;
import org.jclouds.http.options.GetOptions;
@ -197,14 +198,14 @@ public interface AzureBlobClient {
* A Put Blob operation is permitted 10 minutes per MB to complete. If the operation is taking
* longer than 10 minutes per MB on average, the operation will timeout.
*/
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
@Timeout(duration = 10 * 64, timeUnit = TimeUnit.MINUTES)
String putBlob(String container, org.jclouds.azure.storage.blob.domain.AzureBlob object);
/**
* The Get Blob operation reads or downloads a blob from the system, including its metadata and
* properties.
*/
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
@Timeout(duration = 10 * 64, timeUnit = TimeUnit.MINUTES)
org.jclouds.azure.storage.blob.domain.AzureBlob getBlob(String container, String name,
GetOptions... options);
@ -222,4 +223,10 @@ public interface AzureBlobClient {
*/
void deleteBlob(String container, String name);
/**
* @throws ContainerNotFoundException
* if the container is not present.
*/
boolean blobExists(String container, String name);
}

View File

@ -20,20 +20,19 @@ package org.jclouds.azure.storage.blob;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import org.jclouds.azure.storage.blob.config.AzureBlobContextModule;
import org.jclouds.azure.storage.blob.blobstore.config.AzureBlobStoreContextModule;
import org.jclouds.azure.storage.blob.config.AzureBlobRestClientModule;
import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.RestContextBuilder;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Creates {@link AzureBlobContext} or {@link Injector} instances based on the most commonly
* Creates {@link AzureBlobStoreContext} or {@link Injector} instances based on the most commonly
* requested arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
@ -42,38 +41,25 @@ import com.google.inject.TypeLiteral;
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole
* @see AzureBlobAsyncClient
* @author Adrian Cole, Andrew Newdigate
* @see AzureBlobStoreContext
*/
public class AzureBlobContextBuilder extends
RestContextBuilder<AzureBlobAsyncClient, AzureBlobClient> {
BlobStoreContextBuilder<AzureBlobAsyncClient, AzureBlobClient> {
public AzureBlobContextBuilder(Properties properties) {
public AzureBlobContextBuilder(Properties props) {
super(new TypeLiteral<AzureBlobAsyncClient>() {
}, new TypeLiteral<AzureBlobClient>() {
}, properties);
}, props);
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new AzureBlobContextModule());
modules.add(new AzureBlobStoreContextModule());
}
@Override
protected void addClientModule(List<Module> modules) {
modules.add(new AzureBlobRestClientModule());
}
// below is to cast the builder to the correct type so that chained builder methods end correctly
@Override
public AzureBlobContextBuilder withExecutorService(ExecutorService service) {
return (AzureBlobContextBuilder) super.withExecutorService(service);
}
@Override
public AzureBlobContextBuilder withModules(Module... modules) {
return (AzureBlobContextBuilder) super.withModules(modules);
}
}

View File

@ -21,14 +21,14 @@ package org.jclouds.azure.storage.blob;
import java.net.URI;
import java.util.Properties;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.RestContext;
import com.google.inject.Module;
/**
* Creates {@link AzureBlobContext} instances based on the most commonly requested arguments.
* Creates {@link AzureBlobStoreContext} instances based on the most commonly requested arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
@ -36,31 +36,23 @@ import com.google.inject.Module;
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole
* @see AzureBlobAsyncClient
* @author Adrian Cole, Andrew Newdigate
* @see AzureBlobStoreContext
*/
public class AzureBlobContextFactory {
public static RestContext<AzureBlobAsyncClient, AzureBlobClient> createContext(
Properties properties, Module... modules) {
public static BlobStoreContext createContext(Properties properties, Module... modules) {
return new AzureBlobContextBuilder(new AzureBlobPropertiesBuilder(properties).build())
.withModules(modules).buildContext();
.withModules(modules).buildBlobStoreContext();
}
public static RestContext<AzureBlobAsyncClient, AzureBlobClient> createContext(
Properties properties, String account, String encodedKey, Module... modules) {
return new AzureBlobContextBuilder(new AzureBlobPropertiesBuilder(properties)
.withCredentials(account, encodedKey).build()).withModules(modules).buildContext();
public static BlobStoreContext createContext(String user, String encodedKey, Module... modules) {
return new AzureBlobContextBuilder(new AzureBlobPropertiesBuilder(user, encodedKey)
.build()).withModules(modules).buildBlobStoreContext();
}
public static RestContext<AzureBlobAsyncClient, AzureBlobClient> createContext(String account,
String encodedKey, Module... modules) {
return new AzureBlobContextBuilder(new AzureBlobPropertiesBuilder(account, encodedKey)
.build()).withModules(modules).buildContext();
}
public static RestContext<AzureBlobAsyncClient, AzureBlobClient> createContext(URI endpoint,
String account, String encodedKey, Module... modules) {
return new AzureBlobContextBuilder(new AzureBlobPropertiesBuilder(account, encodedKey)
.withEndpoint(endpoint).build()).withModules(modules).buildContext();
public static BlobStoreContext createContext(URI endpoint, String user, String encodedKey,
Module... modules) {
return new AzureBlobContextBuilder(new AzureBlobPropertiesBuilder(user, encodedKey)
.withEndpoint(endpoint).build()).withModules(modules).buildBlobStoreContext();
}
}

View File

@ -20,10 +20,7 @@ package org.jclouds.azure.storage.blob;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_RETRY;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_SESSIONINTERVAL;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_TIMEOUT;
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT;
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY;
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL;
@ -33,7 +30,8 @@ import java.net.URI;
import java.util.Properties;
import java.util.regex.Pattern;
import org.jclouds.http.HttpPropertiesBuilder;
import org.jclouds.PropertiesBuilder;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.util.Utils;
/**
@ -41,13 +39,13 @@ import org.jclouds.util.Utils;
*
* @author Adrian Cole
*/
public class AzureBlobPropertiesBuilder extends HttpPropertiesBuilder {
public class AzureBlobPropertiesBuilder extends PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties
.setProperty(PROPERTY_AZUREBLOB_ENDPOINT, "https://{account}.blob.core.windows.net");
properties.setProperty(PROPERTY_AZUREBLOB_METADATA_PREFIX, "x-ms-meta-");
properties.setProperty(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX, "x-ms-meta-");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "x-ms-meta-");
properties.setProperty(PROPERTY_AZURESTORAGE_SESSIONINTERVAL, 60 + "");
return properties;
@ -89,26 +87,4 @@ public class AzureBlobPropertiesBuilder extends HttpPropertiesBuilder {
return this;
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public AzureBlobPropertiesBuilder withRequestTimeout(long milliseconds) {
properties.setProperty(PROPERTY_AZUREBLOB_TIMEOUT, Long.toString(milliseconds));
return this;
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public AzureBlobPropertiesBuilder withMaxRetries(int retries) {
properties.setProperty(PROPERTY_AZUREBLOB_RETRY, Integer.toString(retries));
return this;
}
protected AzureBlobPropertiesBuilder withMetaPrefix(String prefix) {
properties.setProperty(PROPERTY_AZUREBLOB_METADATA_PREFIX, prefix);
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, prefix);
return this;
}
}

View File

@ -27,7 +27,7 @@ import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.reference.AzureBlobConstants;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
@ -40,7 +40,7 @@ public class BindAzureBlobToPayload implements Binder {
@Inject
public BindAzureBlobToPayload(
@Named(AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX) String prefix,
@Named(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX) String prefix,
EncryptionService encryptionService) {
this.metadataPrefix = prefix;
this.encryptionService = encryptionService;

View File

@ -19,16 +19,19 @@
package org.jclouds.azure.storage.blob.blobstore;
import static com.google.common.util.concurrent.Futures.compose;
import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata;
import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
import static org.jclouds.concurrent.ConcurrentUtils.convertExceptionToValue;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import static org.jclouds.azure.storage.options.ListOptions.Builder.*;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.azure.storage.blob.AzureBlobAsyncClient;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.blobstore.functions.AzureBlobToBlob;
@ -40,8 +43,8 @@ import org.jclouds.azure.storage.blob.blobstore.functions.ListOptionsToListBlobs
import org.jclouds.azure.storage.blob.blobstore.internal.BaseAzureBlobStore;
import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ContainerProperties;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.KeyNotFoundException;
@ -72,68 +75,24 @@ public class AzureAsyncBlobStore extends BaseAzureBlobStore implements AsyncBlob
@Inject
public AzureAsyncBlobStore(AzureBlobAsyncClient async, AzureBlobClient sync,
Factory blobFactory, LoggerFactory logFactory,
ClearListStrategy clearContainerStrategy, BlobPropertiesToBlobMetadata object2BlobMd,
AzureBlobToBlob object2Blob, BlobToAzureBlob blob2Object,
ClearListStrategy clearContainerStrategy, BlobPropertiesToBlobMetadata blob2BlobMd,
AzureBlobToBlob blob2Blob, BlobToAzureBlob blob2Object,
ListOptionsToListBlobsOptions container2ContainerListOptions,
BlobToHttpGetOptions blob2ObjectGetOptions, GetDirectoryStrategy getDirectoryStrategy,
MkdirStrategy mkdirStrategy, ContainerToResourceMetadata container2ResourceMd,
ListBlobsResponseToResourceList container2ResourceList, ExecutorService service) {
super(async, sync, blobFactory, logFactory, clearContainerStrategy, object2BlobMd,
object2Blob, blob2Object, container2ContainerListOptions, blob2ObjectGetOptions,
ListBlobsResponseToResourceList container2ResourceList,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service) {
super(async, sync, blobFactory, logFactory, clearContainerStrategy, blob2BlobMd, blob2Blob,
blob2Object, container2ContainerListOptions, blob2ObjectGetOptions,
getDirectoryStrategy, mkdirStrategy, container2ResourceMd, container2ResourceList,
service);
}
/**
* This implementation uses the AzureBlob HEAD Object command to return the result
* This implementation invokes {@link AzureBlobAsyncClient#listContainers} with the
* {@link org.jclouds.azure.storage.options.ListOptions#includeMetadata} option.
*/
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return compose(convertExceptionToValue(async.getBlobProperties(container, key),
KeyNotFoundException.class, null), new Function<BlobProperties, BlobMetadata>() {
@Override
public BlobMetadata apply(BlobProperties from) {
return object2BlobMd.apply(from);
}
}, service);
}
public ListenableFuture<Void> clearContainer(final String container) {
return makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
clearContainerStrategy.execute(container, recursive());
return null;
}
}), service);
}
/**
* Note that location is currently ignored.
*/
public ListenableFuture<Boolean> createContainerInLocation(String location, String container) {
return async.createContainer(container);
}
public ListenableFuture<Void> deleteContainer(final String container) {
return async.deleteContainer(container);
}
public ListenableFuture<Boolean> containerExists(String container) {
return async.containerExists(container);
}
public ListenableFuture<Blob> getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions... optionsList) {
GetOptions azureOptions = blob2ObjectGetOptions.apply(optionsList);
ListenableFuture<AzureBlob> returnVal = async.getBlob(container, key, azureOptions);
return compose(convertExceptionToValue(returnVal, KeyNotFoundException.class, null),
object2Blob, service);
}
@Override
public ListenableFuture<? extends org.jclouds.blobstore.domain.ListResponse<? extends StorageMetadata>> list() {
return compose(
async.listContainers(includeMetadata()),
@ -146,39 +105,103 @@ public class AzureAsyncBlobStore extends BaseAzureBlobStore implements AsyncBlob
}, service);
}
/**
* This implementation invokes {@link AzureBlobAsyncClient#containerExists}
*
* @param container
* container name
*/
@Override
public ListenableFuture<Boolean> containerExists(String container) {
return async.containerExists(container);
}
/**
* This implementation invokes {@link AzureBlobAsyncClient#createContainer}
*
* @param location
* ignored
* @param container
* container name
*/
@Override
public ListenableFuture<Boolean> createContainerInLocation(String location, String container) {
return async.createContainer(container);
}
/**
* This implementation invokes
* {@link #list(String,org.jclouds.blobstore.options.ListContainerOptions)}
*
* @param container
* container name
*/
@Override
public ListenableFuture<? extends ListContainerResponse<? extends StorageMetadata>> list(
String container, ListContainerOptions... optionsList) {
ListBlobsOptions azureOptions = container2ContainerListOptions.apply(optionsList);
String container) {
return this.list(container, org.jclouds.blobstore.options.ListContainerOptions.NONE);
}
/**
* This implementation invokes {@link AzureBlobAsyncClient#listBucket}
*
* @param container
* container name
*/
@Override
public ListenableFuture<? extends ListContainerResponse<? extends StorageMetadata>> list(
String container, ListContainerOptions options) {
ListBlobsOptions azureOptions = container2ContainerListOptions.apply(options);
ListenableFuture<ListBlobsResponse> returnVal = async.listBlobs(container, azureOptions
.includeMetadata());
return compose(returnVal, container2ResourceList, service);
}
public ListenableFuture<String> putBlob(String container, Blob blob) {
return async.putBlob(container, blob2Object.apply(blob));
}
public ListenableFuture<Void> removeBlob(String container, String key) {
return async.deleteBlob(container, key);
}
public ListenableFuture<Void> createDirectory(final String container, final String directory) {
/**
* This implementation invokes {@link ClearListStrategy#execute} with the
* {@link ListContainerOptions#recursive} option.
*
* @param container
* container name
*/
@Override
public ListenableFuture<Void> clearContainer(final String container) {
return makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
mkdirStrategy.execute(AzureAsyncBlobStore.this, container, directory);
clearContainerStrategy.execute(container, recursive());
return null;
}
}), service);
}
/**
* This implementation invokes {@link AzureBlobAsyncClient#deleteContainer}
*
* @param container
* container name
*/
@Override
public ListenableFuture<Void> deleteContainer(final String container) {
return async.deleteContainer(container);
}
/**
* This implementation invokes {@link GetDirectoryStrategy#execute}
*
* @param container
* container name
* @param directory
* virtual path
*/
@Override
public ListenableFuture<Boolean> directoryExists(final String container, final String directory) {
return makeListenable(service.submit(new Callable<Boolean>() {
public Boolean call() throws Exception {
try {
getDirectoryStrategy.execute(AzureAsyncBlobStore.this, container, directory);
getDirectoryStrategy.execute(container, directory);
return true;
} catch (KeyNotFoundException e) {
return false;
@ -188,4 +211,115 @@ public class AzureAsyncBlobStore extends BaseAzureBlobStore implements AsyncBlob
}), service);
}
/**
* This implementation invokes {@link MkdirStrategy#execute}
*
* @param container
* container name
* @param directory
* virtual path
*/
@Override
public ListenableFuture<Void> createDirectory(final String container, final String directory) {
return makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
mkdirStrategy.execute(container, directory);
return null;
}
}), service);
}
/**
* This implementation invokes {@link AzureBlobAsyncClient#blobExists}
*
* @param container
* bucket name
* @param key
* object key
*/
@Override
public ListenableFuture<Boolean> blobExists(String container, String name) {
return async.blobExists(container, name);
}
/**
* This implementation invokes {@link AzureBlobAsyncClient#getBlobProperties}
*
* @param container
* container name
* @param key
* blob key
*/
@Override
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return compose(convertExceptionToValue(async.getBlobProperties(container, key),
KeyNotFoundException.class, null), new Function<BlobProperties, BlobMetadata>() {
@Override
public BlobMetadata apply(BlobProperties from) {
return blob2BlobMd.apply(from);
}
}, service);
}
/**
* This implementation invokes
* {@link #getBlob(String,String,org.jclouds.blobstore.options.GetOptions)}
*
* @param container
* container name
* @param key
* blob key
*/
@Override
public ListenableFuture<Blob> getBlob(String container, String key) {
return getBlob(container, key, org.jclouds.blobstore.options.GetOptions.NONE);
}
/**
* This implementation invokes {@link AzureBlobAsyncClient#getBlob}
*
* @param container
* container name
* @param key
* blob key
*/
@Override
public ListenableFuture<Blob> getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions options) {
GetOptions azureOptions = blob2ObjectGetOptions.apply(options);
ListenableFuture<AzureBlob> returnVal = async.getBlob(container, key, azureOptions);
return compose(convertExceptionToValue(returnVal, KeyNotFoundException.class, null),
blob2Blob, service);
}
/**
* This implementation invokes {@link AzureBlobAsyncClient#putBlob}
*
* @param container
* container name
* @param blob
* blob
*/
@Override
public ListenableFuture<String> putBlob(String container, Blob blob) {
return async.putBlob(container, blob2Object.apply(blob));
}
/**
* This implementation invokes {@link AzureBlobAsyncClient#deleteObject}
*
* @param container
* container name
* @param key
* blob key
*/
@Override
public ListenableFuture<Void> removeBlob(String container, String key) {
return async.deleteBlob(container, key);
}
}

Some files were not shown because too many files have changed in this diff Show More