mirror of https://github.com/apache/jclouds.git
Issue 352: refactored request signing
This commit is contained in:
parent
d276b70162
commit
f068a06354
|
@ -51,7 +51,6 @@ import org.jclouds.blobstore.domain.PageSet;
|
||||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||||
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.concurrent.Futures;
|
import org.jclouds.concurrent.Futures;
|
||||||
|
@ -86,9 +85,8 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
ObjectToBlob object2Blob, ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
|
ObjectToBlob object2Blob, ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
|
||||||
BlobStoreListOptionsToListOptions container2ContainerListOptions,
|
BlobStoreListOptionsToListOptions container2ContainerListOptions,
|
||||||
DirectoryEntryListToResourceMetadataList container2ResourceList, Crypto crypto,
|
DirectoryEntryListToResourceMetadataList container2ResourceList, Crypto crypto,
|
||||||
BlobToHttpGetOptions blob2ObjectGetOptions, Provider<FetchBlobMetadata> fetchBlobMetadataProvider,
|
BlobToHttpGetOptions blob2ObjectGetOptions, Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
||||||
SignRequestForBlobStrategy signRequestForBlob) {
|
super(context, blobUtils, service, defaultLocation, locations);
|
||||||
super(context, blobUtils, service, defaultLocation, locations, signRequestForBlob);
|
|
||||||
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
||||||
this.sync = checkNotNull(sync, "sync");
|
this.sync = checkNotNull(sync, "sync");
|
||||||
this.async = checkNotNull(async, "async");
|
this.async = checkNotNull(async, "async");
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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 com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.blobstore.util.BlobStoreUtils.cleanRequest;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
|
||||||
|
import org.jclouds.atmosonline.saas.blobstore.functions.BlobToObject;
|
||||||
|
import org.jclouds.atmosonline.saas.domain.AtmosObject;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.options.GetOptions;
|
||||||
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class AtmosBlobRequestSigner implements BlobRequestSigner {
|
||||||
|
private final RestAnnotationProcessor<AtmosStorageAsyncClient> processor;
|
||||||
|
private final BlobToObject blobToObject;
|
||||||
|
private final Method getMethod;
|
||||||
|
private final Method deleteMethod;
|
||||||
|
private final Method createMethod;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AtmosBlobRequestSigner(RestAnnotationProcessor<AtmosStorageAsyncClient> processor, BlobToObject blobToObject)
|
||||||
|
throws SecurityException, NoSuchMethodException {
|
||||||
|
this.processor = checkNotNull(processor, "processor");
|
||||||
|
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
|
||||||
|
this.getMethod = AtmosStorageAsyncClient.class.getMethod("readFile", String.class, GetOptions[].class);
|
||||||
|
this.deleteMethod = AtmosStorageAsyncClient.class.getMethod("deletePath", String.class);
|
||||||
|
this.createMethod = AtmosStorageAsyncClient.class.getMethod("createFile", String.class, AtmosObject.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signGetBlob(String container, String name) {
|
||||||
|
return cleanRequest(processor.createRequest(getMethod, getPath(container, name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signPutBlob(String container, Blob blob) {
|
||||||
|
return cleanRequest(processor.createRequest(createMethod, container, blobToObject.apply(blob)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signRemoveBlob(String container, String name) {
|
||||||
|
return cleanRequest(processor.createRequest(deleteMethod, getPath(container, name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPath(String container, String name) {
|
||||||
|
return checkNotNull(container, "container") + "/" + checkNotNull(name, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -43,7 +43,6 @@ import org.jclouds.blobstore.domain.PageSet;
|
||||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||||
import org.jclouds.blobstore.internal.BaseBlobStore;
|
import org.jclouds.blobstore.internal.BaseBlobStore;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.crypto.Crypto;
|
import org.jclouds.crypto.Crypto;
|
||||||
|
@ -73,9 +72,8 @@ public class AtmosBlobStore extends BaseBlobStore {
|
||||||
ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
|
ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
|
||||||
BlobStoreListOptionsToListOptions container2ContainerListOptions,
|
BlobStoreListOptionsToListOptions container2ContainerListOptions,
|
||||||
DirectoryEntryListToResourceMetadataList container2ResourceList, Crypto crypto,
|
DirectoryEntryListToResourceMetadataList container2ResourceList, Crypto crypto,
|
||||||
BlobToHttpGetOptions blob2ObjectGetOptions, Provider<FetchBlobMetadata> fetchBlobMetadataProvider,
|
BlobToHttpGetOptions blob2ObjectGetOptions, Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
||||||
SignRequestForBlobStrategy signRequestForBlob) {
|
super(context, blobUtils, defaultLocation, locations);
|
||||||
super(context, blobUtils, defaultLocation, locations, signRequestForBlob);
|
|
||||||
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
||||||
this.sync = checkNotNull(sync, "sync");
|
this.sync = checkNotNull(sync, "sync");
|
||||||
this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions,
|
this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions,
|
||||||
|
|
|
@ -26,17 +26,17 @@ import javax.inject.Singleton;
|
||||||
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
|
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
|
||||||
import org.jclouds.atmosonline.saas.AtmosStorageClient;
|
import org.jclouds.atmosonline.saas.AtmosStorageClient;
|
||||||
import org.jclouds.atmosonline.saas.blobstore.AtmosAsyncBlobStore;
|
import org.jclouds.atmosonline.saas.blobstore.AtmosAsyncBlobStore;
|
||||||
|
import org.jclouds.atmosonline.saas.blobstore.AtmosBlobRequestSigner;
|
||||||
import org.jclouds.atmosonline.saas.blobstore.AtmosBlobStore;
|
import org.jclouds.atmosonline.saas.blobstore.AtmosBlobStore;
|
||||||
import org.jclouds.atmosonline.saas.blobstore.strategy.FindMD5InUserMetadata;
|
import org.jclouds.atmosonline.saas.blobstore.strategy.FindMD5InUserMetadata;
|
||||||
import org.jclouds.atmosonline.saas.blobstore.strategy.SignReadFile;
|
|
||||||
import org.jclouds.blobstore.AsyncBlobStore;
|
import org.jclouds.blobstore.AsyncBlobStore;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
import org.jclouds.blobstore.BlobStore;
|
import org.jclouds.blobstore.BlobStore;
|
||||||
import org.jclouds.blobstore.BlobStoreContext;
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||||
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
||||||
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
||||||
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
|
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.domain.LocationScope;
|
import org.jclouds.domain.LocationScope;
|
||||||
import org.jclouds.domain.internal.LocationImpl;
|
import org.jclouds.domain.internal.LocationImpl;
|
||||||
|
@ -67,7 +67,7 @@ public class AtmosBlobStoreContextModule extends AbstractModule {
|
||||||
new TypeLiteral<BlobStoreContextImpl<AtmosStorageClient, AtmosStorageAsyncClient>>() {
|
new TypeLiteral<BlobStoreContextImpl<AtmosStorageClient, AtmosStorageAsyncClient>>() {
|
||||||
}).in(Scopes.SINGLETON);
|
}).in(Scopes.SINGLETON);
|
||||||
bind(ContainsValueInListStrategy.class).to(FindMD5InUserMetadata.class);
|
bind(ContainsValueInListStrategy.class).to(FindMD5InUserMetadata.class);
|
||||||
bind(SignRequestForBlobStrategy.class).to(SignReadFile.class);
|
bind(BlobRequestSigner.class).to(AtmosBlobRequestSigner.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 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.strategy;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
|
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.http.HttpRequestFilter;
|
|
||||||
import org.jclouds.http.options.GetOptions;
|
|
||||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
@Singleton
|
|
||||||
public class SignReadFile implements SignRequestForBlobStrategy {
|
|
||||||
private final RestAnnotationProcessor<AtmosStorageAsyncClient> processor;
|
|
||||||
private final Method method;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public SignReadFile(RestAnnotationProcessor<AtmosStorageAsyncClient> processor) throws SecurityException,
|
|
||||||
NoSuchMethodException {
|
|
||||||
this.processor = checkNotNull(processor, "processor");
|
|
||||||
this.method = AtmosStorageAsyncClient.class.getMethod("readFile", String.class, GetOptions[].class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpRequest apply(String container, String name) {
|
|
||||||
GeneratedHttpRequest<AtmosStorageAsyncClient> returnVal = processor.createRequest(method, checkNotNull(container,
|
|
||||||
"container")
|
|
||||||
+ "/" + checkNotNull(name, "name"));
|
|
||||||
for (HttpRequestFilter filter : returnVal.getFilters())
|
|
||||||
filter.filter(returnVal);
|
|
||||||
return new HttpRequest(returnVal.getMethod(), returnVal.getEndpoint(), ImmutableMultimap.copyOf(returnVal
|
|
||||||
.getHeaders()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -17,7 +17,7 @@
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jclouds.atmosonline.saas.blobstore.integration;
|
package org.jclouds.atmosonline.saas.blobstore;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
@ -25,29 +25,36 @@ import java.io.IOException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
|
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
|
||||||
import org.jclouds.atmosonline.saas.blobstore.strategy.SignReadFile;
|
|
||||||
import org.jclouds.atmosonline.saas.config.AtmosStorageRestClientModule;
|
import org.jclouds.atmosonline.saas.config.AtmosStorageRestClientModule;
|
||||||
import org.jclouds.atmosonline.saas.filters.SignRequest;
|
import org.jclouds.atmosonline.saas.filters.SignRequest;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.domain.Blob.Factory;
|
||||||
import org.jclouds.date.TimeStamp;
|
import org.jclouds.date.TimeStamp;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.RequiresHttp;
|
import org.jclouds.http.RequiresHttp;
|
||||||
|
import org.jclouds.io.payloads.PhantomPayload;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
import org.jclouds.rest.ConfiguresRestClient;
|
||||||
import org.jclouds.rest.RestClientTest;
|
import org.jclouds.rest.RestClientTest;
|
||||||
import org.jclouds.rest.RestContextFactory;
|
import org.jclouds.rest.RestContextFactory;
|
||||||
import org.jclouds.rest.RestContextFactory.ContextSpec;
|
import org.jclouds.rest.RestContextFactory.ContextSpec;
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
@Test(groups = "unit", testName = "emcsaas.SignReadFileTest")
|
@Test(groups = "unit", testName = "emcsaas.AtmosBlobRequestSignerTest")
|
||||||
public class SignReadFileTest extends RestClientTest<AtmosStorageAsyncClient> {
|
public class AtmosBlobRequestSignerTest extends RestClientTest<AtmosStorageAsyncClient> {
|
||||||
|
|
||||||
public void testSignReadFile() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
private BlobRequestSigner signer;
|
||||||
|
private Factory blobFactory;
|
||||||
|
|
||||||
|
public void testSignGetBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
NoSuchMethodException, IOException {
|
NoSuchMethodException, IOException {
|
||||||
HttpRequest request = new SignReadFile(processor).apply("container", "name");
|
HttpRequest request = signer.signGetBlob("container", "name");
|
||||||
|
|
||||||
assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/container/name HTTP/1.1");
|
assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/container/name HTTP/1.1");
|
||||||
assertNonPayloadHeadersEqual(
|
assertNonPayloadHeadersEqual(
|
||||||
|
@ -58,6 +65,47 @@ public class SignReadFileTest extends RestClientTest<AtmosStorageAsyncClient> {
|
||||||
assertEquals(request.getFilters().size(), 0);
|
assertEquals(request.getFilters().size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSignRemoveBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
HttpRequest request = signer.signRemoveBlob("container", "name");
|
||||||
|
|
||||||
|
assertRequestLineEquals(request,
|
||||||
|
"DELETE https://accesspoint.atmosonline.com/rest/namespace/container/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(
|
||||||
|
request,
|
||||||
|
"Accept: */*\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nx-emc-signature: Q3zmO6KNAViNXquiCZSMx/0nuuc=\nx-emc-uid: identity\n");
|
||||||
|
assertPayloadEquals(request, null, null, false);
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSignPutBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
Blob blob = blobFactory.create(null);
|
||||||
|
blob.getMetadata().setName("name");
|
||||||
|
blob.setPayload(new PhantomPayload(2l, new byte[] { 0, 2, 4, 8 }));
|
||||||
|
blob.getPayload().setContentType("text/plain");
|
||||||
|
|
||||||
|
HttpRequest request = signer.signPutBlob("container", blob);
|
||||||
|
|
||||||
|
assertRequestLineEquals(request,
|
||||||
|
"POST https://accesspoint.atmosonline.com/rest/namespace/container/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(
|
||||||
|
request,
|
||||||
|
"Accept: */*\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nx-emc-signature: aLpB1oQaCA27AXT6Nzam7s0f0pI=\nx-emc-uid: identity\n");
|
||||||
|
|
||||||
|
assertContentHeadersEqual(request, "text/plain", (long) 2l, new byte[] { 0, 2, 4, 8 });
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
protected void setupFactory() throws IOException {
|
||||||
|
super.setupFactory();
|
||||||
|
this.blobFactory = injector.getInstance(Blob.Factory.class);
|
||||||
|
this.signer = injector.getInstance(BlobRequestSigner.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void checkFilters(HttpRequest request) {
|
protected void checkFilters(HttpRequest request) {
|
||||||
assertEquals(request.getFilters().size(), 1);
|
assertEquals(request.getFilters().size(), 1);
|
|
@ -17,18 +17,16 @@
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jclouds.blobstore.strategy;
|
package org.jclouds.atmosonline.saas.blobstore.integration;
|
||||||
|
|
||||||
import org.jclouds.blobstore.strategy.internal.SignRequestForBlobUnsupported;
|
import org.jclouds.blobstore.integration.internal.BaseBlobSignerLiveTest;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.inject.ImplementedBy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@ImplementedBy(SignRequestForBlobUnsupported.class)
|
@Test(groups = { "live" }, testName = "emcsaas.AtmosBlobSignerLiveTest")
|
||||||
public interface SignRequestForBlobStrategy {
|
public class AtmosBlobSignerLiveTest extends BaseBlobSignerLiveTest {
|
||||||
HttpRequest apply(String container, String name);
|
|
||||||
}
|
}
|
|
@ -39,7 +39,7 @@ public class AtmosStorageTestInitializer extends TransientBlobStoreTestInitializ
|
||||||
@Override
|
@Override
|
||||||
protected BlobStoreContext createLiveContext(Module configurationModule, String url, String app,
|
protected BlobStoreContext createLiveContext(Module configurationModule, String url, String app,
|
||||||
String identity, String credential) throws IOException {
|
String identity, String credential) throws IOException {
|
||||||
return new BlobStoreContextFactory().createContext("atmosonline", identity, credential, ImmutableSet
|
return new BlobStoreContextFactory().createContext("synaptic", identity, credential, ImmutableSet
|
||||||
.of(configurationModule, new Log4JLoggingModule()), new Properties());
|
.of(configurationModule, new Log4JLoggingModule()), new Properties());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,6 @@ import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||||
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.concurrent.Futures;
|
import org.jclouds.concurrent.Futures;
|
||||||
|
@ -90,8 +89,8 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions,
|
BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions,
|
||||||
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
|
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
|
||||||
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd,
|
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd,
|
||||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider, SignRequestForBlobStrategy signRequestForBlob) {
|
Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
||||||
super(context, blobUtils, service, defaultLocation, locations, signRequestForBlob);
|
super(context, blobUtils, service, defaultLocation, locations);
|
||||||
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
||||||
this.async = checkNotNull(async, "async");
|
this.async = checkNotNull(async, "async");
|
||||||
this.sync = checkNotNull(sync, "sync");
|
this.sync = checkNotNull(sync, "sync");
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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 com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.blobstore.util.BlobStoreUtils.cleanRequest;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.s3.S3AsyncClient;
|
||||||
|
import org.jclouds.aws.s3.blobstore.functions.BlobToObject;
|
||||||
|
import org.jclouds.aws.s3.domain.S3Object;
|
||||||
|
import org.jclouds.aws.s3.options.PutObjectOptions;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.options.GetOptions;
|
||||||
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class S3BlobRequestSigner implements BlobRequestSigner {
|
||||||
|
private final RestAnnotationProcessor<S3AsyncClient> processor;
|
||||||
|
private final BlobToObject blobToObject;
|
||||||
|
private final Method getMethod;
|
||||||
|
private final Method deleteMethod;
|
||||||
|
private final Method createMethod;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public S3BlobRequestSigner(RestAnnotationProcessor<S3AsyncClient> processor, BlobToObject blobToObject)
|
||||||
|
throws SecurityException, NoSuchMethodException {
|
||||||
|
this.processor = checkNotNull(processor, "processor");
|
||||||
|
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
|
||||||
|
this.getMethod = S3AsyncClient.class.getMethod("getObject", String.class, String.class, GetOptions[].class);
|
||||||
|
this.deleteMethod = S3AsyncClient.class.getMethod("deleteObject", String.class, String.class);
|
||||||
|
this.createMethod = S3AsyncClient.class.getMethod("putObject", String.class, S3Object.class,
|
||||||
|
PutObjectOptions[].class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signGetBlob(String container, String name) {
|
||||||
|
return cleanRequest(processor.createRequest(getMethod, container, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signPutBlob(String container, Blob blob) {
|
||||||
|
return cleanRequest(processor.createRequest(createMethod, container, blobToObject.apply(blob)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signRemoveBlob(String container, String name) {
|
||||||
|
return cleanRequest(processor.createRequest(deleteMethod, container, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -47,7 +47,6 @@ import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||||
import org.jclouds.blobstore.internal.BaseBlobStore;
|
import org.jclouds.blobstore.internal.BaseBlobStore;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
|
@ -79,8 +78,8 @@ public class S3BlobStore extends BaseBlobStore {
|
||||||
Supplier<Set<? extends Location>> locations, S3Client sync, BucketToResourceMetadata bucket2ResourceMd,
|
Supplier<Set<? extends Location>> locations, S3Client sync, BucketToResourceMetadata bucket2ResourceMd,
|
||||||
ContainerToBucketListOptions container2BucketListOptions, BucketToResourceList bucket2ResourceList,
|
ContainerToBucketListOptions container2BucketListOptions, BucketToResourceList bucket2ResourceList,
|
||||||
ObjectToBlob object2Blob, BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object,
|
ObjectToBlob object2Blob, BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object,
|
||||||
ObjectToBlobMetadata object2BlobMd, Provider<FetchBlobMetadata> fetchBlobMetadataProvider, SignRequestForBlobStrategy signRequestForBlob) {
|
ObjectToBlobMetadata object2BlobMd, Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
||||||
super(context, blobUtils, defaultLocation, locations, signRequestForBlob);
|
super(context, blobUtils, defaultLocation, locations);
|
||||||
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
||||||
this.sync = checkNotNull(sync, "sync");
|
this.sync = checkNotNull(sync, "sync");
|
||||||
this.bucket2ResourceMd = checkNotNull(bucket2ResourceMd, "bucket2ResourceMd");
|
this.bucket2ResourceMd = checkNotNull(bucket2ResourceMd, "bucket2ResourceMd");
|
||||||
|
|
|
@ -27,16 +27,16 @@ import org.jclouds.aws.Region;
|
||||||
import org.jclouds.aws.s3.S3AsyncClient;
|
import org.jclouds.aws.s3.S3AsyncClient;
|
||||||
import org.jclouds.aws.s3.S3Client;
|
import org.jclouds.aws.s3.S3Client;
|
||||||
import org.jclouds.aws.s3.blobstore.S3AsyncBlobStore;
|
import org.jclouds.aws.s3.blobstore.S3AsyncBlobStore;
|
||||||
|
import org.jclouds.aws.s3.blobstore.S3BlobRequestSigner;
|
||||||
import org.jclouds.aws.s3.blobstore.S3BlobStore;
|
import org.jclouds.aws.s3.blobstore.S3BlobStore;
|
||||||
import org.jclouds.aws.s3.blobstore.strategy.SignGetObject;
|
|
||||||
import org.jclouds.aws.suppliers.DefaultLocationSupplier;
|
import org.jclouds.aws.suppliers.DefaultLocationSupplier;
|
||||||
import org.jclouds.blobstore.AsyncBlobStore;
|
import org.jclouds.blobstore.AsyncBlobStore;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
import org.jclouds.blobstore.BlobStore;
|
import org.jclouds.blobstore.BlobStore;
|
||||||
import org.jclouds.blobstore.BlobStoreContext;
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||||
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
||||||
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.domain.LocationScope;
|
import org.jclouds.domain.LocationScope;
|
||||||
import org.jclouds.domain.internal.LocationImpl;
|
import org.jclouds.domain.internal.LocationImpl;
|
||||||
|
@ -68,7 +68,7 @@ public class S3BlobStoreContextModule extends AbstractModule {
|
||||||
bind(BlobStore.class).to(S3BlobStore.class).in(Scopes.SINGLETON);
|
bind(BlobStore.class).to(S3BlobStore.class).in(Scopes.SINGLETON);
|
||||||
bind(BlobStoreContext.class).to(new TypeLiteral<BlobStoreContextImpl<S3Client, S3AsyncClient>>() {
|
bind(BlobStoreContext.class).to(new TypeLiteral<BlobStoreContextImpl<S3Client, S3AsyncClient>>() {
|
||||||
}).in(Scopes.SINGLETON);
|
}).in(Scopes.SINGLETON);
|
||||||
bind(SignRequestForBlobStrategy.class).to(SignGetObject.class);
|
bind(BlobRequestSigner.class).to(S3BlobRequestSigner.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 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.strategy;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.aws.s3.S3AsyncClient;
|
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.http.HttpRequestFilter;
|
|
||||||
import org.jclouds.http.options.GetOptions;
|
|
||||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
@Singleton
|
|
||||||
public class SignGetObject implements SignRequestForBlobStrategy {
|
|
||||||
private final RestAnnotationProcessor<S3AsyncClient> processor;
|
|
||||||
private final Method method;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public SignGetObject(RestAnnotationProcessor<S3AsyncClient> processor) throws SecurityException,
|
|
||||||
NoSuchMethodException {
|
|
||||||
this.processor = checkNotNull(processor, "processor");
|
|
||||||
this.method = S3AsyncClient.class.getMethod("getObject", String.class, String.class, GetOptions[].class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpRequest apply(String container, String name) {
|
|
||||||
GeneratedHttpRequest<S3AsyncClient> returnVal = processor.createRequest(method, checkNotNull(container,
|
|
||||||
"container"), checkNotNull(name, "name"));
|
|
||||||
for (HttpRequestFilter filter : returnVal.getFilters())
|
|
||||||
filter.filter(returnVal);
|
|
||||||
return new HttpRequest(returnVal.getMethod(), returnVal.getEndpoint(), ImmutableMultimap.copyOf(returnVal
|
|
||||||
.getHeaders()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -82,7 +82,7 @@ public class ComputeAndBlobStoreTogetherHappilyLiveTest extends BlobStoreAndComp
|
||||||
|
|
||||||
// instead of hard-coding to amazon s3, we can use any blobstore, conceding this test is
|
// instead of hard-coding to amazon s3, we can use any blobstore, conceding this test is
|
||||||
// configured for amz. Note we are getting temporary access to a private blob.
|
// configured for amz. Note we are getting temporary access to a private blob.
|
||||||
HttpRequest signedRequestOfInstallScript = blobContext.getBlobStore().signRequestForBlob(tag, "openjdk/install");
|
HttpRequest signedRequestOfInstallScript = blobContext.getSigner().signGetBlob(tag, "openjdk/install");
|
||||||
|
|
||||||
// so one of our commands is to execute the contents of the blob above
|
// so one of our commands is to execute the contents of the blob above
|
||||||
Statement installOpenJDK = execHttpResponse(signedRequestOfInstallScript);
|
Statement installOpenJDK = execHttpResponse(signedRequestOfInstallScript);
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.aws.s3.S3AsyncClient;
|
||||||
|
import org.jclouds.aws.s3.config.S3RestClientModule;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.domain.Blob.Factory;
|
||||||
|
import org.jclouds.date.TimeStamp;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.RequiresHttp;
|
||||||
|
import org.jclouds.io.payloads.PhantomPayload;
|
||||||
|
import org.jclouds.rest.ConfiguresRestClient;
|
||||||
|
import org.jclouds.rest.RestClientTest;
|
||||||
|
import org.jclouds.rest.RestContextFactory;
|
||||||
|
import org.jclouds.rest.RestContextFactory.ContextSpec;
|
||||||
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
@Test(groups = "unit", testName = "s3.S3BlobRequestSignerTest")
|
||||||
|
public class S3BlobRequestSignerTest extends RestClientTest<S3AsyncClient> {
|
||||||
|
|
||||||
|
private BlobRequestSigner signer;
|
||||||
|
private Factory blobFactory;
|
||||||
|
|
||||||
|
public void testSignGetBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
HttpRequest request = signer.signGetBlob("container", "name");
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "GET https://container.s3.amazonaws.com/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(
|
||||||
|
request,
|
||||||
|
"Authorization: AWS identity:0uvBv1wEskuhFHYJF/L6kEV9A7o=\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nHost: container.s3.amazonaws.com\n");
|
||||||
|
assertPayloadEquals(request, null, null, false);
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSignRemoveBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
HttpRequest request = signer.signRemoveBlob("container", "name");
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "DELETE https://container.s3.amazonaws.com/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(
|
||||||
|
request,
|
||||||
|
"Authorization: AWS identity:4FnyjdX/ULdDMRbVlLNjZfEo9RQ=\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nHost: container.s3.amazonaws.com\n");
|
||||||
|
assertPayloadEquals(request, null, null, false);
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSignPutBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
Blob blob = blobFactory.create(null);
|
||||||
|
blob.getMetadata().setName("name");
|
||||||
|
blob.setPayload(new PhantomPayload(2l, new byte[] { 0, 2, 4, 8 }));
|
||||||
|
blob.getPayload().setContentType("text/plain");
|
||||||
|
|
||||||
|
HttpRequest request = signer.signPutBlob("container", blob);
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "PUT https://container.s3.amazonaws.com/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(
|
||||||
|
request,
|
||||||
|
"Authorization: AWS identity:j9Dy/lmmvlCKjA4lkqZenLxMkR4=\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nHost: container.s3.amazonaws.com\n");
|
||||||
|
|
||||||
|
assertContentHeadersEqual(request, "text/plain", (long) 2l, new byte[] { 0, 2, 4, 8 });
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
protected void setupFactory() throws IOException {
|
||||||
|
super.setupFactory();
|
||||||
|
this.blobFactory = injector.getInstance(Blob.Factory.class);
|
||||||
|
this.signer = injector.getInstance(BlobRequestSigner.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void checkFilters(HttpRequest request) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TypeLiteral<RestAnnotationProcessor<S3AsyncClient>> createTypeLiteral() {
|
||||||
|
return new TypeLiteral<RestAnnotationProcessor<S3AsyncClient>>() {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Module createModule() {
|
||||||
|
return new TestS3RestClientModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresHttp
|
||||||
|
@ConfiguresRestClient
|
||||||
|
private static final class TestS3RestClientModule extends S3RestClientModule {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
super.configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||||
|
return "Thu, 05 Jun 2008 16:38:19 GMT";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContextSpec<?, ?> createContextSpec() {
|
||||||
|
return new RestContextFactory().createContextSpec("s3", "identity", "credential", new Properties());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,21 +17,16 @@
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jclouds.blobstore.strategy.internal;
|
package org.jclouds.aws.s3.blobstore.integration;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import org.jclouds.blobstore.integration.internal.BaseBlobSignerLiveTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Test(groups = { "live" }, testName = "s3.S3BlobSignerLiveTest")
|
||||||
public class SignRequestForBlobUnsupported implements SignRequestForBlobStrategy {
|
public class S3BlobSignerLiveTest extends BaseBlobSignerLiveTest {
|
||||||
@Override
|
|
||||||
public HttpRequest apply(String container, String name) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,76 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 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.strategy;
|
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.jclouds.aws.s3.BaseS3AsyncClientTest;
|
|
||||||
import org.jclouds.aws.s3.config.S3RestClientModule;
|
|
||||||
import org.jclouds.date.TimeStamp;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.http.RequiresHttp;
|
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
import com.google.inject.Module;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests behavior of {@code SignGetObject}
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
@Test(groups = "unit", testName = "s3.SignGetObjectTest")
|
|
||||||
public class SignGetObjectTest extends BaseS3AsyncClientTest {
|
|
||||||
|
|
||||||
public void testSignGetObject() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
|
||||||
NoSuchMethodException, IOException {
|
|
||||||
HttpRequest request = new SignGetObject(processor).apply( "bucket", "object");
|
|
||||||
|
|
||||||
assertRequestLineEquals(request, "GET https://bucket.s3.amazonaws.com/object HTTP/1.1");
|
|
||||||
assertNonPayloadHeadersEqual(request, "Authorization: AWS identity:1UqxCBECNncBHUhxJ3Y/Q1O3IiA=\nDate: 2009-11-08T15:54:08.897Z\nHost: bucket.s3.amazonaws.com\n");
|
|
||||||
assertPayloadEquals(request, null, null, false);
|
|
||||||
|
|
||||||
assertEquals(request.getFilters().size(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@RequiresHttp
|
|
||||||
@ConfiguresRestClient
|
|
||||||
protected static final class TestS3RestClientModule extends S3RestClientModule {
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
super.configure();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
|
||||||
return "2009-11-08T15:54:08.897Z";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Module createModule() {
|
|
||||||
return new TestS3RestClientModule();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -52,7 +52,6 @@ import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||||
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.concurrent.Futures;
|
import org.jclouds.concurrent.Futures;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
|
@ -85,8 +84,8 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
|
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
|
||||||
ListBlobsResponseToResourceList azure2BlobStoreResourceList, AzureBlobToBlob azureBlob2Blob,
|
ListBlobsResponseToResourceList azure2BlobStoreResourceList, AzureBlobToBlob azureBlob2Blob,
|
||||||
BlobToAzureBlob blob2AzureBlob, BlobPropertiesToBlobMetadata blob2BlobMd,
|
BlobToAzureBlob blob2AzureBlob, BlobPropertiesToBlobMetadata blob2BlobMd,
|
||||||
BlobToHttpGetOptions blob2ObjectGetOptions, SignRequestForBlobStrategy signRequestForBlob) {
|
BlobToHttpGetOptions blob2ObjectGetOptions) {
|
||||||
super(context, blobUtils, service, defaultLocation, locations, signRequestForBlob);
|
super(context, blobUtils, service, defaultLocation, locations);
|
||||||
this.async = checkNotNull(async, "async");
|
this.async = checkNotNull(async, "async");
|
||||||
this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd");
|
this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd");
|
||||||
this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions,
|
this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions,
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.azure.storage.blob.blobstore;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.blobstore.util.BlobStoreUtils.cleanRequest;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.azure.storage.blob.AzureBlobAsyncClient;
|
||||||
|
import org.jclouds.azure.storage.blob.blobstore.functions.BlobToAzureBlob;
|
||||||
|
import org.jclouds.azure.storage.blob.domain.AzureBlob;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.options.GetOptions;
|
||||||
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class AzureBlobRequestSigner implements BlobRequestSigner {
|
||||||
|
private final RestAnnotationProcessor<AzureBlobAsyncClient> processor;
|
||||||
|
private final BlobToAzureBlob blobToBlob;
|
||||||
|
private final Method getMethod;
|
||||||
|
private final Method deleteMethod;
|
||||||
|
private final Method createMethod;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AzureBlobRequestSigner(RestAnnotationProcessor<AzureBlobAsyncClient> processor, BlobToAzureBlob blobToBlob)
|
||||||
|
throws SecurityException, NoSuchMethodException {
|
||||||
|
this.processor = checkNotNull(processor, "processor");
|
||||||
|
this.blobToBlob = checkNotNull(blobToBlob, "blobToBlob");
|
||||||
|
this.getMethod = AzureBlobAsyncClient.class.getMethod("getBlob", String.class, String.class, GetOptions[].class);
|
||||||
|
this.deleteMethod = AzureBlobAsyncClient.class.getMethod("deleteBlob", String.class, String.class);
|
||||||
|
this.createMethod = AzureBlobAsyncClient.class.getMethod("putBlob", String.class, AzureBlob.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signGetBlob(String container, String name) {
|
||||||
|
return cleanRequest(processor.createRequest(getMethod, container, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signPutBlob(String container, Blob blob) {
|
||||||
|
return cleanRequest(processor.createRequest(createMethod, container, blobToBlob.apply(blob)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signRemoveBlob(String container, String name) {
|
||||||
|
return cleanRequest(processor.createRequest(deleteMethod, container, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -46,7 +46,6 @@ import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||||
import org.jclouds.blobstore.internal.BaseBlobStore;
|
import org.jclouds.blobstore.internal.BaseBlobStore;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.http.options.GetOptions;
|
import org.jclouds.http.options.GetOptions;
|
||||||
|
@ -76,8 +75,8 @@ public class AzureBlobStore extends BaseBlobStore {
|
||||||
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
|
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
|
||||||
ListBlobsResponseToResourceList azure2BlobStoreResourceList, AzureBlobToBlob azureBlob2Blob,
|
ListBlobsResponseToResourceList azure2BlobStoreResourceList, AzureBlobToBlob azureBlob2Blob,
|
||||||
BlobToAzureBlob blob2AzureBlob, BlobPropertiesToBlobMetadata blob2BlobMd,
|
BlobToAzureBlob blob2AzureBlob, BlobPropertiesToBlobMetadata blob2BlobMd,
|
||||||
BlobToHttpGetOptions blob2ObjectGetOptions, SignRequestForBlobStrategy signRequestForBlob) {
|
BlobToHttpGetOptions blob2ObjectGetOptions) {
|
||||||
super(context, blobUtils, defaultLocation, locations, signRequestForBlob);
|
super(context, blobUtils, defaultLocation, locations);
|
||||||
this.sync = checkNotNull(sync, "sync");
|
this.sync = checkNotNull(sync, "sync");
|
||||||
this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd");
|
this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd");
|
||||||
this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions,
|
this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions,
|
||||||
|
|
|
@ -26,17 +26,17 @@ import javax.inject.Singleton;
|
||||||
import org.jclouds.azure.storage.blob.AzureBlobAsyncClient;
|
import org.jclouds.azure.storage.blob.AzureBlobAsyncClient;
|
||||||
import org.jclouds.azure.storage.blob.AzureBlobClient;
|
import org.jclouds.azure.storage.blob.AzureBlobClient;
|
||||||
import org.jclouds.azure.storage.blob.blobstore.AzureAsyncBlobStore;
|
import org.jclouds.azure.storage.blob.blobstore.AzureAsyncBlobStore;
|
||||||
|
import org.jclouds.azure.storage.blob.blobstore.AzureBlobRequestSigner;
|
||||||
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStore;
|
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStore;
|
||||||
import org.jclouds.azure.storage.blob.blobstore.strategy.FindMD5InBlobProperties;
|
import org.jclouds.azure.storage.blob.blobstore.strategy.FindMD5InBlobProperties;
|
||||||
import org.jclouds.azure.storage.blob.blobstore.strategy.SignGetBlob;
|
|
||||||
import org.jclouds.blobstore.AsyncBlobStore;
|
import org.jclouds.blobstore.AsyncBlobStore;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
import org.jclouds.blobstore.BlobStore;
|
import org.jclouds.blobstore.BlobStore;
|
||||||
import org.jclouds.blobstore.BlobStoreContext;
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||||
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
||||||
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
||||||
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
|
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.domain.LocationScope;
|
import org.jclouds.domain.LocationScope;
|
||||||
import org.jclouds.domain.internal.LocationImpl;
|
import org.jclouds.domain.internal.LocationImpl;
|
||||||
|
@ -66,7 +66,7 @@ public class AzureBlobStoreContextModule extends AbstractModule {
|
||||||
bind(BlobStoreContext.class).to(new TypeLiteral<BlobStoreContextImpl<AzureBlobClient, AzureBlobAsyncClient>>() {
|
bind(BlobStoreContext.class).to(new TypeLiteral<BlobStoreContextImpl<AzureBlobClient, AzureBlobAsyncClient>>() {
|
||||||
}).in(Scopes.SINGLETON);
|
}).in(Scopes.SINGLETON);
|
||||||
bind(ContainsValueInListStrategy.class).to(FindMD5InBlobProperties.class);
|
bind(ContainsValueInListStrategy.class).to(FindMD5InBlobProperties.class);
|
||||||
bind(SignRequestForBlobStrategy.class).to(SignGetBlob.class);
|
bind(BlobRequestSigner.class).to(AzureBlobRequestSigner.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 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.azure.storage.blob.blobstore.strategy;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.azure.storage.blob.AzureBlobAsyncClient;
|
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.http.HttpRequestFilter;
|
|
||||||
import org.jclouds.http.options.GetOptions;
|
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
@Singleton
|
|
||||||
public class SignGetBlob implements SignRequestForBlobStrategy {
|
|
||||||
private final RestAnnotationProcessor<AzureBlobAsyncClient> processor;
|
|
||||||
private final Method method;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public SignGetBlob(RestAnnotationProcessor<AzureBlobAsyncClient> processor) throws SecurityException,
|
|
||||||
NoSuchMethodException {
|
|
||||||
this.processor = checkNotNull(processor, "processor");
|
|
||||||
this.method = AzureBlobAsyncClient.class.getMethod("getBlob", String.class, String.class, GetOptions[].class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpRequest apply(String container, String name) {
|
|
||||||
HttpRequest returnVal = processor.createRequest(method, checkNotNull(container,
|
|
||||||
"container"), checkNotNull(name, "name"));
|
|
||||||
for (HttpRequestFilter filter : returnVal.getFilters())
|
|
||||||
filter.filter(returnVal);
|
|
||||||
returnVal.getFilters().clear();
|
|
||||||
return new HttpRequest(returnVal.getMethod(), returnVal.getEndpoint(), ImmutableMultimap.copyOf(returnVal.getHeaders()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.azure.storage.blob.blobstore;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.azure.storage.blob.AzureBlobAsyncClient;
|
||||||
|
import org.jclouds.azure.storage.blob.config.AzureBlobRestClientModule;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.domain.Blob.Factory;
|
||||||
|
import org.jclouds.date.TimeStamp;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.RequiresHttp;
|
||||||
|
import org.jclouds.io.payloads.PhantomPayload;
|
||||||
|
import org.jclouds.rest.ConfiguresRestClient;
|
||||||
|
import org.jclouds.rest.RestClientTest;
|
||||||
|
import org.jclouds.rest.RestContextFactory;
|
||||||
|
import org.jclouds.rest.RestContextFactory.ContextSpec;
|
||||||
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
@Test(groups = "unit", testName = "s3.AzureBlobBlobRequestSignerTest")
|
||||||
|
public class AzureBlobBlobRequestSignerTest extends RestClientTest<AzureBlobAsyncClient> {
|
||||||
|
|
||||||
|
private BlobRequestSigner signer;
|
||||||
|
private Factory blobFactory;
|
||||||
|
|
||||||
|
public void testSignGetBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
HttpRequest request = signer.signGetBlob("container", "name");
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "GET https://identity.blob.core.windows.net/container/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(
|
||||||
|
request,
|
||||||
|
"Authorization: SharedKeyLite identity:nI6ca9CdLWhPoMuSzk4perqx5pzi2hx7YBJ92FCqeXM=\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nx-ms-version: 2009-09-19\n");
|
||||||
|
assertPayloadEquals(request, null, null, false);
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSignRemoveBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
HttpRequest request = signer.signRemoveBlob("container", "name");
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "DELETE https://identity.blob.core.windows.net/container/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(
|
||||||
|
request,
|
||||||
|
"Authorization: SharedKeyLite identity:+BDU2AGqS9LwevaKH+jaRKNrxTZ3LsFDpnnWFKpN0jc=\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nx-ms-version: 2009-09-19\n");
|
||||||
|
assertPayloadEquals(request, null, null, false);
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSignPutBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
Blob blob = blobFactory.create(null);
|
||||||
|
blob.getMetadata().setName("name");
|
||||||
|
blob.setPayload(new PhantomPayload(2l, new byte[] { 0, 2, 4, 8 }));
|
||||||
|
blob.getPayload().setContentType("text/plain");
|
||||||
|
|
||||||
|
HttpRequest request = signer.signPutBlob("container", blob);
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "PUT https://identity.blob.core.windows.net/container/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(
|
||||||
|
request,
|
||||||
|
"Authorization: SharedKeyLite identity:LT+HBNzhbRsZY07kC+/JxeuAURbxTmwJaIe464LO36c=\nDate: Thu, 05 Jun 2008 16:38:19 GMT\nx-ms-blob-type: BlockBlob\nx-ms-version: 2009-09-19\n");
|
||||||
|
assertContentHeadersEqual(request, "text/plain", (long) 2l, new byte[] { 0, 2, 4, 8 });
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
protected void setupFactory() throws IOException {
|
||||||
|
super.setupFactory();
|
||||||
|
this.blobFactory = injector.getInstance(Blob.Factory.class);
|
||||||
|
this.signer = injector.getInstance(BlobRequestSigner.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void checkFilters(HttpRequest request) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TypeLiteral<RestAnnotationProcessor<AzureBlobAsyncClient>> createTypeLiteral() {
|
||||||
|
return new TypeLiteral<RestAnnotationProcessor<AzureBlobAsyncClient>>() {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Module createModule() {
|
||||||
|
return new TestAzureBlobRestClientModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresHttp
|
||||||
|
@ConfiguresRestClient
|
||||||
|
private static final class TestAzureBlobRestClientModule extends AzureBlobRestClientModule {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
super.configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||||
|
return "Thu, 05 Jun 2008 16:38:19 GMT";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContextSpec<?, ?> createContextSpec() {
|
||||||
|
return new RestContextFactory().createContextSpec("azureblob", "identity", "credential", new Properties());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,102 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 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.azure.storage.blob.blobstore.config;
|
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.jclouds.azure.storage.blob.AzureBlobAsyncClient;
|
|
||||||
import org.jclouds.azure.storage.blob.blobstore.strategy.SignGetBlob;
|
|
||||||
import org.jclouds.azure.storage.blob.config.AzureBlobRestClientModule;
|
|
||||||
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
|
|
||||||
import org.jclouds.date.TimeStamp;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.http.RequiresHttp;
|
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
|
||||||
import org.jclouds.rest.RestClientTest;
|
|
||||||
import org.jclouds.rest.RestContextFactory;
|
|
||||||
import org.jclouds.rest.RestContextFactory.ContextSpec;
|
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
import com.google.inject.Module;
|
|
||||||
import com.google.inject.TypeLiteral;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests behavior of {@code SignGetBlob}
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
@Test(groups = "unit", testName = "azureblob.SignGetBlobTest")
|
|
||||||
public class SignGetBlobTest extends RestClientTest<AzureBlobAsyncClient> {
|
|
||||||
|
|
||||||
public void testSignGetBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
|
||||||
NoSuchMethodException, IOException {
|
|
||||||
HttpRequest request = new SignGetBlob(processor).apply("container", "blob");
|
|
||||||
|
|
||||||
assertRequestLineEquals(request, "GET https://identity.blob.core.windows.net/container/blob HTTP/1.1");
|
|
||||||
assertNonPayloadHeadersEqual(
|
|
||||||
request,
|
|
||||||
"Authorization: SharedKeyLite identity:bX3fHsuXQQEzvLey2TD76FcDDvDIHZpgSX2j5oH4Iy8=\nDate: 2009-11-08T15:54:08.897Z\nx-ms-version: 2009-09-19\n");
|
|
||||||
assertPayloadEquals(request, null, null, false);
|
|
||||||
|
|
||||||
assertEquals(request.getFilters().size(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresHttp
|
|
||||||
@ConfiguresRestClient
|
|
||||||
protected static final class TestAzureBlobRestClientModule extends AzureBlobRestClientModule {
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
super.configure();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
|
||||||
return "2009-11-08T15:54:08.897Z";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Module createModule() {
|
|
||||||
return new TestAzureBlobRestClientModule();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void checkFilters(HttpRequest request) {
|
|
||||||
assertEquals(request.getFilters().size(), 1);
|
|
||||||
assertEquals(request.getFilters().get(0).getClass(), SharedKeyLiteAuthentication.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TypeLiteral<RestAnnotationProcessor<AzureBlobAsyncClient>> createTypeLiteral() {
|
|
||||||
return new TypeLiteral<RestAnnotationProcessor<AzureBlobAsyncClient>>() {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ContextSpec<?, ?> createContextSpec() {
|
|
||||||
return new RestContextFactory().createContextSpec("azureblob", "identity", "credential", new Properties());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.azure.storage.blob.blobstore.integration;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.integration.internal.BaseBlobSignerLiveTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = { "live" }, testName = "azureblob.AzureBlobSignerLiveTest")
|
||||||
|
public class AzureBlobSignerLiveTest extends BaseBlobSignerLiveTest {
|
||||||
|
|
||||||
|
}
|
|
@ -45,6 +45,7 @@ See http://code.google.com/p/jclouds for details."
|
||||||
domain.BlobMetadata domain.StorageMetadata domain.Blob
|
domain.BlobMetadata domain.StorageMetadata domain.Blob
|
||||||
options.ListContainerOptions]
|
options.ListContainerOptions]
|
||||||
[org.jclouds.io Payloads]
|
[org.jclouds.io Payloads]
|
||||||
|
[org.jclouds.io.payloads PhantomPayload]
|
||||||
[java.util Arrays]
|
[java.util Arrays]
|
||||||
[java.security DigestOutputStream MessageDigest]
|
[java.security DigestOutputStream MessageDigest]
|
||||||
[com.google.common.collect ImmutableSet]))
|
[com.google.common.collect ImmutableSet]))
|
||||||
|
@ -238,13 +239,34 @@ Options can also be specified for extension modules
|
||||||
([container-name path #^BlobStore blobstore]
|
([container-name path #^BlobStore blobstore]
|
||||||
(.getBlob blobstore container-name path)))
|
(.getBlob blobstore container-name path)))
|
||||||
|
|
||||||
(defn sign-blob-request
|
(defn sign-get-blob-request
|
||||||
"Get a signed http request for a blob, so that you can retrieve it
|
"Get a signed http request for a blob, so that you can retrieve it
|
||||||
in another application. ex. curl"
|
in another application. ex. curl"
|
||||||
([container-name path]
|
([container-name path]
|
||||||
(sign-blob-request container-name path *blobstore*))
|
(sign-get-blob-request container-name path *blobstore*))
|
||||||
([container-name path #^BlobStore blobstore]
|
([container-name path #^BlobStore blobstore]
|
||||||
(.signRequestForBlob blobstore container-name path)))
|
(.signGetBlob (.getContext blobstore) container-name path)))
|
||||||
|
|
||||||
|
(defn sign-remove-blob-request
|
||||||
|
"Get a signed http request for deleting a blob in another application.
|
||||||
|
ex. curl"
|
||||||
|
([container-name path]
|
||||||
|
(sign-remove-blob-request container-name path *blobstore*))
|
||||||
|
([container-name path #^BlobStore blobstore]
|
||||||
|
(.signRemoveBlob (.getContext blobstore) container-name path)))
|
||||||
|
|
||||||
|
(defn sign-put-blob-request
|
||||||
|
"Get a signed http request for uploading a blob in another application.
|
||||||
|
ex. curl"
|
||||||
|
([container-name path content-type size]
|
||||||
|
(sign-put-blob-request container-name path content-type size *blobstore*))
|
||||||
|
([container-name path content-type size #^BlobStore blobstore]
|
||||||
|
(.signPutBlob (.getContext blobstore) container-name
|
||||||
|
(doto (.newBlob blobstore path)
|
||||||
|
(.setPayload (doto
|
||||||
|
;; until we pass content md5
|
||||||
|
(PhantomPayload. size nil)
|
||||||
|
(.setContentType content-type)))))))
|
||||||
|
|
||||||
(defn get-blob-stream
|
(defn get-blob-stream
|
||||||
"Get an inputstream from the blob at a given path"
|
"Get an inputstream from the blob at a given path"
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.jclouds.blobstore;
|
package org.jclouds.blobstore;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@ -31,7 +30,8 @@ import org.jclouds.blobstore.domain.StorageMetadata;
|
||||||
import org.jclouds.blobstore.options.GetOptions;
|
import org.jclouds.blobstore.options.GetOptions;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides hooks needed to run a blob store asynchronously
|
* Provides hooks needed to run a blob store asynchronously
|
||||||
|
@ -49,11 +49,6 @@ public interface AsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
Blob newBlob(String name);
|
Blob newBlob(String name);
|
||||||
|
|
||||||
/**
|
|
||||||
* @see BlobStore#signRequestForBlob
|
|
||||||
*/
|
|
||||||
HttpRequest signRequestForBlob(String container, String name);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see BlobStore#listAssignableLocations
|
* @see BlobStore#listAssignableLocations
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.blobstore;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.internal.RequestSigningUnsupported;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.io.payloads.PhantomPayload;
|
||||||
|
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates signed requests for blobs. useful in other tools such as backup utilities.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@ImplementedBy(RequestSigningUnsupported.class)
|
||||||
|
public interface BlobRequestSigner {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets a signed request, including headers as necessary, to access a blob from an external
|
||||||
|
* client.
|
||||||
|
*
|
||||||
|
* @param container
|
||||||
|
* container where the blob resides
|
||||||
|
* @param directory
|
||||||
|
* full path to the blob
|
||||||
|
* @throws UnsupportedOperationException
|
||||||
|
* if not supported by the provider
|
||||||
|
*/
|
||||||
|
HttpRequest signGetBlob(String container, String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets a signed request, including headers as necessary, to delete a blob from an external
|
||||||
|
* client.
|
||||||
|
*
|
||||||
|
* @param container
|
||||||
|
* container where the blob resides
|
||||||
|
* @param directory
|
||||||
|
* full path to the blob
|
||||||
|
* @throws UnsupportedOperationException
|
||||||
|
* if not supported by the provider
|
||||||
|
*/
|
||||||
|
HttpRequest signRemoveBlob(String container, String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets a signed request, including headers as necessary, to upload a blob from an external
|
||||||
|
* client.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Blob blob = context.getBlobStore.newBlob();
|
||||||
|
* blob.getMetadata().setName("name");
|
||||||
|
* blob.setPayload(new PhantomPayload(length, md5));
|
||||||
|
* blob.getPayload().setContentType("text/plain");
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param container
|
||||||
|
* container where the blob resides
|
||||||
|
* @param blob
|
||||||
|
* what to upload
|
||||||
|
* @throws UnsupportedOperationException
|
||||||
|
* if not supported by the provider
|
||||||
|
* @see PhantomPayload
|
||||||
|
*/
|
||||||
|
HttpRequest signPutBlob(String container, Blob blob);
|
||||||
|
}
|
|
@ -30,7 +30,6 @@ import org.jclouds.blobstore.domain.StorageMetadata;
|
||||||
import org.jclouds.blobstore.options.GetOptions;
|
import org.jclouds.blobstore.options.GetOptions;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronous access to a BlobStore such as Amazon S3
|
* Synchronous access to a BlobStore such as Amazon S3
|
||||||
|
@ -51,19 +50,6 @@ public interface BlobStore {
|
||||||
*/
|
*/
|
||||||
Blob newBlob(String name);
|
Blob newBlob(String name);
|
||||||
|
|
||||||
/**
|
|
||||||
* gets a signed request, including headers as necessary, to access a blob from an external
|
|
||||||
* client.
|
|
||||||
*
|
|
||||||
* @param container
|
|
||||||
* container where the blob resides
|
|
||||||
* @param directory
|
|
||||||
* full path to the blob
|
|
||||||
* @throws UnsupportedOperationException
|
|
||||||
* if not supported by the provider
|
|
||||||
*/
|
|
||||||
HttpRequest signRequestForBlob(String container, String name);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The get locations command returns all the valid locations for containers. A location has a
|
* The get locations command returns all the valid locations for containers. A location has a
|
||||||
* scope, which is typically region or zone. A region is a general area, like eu-west, where a
|
* scope, which is typically region or zone. A region is a general area, like eu-west, where a
|
||||||
|
|
|
@ -36,6 +36,12 @@ import com.google.inject.ImplementedBy;
|
||||||
*/
|
*/
|
||||||
@ImplementedBy(BlobStoreContextImpl.class)
|
@ImplementedBy(BlobStoreContextImpl.class)
|
||||||
public interface BlobStoreContext {
|
public interface BlobStoreContext {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Generates signed requests for blobs. useful in other tools such as backup utilities.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BlobRequestSigner getSigner();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a <code>Map<String,InputStream></code> view of the specified container. Use this for
|
* Creates a <code>Map<String,InputStream></code> view of the specified container. Use this for
|
||||||
|
|
|
@ -77,7 +77,6 @@ import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||||
import org.jclouds.blobstore.options.GetOptions;
|
import org.jclouds.blobstore.options.GetOptions;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy;
|
import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.crypto.Crypto;
|
import org.jclouds.crypto.Crypto;
|
||||||
import org.jclouds.crypto.CryptoStreams;
|
import org.jclouds.crypto.CryptoStreams;
|
||||||
|
@ -125,8 +124,8 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
HttpGetOptionsListToGetOptions httpGetOptionsConverter,
|
HttpGetOptionsListToGetOptions httpGetOptionsConverter,
|
||||||
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory, BlobUtils blobUtils,
|
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory, BlobUtils blobUtils,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||||
Supplier<Set<? extends Location>> locations, SignRequestForBlobStrategy signRequestForBlob) {
|
Supplier<Set<? extends Location>> locations) {
|
||||||
super(context, blobUtils, service, defaultLocation, locations, signRequestForBlob);
|
super(context, blobUtils, service, defaultLocation, locations);
|
||||||
this.blobFactory = blobFactory;
|
this.blobFactory = blobFactory;
|
||||||
this.dateService = dateService;
|
this.dateService = dateService;
|
||||||
this.crypto = crypto;
|
this.crypto = crypto;
|
||||||
|
|
|
@ -37,11 +37,9 @@ import org.jclouds.blobstore.domain.Blob;
|
||||||
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.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.blobstore.util.internal.BlobUtilsImpl;
|
import org.jclouds.blobstore.util.internal.BlobUtilsImpl;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.util.Utils;
|
import org.jclouds.util.Utils;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
@ -59,18 +57,16 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
|
||||||
protected final ExecutorService service;
|
protected final ExecutorService service;
|
||||||
protected final Supplier<Location> defaultLocation;
|
protected final Supplier<Location> defaultLocation;
|
||||||
protected final Supplier<Set<? extends Location>> locations;
|
protected final Supplier<Set<? extends Location>> locations;
|
||||||
protected final SignRequestForBlobStrategy signRequestForBlob;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected BaseAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
protected BaseAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||||
Supplier<Set<? extends Location>> locations, SignRequestForBlobStrategy signRequestForBlob) {
|
Supplier<Set<? extends Location>> locations) {
|
||||||
this.context = checkNotNull(context, "context");
|
this.context = checkNotNull(context, "context");
|
||||||
this.blobUtils = checkNotNull(blobUtils, "blobUtils");
|
this.blobUtils = checkNotNull(blobUtils, "blobUtils");
|
||||||
this.service = checkNotNull(service, "service");
|
this.service = checkNotNull(service, "service");
|
||||||
this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation");
|
this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation");
|
||||||
this.locations = checkNotNull(locations, "locations");
|
this.locations = checkNotNull(locations, "locations");
|
||||||
this.signRequestForBlob = checkNotNull(signRequestForBlob, "signRequestForBlob");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -271,8 +267,5 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
|
||||||
|
|
||||||
protected abstract boolean deleteAndVerifyContainerGone(String container);
|
protected abstract boolean deleteAndVerifyContainerGone(String container);
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpRequest signRequestForBlob(String container, String name) {
|
|
||||||
return signRequestForBlob.apply(container, name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,9 @@ import org.jclouds.blobstore.domain.Blob;
|
||||||
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.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.blobstore.util.internal.BlobUtilsImpl;
|
import org.jclouds.blobstore.util.internal.BlobUtilsImpl;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.util.Utils;
|
import org.jclouds.util.Utils;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
@ -52,16 +50,14 @@ public abstract class BaseBlobStore implements BlobStore {
|
||||||
protected final BlobUtils blobUtils;
|
protected final BlobUtils blobUtils;
|
||||||
protected final Supplier<Location> defaultLocation;
|
protected final Supplier<Location> defaultLocation;
|
||||||
protected final Supplier<Set<? extends Location>> locations;
|
protected final Supplier<Set<? extends Location>> locations;
|
||||||
protected final SignRequestForBlobStrategy signRequestForBlob;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected BaseBlobStore(BlobStoreContext context, BlobUtils blobUtils, Supplier<Location> defaultLocation,
|
protected BaseBlobStore(BlobStoreContext context, BlobUtils blobUtils, Supplier<Location> defaultLocation,
|
||||||
Supplier<Set<? extends Location>> locations, SignRequestForBlobStrategy signRequestForBlob) {
|
Supplier<Set<? extends Location>> locations) {
|
||||||
this.context = checkNotNull(context, "context");
|
this.context = checkNotNull(context, "context");
|
||||||
this.blobUtils = checkNotNull(blobUtils, "blobUtils");
|
this.blobUtils = checkNotNull(blobUtils, "blobUtils");
|
||||||
this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation");
|
this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation");
|
||||||
this.locations = checkNotNull(locations, "locations");
|
this.locations = checkNotNull(locations, "locations");
|
||||||
this.signRequestForBlob = checkNotNull(signRequestForBlob, "signRequestForBlob");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -224,8 +220,4 @@ public abstract class BaseBlobStore implements BlobStore {
|
||||||
|
|
||||||
protected abstract boolean deleteAndVerifyContainerGone(String container);
|
protected abstract boolean deleteAndVerifyContainerGone(String container);
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpRequest signRequestForBlob(String container, String name) {
|
|
||||||
return signRequestForBlob.apply(container, name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.blobstore.AsyncBlobStore;
|
import org.jclouds.blobstore.AsyncBlobStore;
|
||||||
import org.jclouds.blobstore.BlobMap;
|
import org.jclouds.blobstore.BlobMap;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
import org.jclouds.blobstore.BlobStore;
|
import org.jclouds.blobstore.BlobStore;
|
||||||
import org.jclouds.blobstore.BlobStoreContext;
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
import org.jclouds.blobstore.InputStreamMap;
|
import org.jclouds.blobstore.InputStreamMap;
|
||||||
|
@ -46,22 +47,23 @@ public class BlobStoreContextImpl<S, A> implements BlobStoreContext {
|
||||||
private final RestContext<S, A> providerSpecificContext;
|
private final RestContext<S, A> providerSpecificContext;
|
||||||
private final ConsistencyModel consistencyModel;
|
private final ConsistencyModel consistencyModel;
|
||||||
private final Utils utils;
|
private final Utils utils;
|
||||||
|
private final BlobRequestSigner blobRequestSigner;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Inject
|
@Inject
|
||||||
public BlobStoreContextImpl(BlobMap.Factory blobMapFactory, Utils utils,
|
public BlobStoreContextImpl(BlobMap.Factory blobMapFactory, Utils utils, ConsistencyModel consistencyModel,
|
||||||
ConsistencyModel consistencyModel, InputStreamMap.Factory inputStreamMapFactory,
|
InputStreamMap.Factory inputStreamMapFactory, AsyncBlobStore ablobStore, BlobStore blobStore,
|
||||||
AsyncBlobStore ablobStore, BlobStore blobStore, RestContext providerSpecificContext) {
|
RestContext providerSpecificContext, BlobRequestSigner blobRequestSigner) {
|
||||||
// unravel guice and avoid passing in a million type args by not injecting generic types for
|
// unravel guice and avoid passing in a million type args by not injecting generic types for
|
||||||
// rest context
|
// rest context
|
||||||
this.providerSpecificContext = checkNotNull(providerSpecificContext,
|
this.providerSpecificContext = checkNotNull(providerSpecificContext, "providerSpecificContext");
|
||||||
"providerSpecificContext");
|
|
||||||
this.consistencyModel = checkNotNull(consistencyModel, "consistencyModel");
|
this.consistencyModel = checkNotNull(consistencyModel, "consistencyModel");
|
||||||
this.blobMapFactory = checkNotNull(blobMapFactory, "blobMapFactory");
|
this.blobMapFactory = checkNotNull(blobMapFactory, "blobMapFactory");
|
||||||
this.inputStreamMapFactory = checkNotNull(inputStreamMapFactory, "inputStreamMapFactory");
|
this.inputStreamMapFactory = checkNotNull(inputStreamMapFactory, "inputStreamMapFactory");
|
||||||
this.ablobStore = checkNotNull(ablobStore, "ablobStore");
|
this.ablobStore = checkNotNull(ablobStore, "ablobStore");
|
||||||
this.blobStore = checkNotNull(blobStore, "blobStore");
|
this.blobStore = checkNotNull(blobStore, "blobStore");
|
||||||
this.utils = utils;
|
this.utils = checkNotNull(utils, "utils");
|
||||||
|
this.blobRequestSigner = checkNotNull(blobRequestSigner, "blobRequestSigner");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -134,4 +136,9 @@ public class BlobStoreContextImpl<S, A> implements BlobStoreContext {
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
return providerSpecificContext.equals(obj);
|
return providerSpecificContext.equals(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlobRequestSigner getSigner() {
|
||||||
|
return blobRequestSigner;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.blobstore.internal;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class RequestSigningUnsupported implements BlobRequestSigner {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signGetBlob(String container, String name) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signPutBlob(String container, Blob blob) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signRemoveBlob(String container, String name) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -37,14 +37,27 @@ import org.jclouds.blobstore.domain.Blob;
|
||||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||||
import org.jclouds.functions.ExceptionToValueOrPropagate;
|
import org.jclouds.functions.ExceptionToValueOrPropagate;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpRequestFilter;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class BlobStoreUtils {
|
public class BlobStoreUtils {
|
||||||
|
public static <T> HttpRequest cleanRequest(GeneratedHttpRequest<T> returnVal) {
|
||||||
|
for (HttpRequestFilter filter : returnVal.getFilters())
|
||||||
|
filter.filter(returnVal);
|
||||||
|
HttpRequest toReturn = new HttpRequest(returnVal.getMethod(), returnVal.getEndpoint(), ImmutableMultimap
|
||||||
|
.copyOf(returnVal.getHeaders()));
|
||||||
|
if (returnVal.getPayload() != null)
|
||||||
|
toReturn.setPayload(returnVal.getPayload());
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static final ExceptionToValueOrPropagate keyNotFoundToNullOrPropagate = new ExceptionToValueOrPropagate(
|
public static final ExceptionToValueOrPropagate keyNotFoundToNullOrPropagate = new ExceptionToValueOrPropagate(
|
||||||
|
@ -131,8 +144,7 @@ public class BlobStoreUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void createParentIfNeededAsync(AsyncBlobStore asyncBlobStore, String container,
|
public static void createParentIfNeededAsync(AsyncBlobStore asyncBlobStore, String container, Blob blob) {
|
||||||
Blob blob) {
|
|
||||||
String name = blob.getMetadata().getName();
|
String name = blob.getMetadata().getName();
|
||||||
if (name.indexOf('/') > 0) {
|
if (name.indexOf('/') > 0) {
|
||||||
asyncBlobStore.createDirectory(container, parseDirectoryFromPath(name));
|
asyncBlobStore.createDirectory(container, parseDirectoryFromPath(name));
|
||||||
|
|
|
@ -28,8 +28,6 @@ import java.net.URLConnection;
|
||||||
|
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
import org.jclouds.crypto.CryptoStreams;
|
import org.jclouds.crypto.CryptoStreams;
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.util.Utils;
|
|
||||||
import org.testng.annotations.Optional;
|
import org.testng.annotations.Optional;
|
||||||
import org.testng.annotations.Parameters;
|
import org.testng.annotations.Parameters;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -76,26 +74,4 @@ public class BaseBlobLiveTest extends BaseBlobStoreIntegrationTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSignUrl() throws Exception {
|
|
||||||
String name = "hello";
|
|
||||||
String text = "fooooooooooooooooooooooo";
|
|
||||||
|
|
||||||
Blob blob = context.getBlobStore().newBlob(name);
|
|
||||||
blob.setPayload(text);
|
|
||||||
blob.getPayload().setContentType("text/plain");
|
|
||||||
String container = getContainerName();
|
|
||||||
try {
|
|
||||||
context.getBlobStore().putBlob(container, blob);
|
|
||||||
HttpRequest request = context.getBlobStore().signRequestForBlob(container, name);
|
|
||||||
assertEquals(request.getFilters().size(), 0);
|
|
||||||
assertEquals(Utils.toStringAndClose(context.utils().http().get(request)), text);
|
|
||||||
request = context.getAsyncBlobStore().signRequestForBlob(container, name);
|
|
||||||
assertEquals(request.getFilters().size(), 0);
|
|
||||||
assertEquals(Utils.toStringAndClose(context.utils().http().get(request)), text);
|
|
||||||
} finally {
|
|
||||||
returnContainer(container);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.blobstore.integration.internal;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.util.Utils;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests integrated functionality of all signature commands.
|
||||||
|
* <p/>
|
||||||
|
* Each test uses a different container name, so it should be perfectly fine to run in parallel.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = { "live" }, testName = "blobstore.BlobLiveTest")
|
||||||
|
public class BaseBlobSignerLiveTest extends BaseBlobStoreIntegrationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSignRemoveUrl() throws Exception {
|
||||||
|
String name = "hello";
|
||||||
|
String text = "fooooooooooooooooooooooo";
|
||||||
|
|
||||||
|
Blob blob = context.getBlobStore().newBlob(name);
|
||||||
|
blob.setPayload(text);
|
||||||
|
blob.getPayload().setContentType("text/plain");
|
||||||
|
String container = getContainerName();
|
||||||
|
try {
|
||||||
|
context.getBlobStore().putBlob(container, blob);
|
||||||
|
HttpRequest request = context.getSigner().signRemoveBlob(container, name);
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
context.utils().http().invoke(request);
|
||||||
|
assert !context.getBlobStore().blobExists(container, name);
|
||||||
|
} finally {
|
||||||
|
returnContainer(container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSignGetUrl() throws Exception {
|
||||||
|
String name = "hello";
|
||||||
|
String text = "fooooooooooooooooooooooo";
|
||||||
|
|
||||||
|
Blob blob = context.getBlobStore().newBlob(name);
|
||||||
|
blob.setPayload(text);
|
||||||
|
blob.getPayload().setContentType("text/plain");
|
||||||
|
String container = getContainerName();
|
||||||
|
try {
|
||||||
|
context.getBlobStore().putBlob(container, blob);
|
||||||
|
HttpRequest request = context.getSigner().signGetBlob(container, name);
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
assertEquals(Utils.toStringAndClose(context.utils().http().invoke(request)), text);
|
||||||
|
} finally {
|
||||||
|
returnContainer(container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSignPutUrl() throws Exception {
|
||||||
|
String name = "hello";
|
||||||
|
String text = "fooooooooooooooooooooooo";
|
||||||
|
|
||||||
|
Blob blob = context.getBlobStore().newBlob(name);
|
||||||
|
blob.setPayload(text);
|
||||||
|
blob.getPayload().setContentType("text/plain");
|
||||||
|
String container = getContainerName();
|
||||||
|
try {
|
||||||
|
HttpRequest request = context.getSigner().signPutBlob(container, blob);
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
Utils.toStringAndClose(context.utils().http().invoke(request));
|
||||||
|
assert context.getBlobStore().blobExists(container, name);
|
||||||
|
} finally {
|
||||||
|
returnContainer(container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -36,6 +36,6 @@ import com.google.common.base.Function;
|
||||||
public class ReturnInputStream implements Function<HttpResponse, InputStream> {
|
public class ReturnInputStream implements Function<HttpResponse, InputStream> {
|
||||||
|
|
||||||
public InputStream apply(HttpResponse from) {
|
public InputStream apply(HttpResponse from) {
|
||||||
return from.getPayload().getInput();
|
return from.getPayload() != null ? from.getPayload().getInput() : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.io.payloads;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class PhantomPayload extends BasePayload<Object> {
|
||||||
|
|
||||||
|
public PhantomPayload(@Nullable Long contentLength, @Nullable byte[] contentMD5) {
|
||||||
|
super(Object.class, null, contentLength, contentMD5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public InputStream getInput() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(OutputStream outstream) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -92,8 +92,9 @@ public interface HttpAsyncClient {
|
||||||
/**
|
/**
|
||||||
* @see HttpClient#get
|
* @see HttpClient#get
|
||||||
*/
|
*/
|
||||||
|
@Path("")
|
||||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
ListenableFuture<InputStream> get(HttpRequest location);
|
ListenableFuture<InputStream> invoke(HttpRequest location);
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("")
|
@Path("")
|
||||||
|
|
|
@ -63,10 +63,7 @@ public interface HttpClient {
|
||||||
*/
|
*/
|
||||||
InputStream get(URI location);
|
InputStream get(URI location);
|
||||||
|
|
||||||
/**
|
InputStream invoke(HttpRequest location);
|
||||||
* @return null if the resource didn't exist.
|
|
||||||
*/
|
|
||||||
InputStream get(HttpRequest location);
|
|
||||||
|
|
||||||
InputStream get(URI location, HttpRequestOptions options);
|
InputStream get(URI location, HttpRequestOptions options);
|
||||||
|
|
||||||
|
|
|
@ -84,23 +84,29 @@ public abstract class BaseRestClientTest {
|
||||||
propagate(e);
|
propagate(e);
|
||||||
}
|
}
|
||||||
assertEquals(payload, toMatch);
|
assertEquals(payload, toMatch);
|
||||||
if (request.getFirstHeaderOrNull(TRANSFER_ENCODING) == null) {
|
Long length = new Long(payload.getBytes().length);
|
||||||
assertEquals(request.getPayload().getContentLength(), new Long(payload.getBytes().length));
|
|
||||||
} else {
|
|
||||||
assertEquals(request.getFirstHeaderOrNull(TRANSFER_ENCODING), "chunked");
|
|
||||||
assert request.getPayload().getContentLength() == null
|
|
||||||
|| request.getPayload().getContentLength().equals(new Long(payload.getBytes().length));
|
|
||||||
}
|
|
||||||
assertEquals(request.getPayload().getContentType(), contentType);
|
|
||||||
try {
|
try {
|
||||||
assertEquals(request.getPayload().getContentMD5(), contentMD5 ? CryptoStreams.md5(request.getPayload())
|
assertContentHeadersEqual(request, contentType, length, contentMD5 ? CryptoStreams
|
||||||
: null);
|
.md5(request.getPayload()) : null);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
propagate(e);
|
propagate(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void assertContentHeadersEqual(HttpRequest request, String contentType, Long length, byte[] contentMD5) {
|
||||||
|
if (request.getFirstHeaderOrNull(TRANSFER_ENCODING) == null) {
|
||||||
|
assertEquals(request.getPayload().getContentLength(), length);
|
||||||
|
} else {
|
||||||
|
assertEquals(request.getFirstHeaderOrNull(TRANSFER_ENCODING), "chunked");
|
||||||
|
assert request.getPayload().getContentLength() == null
|
||||||
|
|| request.getPayload().getContentLength().equals(length);
|
||||||
|
}
|
||||||
|
assertEquals(request.getPayload().getContentType(), contentType);
|
||||||
|
assertEquals(request.getPayload().getContentMD5(), contentMD5);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
protected void assertNonPayloadHeadersEqual(HttpRequest request, String toMatch) {
|
protected void assertNonPayloadHeadersEqual(HttpRequest request, String toMatch) {
|
||||||
assertEquals(sortAndConcatHeadersIntoString(request.getHeaders()), toMatch);
|
assertEquals(sortAndConcatHeadersIntoString(request.getHeaders()), toMatch);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@ import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||||
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.concurrent.Futures;
|
import org.jclouds.concurrent.Futures;
|
||||||
|
@ -89,8 +88,8 @@ public class CloudFilesAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
|
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
|
||||||
ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob, BlobToObject blob2Object,
|
ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob, BlobToObject blob2Object,
|
||||||
ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions,
|
ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions,
|
||||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider, SignRequestForBlobStrategy signRequestForBlob) {
|
Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
||||||
super(context, blobUtils, service, defaultLocation, locations, signRequestForBlob);
|
super(context, blobUtils, service, defaultLocation, locations);
|
||||||
this.sync = sync;
|
this.sync = sync;
|
||||||
this.async = async;
|
this.async = async;
|
||||||
this.container2ResourceMd = container2ResourceMd;
|
this.container2ResourceMd = container2ResourceMd;
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.rackspace.cloudfiles.blobstore;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.blobstore.util.BlobStoreUtils.cleanRequest;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.options.GetOptions;
|
||||||
|
import org.jclouds.rackspace.cloudfiles.CloudFilesAsyncClient;
|
||||||
|
import org.jclouds.rackspace.cloudfiles.blobstore.functions.BlobToObject;
|
||||||
|
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
|
||||||
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class CloudFilesBlobRequestSigner implements BlobRequestSigner {
|
||||||
|
private final RestAnnotationProcessor<CloudFilesAsyncClient> processor;
|
||||||
|
private final BlobToObject blobToObject;
|
||||||
|
private final Method getMethod;
|
||||||
|
private final Method deleteMethod;
|
||||||
|
private final Method createMethod;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CloudFilesBlobRequestSigner(RestAnnotationProcessor<CloudFilesAsyncClient> processor, BlobToObject blobToObject)
|
||||||
|
throws SecurityException, NoSuchMethodException {
|
||||||
|
this.processor = checkNotNull(processor, "processor");
|
||||||
|
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
|
||||||
|
this.getMethod = CloudFilesAsyncClient.class.getMethod("getObject", String.class, String.class, GetOptions[].class);
|
||||||
|
this.deleteMethod = CloudFilesAsyncClient.class.getMethod("removeObject", String.class, String.class);
|
||||||
|
this.createMethod = CloudFilesAsyncClient.class.getMethod("putObject", String.class, CFObject.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signGetBlob(String container, String name) {
|
||||||
|
return cleanRequest(processor.createRequest(getMethod, container, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signPutBlob(String container, Blob blob) {
|
||||||
|
return cleanRequest(processor.createRequest(createMethod, container, blobToObject.apply(blob)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signRemoveBlob(String container, String name) {
|
||||||
|
return cleanRequest(processor.createRequest(deleteMethod, container, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -37,7 +37,6 @@ import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||||
import org.jclouds.blobstore.internal.BaseBlobStore;
|
import org.jclouds.blobstore.internal.BaseBlobStore;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
|
@ -78,8 +77,8 @@ public class CloudFilesBlobStore extends BaseBlobStore {
|
||||||
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
|
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
|
||||||
ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob, BlobToObject blob2Object,
|
ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob, BlobToObject blob2Object,
|
||||||
ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions,
|
ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions,
|
||||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider, SignRequestForBlobStrategy signRequestForBlob) {
|
Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
||||||
super(context, blobUtils, defaultLocation, locations, signRequestForBlob);
|
super(context, blobUtils, defaultLocation, locations);
|
||||||
this.sync = sync;
|
this.sync = sync;
|
||||||
this.container2ResourceMd = container2ResourceMd;
|
this.container2ResourceMd = container2ResourceMd;
|
||||||
this.container2ContainerListOptions = container2ContainerListOptions;
|
this.container2ContainerListOptions = container2ContainerListOptions;
|
||||||
|
|
|
@ -24,18 +24,18 @@ import java.util.Set;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.blobstore.AsyncBlobStore;
|
import org.jclouds.blobstore.AsyncBlobStore;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
import org.jclouds.blobstore.BlobStore;
|
import org.jclouds.blobstore.BlobStore;
|
||||||
import org.jclouds.blobstore.BlobStoreContext;
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||||
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
||||||
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.rackspace.cloudfiles.CloudFilesAsyncClient;
|
import org.jclouds.rackspace.cloudfiles.CloudFilesAsyncClient;
|
||||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||||
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesAsyncBlobStore;
|
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesAsyncBlobStore;
|
||||||
|
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobRequestSigner;
|
||||||
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStore;
|
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStore;
|
||||||
import org.jclouds.rackspace.cloudfiles.blobstore.strategy.SignGetObject;
|
|
||||||
import org.jclouds.rackspace.config.RackspaceLocationsModule;
|
import org.jclouds.rackspace.config.RackspaceLocationsModule;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
@ -63,7 +63,7 @@ public class CloudFilesBlobStoreContextModule extends AbstractModule {
|
||||||
bind(BlobStore.class).to(CloudFilesBlobStore.class).in(Scopes.SINGLETON);
|
bind(BlobStore.class).to(CloudFilesBlobStore.class).in(Scopes.SINGLETON);
|
||||||
bind(BlobStoreContext.class).to(new TypeLiteral<BlobStoreContextImpl<CloudFilesClient, CloudFilesAsyncClient>>() {
|
bind(BlobStoreContext.class).to(new TypeLiteral<BlobStoreContextImpl<CloudFilesClient, CloudFilesAsyncClient>>() {
|
||||||
}).in(Scopes.SINGLETON);
|
}).in(Scopes.SINGLETON);
|
||||||
bind(SignRequestForBlobStrategy.class).to(SignGetObject.class);
|
bind(BlobRequestSigner.class).to(CloudFilesBlobRequestSigner.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 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.rackspace.cloudfiles.blobstore.strategy;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.http.HttpRequestFilter;
|
|
||||||
import org.jclouds.http.options.GetOptions;
|
|
||||||
import org.jclouds.rackspace.cloudfiles.CloudFilesAsyncClient;
|
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
@Singleton
|
|
||||||
public class SignGetObject implements SignRequestForBlobStrategy {
|
|
||||||
private final RestAnnotationProcessor<CloudFilesAsyncClient> processor;
|
|
||||||
private final Method method;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public SignGetObject(RestAnnotationProcessor<CloudFilesAsyncClient> processor) throws SecurityException,
|
|
||||||
NoSuchMethodException {
|
|
||||||
this.processor = checkNotNull(processor, "processor");
|
|
||||||
this.method = CloudFilesAsyncClient.class.getMethod("getObject", String.class, String.class, GetOptions[].class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpRequest apply(String container, String name) {
|
|
||||||
HttpRequest returnVal = processor.createRequest(method, checkNotNull(container,
|
|
||||||
"container"), checkNotNull(name, "name"));
|
|
||||||
for (HttpRequestFilter filter : returnVal.getFilters())
|
|
||||||
filter.filter(returnVal);
|
|
||||||
returnVal.getFilters().clear();
|
|
||||||
return new HttpRequest(returnVal.getMethod(), returnVal.getEndpoint(), ImmutableMultimap.copyOf(returnVal.getHeaders()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.rackspace.cloudfiles.blobstore;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.domain.Blob.Factory;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.io.payloads.PhantomPayload;
|
||||||
|
import org.jclouds.rackspace.cloudfiles.CloudFilesAsyncClient;
|
||||||
|
import org.jclouds.rackspace.cloudfiles.config.CloudFilesRestClientModule;
|
||||||
|
import org.jclouds.rackspace.cloudservers.TestRackspaceAuthenticationRestClientModule;
|
||||||
|
import org.jclouds.rest.RestClientTest;
|
||||||
|
import org.jclouds.rest.RestContextFactory;
|
||||||
|
import org.jclouds.rest.RestContextFactory.ContextSpec;
|
||||||
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
@Test(groups = "unit", testName = "cloudfiles.CloudFilesBlobRequestSignerTest")
|
||||||
|
public class CloudFilesBlobRequestSignerTest extends RestClientTest<CloudFilesAsyncClient> {
|
||||||
|
|
||||||
|
private BlobRequestSigner signer;
|
||||||
|
private Factory blobFactory;
|
||||||
|
|
||||||
|
public void testSignGetBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
HttpRequest request = signer.signGetBlob("container", "name");
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "GET http://storageUrl/container/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "X-Auth-Token: testtoken\n");
|
||||||
|
assertPayloadEquals(request, null, null, false);
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSignRemoveBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
HttpRequest request = signer.signRemoveBlob("container", "name");
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "DELETE http://storageUrl/container/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "X-Auth-Token: testtoken\n");
|
||||||
|
assertPayloadEquals(request, null, null, false);
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSignPutBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
Blob blob = blobFactory.create(null);
|
||||||
|
blob.getMetadata().setName("name");
|
||||||
|
blob.setPayload(new PhantomPayload(2l, new byte[] { 0, 2, 4, 8 }));
|
||||||
|
blob.getPayload().setContentType("text/plain");
|
||||||
|
|
||||||
|
HttpRequest request = signer.signPutBlob("container", blob);
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "PUT http://storageUrl/container/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "X-Auth-Token: testtoken\n");
|
||||||
|
assertContentHeadersEqual(request, "text/plain", (long) 2l, new byte[] { 0, 2, 4, 8 });
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
protected void setupFactory() throws IOException {
|
||||||
|
super.setupFactory();
|
||||||
|
this.blobFactory = injector.getInstance(Blob.Factory.class);
|
||||||
|
this.signer = injector.getInstance(BlobRequestSigner.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void checkFilters(HttpRequest request) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TypeLiteral<RestAnnotationProcessor<CloudFilesAsyncClient>> createTypeLiteral() {
|
||||||
|
return new TypeLiteral<RestAnnotationProcessor<CloudFilesAsyncClient>>() {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Module createModule() {
|
||||||
|
return new CloudFilesRestClientModule(new TestRackspaceAuthenticationRestClientModule());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContextSpec<?, ?> createContextSpec() {
|
||||||
|
return new RestContextFactory().createContextSpec("cloudfiles", "identity", "credential", new Properties());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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.rackspace.cloudfiles.blobstore.integration;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.integration.internal.BaseBlobSignerLiveTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = { "live" }, testName = "cloudfiles.CloudFilesBlobSignerLiveTest")
|
||||||
|
public class CloudFilesBlobSignerLiveTest extends BaseBlobSignerLiveTest {
|
||||||
|
|
||||||
|
}
|
|
@ -1,60 +0,0 @@
|
||||||
package org.jclouds.rackspace.cloudfiles.blobstore.strategy;
|
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.rackspace.cloudfiles.CloudFilesAsyncClient;
|
|
||||||
import org.jclouds.rackspace.cloudfiles.config.CloudFilesRestClientModule;
|
|
||||||
import org.jclouds.rackspace.cloudservers.TestRackspaceAuthenticationRestClientModule;
|
|
||||||
import org.jclouds.rest.RestClientTest;
|
|
||||||
import org.jclouds.rest.RestContextFactory;
|
|
||||||
import org.jclouds.rest.RestContextFactory.ContextSpec;
|
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
import com.google.inject.Module;
|
|
||||||
import com.google.inject.TypeLiteral;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests behavior of {@code SignGetBlob}
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
@Test(groups = "unit", testName = "cloudfiles.SignGetBlobTest")
|
|
||||||
public class SignGetBlobTest extends RestClientTest<CloudFilesAsyncClient> {
|
|
||||||
|
|
||||||
public void testSignGetBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
|
||||||
NoSuchMethodException, IOException {
|
|
||||||
HttpRequest request = new SignGetObject(processor).apply("container", "blob");
|
|
||||||
|
|
||||||
assertRequestLineEquals(request, "GET http://storageUrl/container/blob HTTP/1.1");
|
|
||||||
assertNonPayloadHeadersEqual(request, "X-Auth-Token: testtoken\n");
|
|
||||||
assertPayloadEquals(request, null, null, false);
|
|
||||||
|
|
||||||
assertEquals(request.getFilters().size(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Module createModule() {
|
|
||||||
return new CloudFilesRestClientModule(new TestRackspaceAuthenticationRestClientModule());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void checkFilters(HttpRequest request) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TypeLiteral<RestAnnotationProcessor<CloudFilesAsyncClient>> createTypeLiteral() {
|
|
||||||
return new TypeLiteral<RestAnnotationProcessor<CloudFilesAsyncClient>>() {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ContextSpec<?, ?> createContextSpec() {
|
|
||||||
return new RestContextFactory().createContextSpec("cloudfiles", "identity", "credential", new Properties());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue