mirror of https://github.com/apache/jclouds.git
Issue 301: removed encryption service dependency from blob and added helper methods to blobstore.clj
This commit is contained in:
parent
ef496e7262
commit
31d2da3c6f
|
@ -27,7 +27,6 @@ import org.jclouds.atmosonline.saas.domain.SystemMetadata;
|
||||||
import org.jclouds.atmosonline.saas.domain.UserMetadata;
|
import org.jclouds.atmosonline.saas.domain.UserMetadata;
|
||||||
import org.jclouds.atmosonline.saas.domain.internal.AtmosObjectImpl;
|
import org.jclouds.atmosonline.saas.domain.internal.AtmosObjectImpl;
|
||||||
import org.jclouds.blobstore.config.BlobStoreObjectModule;
|
import org.jclouds.blobstore.config.BlobStoreObjectModule;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
@ -52,25 +51,22 @@ public class AtmosObjectModule extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AtmosObjectFactory implements AtmosObject.Factory {
|
private static class AtmosObjectFactory implements AtmosObject.Factory {
|
||||||
@Inject
|
|
||||||
EncryptionService encryptionService;
|
|
||||||
@Inject
|
@Inject
|
||||||
Provider<MutableContentMetadata> metadataProvider;
|
Provider<MutableContentMetadata> metadataProvider;
|
||||||
|
|
||||||
public AtmosObject create(MutableContentMetadata contentMetadata) {
|
public AtmosObject create(MutableContentMetadata contentMetadata) {
|
||||||
return new AtmosObjectImpl(encryptionService, contentMetadata != null ? contentMetadata
|
return new AtmosObjectImpl(contentMetadata != null ? contentMetadata : metadataProvider
|
||||||
: metadataProvider.get());
|
.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
public AtmosObject create(SystemMetadata systemMetadata, UserMetadata userMetadata) {
|
public AtmosObject create(SystemMetadata systemMetadata, UserMetadata userMetadata) {
|
||||||
return new AtmosObjectImpl(encryptionService, metadataProvider.get(), systemMetadata,
|
return new AtmosObjectImpl(metadataProvider.get(), systemMetadata, userMetadata);
|
||||||
userMetadata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AtmosObject create(MutableContentMetadata contentMetadata,
|
public AtmosObject create(MutableContentMetadata contentMetadata,
|
||||||
SystemMetadata systemMetadata, UserMetadata userMetadata) {
|
SystemMetadata systemMetadata, UserMetadata userMetadata) {
|
||||||
return new AtmosObjectImpl(encryptionService, contentMetadata, systemMetadata,
|
return new AtmosObjectImpl(contentMetadata, systemMetadata, userMetadata);
|
||||||
userMetadata);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ import org.jclouds.atmosonline.saas.domain.AtmosObject;
|
||||||
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
|
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
|
||||||
import org.jclouds.atmosonline.saas.domain.SystemMetadata;
|
import org.jclouds.atmosonline.saas.domain.SystemMetadata;
|
||||||
import org.jclouds.atmosonline.saas.domain.UserMetadata;
|
import org.jclouds.atmosonline.saas.domain.UserMetadata;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
import org.jclouds.http.Payload;
|
import org.jclouds.http.Payload;
|
||||||
import org.jclouds.http.PayloadEnclosing;
|
import org.jclouds.http.PayloadEnclosing;
|
||||||
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
||||||
|
@ -57,10 +56,9 @@ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject
|
||||||
private final SetPayloadPropertiesMutableContentMetadata contentMetadata;
|
private final SetPayloadPropertiesMutableContentMetadata contentMetadata;
|
||||||
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
||||||
|
|
||||||
public AtmosObjectImpl(EncryptionService encryptionService,
|
public AtmosObjectImpl(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata,
|
||||||
MutableContentMetadata contentMetadata, SystemMetadata systemMetadata,
|
|
||||||
UserMetadata userMetadata) {
|
UserMetadata userMetadata) {
|
||||||
super(encryptionService);
|
super();
|
||||||
this.contentMetadata = linkMetadataToThis(contentMetadata);
|
this.contentMetadata = linkMetadataToThis(contentMetadata);
|
||||||
this._contentMetadata = this.contentMetadata.getDelegate();
|
this._contentMetadata = this.contentMetadata.getDelegate();
|
||||||
this.systemMetadata = systemMetadata;
|
this.systemMetadata = systemMetadata;
|
||||||
|
@ -68,9 +66,8 @@ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AtmosObjectImpl(EncryptionService encryptionService,
|
public AtmosObjectImpl(MutableContentMetadata contentMetadata) {
|
||||||
MutableContentMetadata contentMetadata) {
|
this(contentMetadata, null, new UserMetadata());
|
||||||
this(encryptionService, contentMetadata, null, new UserMetadata());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -112,6 +112,7 @@ public class AtmosStorageClientLiveTest {
|
||||||
|
|
||||||
URI container1;
|
URI container1;
|
||||||
URI container2;
|
URI container2;
|
||||||
|
private BlobStoreContext context;
|
||||||
|
|
||||||
@BeforeGroups(groups = { "live" })
|
@BeforeGroups(groups = { "live" })
|
||||||
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
|
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
|
||||||
|
@ -120,15 +121,14 @@ public class AtmosStorageClientLiveTest {
|
||||||
"jclouds.test.identity");
|
"jclouds.test.identity");
|
||||||
String credential = checkNotNull(System.getProperty("jclouds.test.credential"),
|
String credential = checkNotNull(System.getProperty("jclouds.test.credential"),
|
||||||
"jclouds.test.credential");
|
"jclouds.test.credential");
|
||||||
BlobStoreContext blobStoreContext = new BlobStoreContextFactory().createContext(
|
context = new BlobStoreContextFactory().createContext("atmosonline", identity, credential,
|
||||||
"atmosonline", identity, credential, ImmutableSet
|
ImmutableSet.<Module> of(new Log4JLoggingModule()));
|
||||||
.<Module> of(new Log4JLoggingModule()));
|
RestContext<AtmosStorageClient, AtmosStorageAsyncClient> restContext = context
|
||||||
RestContext<AtmosStorageClient, AtmosStorageAsyncClient> context = blobStoreContext
|
|
||||||
.getProviderSpecificContext();
|
.getProviderSpecificContext();
|
||||||
connection = context.getApi();
|
connection = restContext.getApi();
|
||||||
for (DirectoryEntry entry : connection.listDirectories()) {
|
for (DirectoryEntry entry : connection.listDirectories()) {
|
||||||
if (entry.getObjectName().startsWith(containerPrefix)) {
|
if (entry.getObjectName().startsWith(containerPrefix)) {
|
||||||
blobStoreContext.getBlobStore().deleteContainer(entry.getObjectName());
|
context.getBlobStore().deleteContainer(entry.getObjectName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ public class AtmosStorageClientLiveTest {
|
||||||
object.getContentMetadata().setName(name);
|
object.getContentMetadata().setName(name);
|
||||||
object.setPayload(Payloads.newPayload(data));
|
object.setPayload(Payloads.newPayload(data));
|
||||||
object.getContentMetadata().setContentLength(16l);
|
object.getContentMetadata().setContentLength(16l);
|
||||||
object.generateMD5();
|
context.utils().encryption().generateMD5BufferingIfNotRepeatable(object);
|
||||||
object.getContentMetadata().setContentType("text/plain");
|
object.getContentMetadata().setContentType("text/plain");
|
||||||
object.getUserMetadata().getMetadata().put("Metadata", metadataValue);
|
object.getUserMetadata().getMetadata().put("Metadata", metadataValue);
|
||||||
replaceObject(object);
|
replaceObject(object);
|
||||||
|
|
|
@ -25,7 +25,6 @@ import org.jclouds.aws.s3.domain.MutableObjectMetadata;
|
||||||
import org.jclouds.aws.s3.domain.S3Object;
|
import org.jclouds.aws.s3.domain.S3Object;
|
||||||
import org.jclouds.aws.s3.domain.internal.S3ObjectImpl;
|
import org.jclouds.aws.s3.domain.internal.S3ObjectImpl;
|
||||||
import org.jclouds.blobstore.config.BlobStoreObjectModule;
|
import org.jclouds.blobstore.config.BlobStoreObjectModule;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
@ -49,14 +48,11 @@ public class S3ObjectModule extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class S3ObjectFactory implements S3Object.Factory {
|
private static class S3ObjectFactory implements S3Object.Factory {
|
||||||
@Inject
|
|
||||||
EncryptionService encryptionService;
|
|
||||||
@Inject
|
@Inject
|
||||||
Provider<MutableObjectMetadata> metadataProvider;
|
Provider<MutableObjectMetadata> metadataProvider;
|
||||||
|
|
||||||
public S3Object create(MutableObjectMetadata metadata) {
|
public S3Object create(MutableObjectMetadata metadata) {
|
||||||
return new S3ObjectImpl(encryptionService, metadata != null ? metadata : metadataProvider
|
return new S3ObjectImpl(metadata != null ? metadata : metadataProvider.get());
|
||||||
.get());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ import javax.inject.Inject;
|
||||||
import org.jclouds.aws.s3.domain.AccessControlList;
|
import org.jclouds.aws.s3.domain.AccessControlList;
|
||||||
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
|
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
|
||||||
import org.jclouds.aws.s3.domain.S3Object;
|
import org.jclouds.aws.s3.domain.S3Object;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
import org.jclouds.http.Payload;
|
import org.jclouds.http.Payload;
|
||||||
import org.jclouds.http.PayloadEnclosing;
|
import org.jclouds.http.PayloadEnclosing;
|
||||||
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
||||||
|
@ -64,8 +63,8 @@ public class S3ObjectImpl extends PayloadEnclosingImpl implements S3Object, Comp
|
||||||
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public S3ObjectImpl(EncryptionService encryptionService, MutableObjectMetadata metadata) {
|
public S3ObjectImpl(MutableObjectMetadata metadata) {
|
||||||
super(encryptionService);
|
super();
|
||||||
this.metadata = linkMetadataToThis(metadata);
|
this.metadata = linkMetadataToThis(metadata);
|
||||||
this._metadata = this.metadata.getDelegate();
|
this._metadata = this.metadata.getDelegate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import org.jclouds.azure.storage.blob.domain.AzureBlob;
|
||||||
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
|
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
|
||||||
import org.jclouds.azure.storage.blob.domain.internal.AzureBlobImpl;
|
import org.jclouds.azure.storage.blob.domain.internal.AzureBlobImpl;
|
||||||
import org.jclouds.blobstore.config.BlobStoreObjectModule;
|
import org.jclouds.blobstore.config.BlobStoreObjectModule;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
@ -50,14 +49,11 @@ public class AzureBlobModule extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AzureBlobFactory implements AzureBlob.Factory {
|
private static class AzureBlobFactory implements AzureBlob.Factory {
|
||||||
@Inject
|
|
||||||
EncryptionService encryptionService;
|
|
||||||
@Inject
|
@Inject
|
||||||
Provider<MutableBlobProperties> metadataProvider;
|
Provider<MutableBlobProperties> metadataProvider;
|
||||||
|
|
||||||
public AzureBlob create(MutableBlobProperties metadata) {
|
public AzureBlob create(MutableBlobProperties metadata) {
|
||||||
return new AzureBlobImpl(encryptionService, metadata != null ? metadata : metadataProvider
|
return new AzureBlobImpl(metadata != null ? metadata : metadataProvider.get());
|
||||||
.get());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ import javax.inject.Inject;
|
||||||
|
|
||||||
import org.jclouds.azure.storage.blob.domain.AzureBlob;
|
import org.jclouds.azure.storage.blob.domain.AzureBlob;
|
||||||
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
|
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
import org.jclouds.http.Payload;
|
import org.jclouds.http.Payload;
|
||||||
import org.jclouds.http.PayloadEnclosing;
|
import org.jclouds.http.PayloadEnclosing;
|
||||||
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
||||||
|
@ -45,8 +44,8 @@ public class AzureBlobImpl extends PayloadEnclosingImpl implements AzureBlob, Co
|
||||||
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AzureBlobImpl(EncryptionService encryptionService, MutableBlobProperties properties) {
|
public AzureBlobImpl(MutableBlobProperties properties) {
|
||||||
super(encryptionService);
|
super();
|
||||||
this.properties = linkMetadataToThis(properties);
|
this.properties = linkMetadataToThis(properties);
|
||||||
this._properties = this.properties.getDelegate();
|
this._properties = this.properties.getDelegate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,10 +39,9 @@ import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
|
||||||
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
|
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
|
||||||
import org.jclouds.azure.storage.domain.BoundedSet;
|
import org.jclouds.azure.storage.domain.BoundedSet;
|
||||||
import org.jclouds.azure.storage.options.ListOptions;
|
import org.jclouds.azure.storage.options.ListOptions;
|
||||||
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
import org.jclouds.blobstore.BlobStoreContextFactory;
|
import org.jclouds.blobstore.BlobStoreContextFactory;
|
||||||
import org.jclouds.blobstore.ContainerNotFoundException;
|
import org.jclouds.blobstore.ContainerNotFoundException;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
import org.jclouds.encryption.internal.JCEEncryptionService;
|
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.http.options.GetOptions;
|
import org.jclouds.http.options.GetOptions;
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
|
@ -67,15 +66,16 @@ public class AzureBlobClientLiveTest {
|
||||||
protected AzureBlobClient client;
|
protected AzureBlobClient client;
|
||||||
|
|
||||||
private String containerPrefix = System.getProperty("user.name") + "-azureblob";
|
private String containerPrefix = System.getProperty("user.name") + "-azureblob";
|
||||||
private EncryptionService encryptionService = new JCEEncryptionService();
|
|
||||||
|
private BlobStoreContext context;
|
||||||
|
|
||||||
@BeforeTest
|
@BeforeTest
|
||||||
public void setupClient() throws IOException {
|
public void setupClient() throws IOException {
|
||||||
identity = System.getProperty("jclouds.test.identity");
|
identity = System.getProperty("jclouds.test.identity");
|
||||||
String credential = System.getProperty("jclouds.test.credential");
|
String credential = System.getProperty("jclouds.test.credential");
|
||||||
client = (AzureBlobClient) new BlobStoreContextFactory().createContext("azureblob", identity,
|
context = new BlobStoreContextFactory().createContext("azureblob", identity, credential,
|
||||||
credential, ImmutableSet.<Module> of(new Log4JLoggingModule()))
|
ImmutableSet.<Module> of(new Log4JLoggingModule()));
|
||||||
.getProviderSpecificContext().getApi();
|
client = (AzureBlobClient) context.getProviderSpecificContext().getApi();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -113,7 +113,7 @@ public class AzureBlobClientLiveTest {
|
||||||
ListBlobsResponse list = client.listBlobs(privateContainer);
|
ListBlobsResponse list = client.listBlobs(privateContainer);
|
||||||
assertEquals(list.getUrl(), URI.create(String.format("https://%s.blob.core.windows.net/%s",
|
assertEquals(list.getUrl(), URI.create(String.format("https://%s.blob.core.windows.net/%s",
|
||||||
identity, privateContainer)));
|
identity, privateContainer)));
|
||||||
// TODO ... check to see the container actually exists
|
// TODO .. check to see the container actually exists
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeOut = 5 * 60 * 1000)
|
@Test(timeOut = 5 * 60 * 1000)
|
||||||
|
@ -231,12 +231,12 @@ public class AzureBlobClientLiveTest {
|
||||||
AzureBlob object = client.newBlob();
|
AzureBlob object = client.newBlob();
|
||||||
object.getProperties().setName("object");
|
object.getProperties().setName("object");
|
||||||
object.setPayload(data);
|
object.setPayload(data);
|
||||||
object.generateMD5();
|
context.utils().encryption().generateMD5BufferingIfNotRepeatable(object);
|
||||||
object.getProperties().setContentType("text/plain");
|
object.getProperties().setContentType("text/plain");
|
||||||
object.getProperties().getMetadata().put("mykey", "metadata-value");
|
object.getProperties().getMetadata().put("mykey", "metadata-value");
|
||||||
byte[] md5 = object.getProperties().getContentMD5();
|
byte[] md5 = object.getProperties().getContentMD5();
|
||||||
String newEtag = client.putBlob(privateContainer, object);
|
String newEtag = client.putBlob(privateContainer, object);
|
||||||
assertEquals(encryptionService.hex(md5), encryptionService.hex(object.getProperties()
|
assertEquals(context.utils().encryption().hex(md5), context.utils().encryption().hex(object.getProperties()
|
||||||
.getContentMD5()));
|
.getContentMD5()));
|
||||||
|
|
||||||
// Test HEAD of missing object
|
// Test HEAD of missing object
|
||||||
|
@ -253,8 +253,8 @@ public class AzureBlobClientLiveTest {
|
||||||
// http://code.google.com/p/jclouds/issues/detail?id=92
|
// http://code.google.com/p/jclouds/issues/detail?id=92
|
||||||
// assertEquals(metadata.getSize(), data.length());
|
// assertEquals(metadata.getSize(), data.length());
|
||||||
assertEquals(metadata.getContentType(), "text/plain");
|
assertEquals(metadata.getContentType(), "text/plain");
|
||||||
// Azure doesn't return the Content-MD5 on head request...
|
// Azure doesn't return the Content-MD5 on head request..
|
||||||
assertEquals(encryptionService.hex(md5), encryptionService.hex(object.getProperties()
|
assertEquals(context.utils().encryption().hex(md5), context.utils().encryption().hex(object.getProperties()
|
||||||
.getContentMD5()));
|
.getContentMD5()));
|
||||||
assertEquals(metadata.getETag(), newEtag);
|
assertEquals(metadata.getETag(), newEtag);
|
||||||
assertEquals(metadata.getMetadata().entrySet().size(), 1);
|
assertEquals(metadata.getMetadata().entrySet().size(), 1);
|
||||||
|
@ -276,7 +276,7 @@ public class AzureBlobClientLiveTest {
|
||||||
// TODO assertEquals(getBlob.getName(), object.getProperties().getName());
|
// TODO assertEquals(getBlob.getName(), object.getProperties().getName());
|
||||||
assertEquals(getBlob.getPayload().getContentLength(), new Long(data.length()));
|
assertEquals(getBlob.getPayload().getContentLength(), new Long(data.length()));
|
||||||
assertEquals(getBlob.getProperties().getContentType(), "text/plain");
|
assertEquals(getBlob.getProperties().getContentType(), "text/plain");
|
||||||
assertEquals(encryptionService.hex(md5), encryptionService.hex(getBlob.getProperties()
|
assertEquals(context.utils().encryption().hex(md5), context.utils().encryption().hex(getBlob.getProperties()
|
||||||
.getContentMD5()));
|
.getContentMD5()));
|
||||||
assertEquals(newEtag, getBlob.getProperties().getETag());
|
assertEquals(newEtag, getBlob.getProperties().getETag());
|
||||||
// wait until we can update metadata
|
// wait until we can update metadata
|
||||||
|
@ -318,7 +318,7 @@ public class AzureBlobClientLiveTest {
|
||||||
object.setPayload(bais);
|
object.setPayload(bais);
|
||||||
object.getPayload().setContentLength(new Long(data.getBytes().length));
|
object.getPayload().setContentLength(new Long(data.getBytes().length));
|
||||||
newEtag = client.putBlob(privateContainer, object);
|
newEtag = client.putBlob(privateContainer, object);
|
||||||
assertEquals(encryptionService.hex(md5), encryptionService.hex(getBlob.getProperties()
|
assertEquals(context.utils().encryption().hex(md5), context.utils().encryption().hex(getBlob.getProperties()
|
||||||
.getContentMD5()));
|
.getContentMD5()));
|
||||||
|
|
||||||
// Test GET with options
|
// Test GET with options
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
Current supported services are:
|
Current supported services are:
|
||||||
[s3, azureblob, atmos, cloudfiles, walrus, googlestorage]
|
[s3, azureblob, atmos, cloudfiles, walrus, googlestorage]
|
||||||
|
|
||||||
Here's a quick example of how to view blob resources in rackspace
|
Here's a quick example of how to viewresources in rackspace
|
||||||
|
|
||||||
(use 'org.jclouds.blobstore)
|
(use 'org.jclouds.blobstore)
|
||||||
(use 'clojure.contrib.pprint)
|
(use 'clojure.contrib.pprint)
|
||||||
|
@ -92,8 +92,6 @@ Options can also be specified for extension modules
|
||||||
|
|
||||||
(def *blobstore*)
|
(def *blobstore*)
|
||||||
|
|
||||||
(def *encryption-service* (JCEEncryptionService.)) ;; TODO: use guice
|
|
||||||
|
|
||||||
(def *max-retries* 3)
|
(def *max-retries* 3)
|
||||||
|
|
||||||
(defmacro with-blobstore [[& blobstore-or-args] & body]
|
(defmacro with-blobstore [[& blobstore-or-args] & body]
|
||||||
|
@ -222,7 +220,7 @@ Options can also be specified for extension modules
|
||||||
(.putBlob blobstore container-name blob)))
|
(.putBlob blobstore container-name blob)))
|
||||||
|
|
||||||
(defn blob-metadata
|
(defn blob-metadata
|
||||||
"Get blob metadata from given path"
|
"Get metadata from given path"
|
||||||
([container-name path]
|
([container-name path]
|
||||||
(blob-metadata container-name path *blobstore*))
|
(blob-metadata container-name path *blobstore*))
|
||||||
([container-name path blobstore]
|
([container-name path blobstore]
|
||||||
|
@ -268,17 +266,29 @@ example:
|
||||||
(.list (as-blobstore blobstore) container-name
|
(.list (as-blobstore blobstore) container-name
|
||||||
(.inDirectory (new ListContainerOptions) dir))))
|
(.inDirectory (new ListContainerOptions) dir))))
|
||||||
|
|
||||||
|
(defn md5-blob
|
||||||
|
"add a content md5 to a blob. note that this implies rebuffering, if theisn't repeatable"
|
||||||
|
([blob]
|
||||||
|
(md5-blob *blobstore*))
|
||||||
|
([blob blobstore]
|
||||||
|
(.generateMD5BufferingIfNotRepeatable (.encryption (.utils (blobstore-context blobstore)))
|
||||||
|
blob)))
|
||||||
|
(defn blob
|
||||||
|
"create a new blob with the specified payload"
|
||||||
|
([name payload]
|
||||||
|
(blob name payload *blobstore*))
|
||||||
|
([name payload blobstore]
|
||||||
|
(doto (.newBlob blobstore name)
|
||||||
|
(.setPayload payload))))
|
||||||
|
|
||||||
(defn upload-blob
|
(defn upload-blob
|
||||||
"Create an blob representing text data:
|
"Create anrepresenting text data:
|
||||||
container, name, string -> etag"
|
container, name, string -> etag"
|
||||||
([container-name name data] ;; TODO: allow payload to be a stream
|
([container-name name data]
|
||||||
(upload-blob container-name name data *blobstore*))
|
(upload-blob container-name name data *blobstore*))
|
||||||
([container-name name data blobstore]
|
([container-name name data blobstore]
|
||||||
(put-blob container-name
|
(put-blob container-name
|
||||||
(doto (.newBlob blobstore name)
|
(md5-blob (blob name data) blobstore) blobstore)))
|
||||||
(.setPayload data)
|
|
||||||
(.generateMD5))
|
|
||||||
blobstore)))
|
|
||||||
|
|
||||||
(defmulti #^{:arglists '[[container-name name target]
|
(defmulti #^{:arglists '[[container-name name target]
|
||||||
[container-name name target blobstore]]}
|
[container-name name target blobstore]]}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
|
||||||
import org.jclouds.blobstore.strategy.GetBlobsInListStrategy;
|
import org.jclouds.blobstore.strategy.GetBlobsInListStrategy;
|
||||||
import org.jclouds.blobstore.strategy.PutBlobsStrategy;
|
import org.jclouds.blobstore.strategy.PutBlobsStrategy;
|
||||||
import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
|
import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
|
||||||
|
import org.jclouds.encryption.EncryptionService;
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Scopes;
|
import com.google.inject.Scopes;
|
||||||
|
@ -83,11 +84,14 @@ public class BlobStoreMapModule extends AbstractModule {
|
||||||
@Inject
|
@Inject
|
||||||
PutBlobsStrategy putBlobsStrategy;
|
PutBlobsStrategy putBlobsStrategy;
|
||||||
@Inject
|
@Inject
|
||||||
|
EncryptionService encryptionService;
|
||||||
|
@Inject
|
||||||
ListContainerAndRecurseThroughFolders listStrategy;
|
ListContainerAndRecurseThroughFolders listStrategy;
|
||||||
|
|
||||||
public InputStreamMap create(String containerName, ListContainerOptions options) {
|
public InputStreamMap create(String containerName, ListContainerOptions options) {
|
||||||
return new InputStreamMapImpl(connection, blobFactory, getAllBlobs, listStrategy,
|
return new InputStreamMapImpl(connection, blobFactory, getAllBlobs, listStrategy,
|
||||||
containsValueStrategy, putBlobsStrategy, containerName, options);
|
containsValueStrategy, putBlobsStrategy, containerName, options,
|
||||||
|
encryptionService);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import javax.inject.Provider;
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||||
import org.jclouds.blobstore.domain.internal.BlobImpl;
|
import org.jclouds.blobstore.domain.internal.BlobImpl;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
@ -47,14 +46,12 @@ public class BlobStoreObjectModule extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class BlobFactory implements Blob.Factory {
|
private static class BlobFactory implements Blob.Factory {
|
||||||
@Inject
|
|
||||||
EncryptionService encryptionService;
|
|
||||||
@Inject
|
@Inject
|
||||||
Provider<MutableBlobMetadata> metadataProvider;
|
Provider<MutableBlobMetadata> metadataProvider;
|
||||||
|
|
||||||
public Blob create(MutableBlobMetadata metadata) {
|
public Blob create(MutableBlobMetadata metadata) {
|
||||||
return new BlobImpl(encryptionService, metadata != null ? metadata : metadataProvider
|
return new BlobImpl(metadata != null ? metadata : metadataProvider.get());
|
||||||
.get());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ import javax.inject.Inject;
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
import org.jclouds.http.Payload;
|
import org.jclouds.http.Payload;
|
||||||
import org.jclouds.http.PayloadEnclosing;
|
import org.jclouds.http.PayloadEnclosing;
|
||||||
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
||||||
|
@ -49,8 +48,8 @@ public class BlobImpl extends PayloadEnclosingImpl implements Blob, Comparable<B
|
||||||
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public BlobImpl(EncryptionService encryptionService, MutableBlobMetadata metadata) {
|
public BlobImpl(MutableBlobMetadata metadata) {
|
||||||
super(encryptionService);
|
super();
|
||||||
this.metadata = linkMetadataToThis(metadata);
|
this.metadata = linkMetadataToThis(metadata);
|
||||||
this._metadata = this.metadata.getDelegate();
|
this._metadata = this.metadata.getDelegate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ package org.jclouds.blobstore.functions;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.encryption.EncryptionService;
|
||||||
import org.jclouds.http.Payloads;
|
import org.jclouds.http.Payloads;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
@ -28,10 +29,12 @@ import com.google.common.base.Function;
|
||||||
public class ObjectMD5 implements Function<Object, byte[]> {
|
public class ObjectMD5 implements Function<Object, byte[]> {
|
||||||
|
|
||||||
protected final Blob.Factory blobFactory;
|
protected final Blob.Factory blobFactory;
|
||||||
|
protected final EncryptionService encryptionService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ObjectMD5(Blob.Factory blobFactory) {
|
ObjectMD5(EncryptionService encryptionService, Blob.Factory blobFactory) {
|
||||||
this.blobFactory = blobFactory;
|
this.blobFactory = blobFactory;
|
||||||
|
this.encryptionService = encryptionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] apply(Object from) {
|
public byte[] apply(Object from) {
|
||||||
|
@ -43,7 +46,7 @@ public class ObjectMD5 implements Function<Object, byte[]> {
|
||||||
object.setPayload(Payloads.newPayload(from));
|
object.setPayload(Payloads.newPayload(from));
|
||||||
}
|
}
|
||||||
if (object.getMetadata().getContentMD5() == null)
|
if (object.getMetadata().getContentMD5() == null)
|
||||||
object.generateMD5();
|
encryptionService.generateMD5BufferingIfNotRepeatable(object);
|
||||||
return object.getPayload().getContentMD5();
|
return object.getPayload().getContentMD5();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
|
||||||
import org.jclouds.blobstore.strategy.GetBlobsInListStrategy;
|
import org.jclouds.blobstore.strategy.GetBlobsInListStrategy;
|
||||||
import org.jclouds.blobstore.strategy.PutBlobsStrategy;
|
import org.jclouds.blobstore.strategy.PutBlobsStrategy;
|
||||||
import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
|
import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
|
||||||
|
import org.jclouds.encryption.EncryptionService;
|
||||||
import org.jclouds.http.Payload;
|
import org.jclouds.http.Payload;
|
||||||
import org.jclouds.http.payloads.ByteArrayPayload;
|
import org.jclouds.http.payloads.ByteArrayPayload;
|
||||||
import org.jclouds.http.payloads.FilePayload;
|
import org.jclouds.http.payloads.FilePayload;
|
||||||
|
@ -58,14 +59,16 @@ import com.google.common.base.Function;
|
||||||
* @see BaseBlobMap
|
* @see BaseBlobMap
|
||||||
*/
|
*/
|
||||||
public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements InputStreamMap {
|
public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements InputStreamMap {
|
||||||
|
protected final EncryptionService encryptionService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public InputStreamMapImpl(BlobStore connection, Blob.Factory blobFactory,
|
public InputStreamMapImpl(BlobStore connection, Blob.Factory blobFactory,
|
||||||
GetBlobsInListStrategy getAllBlobs, ListContainerAndRecurseThroughFolders listStrategy,
|
GetBlobsInListStrategy getAllBlobs, ListContainerAndRecurseThroughFolders listStrategy,
|
||||||
ContainsValueInListStrategy containsValueStrategy, PutBlobsStrategy putBlobsStrategy,
|
ContainsValueInListStrategy containsValueStrategy, PutBlobsStrategy putBlobsStrategy,
|
||||||
String containerName, ListContainerOptions options) {
|
String containerName, ListContainerOptions options, EncryptionService encryptionService) {
|
||||||
super(connection, getAllBlobs, containsValueStrategy, putBlobsStrategy, listStrategy,
|
super(connection, getAllBlobs, containsValueStrategy, putBlobsStrategy, listStrategy,
|
||||||
containerName, options);
|
containerName, options);
|
||||||
|
this.encryptionService = encryptionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -129,14 +132,22 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
|
||||||
new Function<Map.Entry<? extends String, ? extends Object>, Blob>() {
|
new Function<Map.Entry<? extends String, ? extends Object>, Blob>() {
|
||||||
@Override
|
@Override
|
||||||
public Blob apply(Map.Entry<? extends String, ? extends Object> from) {
|
public Blob apply(Map.Entry<? extends String, ? extends Object> from) {
|
||||||
Blob blob = blobstore.newBlob(prefixer.apply(from.getKey()));
|
String name = from.getKey();
|
||||||
blob.setPayload(newPayload(from.getValue()));
|
Object value = from.getValue();
|
||||||
blob.generateMD5();
|
return newBlobWithMD5(name, value);
|
||||||
return blob;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
Blob newBlobWithMD5(String name, Object value) {
|
||||||
|
Blob blob = blobstore.newBlob(prefixer.apply(name));
|
||||||
|
blob.setPayload(newPayload(value));
|
||||||
|
encryptionService.generateMD5BufferingIfNotRepeatable(blob);
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream putString(String key, String value) {
|
public InputStream putString(String key, String value) {
|
||||||
return putInternal(key, new StringPayload(value));
|
return putInternal(key, new StringPayload(value));
|
||||||
|
@ -166,9 +177,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
InputStream putInternal(String name, Payload payload) {
|
InputStream putInternal(String name, Payload payload) {
|
||||||
InputStream returnVal = containsKey(name) ? get(name) : null;
|
InputStream returnVal = containsKey(name) ? get(name) : null;
|
||||||
Blob blob = blobstore.newBlob(prefixer.apply(name));
|
Blob blob = newBlobWithMD5(name, payload);
|
||||||
blob.setPayload(payload);
|
|
||||||
blob.generateMD5();
|
|
||||||
blobstore.putBlob(containerName, blob);
|
blobstore.putBlob(containerName, blob);
|
||||||
return returnVal;
|
return returnVal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,6 @@ import org.jclouds.blobstore.domain.BlobMetadata;
|
||||||
import org.jclouds.blobstore.domain.PageSet;
|
import org.jclouds.blobstore.domain.PageSet;
|
||||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||||
import org.jclouds.blobstore.domain.StorageType;
|
import org.jclouds.blobstore.domain.StorageType;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
import org.jclouds.encryption.internal.JCEEncryptionService;
|
import org.jclouds.encryption.internal.JCEEncryptionService;
|
||||||
import org.jclouds.http.BaseJettyTest;
|
import org.jclouds.http.BaseJettyTest;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
|
@ -68,25 +67,22 @@ import com.google.common.io.ByteStreams;
|
||||||
import com.google.common.io.InputSupplier;
|
import com.google.common.io.InputSupplier;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.Guice;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
private byte[] oneHundredOneConstitutions;
|
private byte[] oneHundredOneConstitutions;
|
||||||
private EncryptionService encryptionService;
|
|
||||||
private byte[] oneHundredOneConstitutionsMD5;
|
private byte[] oneHundredOneConstitutionsMD5;
|
||||||
|
|
||||||
@BeforeClass(groups = { "integration", "live" })
|
@BeforeClass(groups = { "integration", "live" })
|
||||||
@Override
|
@Override
|
||||||
public void setUpResourcesOnThisThread(ITestContext testContext) throws Exception {
|
public void setUpResourcesOnThisThread(ITestContext testContext) throws Exception {
|
||||||
encryptionService = Guice.createInjector().getInstance(EncryptionService.class);
|
super.setUpResourcesOnThisThread(testContext);
|
||||||
Payload result = encryptionService
|
Payload result = context.utils().encryption().generatePayloadWithMD5For(
|
||||||
.generatePayloadWithMD5For(getTestDataSupplier().getInput());
|
getTestDataSupplier().getInput());
|
||||||
oneHundredOneConstitutions = (byte[]) result.getRawContent();
|
oneHundredOneConstitutions = (byte[]) result.getRawContent();
|
||||||
oneHundredOneConstitutionsMD5 = result.getContentMD5();
|
oneHundredOneConstitutionsMD5 = result.getContentMD5();
|
||||||
super.setUpResourcesOnThisThread(testContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -119,7 +115,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void apply(Blob from) {
|
public Void apply(Blob from) {
|
||||||
assertEquals(encryptionService.md5(from.getPayload().getInput()),
|
assertEquals(context.utils().encryption().md5(from.getPayload().getInput()),
|
||||||
oneHundredOneConstitutionsMD5);
|
oneHundredOneConstitutionsMD5);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -151,7 +147,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
String key = "apples";
|
String key = "apples";
|
||||||
|
|
||||||
Date before = new Date(System.currentTimeMillis() - 1000);
|
Date before = new Date(System.currentTimeMillis() - 1000);
|
||||||
// first create the object
|
// first create the blob
|
||||||
addObjectAndValidateContent(containerName, key);
|
addObjectAndValidateContent(containerName, key);
|
||||||
// now, modify it
|
// now, modify it
|
||||||
addObjectAndValidateContent(containerName, key);
|
addObjectAndValidateContent(containerName, key);
|
||||||
|
@ -251,13 +247,13 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
String key = "apples";
|
String key = "apples";
|
||||||
|
|
||||||
addObjectAndValidateContent(containerName, key);
|
addObjectAndValidateContent(containerName, key);
|
||||||
Blob object1 = context.getBlobStore().getBlob(containerName, key, range(0, 5));
|
Blob blob1 = context.getBlobStore().getBlob(containerName, key, range(0, 5));
|
||||||
assertEquals(getContentAsStringOrNullAndClose(object1), TEST_STRING.substring(0, 6));
|
assertEquals(getContentAsStringOrNullAndClose(blob1), TEST_STRING.substring(0, 6));
|
||||||
|
|
||||||
Blob object2 = context.getBlobStore().getBlob(containerName, key,
|
Blob blob2 = context.getBlobStore().getBlob(containerName, key,
|
||||||
range(6, TEST_STRING.length()));
|
range(6, TEST_STRING.length()));
|
||||||
assertEquals(getContentAsStringOrNullAndClose(object2), TEST_STRING.substring(6,
|
assertEquals(getContentAsStringOrNullAndClose(blob2), TEST_STRING.substring(6, TEST_STRING
|
||||||
TEST_STRING.length()));
|
.length()));
|
||||||
} finally {
|
} finally {
|
||||||
returnContainer(containerName);
|
returnContainer(containerName);
|
||||||
}
|
}
|
||||||
|
@ -271,10 +267,10 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
String key = "apples";
|
String key = "apples";
|
||||||
|
|
||||||
addObjectAndValidateContent(containerName, key);
|
addObjectAndValidateContent(containerName, key);
|
||||||
Blob object = context.getBlobStore().getBlob(containerName, key,
|
Blob blob = context.getBlobStore().getBlob(containerName, key,
|
||||||
range(0, 5).range(6, TEST_STRING.length()));
|
range(0, 5).range(6, TEST_STRING.length()));
|
||||||
|
|
||||||
assertEquals(getContentAsStringOrNullAndClose(object), TEST_STRING);
|
assertEquals(getContentAsStringOrNullAndClose(blob), TEST_STRING);
|
||||||
} finally {
|
} finally {
|
||||||
returnContainer(containerName);
|
returnContainer(containerName);
|
||||||
}
|
}
|
||||||
|
@ -289,12 +285,12 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
// String key = "apples";
|
// String key = "apples";
|
||||||
//
|
//
|
||||||
// addObjectAndValidateContent(containerName, key);
|
// addObjectAndValidateContent(containerName, key);
|
||||||
// Blob object = context.getBlobStore().getBlob(containerName, key, tail(5)).get(30,
|
// Blob blob = context.getBlobStore().getBlob(containerName, key, tail(5)).get(30,
|
||||||
// TimeUnit.SECONDS);
|
// TimeUnit.SECONDS);
|
||||||
// assertEquals(BlobStoreUtils.getContentAsStringAndClose(object), TEST_STRING
|
// assertEquals(BlobStoreUtils.getContentAsStringAndClose(blob), TEST_STRING
|
||||||
// .substring(TEST_STRING.length() - 5));
|
// .substring(TEST_STRING.length() - 5));
|
||||||
// assertEquals(object.getContentLength(), 5);
|
// assertEquals(blob.getContentLength(), 5);
|
||||||
// assertEquals(object.getMetadata().getSize(), TEST_STRING.length());
|
// assertEquals(blob.getMetadata().getSize(), TEST_STRING.length());
|
||||||
// } finally {
|
// } finally {
|
||||||
// returnContainer(containerName);
|
// returnContainer(containerName);
|
||||||
// }
|
// }
|
||||||
|
@ -309,12 +305,12 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
// String key = "apples";
|
// String key = "apples";
|
||||||
//
|
//
|
||||||
// addObjectAndValidateContent(containerName, key);
|
// addObjectAndValidateContent(containerName, key);
|
||||||
// Blob object = context.getBlobStore().getBlob(containerName, key, startAt(5)).get(30,
|
// Blob blob = context.getBlobStore().getBlob(containerName, key, startAt(5)).get(30,
|
||||||
// TimeUnit.SECONDS);
|
// TimeUnit.SECONDS);
|
||||||
// assertEquals(BlobStoreUtils.getContentAsStringAndClose(object), TEST_STRING.substring(5,
|
// assertEquals(BlobStoreUtils.getContentAsStringAndClose(blob), TEST_STRING.substring(5,
|
||||||
// TEST_STRING.length()));
|
// TEST_STRING.length()));
|
||||||
// assertEquals(object.getContentLength(), TEST_STRING.length() - 5);
|
// assertEquals(blob.getContentLength(), TEST_STRING.length() - 5);
|
||||||
// assertEquals(object.getMetadata().getSize(), TEST_STRING.length());
|
// assertEquals(blob.getMetadata().getSize(), TEST_STRING.length());
|
||||||
// } finally {
|
// } finally {
|
||||||
// returnContainer(containerName);
|
// returnContainer(containerName);
|
||||||
// }
|
// }
|
||||||
|
@ -339,7 +335,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(groups = { "integration", "live" })
|
@Test(groups = { "integration", "live" })
|
||||||
public void objectNotFound() throws InterruptedException {
|
public void blobNotFound() throws InterruptedException {
|
||||||
String containerName = getContainerName();
|
String containerName = getContainerName();
|
||||||
String key = "test";
|
String key = "test";
|
||||||
try {
|
try {
|
||||||
|
@ -407,17 +403,17 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
@Test(groups = { "integration", "live" }, dataProvider = "putTests")
|
@Test(groups = { "integration", "live" }, dataProvider = "putTests")
|
||||||
public void testPutObject(String key, String type, Object content, Object realObject)
|
public void testPutObject(String key, String type, Object content, Object realObject)
|
||||||
throws InterruptedException, IOException {
|
throws InterruptedException, IOException {
|
||||||
Blob object = context.getBlobStore().newBlob(key);
|
Blob blob = context.getBlobStore().newBlob(key);
|
||||||
object.getMetadata().setContentType(type);
|
blob.getMetadata().setContentType(type);
|
||||||
object.setPayload(Payloads.newPayload(content));
|
blob.setPayload(Payloads.newPayload(content));
|
||||||
if (content instanceof InputStream) {
|
if (content instanceof InputStream) {
|
||||||
object.generateMD5();
|
context.utils().encryption().generateMD5BufferingIfNotRepeatable(blob);
|
||||||
}
|
}
|
||||||
String containerName = getContainerName();
|
String containerName = getContainerName();
|
||||||
try {
|
try {
|
||||||
assertNotNull(context.getBlobStore().putBlob(containerName, object));
|
assertNotNull(context.getBlobStore().putBlob(containerName, blob));
|
||||||
object = context.getBlobStore().getBlob(containerName, object.getMetadata().getName());
|
blob = context.getBlobStore().getBlob(containerName, blob.getMetadata().getName());
|
||||||
String returnedString = getContentAsStringOrNullAndClose(object);
|
String returnedString = getContentAsStringOrNullAndClose(blob);
|
||||||
assertEquals(returnedString, realObject);
|
assertEquals(returnedString, realObject);
|
||||||
PageSet<? extends StorageMetadata> set = context.getBlobStore().list(containerName);
|
PageSet<? extends StorageMetadata> set = context.getBlobStore().list(containerName);
|
||||||
assert set.size() == 1 : set;
|
assert set.size() == 1 : set;
|
||||||
|
@ -430,20 +426,20 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
public void testMetadata() throws InterruptedException {
|
public void testMetadata() throws InterruptedException {
|
||||||
String key = "hello";
|
String key = "hello";
|
||||||
|
|
||||||
Blob object = context.getBlobStore().newBlob(key);
|
Blob blob = context.getBlobStore().newBlob(key);
|
||||||
object.setPayload(TEST_STRING);
|
blob.setPayload(TEST_STRING);
|
||||||
object.getMetadata().setContentType(MediaType.TEXT_PLAIN);
|
blob.getMetadata().setContentType(MediaType.TEXT_PLAIN);
|
||||||
object.getMetadata().setSize(new Long(TEST_STRING.length()));
|
blob.getMetadata().setSize(new Long(TEST_STRING.length()));
|
||||||
// NOTE all metadata in jclouds comes out as lowercase, in an effort to normalize the
|
// NOTE all metadata in jclouds comes out as lowercase, in an effort to normalize the
|
||||||
// providers.
|
// providers.
|
||||||
object.getMetadata().getUserMetadata().put("Adrian", "powderpuff");
|
blob.getMetadata().getUserMetadata().put("Adrian", "powderpuff");
|
||||||
object.getMetadata().setContentMD5(
|
blob.getMetadata().setContentMD5(
|
||||||
new JCEEncryptionService().md5(Utils.toInputStream(TEST_STRING)));
|
new JCEEncryptionService().md5(Utils.toInputStream(TEST_STRING)));
|
||||||
String containerName = getContainerName();
|
String containerName = getContainerName();
|
||||||
try {
|
try {
|
||||||
assertNull(context.getBlobStore().blobMetadata(containerName, "powderpuff"));
|
assertNull(context.getBlobStore().blobMetadata(containerName, "powderpuff"));
|
||||||
|
|
||||||
addBlobToContainer(containerName, object);
|
addBlobToContainer(containerName, blob);
|
||||||
Blob newObject = validateContent(containerName, key);
|
Blob newObject = validateContent(containerName, key);
|
||||||
|
|
||||||
BlobMetadata metadata = newObject.getMetadata();
|
BlobMetadata metadata = newObject.getMetadata();
|
||||||
|
@ -452,10 +448,10 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
validateMetadata(context.getBlobStore().blobMetadata(containerName, key));
|
validateMetadata(context.getBlobStore().blobMetadata(containerName, key));
|
||||||
|
|
||||||
// write 2 items with the same key to ensure that provider doesn't accept dupes
|
// write 2 items with the same key to ensure that provider doesn't accept dupes
|
||||||
object.getMetadata().getUserMetadata().put("Adrian", "wonderpuff");
|
blob.getMetadata().getUserMetadata().put("Adrian", "wonderpuff");
|
||||||
object.getMetadata().getUserMetadata().put("Adrian", "powderpuff");
|
blob.getMetadata().getUserMetadata().put("Adrian", "powderpuff");
|
||||||
|
|
||||||
addBlobToContainer(containerName, object);
|
addBlobToContainer(containerName, blob);
|
||||||
validateMetadata(context.getBlobStore().blobMetadata(containerName, key));
|
validateMetadata(context.getBlobStore().blobMetadata(containerName, key));
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -59,15 +59,15 @@ public abstract class BaseBlobMapIntegrationTest extends BaseMapIntegrationTest<
|
||||||
putFiveStrings(map);
|
putFiveStrings(map);
|
||||||
putFiveStringsUnderPath(map);
|
putFiveStringsUnderPath(map);
|
||||||
|
|
||||||
Collection<Blob> values = map.values();
|
Collection<Blob> blobs = map.values();
|
||||||
assertConsistencyAwareMapSize(map, 5);
|
assertConsistencyAwareMapSize(map, 5);
|
||||||
Set<String> valuesAsString = new HashSet<String>();
|
Set<String> blobsAsString = new HashSet<String>();
|
||||||
for (Blob object : values) {
|
for (Blob blob : blobs) {
|
||||||
valuesAsString.add(getContentAsStringOrNullAndClose(object));
|
blobsAsString.add(getContentAsStringOrNullAndClose(blob));
|
||||||
}
|
}
|
||||||
valuesAsString.removeAll(fiveStrings.values());
|
blobsAsString.removeAll(fiveStrings.values());
|
||||||
assert valuesAsString.size() == 0 : valuesAsString.size() + ": " + values + ": "
|
assert blobsAsString.size() == 0 : blobsAsString.size() + ": " + blobs + ": "
|
||||||
+ valuesAsString;
|
+ blobsAsString;
|
||||||
} finally {
|
} finally {
|
||||||
returnContainer(bucketName);
|
returnContainer(bucketName);
|
||||||
}
|
}
|
||||||
|
@ -90,12 +90,12 @@ public abstract class BaseBlobMapIntegrationTest extends BaseMapIntegrationTest<
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertConsistencyAwareContentEquals(final Map<String, Blob> map, final String key,
|
private void assertConsistencyAwareContentEquals(final Map<String, Blob> map, final String key,
|
||||||
final String value) throws InterruptedException {
|
final String blob) throws InterruptedException {
|
||||||
assertConsistencyAware(new Runnable() {
|
assertConsistencyAware(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
Blob old = map.remove(key);
|
Blob old = map.remove(key);
|
||||||
try {
|
try {
|
||||||
assertEquals(getContentAsStringOrNullAndClose(old), value);
|
assertEquals(getContentAsStringOrNullAndClose(old), blob);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -116,16 +116,16 @@ public abstract class BaseBlobMapIntegrationTest extends BaseMapIntegrationTest<
|
||||||
for (Entry<String, Blob> entry : entries) {
|
for (Entry<String, Blob> entry : entries) {
|
||||||
assertEquals(fiveStrings.get(entry.getKey()), getContentAsStringOrNullAndClose(entry
|
assertEquals(fiveStrings.get(entry.getKey()), getContentAsStringOrNullAndClose(entry
|
||||||
.getValue()));
|
.getValue()));
|
||||||
Blob value = entry.getValue();
|
Blob blob = entry.getValue();
|
||||||
value.setPayload("");
|
blob.setPayload("");
|
||||||
value.generateMD5();
|
context.utils().encryption().generateMD5BufferingIfNotRepeatable(blob);
|
||||||
entry.setValue(value);
|
entry.setValue(blob);
|
||||||
}
|
}
|
||||||
assertConsistencyAware(new Runnable() {
|
assertConsistencyAware(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
for (Blob value : map.values()) {
|
for (Blob blob : map.values()) {
|
||||||
try {
|
try {
|
||||||
assertEquals(getContentAsStringOrNullAndClose(value), "");
|
assertEquals(getContentAsStringOrNullAndClose(blob), "");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Throwables.propagate(e);
|
Throwables.propagate(e);
|
||||||
}
|
}
|
||||||
|
@ -144,10 +144,10 @@ public abstract class BaseBlobMapIntegrationTest extends BaseMapIntegrationTest<
|
||||||
try {
|
try {
|
||||||
Map<String, Blob> map = createMap(context, bucketName);
|
Map<String, Blob> map = createMap(context, bucketName);
|
||||||
putStringWithMD5(map, "one", "apple");
|
putStringWithMD5(map, "one", "apple");
|
||||||
Blob object = context.getBlobStore().newBlob("one");
|
Blob blob = context.getBlobStore().newBlob("one");
|
||||||
object.setPayload("apple");
|
blob.setPayload("apple");
|
||||||
object.generateMD5();
|
context.utils().encryption().generateMD5BufferingIfNotRepeatable(blob);
|
||||||
assertConsistencyAwareContainsValue(map, object);
|
assertConsistencyAwareContainsValue(map, blob);
|
||||||
} finally {
|
} finally {
|
||||||
returnContainer(bucketName);
|
returnContainer(bucketName);
|
||||||
}
|
}
|
||||||
|
@ -172,14 +172,14 @@ public abstract class BaseBlobMapIntegrationTest extends BaseMapIntegrationTest<
|
||||||
String bucketName = getContainerName();
|
String bucketName = getContainerName();
|
||||||
try {
|
try {
|
||||||
Map<String, Blob> map = createMap(context, bucketName);
|
Map<String, Blob> map = createMap(context, bucketName);
|
||||||
Blob object = context.getBlobStore().newBlob("one");
|
Blob blob = context.getBlobStore().newBlob("one");
|
||||||
object.setPayload(Utils.toInputStream("apple"));
|
blob.setPayload(Utils.toInputStream("apple"));
|
||||||
object.generateMD5();
|
context.utils().encryption().generateMD5BufferingIfNotRepeatable(blob);
|
||||||
Blob old = map.put(object.getMetadata().getName(), object);
|
Blob old = map.put(blob.getMetadata().getName(), blob);
|
||||||
getOneReturnsAppleAndOldValueIsNull(map, old);
|
getOneReturnsAppleAndOldValueIsNull(map, old);
|
||||||
object.setPayload(Utils.toInputStream("bear"));
|
blob.setPayload(Utils.toInputStream("bear"));
|
||||||
object.generateMD5();
|
context.utils().encryption().generateMD5BufferingIfNotRepeatable(blob);
|
||||||
Blob apple = map.put(object.getMetadata().getName(), object);
|
Blob apple = map.put(blob.getMetadata().getName(), blob);
|
||||||
getOneReturnsBearAndOldValueIsApple(map, apple);
|
getOneReturnsBearAndOldValueIsApple(map, apple);
|
||||||
} finally {
|
} finally {
|
||||||
returnContainer(bucketName);
|
returnContainer(bucketName);
|
||||||
|
@ -193,10 +193,10 @@ public abstract class BaseBlobMapIntegrationTest extends BaseMapIntegrationTest<
|
||||||
Map<String, Blob> map = createMap(context, bucketName);
|
Map<String, Blob> map = createMap(context, bucketName);
|
||||||
Map<String, Blob> newMap = new HashMap<String, Blob>();
|
Map<String, Blob> newMap = new HashMap<String, Blob>();
|
||||||
for (String key : fiveInputs.keySet()) {
|
for (String key : fiveInputs.keySet()) {
|
||||||
Blob object = context.getBlobStore().newBlob(key);
|
Blob blob = context.getBlobStore().newBlob(key);
|
||||||
object.setPayload(fiveInputs.get(key));
|
blob.setPayload(fiveInputs.get(key));
|
||||||
object.getPayload().setContentLength((long) fiveBytes.get(key).length);
|
blob.getPayload().setContentLength((long) fiveBytes.get(key).length);
|
||||||
newMap.put(key, object);
|
newMap.put(key, blob);
|
||||||
}
|
}
|
||||||
map.putAll(newMap);
|
map.putAll(newMap);
|
||||||
assertConsistencyAwareMapSize(map, 5);
|
assertConsistencyAwareMapSize(map, 5);
|
||||||
|
@ -222,9 +222,9 @@ public abstract class BaseBlobMapIntegrationTest extends BaseMapIntegrationTest<
|
||||||
|
|
||||||
Map<String, Blob> newMap = new HashMap<String, Blob>();
|
Map<String, Blob> newMap = new HashMap<String, Blob>();
|
||||||
for (String key : keySet) {
|
for (String key : keySet) {
|
||||||
Blob object = context.getBlobStore().newBlob(key);
|
Blob blob = context.getBlobStore().newBlob(key);
|
||||||
object.setPayload(key);
|
blob.setPayload(key);
|
||||||
newMap.put(key, object);
|
newMap.put(key, blob);
|
||||||
}
|
}
|
||||||
map.putAll(newMap);
|
map.putAll(newMap);
|
||||||
newMap.clear();
|
newMap.clear();
|
||||||
|
@ -239,19 +239,19 @@ public abstract class BaseBlobMapIntegrationTest extends BaseMapIntegrationTest<
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void putStringWithMD5(Map<String, Blob> map, String key, String value) {
|
protected void putStringWithMD5(Map<String, Blob> map, String key, String text) {
|
||||||
Blob object = context.getBlobStore().newBlob(key);
|
Blob blob = context.getBlobStore().newBlob(key);
|
||||||
object.setPayload(value);
|
blob.setPayload(text);
|
||||||
object.generateMD5();
|
context.utils().encryption().generateMD5BufferingIfNotRepeatable(blob);
|
||||||
map.put(key, object);
|
map.put(key, blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void putFiveStrings(Map<String, Blob> map) {
|
protected void putFiveStrings(Map<String, Blob> map) {
|
||||||
Map<String, Blob> newMap = new HashMap<String, Blob>();
|
Map<String, Blob> newMap = new HashMap<String, Blob>();
|
||||||
for (Map.Entry<String, String> entry : fiveStrings.entrySet()) {
|
for (Map.Entry<String, String> entry : fiveStrings.entrySet()) {
|
||||||
Blob object = context.getBlobStore().newBlob(entry.getKey());
|
Blob blob = context.getBlobStore().newBlob(entry.getKey());
|
||||||
object.setPayload(entry.getValue());
|
blob.setPayload(entry.getValue());
|
||||||
newMap.put(entry.getKey(), object);
|
newMap.put(entry.getKey(), blob);
|
||||||
}
|
}
|
||||||
map.putAll(newMap);
|
map.putAll(newMap);
|
||||||
}
|
}
|
||||||
|
@ -259,9 +259,9 @@ public abstract class BaseBlobMapIntegrationTest extends BaseMapIntegrationTest<
|
||||||
protected void putFiveStringsUnderPath(Map<String, Blob> map) {
|
protected void putFiveStringsUnderPath(Map<String, Blob> map) {
|
||||||
Map<String, Blob> newMap = new HashMap<String, Blob>();
|
Map<String, Blob> newMap = new HashMap<String, Blob>();
|
||||||
for (Map.Entry<String, String> entry : fiveStringsUnderPath.entrySet()) {
|
for (Map.Entry<String, String> entry : fiveStringsUnderPath.entrySet()) {
|
||||||
Blob object = context.getBlobStore().newBlob(entry.getKey());
|
Blob blob = context.getBlobStore().newBlob(entry.getKey());
|
||||||
object.setPayload(entry.getValue());
|
blob.setPayload(entry.getValue());
|
||||||
newMap.put(entry.getKey(), object);
|
newMap.put(entry.getKey(), blob);
|
||||||
}
|
}
|
||||||
map.putAll(newMap);
|
map.putAll(newMap);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.security.Key;
|
||||||
|
|
||||||
import org.jclouds.encryption.internal.JCEEncryptionService;
|
import org.jclouds.encryption.internal.JCEEncryptionService;
|
||||||
import org.jclouds.http.Payload;
|
import org.jclouds.http.Payload;
|
||||||
|
import org.jclouds.http.PayloadEnclosing;
|
||||||
import org.jclouds.http.payloads.ByteArrayPayload;
|
import org.jclouds.http.payloads.ByteArrayPayload;
|
||||||
|
|
||||||
import com.google.inject.ImplementedBy;
|
import com.google.inject.ImplementedBy;
|
||||||
|
@ -55,6 +56,15 @@ public interface EncryptionService {
|
||||||
|
|
||||||
byte[] md5(InputStream toEncode);
|
byte[] md5(InputStream toEncode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate an MD5 Hash for the current data.
|
||||||
|
* <p/>
|
||||||
|
* <h2>Note</h2>
|
||||||
|
* <p/>
|
||||||
|
* If this is an InputStream, it will be converted to a byte array first.
|
||||||
|
*/
|
||||||
|
<T extends PayloadEnclosing> T generateMD5BufferingIfNotRepeatable(T payloadEnclosing);
|
||||||
|
|
||||||
Payload generateMD5BufferingIfNotRepeatable(Payload in);
|
Payload generateMD5BufferingIfNotRepeatable(Payload in);
|
||||||
|
|
||||||
ByteArrayPayload generatePayloadWithMD5For(InputStream toEncode);
|
ByteArrayPayload generatePayloadWithMD5For(InputStream toEncode);
|
||||||
|
|
|
@ -19,11 +19,13 @@
|
||||||
package org.jclouds.encryption.internal;
|
package org.jclouds.encryption.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
import org.jclouds.encryption.EncryptionService;
|
import org.jclouds.encryption.EncryptionService;
|
||||||
import org.jclouds.http.Payload;
|
import org.jclouds.http.Payload;
|
||||||
|
import org.jclouds.http.PayloadEnclosing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -76,4 +78,16 @@ public abstract class BaseEncryptionService implements EncryptionService {
|
||||||
return payload;
|
return payload;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public <T extends PayloadEnclosing> T generateMD5BufferingIfNotRepeatable(T payloadEnclosing) {
|
||||||
|
checkState(payloadEnclosing != null, "payloadEnclosing");
|
||||||
|
Payload newPayload = generateMD5BufferingIfNotRepeatable(payloadEnclosing.getPayload());
|
||||||
|
if (newPayload != payloadEnclosing.getPayload())
|
||||||
|
payloadEnclosing.setPayload(newPayload);
|
||||||
|
return payloadEnclosing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,16 +20,18 @@ package org.jclouds.http;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.io.Closeables.closeQuietly;
|
|
||||||
import static com.google.inject.internal.Lists.newArrayList;
|
import static com.google.inject.internal.Lists.newArrayList;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
||||||
|
|
||||||
|
import com.google.common.collect.LinkedHashMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.Multimaps;
|
||||||
import com.google.inject.internal.Nullable;
|
import com.google.inject.internal.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,7 +39,7 @@ import com.google.inject.internal.Nullable;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class HttpRequest extends HttpMessage {
|
public class HttpRequest extends PayloadEnclosingImpl implements PayloadEnclosing {
|
||||||
|
|
||||||
private List<HttpRequestFilter> requestFilters = newArrayList();
|
private List<HttpRequestFilter> requestFilters = newArrayList();
|
||||||
private String method;
|
private String method;
|
||||||
|
@ -45,6 +47,26 @@ public class HttpRequest extends HttpMessage {
|
||||||
private Payload payload;
|
private Payload payload;
|
||||||
private char[] skips;
|
private char[] skips;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* synchronized as there is no concurrent version. Headers may change in flight due to redirects.
|
||||||
|
*/
|
||||||
|
private Multimap<String, String> headers = Multimaps.synchronizedMultimap(LinkedHashMultimap
|
||||||
|
.<String, String> create());
|
||||||
|
|
||||||
|
public Multimap<String, String> getHeaders() {
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* try to get the value, then try as lowercase.
|
||||||
|
*/
|
||||||
|
public String getFirstHeaderOrNull(String string) {
|
||||||
|
Collection<String> values = headers.get(string);
|
||||||
|
if (values.size() == 0)
|
||||||
|
values = headers.get(string.toLowerCase());
|
||||||
|
return (values.size() >= 1) ? values.iterator().next() : null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param endpoint
|
* @param endpoint
|
||||||
|
@ -104,31 +126,6 @@ public class HttpRequest extends HttpMessage {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Payload getPayload() {
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayload(Payload data) {
|
|
||||||
closeContentIfPresent();
|
|
||||||
this.payload = checkNotNull(data, "data");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayload(InputStream data) {
|
|
||||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayload(byte[] data) {
|
|
||||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayload(String data) {
|
|
||||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayload(File data) {
|
|
||||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* characters to skip encoding on.
|
* characters to skip encoding on.
|
||||||
*/
|
*/
|
||||||
|
@ -160,18 +157,6 @@ public class HttpRequest extends HttpMessage {
|
||||||
this.endpoint = endpoint;
|
this.endpoint = endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
closeContentIfPresent();
|
|
||||||
super.finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void closeContentIfPresent() {
|
|
||||||
if (getPayload() != null && getPayload().getInput() != null) {
|
|
||||||
closeQuietly(getPayload().getInput());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
|
|
|
@ -47,13 +47,4 @@ public interface PayloadEnclosing {
|
||||||
|
|
||||||
Payload getPayload();
|
Payload getPayload();
|
||||||
|
|
||||||
/**
|
|
||||||
* generate an MD5 Hash for the current data.
|
|
||||||
* <p/>
|
|
||||||
* <h2>Note</h2>
|
|
||||||
* <p/>
|
|
||||||
* If this is an InputStream, it will be converted to a byte array first.
|
|
||||||
*/
|
|
||||||
void generateMD5();
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,7 +19,6 @@
|
||||||
package org.jclouds.http.internal;
|
package org.jclouds.http.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
|
||||||
import static com.google.common.io.Closeables.closeQuietly;
|
import static com.google.common.io.Closeables.closeQuietly;
|
||||||
import static org.jclouds.http.Payloads.newPayload;
|
import static org.jclouds.http.Payloads.newPayload;
|
||||||
|
|
||||||
|
@ -28,7 +27,6 @@ import java.io.InputStream;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
import org.jclouds.http.Payload;
|
import org.jclouds.http.Payload;
|
||||||
import org.jclouds.http.PayloadEnclosing;
|
import org.jclouds.http.PayloadEnclosing;
|
||||||
|
|
||||||
|
@ -37,29 +35,16 @@ import org.jclouds.http.PayloadEnclosing;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class PayloadEnclosingImpl implements PayloadEnclosing {
|
public class PayloadEnclosingImpl implements PayloadEnclosing {
|
||||||
private final EncryptionService encryptionService;
|
|
||||||
protected Payload payload;
|
protected Payload payload;
|
||||||
|
|
||||||
public PayloadEnclosingImpl(EncryptionService encryptionService, @Nullable Payload payload) {
|
public PayloadEnclosingImpl() {
|
||||||
this.encryptionService = encryptionService;
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PayloadEnclosingImpl(@Nullable Payload payload) {
|
||||||
this.payload = payload;
|
this.payload = payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PayloadEnclosingImpl(EncryptionService encryptionService) {
|
|
||||||
this(encryptionService, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void generateMD5() {
|
|
||||||
checkState(payload != null, "payload");
|
|
||||||
Payload newPayload = encryptionService.generateMD5BufferingIfNotRepeatable(payload);
|
|
||||||
if (newPayload != payload)
|
|
||||||
setPayload(newPayload);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
@ -98,6 +83,7 @@ public class PayloadEnclosingImpl implements PayloadEnclosing {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setPayload(String data) {
|
public void setPayload(String data) {
|
||||||
|
closeContentIfPresent();
|
||||||
setPayload(newPayload(checkNotNull(data, "data")));
|
setPayload(newPayload(checkNotNull(data, "data")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,4 +126,9 @@ public class PayloadEnclosingImpl implements PayloadEnclosing {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
closeContentIfPresent();
|
||||||
|
super.finalize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -614,10 +614,11 @@ public class RestAnnotationProcessorTest {
|
||||||
assertEquals(request.getPayload().getRawContent(), "\"data\"");
|
assertEquals(request.getPayload().getRawContent(), "\"data\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreatePostWithPathRequest() throws SecurityException, NoSuchMethodException, IOException {
|
public void testCreatePostWithPathRequest() throws SecurityException, NoSuchMethodException,
|
||||||
|
IOException {
|
||||||
Method method = TestPost.class.getMethod("postWithPath", String.class, MapBinder.class);
|
Method method = TestPost.class.getMethod("postWithPath", String.class, MapBinder.class);
|
||||||
HttpRequest request = factory(TestPost.class).createRequest(method,
|
HttpRequest request = factory(TestPost.class).createRequest(method, "data",
|
||||||
"data", new org.jclouds.rest.MapBinder() {
|
new org.jclouds.rest.MapBinder() {
|
||||||
public void bindToRequest(HttpRequest request, Map<String, String> postParams) {
|
public void bindToRequest(HttpRequest request, Map<String, String> postParams) {
|
||||||
request.setPayload(postParams.get("fooble"));
|
request.setPayload(postParams.get("fooble"));
|
||||||
}
|
}
|
||||||
|
@ -625,7 +626,7 @@ public class RestAnnotationProcessorTest {
|
||||||
public void bindToRequest(HttpRequest request, Object toBind) {
|
public void bindToRequest(HttpRequest request, Object toBind) {
|
||||||
throw new RuntimeException("this shouldn't be used in POST");
|
throw new RuntimeException("this shouldn't be used in POST");
|
||||||
}
|
}
|
||||||
} );
|
});
|
||||||
assertRequestLineEquals(request, "POST http://localhost:9999/data HTTP/1.1");
|
assertRequestLineEquals(request, "POST http://localhost:9999/data HTTP/1.1");
|
||||||
assertHeadersEqual(request, "Content-Length: 4\nContent-Type: application/unknown\n");
|
assertHeadersEqual(request, "Content-Length: 4\nContent-Type: application/unknown\n");
|
||||||
assertPayloadEquals(request, "data");
|
assertPayloadEquals(request, "data");
|
||||||
|
@ -1405,10 +1406,8 @@ public class RestAnnotationProcessorTest {
|
||||||
public void testPutPayloadEnclosing() throws SecurityException, NoSuchMethodException,
|
public void testPutPayloadEnclosing() throws SecurityException, NoSuchMethodException,
|
||||||
IOException {
|
IOException {
|
||||||
Method method = TestTransformers.class.getMethod("put", PayloadEnclosing.class);
|
Method method = TestTransformers.class.getMethod("put", PayloadEnclosing.class);
|
||||||
HttpRequest request = factory(TestQuery.class).createRequest(
|
HttpRequest request = factory(TestQuery.class).createRequest(method,
|
||||||
method,
|
new PayloadEnclosingImpl(newStringPayload("whoops")));
|
||||||
new PayloadEnclosingImpl(injector.getInstance(EncryptionService.class),
|
|
||||||
newStringPayload("whoops")));
|
|
||||||
assertRequestLineEquals(request, "PUT http://localhost:9999?x-ms-version=2009-07-17 HTTP/1.1");
|
assertRequestLineEquals(request, "PUT http://localhost:9999?x-ms-version=2009-07-17 HTTP/1.1");
|
||||||
assertHeadersEqual(request, "Content-Length: 6\nContent-Type: application/unknown\n");
|
assertHeadersEqual(request, "Content-Length: 6\nContent-Type: application/unknown\n");
|
||||||
assertPayloadEquals(request, "whoops");
|
assertPayloadEquals(request, "whoops");
|
||||||
|
@ -1417,10 +1416,10 @@ public class RestAnnotationProcessorTest {
|
||||||
public void testPutPayloadEnclosingGenerateMD5() throws SecurityException,
|
public void testPutPayloadEnclosingGenerateMD5() throws SecurityException,
|
||||||
NoSuchMethodException, IOException {
|
NoSuchMethodException, IOException {
|
||||||
Method method = TestTransformers.class.getMethod("put", PayloadEnclosing.class);
|
Method method = TestTransformers.class.getMethod("put", PayloadEnclosing.class);
|
||||||
PayloadEnclosing payloadEnclosing = new PayloadEnclosingImpl(injector
|
PayloadEnclosing payloadEnclosing = new PayloadEnclosingImpl(newStringPayload("whoops"));
|
||||||
.getInstance(EncryptionService.class), newStringPayload("whoops"));
|
|
||||||
|
|
||||||
payloadEnclosing.generateMD5();
|
injector.getInstance(EncryptionService.class).generateMD5BufferingIfNotRepeatable(
|
||||||
|
payloadEnclosing);
|
||||||
HttpRequest request = factory(TestQuery.class).createRequest(method, payloadEnclosing);
|
HttpRequest request = factory(TestQuery.class).createRequest(method, payloadEnclosing);
|
||||||
assertRequestLineEquals(request, "PUT http://localhost:9999?x-ms-version=2009-07-17 HTTP/1.1");
|
assertRequestLineEquals(request, "PUT http://localhost:9999?x-ms-version=2009-07-17 HTTP/1.1");
|
||||||
assertHeadersEqual(request,
|
assertHeadersEqual(request,
|
||||||
|
@ -1432,11 +1431,11 @@ public class RestAnnotationProcessorTest {
|
||||||
public void testPutInputStreamPayloadEnclosingGenerateMD5() throws SecurityException,
|
public void testPutInputStreamPayloadEnclosingGenerateMD5() throws SecurityException,
|
||||||
NoSuchMethodException, IOException {
|
NoSuchMethodException, IOException {
|
||||||
Method method = TestTransformers.class.getMethod("put", PayloadEnclosing.class);
|
Method method = TestTransformers.class.getMethod("put", PayloadEnclosing.class);
|
||||||
PayloadEnclosing payloadEnclosing = new PayloadEnclosingImpl(injector
|
PayloadEnclosing payloadEnclosing = new PayloadEnclosingImpl(
|
||||||
.getInstance(EncryptionService.class),
|
|
||||||
newInputStreamPayload(toInputStream("whoops")));
|
newInputStreamPayload(toInputStream("whoops")));
|
||||||
|
|
||||||
payloadEnclosing.generateMD5();
|
injector.getInstance(EncryptionService.class).generateMD5BufferingIfNotRepeatable(
|
||||||
|
payloadEnclosing);
|
||||||
HttpRequest request = factory(TestQuery.class).createRequest(method, payloadEnclosing);
|
HttpRequest request = factory(TestQuery.class).createRequest(method, payloadEnclosing);
|
||||||
assertRequestLineEquals(request, "PUT http://localhost:9999?x-ms-version=2009-07-17 HTTP/1.1");
|
assertRequestLineEquals(request, "PUT http://localhost:9999?x-ms-version=2009-07-17 HTTP/1.1");
|
||||||
assertHeadersEqual(request,
|
assertHeadersEqual(request,
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class PCSFileImpl extends PayloadEnclosingImpl implements PCSFile, Compar
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public PCSFileImpl(MutableFileInfo metadata) {
|
public PCSFileImpl(MutableFileInfo metadata) {
|
||||||
super(null);// no MD5 support
|
super();// no MD5 support
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class SDNClientLiveTest {
|
||||||
Blob blob = connection.newBlob();
|
Blob blob = connection.newBlob();
|
||||||
blob.getMetadata().setName("test.txt");
|
blob.getMetadata().setName("test.txt");
|
||||||
blob.setPayload("value");
|
blob.setPayload("value");
|
||||||
blob.generateMD5();
|
context.utils().encryption().generateMD5BufferingIfNotRepeatable(blob);
|
||||||
|
|
||||||
byte[] md5 = blob.getMetadata().getContentMD5();
|
byte[] md5 = blob.getMetadata().getContentMD5();
|
||||||
connection.upload(uploadInfo.getHost(), uploadInfo.getToken(), containerName, blob);
|
connection.upload(uploadInfo.getHost(), uploadInfo.getToken(), containerName, blob);
|
||||||
|
|
|
@ -22,7 +22,6 @@ import javax.inject.Inject;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
|
|
||||||
import org.jclouds.blobstore.config.BlobStoreObjectModule;
|
import org.jclouds.blobstore.config.BlobStoreObjectModule;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
|
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
|
||||||
import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
|
import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
|
||||||
import org.jclouds.rackspace.cloudfiles.domain.internal.CFObjectImpl;
|
import org.jclouds.rackspace.cloudfiles.domain.internal.CFObjectImpl;
|
||||||
|
@ -50,14 +49,11 @@ public class CFObjectModule extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CFObjectFactory implements CFObject.Factory {
|
private static class CFObjectFactory implements CFObject.Factory {
|
||||||
@Inject
|
|
||||||
EncryptionService encryptionService;
|
|
||||||
@Inject
|
@Inject
|
||||||
Provider<MutableObjectInfoWithMetadata> metadataProvider;
|
Provider<MutableObjectInfoWithMetadata> metadataProvider;
|
||||||
|
|
||||||
public CFObject create(MutableObjectInfoWithMetadata metadata) {
|
public CFObject create(MutableObjectInfoWithMetadata metadata) {
|
||||||
return new CFObjectImpl(encryptionService, metadata != null ? metadata : metadataProvider
|
return new CFObjectImpl(metadata != null ? metadata : metadataProvider.get());
|
||||||
.get());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.jclouds.encryption.EncryptionService;
|
|
||||||
import org.jclouds.http.Payload;
|
import org.jclouds.http.Payload;
|
||||||
import org.jclouds.http.PayloadEnclosing;
|
import org.jclouds.http.PayloadEnclosing;
|
||||||
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
||||||
|
@ -45,8 +44,8 @@ public class CFObjectImpl extends PayloadEnclosingImpl implements CFObject, Comp
|
||||||
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CFObjectImpl(EncryptionService encryptionService, MutableObjectInfoWithMetadata info) {
|
public CFObjectImpl(MutableObjectInfoWithMetadata info) {
|
||||||
super(encryptionService);
|
super();
|
||||||
this.info = linkMetadataToThis(info);
|
this.info = linkMetadataToThis(info);
|
||||||
this._info = this.info.getDelegate();
|
this._info = this.info.getDelegate();
|
||||||
|
|
||||||
|
|
|
@ -386,7 +386,7 @@ public class CloudFilesClientLiveTest extends BaseBlobStoreIntegrationTest {
|
||||||
CFObject object = getApi().newCFObject();
|
CFObject object = getApi().newCFObject();
|
||||||
object.getInfo().setName(key);
|
object.getInfo().setName(key);
|
||||||
object.setPayload(data);
|
object.setPayload(data);
|
||||||
object.generateMD5();
|
context.utils().encryption().generateMD5BufferingIfNotRepeatable(object);
|
||||||
object.getInfo().setContentType("text/plain");
|
object.getInfo().setContentType("text/plain");
|
||||||
object.getInfo().getMetadata().put("Metadata", "metadata-value");
|
object.getInfo().getMetadata().put("Metadata", "metadata-value");
|
||||||
return object;
|
return object;
|
||||||
|
|
|
@ -102,7 +102,7 @@ public class BlobStoreFileObject extends AbstractFileObject {
|
||||||
protected void onClose() throws IOException {
|
protected void onClose() throws IOException {
|
||||||
try {
|
try {
|
||||||
blob.setPayload(file);
|
blob.setPayload(file);
|
||||||
blob.generateMD5();
|
context.getContext().utils().encryption().generateMD5BufferingIfNotRepeatable(blob);
|
||||||
logger.info(String.format(">> put: %s/%s %d bytes", getContainer(),
|
logger.info(String.format(">> put: %s/%s %d bytes", getContainer(),
|
||||||
getNameTrimLeadingSlashes(), blob.getPayload().getContentLength()));
|
getNameTrimLeadingSlashes(), blob.getPayload().getContentLength()));
|
||||||
String tag = context.putBlob(getContainer(), blob);
|
String tag = context.putBlob(getContainer(), blob);
|
||||||
|
|
Loading…
Reference in New Issue