mirror of https://github.com/apache/jclouds.git
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:
parent
99f201f0f8
commit
70aa7e4ef3
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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";
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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>
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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";
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -446,7 +446,6 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest {
|
|||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(destinationContainer);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue