From f068a06354272521a6dfa80f276e12261a8c3437 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Mon, 13 Sep 2010 18:24:16 -0700 Subject: [PATCH] Issue 352: refactored request signing --- .../saas/blobstore/AtmosAsyncBlobStore.java | 6 +- .../blobstore/AtmosBlobRequestSigner.java | 81 ++++++++++ .../saas/blobstore/AtmosBlobStore.java | 6 +- .../config/AtmosBlobStoreContextModule.java | 6 +- .../saas/blobstore/strategy/SignReadFile.java | 66 --------- ...t.java => AtmosBlobRequestSignerTest.java} | 60 +++++++- .../integration/AtmosBlobSignerLiveTest.java | 14 +- .../AtmosStorageTestInitializer.java | 2 +- .../aws/s3/blobstore/S3AsyncBlobStore.java | 5 +- .../aws/s3/blobstore/S3BlobRequestSigner.java | 79 ++++++++++ .../jclouds/aws/s3/blobstore/S3BlobStore.java | 5 +- .../config/S3BlobStoreContextModule.java | 6 +- .../s3/blobstore/strategy/SignGetObject.java | 65 -------- ...teAndBlobStoreTogetherHappilyLiveTest.java | 2 +- .../s3/blobstore/S3BlobRequestSignerTest.java | 140 ++++++++++++++++++ .../integration/S3BlobSignerLiveTest.java | 17 +-- .../blobstore/strategy/SignGetObjectTest.java | 76 ---------- .../blob/blobstore/AzureAsyncBlobStore.java | 5 +- .../blobstore/AzureBlobRequestSigner.java | 77 ++++++++++ .../blob/blobstore/AzureBlobStore.java | 5 +- .../config/AzureBlobStoreContextModule.java | 6 +- .../blob/blobstore/strategy/SignGetBlob.java | 64 -------- .../AzureBlobBlobRequestSignerTest.java | 139 +++++++++++++++++ .../blobstore/config/SignGetBlobTest.java | 102 ------------- .../integration/AzureBlobSignerLiveTest.java | 32 ++++ .../main/clojure/org/jclouds/blobstore.clj | 28 +++- .../org/jclouds/blobstore/AsyncBlobStore.java | 9 +- .../jclouds/blobstore/BlobRequestSigner.java | 83 +++++++++++ .../java/org/jclouds/blobstore/BlobStore.java | 14 -- .../jclouds/blobstore/BlobStoreContext.java | 6 + .../blobstore/TransientAsyncBlobStore.java | 5 +- .../internal/BaseAsyncBlobStore.java | 11 +- .../blobstore/internal/BaseBlobStore.java | 10 +- .../internal/BlobStoreContextImpl.java | 19 ++- .../internal/RequestSigningUnsupported.java | 50 +++++++ .../blobstore/util/BlobStoreUtils.java | 16 +- .../internal/BaseBlobLiveTest.java | 24 --- .../internal/BaseBlobSignerLiveTest.java | 97 ++++++++++++ .../http/functions/ReturnInputStream.java | 2 +- .../jclouds/io/payloads/PhantomPayload.java | 50 +++++++ .../org/jclouds/rest/HttpAsyncClient.java | 3 +- .../java/org/jclouds/rest/HttpClient.java | 5 +- .../org/jclouds/rest/BaseRestClientTest.java | 26 ++-- .../blobstore/CloudFilesAsyncBlobStore.java | 5 +- .../CloudFilesBlobRequestSigner.java | 77 ++++++++++ .../blobstore/CloudFilesBlobStore.java | 5 +- .../CloudFilesBlobStoreContextModule.java | 6 +- .../blobstore/strategy/SignGetObject.java | 64 -------- .../CloudFilesBlobRequestSignerTest.java | 116 +++++++++++++++ .../CloudFilesBlobSignerLiveTest.java | 32 ++++ .../blobstore/strategy/SignGetBlobTest.java | 60 -------- 51 files changed, 1234 insertions(+), 655 deletions(-) create mode 100644 atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobRequestSigner.java delete mode 100644 atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/strategy/SignReadFile.java rename atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/{integration/SignReadFileTest.java => AtmosBlobRequestSignerTest.java} (55%) rename blobstore/src/main/java/org/jclouds/blobstore/strategy/SignRequestForBlobStrategy.java => atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosBlobSignerLiveTest.java (70%) create mode 100644 aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3BlobRequestSigner.java delete mode 100644 aws/core/src/main/java/org/jclouds/aws/s3/blobstore/strategy/SignGetObject.java create mode 100644 aws/core/src/test/java/org/jclouds/aws/s3/blobstore/S3BlobRequestSignerTest.java rename blobstore/src/main/java/org/jclouds/blobstore/strategy/internal/SignRequestForBlobUnsupported.java => aws/core/src/test/java/org/jclouds/aws/s3/blobstore/integration/S3BlobSignerLiveTest.java (66%) delete mode 100644 aws/core/src/test/java/org/jclouds/aws/s3/blobstore/strategy/SignGetObjectTest.java create mode 100644 azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobRequestSigner.java delete mode 100644 azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/strategy/SignGetBlob.java create mode 100644 azure/src/test/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobBlobRequestSignerTest.java delete mode 100644 azure/src/test/java/org/jclouds/azure/storage/blob/blobstore/config/SignGetBlobTest.java create mode 100644 azure/src/test/java/org/jclouds/azure/storage/blob/blobstore/integration/AzureBlobSignerLiveTest.java create mode 100644 blobstore/src/main/java/org/jclouds/blobstore/BlobRequestSigner.java create mode 100644 blobstore/src/main/java/org/jclouds/blobstore/internal/RequestSigningUnsupported.java create mode 100644 blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobSignerLiveTest.java create mode 100644 core/src/main/java/org/jclouds/io/payloads/PhantomPayload.java create mode 100644 rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobRequestSigner.java delete mode 100644 rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/strategy/SignGetObject.java create mode 100644 rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobRequestSignerTest.java create mode 100644 rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobSignerLiveTest.java delete mode 100644 rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/strategy/SignGetBlobTest.java diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosAsyncBlobStore.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosAsyncBlobStore.java index d775dc939b..e314ecf9f8 100644 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosAsyncBlobStore.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosAsyncBlobStore.java @@ -51,7 +51,6 @@ import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.functions.BlobToHttpGetOptions; import org.jclouds.blobstore.internal.BaseAsyncBlobStore; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.concurrent.Futures; @@ -86,9 +85,8 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore { ObjectToBlob object2Blob, ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object, BlobStoreListOptionsToListOptions container2ContainerListOptions, DirectoryEntryListToResourceMetadataList container2ResourceList, Crypto crypto, - BlobToHttpGetOptions blob2ObjectGetOptions, Provider fetchBlobMetadataProvider, - SignRequestForBlobStrategy signRequestForBlob) { - super(context, blobUtils, service, defaultLocation, locations, signRequestForBlob); + BlobToHttpGetOptions blob2ObjectGetOptions, Provider fetchBlobMetadataProvider) { + super(context, blobUtils, service, defaultLocation, locations); this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions"); this.sync = checkNotNull(sync, "sync"); this.async = checkNotNull(async, "async"); diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobRequestSigner.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobRequestSigner.java new file mode 100644 index 0000000000..ddbdfbc48a --- /dev/null +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobRequestSigner.java @@ -0,0 +1,81 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 processor; + private final BlobToObject blobToObject; + private final Method getMethod; + private final Method deleteMethod; + private final Method createMethod; + + @Inject + public AtmosBlobRequestSigner(RestAnnotationProcessor 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"); + } + +} \ No newline at end of file diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobStore.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobStore.java index 9d8d68ba9e..73c29b4568 100644 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobStore.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobStore.java @@ -43,7 +43,6 @@ import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.functions.BlobToHttpGetOptions; import org.jclouds.blobstore.internal.BaseBlobStore; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.crypto.Crypto; @@ -73,9 +72,8 @@ public class AtmosBlobStore extends BaseBlobStore { ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object, BlobStoreListOptionsToListOptions container2ContainerListOptions, DirectoryEntryListToResourceMetadataList container2ResourceList, Crypto crypto, - BlobToHttpGetOptions blob2ObjectGetOptions, Provider fetchBlobMetadataProvider, - SignRequestForBlobStrategy signRequestForBlob) { - super(context, blobUtils, defaultLocation, locations, signRequestForBlob); + BlobToHttpGetOptions blob2ObjectGetOptions, Provider fetchBlobMetadataProvider) { + super(context, blobUtils, defaultLocation, locations); this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions"); this.sync = checkNotNull(sync, "sync"); this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions, diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/config/AtmosBlobStoreContextModule.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/config/AtmosBlobStoreContextModule.java index fb68a68356..8183cdadd0 100755 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/config/AtmosBlobStoreContextModule.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/config/AtmosBlobStoreContextModule.java @@ -26,17 +26,17 @@ import javax.inject.Singleton; import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient; import org.jclouds.atmosonline.saas.AtmosStorageClient; 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.strategy.FindMD5InUserMetadata; -import org.jclouds.atmosonline.saas.blobstore.strategy.SignReadFile; import org.jclouds.blobstore.AsyncBlobStore; +import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.attr.ConsistencyModel; import org.jclouds.blobstore.config.BlobStoreMapModule; import org.jclouds.blobstore.internal.BlobStoreContextImpl; import org.jclouds.blobstore.strategy.ContainsValueInListStrategy; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.domain.Location; import org.jclouds.domain.LocationScope; import org.jclouds.domain.internal.LocationImpl; @@ -67,7 +67,7 @@ public class AtmosBlobStoreContextModule extends AbstractModule { new TypeLiteral>() { }).in(Scopes.SINGLETON); bind(ContainsValueInListStrategy.class).to(FindMD5InUserMetadata.class); - bind(SignRequestForBlobStrategy.class).to(SignReadFile.class); + bind(BlobRequestSigner.class).to(AtmosBlobRequestSigner.class); } @Provides diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/strategy/SignReadFile.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/strategy/SignReadFile.java deleted file mode 100644 index b212719f55..0000000000 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/blobstore/strategy/SignReadFile.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * - * Copyright (C) 2010 Cloud Conscious, LLC. - * - * ==================================================================== - * 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 processor; - private final Method method; - - @Inject - public SignReadFile(RestAnnotationProcessor 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 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())); - } - -} \ No newline at end of file diff --git a/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/SignReadFileTest.java b/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobRequestSignerTest.java similarity index 55% rename from atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/SignReadFileTest.java rename to atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobRequestSignerTest.java index c33c4bc7ff..e5d2c1e8a0 100644 --- a/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/SignReadFileTest.java +++ b/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/AtmosBlobRequestSignerTest.java @@ -17,7 +17,7 @@ * ==================================================================== */ -package org.jclouds.atmosonline.saas.blobstore.integration; +package org.jclouds.atmosonline.saas.blobstore; import static org.testng.Assert.assertEquals; @@ -25,29 +25,36 @@ import java.io.IOException; import java.util.Properties; 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.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.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 = "emcsaas.SignReadFileTest") -public class SignReadFileTest extends RestClientTest { +@Test(groups = "unit", testName = "emcsaas.AtmosBlobRequestSignerTest") +public class AtmosBlobRequestSignerTest extends RestClientTest { - public void testSignReadFile() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException, + private BlobRequestSigner signer; + private Factory blobFactory; + + public void testSignGetBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException, 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"); assertNonPayloadHeadersEqual( @@ -58,6 +65,47 @@ public class SignReadFileTest extends RestClientTest { 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 protected void checkFilters(HttpRequest request) { assertEquals(request.getFilters().size(), 1); diff --git a/blobstore/src/main/java/org/jclouds/blobstore/strategy/SignRequestForBlobStrategy.java b/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosBlobSignerLiveTest.java similarity index 70% rename from blobstore/src/main/java/org/jclouds/blobstore/strategy/SignRequestForBlobStrategy.java rename to atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosBlobSignerLiveTest.java index 88d8cadbb6..44867392a4 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/strategy/SignRequestForBlobStrategy.java +++ b/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosBlobSignerLiveTest.java @@ -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.http.HttpRequest; - -import com.google.inject.ImplementedBy; +import org.jclouds.blobstore.integration.internal.BaseBlobSignerLiveTest; +import org.testng.annotations.Test; /** * * @author Adrian Cole */ -@ImplementedBy(SignRequestForBlobUnsupported.class) -public interface SignRequestForBlobStrategy { - HttpRequest apply(String container, String name); +@Test(groups = { "live" }, testName = "emcsaas.AtmosBlobSignerLiveTest") +public class AtmosBlobSignerLiveTest extends BaseBlobSignerLiveTest { + } \ No newline at end of file diff --git a/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosStorageTestInitializer.java b/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosStorageTestInitializer.java index 0c370d4402..e71b4899fe 100644 --- a/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosStorageTestInitializer.java +++ b/atmos/src/test/java/org/jclouds/atmosonline/saas/blobstore/integration/AtmosStorageTestInitializer.java @@ -39,7 +39,7 @@ public class AtmosStorageTestInitializer extends TransientBlobStoreTestInitializ @Override protected BlobStoreContext createLiveContext(Module configurationModule, String url, String app, 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()); } diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3AsyncBlobStore.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3AsyncBlobStore.java index 6345214575..066657a7d5 100644 --- a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3AsyncBlobStore.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3AsyncBlobStore.java @@ -53,7 +53,6 @@ import org.jclouds.blobstore.domain.internal.PageSetImpl; import org.jclouds.blobstore.functions.BlobToHttpGetOptions; import org.jclouds.blobstore.internal.BaseAsyncBlobStore; import org.jclouds.blobstore.options.ListContainerOptions; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.concurrent.Futures; @@ -90,8 +89,8 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore { BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions, BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob, BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd, - Provider fetchBlobMetadataProvider, SignRequestForBlobStrategy signRequestForBlob) { - super(context, blobUtils, service, defaultLocation, locations, signRequestForBlob); + Provider fetchBlobMetadataProvider) { + super(context, blobUtils, service, defaultLocation, locations); this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions"); this.async = checkNotNull(async, "async"); this.sync = checkNotNull(sync, "sync"); diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3BlobRequestSigner.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3BlobRequestSigner.java new file mode 100644 index 0000000000..655ad1c76c --- /dev/null +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3BlobRequestSigner.java @@ -0,0 +1,79 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 processor; + private final BlobToObject blobToObject; + private final Method getMethod; + private final Method deleteMethod; + private final Method createMethod; + + @Inject + public S3BlobRequestSigner(RestAnnotationProcessor 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)); + } + +} \ No newline at end of file diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3BlobStore.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3BlobStore.java index c0cd063e68..930e9b47b8 100644 --- a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3BlobStore.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/S3BlobStore.java @@ -47,7 +47,6 @@ import org.jclouds.blobstore.domain.internal.PageSetImpl; import org.jclouds.blobstore.functions.BlobToHttpGetOptions; import org.jclouds.blobstore.internal.BaseBlobStore; import org.jclouds.blobstore.options.ListContainerOptions; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.domain.Location; @@ -79,8 +78,8 @@ public class S3BlobStore extends BaseBlobStore { Supplier> locations, S3Client sync, BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions, BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob, BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, - ObjectToBlobMetadata object2BlobMd, Provider fetchBlobMetadataProvider, SignRequestForBlobStrategy signRequestForBlob) { - super(context, blobUtils, defaultLocation, locations, signRequestForBlob); + ObjectToBlobMetadata object2BlobMd, Provider fetchBlobMetadataProvider) { + super(context, blobUtils, defaultLocation, locations); this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions"); this.sync = checkNotNull(sync, "sync"); this.bucket2ResourceMd = checkNotNull(bucket2ResourceMd, "bucket2ResourceMd"); diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/config/S3BlobStoreContextModule.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/config/S3BlobStoreContextModule.java index f0ae94213c..076cf69b61 100755 --- a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/config/S3BlobStoreContextModule.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/config/S3BlobStoreContextModule.java @@ -27,16 +27,16 @@ import org.jclouds.aws.Region; import org.jclouds.aws.s3.S3AsyncClient; import org.jclouds.aws.s3.S3Client; 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.strategy.SignGetObject; import org.jclouds.aws.suppliers.DefaultLocationSupplier; import org.jclouds.blobstore.AsyncBlobStore; +import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.attr.ConsistencyModel; import org.jclouds.blobstore.config.BlobStoreMapModule; import org.jclouds.blobstore.internal.BlobStoreContextImpl; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.domain.Location; import org.jclouds.domain.LocationScope; 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(BlobStoreContext.class).to(new TypeLiteral>() { }).in(Scopes.SINGLETON); - bind(SignRequestForBlobStrategy.class).to(SignGetObject.class); + bind(BlobRequestSigner.class).to(S3BlobRequestSigner.class); } @Provides diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/strategy/SignGetObject.java b/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/strategy/SignGetObject.java deleted file mode 100644 index 88007a3d5d..0000000000 --- a/aws/core/src/main/java/org/jclouds/aws/s3/blobstore/strategy/SignGetObject.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * - * Copyright (C) 2010 Cloud Conscious, LLC. - * - * ==================================================================== - * 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 processor; - private final Method method; - - @Inject - public SignGetObject(RestAnnotationProcessor 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 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())); - } - -} \ No newline at end of file diff --git a/aws/core/src/test/java/org/jclouds/aws/ComputeAndBlobStoreTogetherHappilyLiveTest.java b/aws/core/src/test/java/org/jclouds/aws/ComputeAndBlobStoreTogetherHappilyLiveTest.java index 9d7b37602e..18f92a3160 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ComputeAndBlobStoreTogetherHappilyLiveTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ComputeAndBlobStoreTogetherHappilyLiveTest.java @@ -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 // 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 Statement installOpenJDK = execHttpResponse(signedRequestOfInstallScript); diff --git a/aws/core/src/test/java/org/jclouds/aws/s3/blobstore/S3BlobRequestSignerTest.java b/aws/core/src/test/java/org/jclouds/aws/s3/blobstore/S3BlobRequestSignerTest.java new file mode 100644 index 0000000000..81d3e082b1 --- /dev/null +++ b/aws/core/src/test/java/org/jclouds/aws/s3/blobstore/S3BlobRequestSignerTest.java @@ -0,0 +1,140 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + + 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> createTypeLiteral() { + return new TypeLiteral>() { + }; + } + + @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 cache) { + return "Thu, 05 Jun 2008 16:38:19 GMT"; + } + } + + @Override + public ContextSpec createContextSpec() { + return new RestContextFactory().createContextSpec("s3", "identity", "credential", new Properties()); + } + +} \ No newline at end of file diff --git a/blobstore/src/main/java/org/jclouds/blobstore/strategy/internal/SignRequestForBlobUnsupported.java b/aws/core/src/test/java/org/jclouds/aws/s3/blobstore/integration/S3BlobSignerLiveTest.java similarity index 66% rename from blobstore/src/main/java/org/jclouds/blobstore/strategy/internal/SignRequestForBlobUnsupported.java rename to aws/core/src/test/java/org/jclouds/aws/s3/blobstore/integration/S3BlobSignerLiveTest.java index 419fe0bc31..a42b1b4d41 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/strategy/internal/SignRequestForBlobUnsupported.java +++ b/aws/core/src/test/java/org/jclouds/aws/s3/blobstore/integration/S3BlobSignerLiveTest.java @@ -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.strategy.SignRequestForBlobStrategy; -import org.jclouds.http.HttpRequest; +import org.jclouds.blobstore.integration.internal.BaseBlobSignerLiveTest; +import org.testng.annotations.Test; /** * * @author Adrian Cole */ -@Singleton -public class SignRequestForBlobUnsupported implements SignRequestForBlobStrategy { - @Override - public HttpRequest apply(String container, String name) { - throw new UnsupportedOperationException(); - } +@Test(groups = { "live" }, testName = "s3.S3BlobSignerLiveTest") +public class S3BlobSignerLiveTest extends BaseBlobSignerLiveTest { + } \ No newline at end of file diff --git a/aws/core/src/test/java/org/jclouds/aws/s3/blobstore/strategy/SignGetObjectTest.java b/aws/core/src/test/java/org/jclouds/aws/s3/blobstore/strategy/SignGetObjectTest.java deleted file mode 100644 index d0544bb35f..0000000000 --- a/aws/core/src/test/java/org/jclouds/aws/s3/blobstore/strategy/SignGetObjectTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * - * Copyright (C) 2010 Cloud Conscious, LLC. - * - * ==================================================================== - * 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 cache) { - return "2009-11-08T15:54:08.897Z"; - } - } - - @Override - protected Module createModule() { - return new TestS3RestClientModule(); - } - -} \ No newline at end of file diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureAsyncBlobStore.java b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureAsyncBlobStore.java index 5adc4ff0b0..deff8df23d 100644 --- a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureAsyncBlobStore.java +++ b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureAsyncBlobStore.java @@ -52,7 +52,6 @@ import org.jclouds.blobstore.domain.internal.PageSetImpl; import org.jclouds.blobstore.functions.BlobToHttpGetOptions; import org.jclouds.blobstore.internal.BaseAsyncBlobStore; import org.jclouds.blobstore.options.ListContainerOptions; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.concurrent.Futures; import org.jclouds.domain.Location; @@ -85,8 +84,8 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore { ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions, ListBlobsResponseToResourceList azure2BlobStoreResourceList, AzureBlobToBlob azureBlob2Blob, BlobToAzureBlob blob2AzureBlob, BlobPropertiesToBlobMetadata blob2BlobMd, - BlobToHttpGetOptions blob2ObjectGetOptions, SignRequestForBlobStrategy signRequestForBlob) { - super(context, blobUtils, service, defaultLocation, locations, signRequestForBlob); + BlobToHttpGetOptions blob2ObjectGetOptions) { + super(context, blobUtils, service, defaultLocation, locations); this.async = checkNotNull(async, "async"); this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd"); this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions, diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobRequestSigner.java b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobRequestSigner.java new file mode 100644 index 0000000000..fd5f544976 --- /dev/null +++ b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobRequestSigner.java @@ -0,0 +1,77 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 processor; + private final BlobToAzureBlob blobToBlob; + private final Method getMethod; + private final Method deleteMethod; + private final Method createMethod; + + @Inject + public AzureBlobRequestSigner(RestAnnotationProcessor 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)); + } + +} \ No newline at end of file diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobStore.java b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobStore.java index 9b7e9f6803..f88ff553ad 100644 --- a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobStore.java +++ b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobStore.java @@ -46,7 +46,6 @@ import org.jclouds.blobstore.domain.internal.PageSetImpl; import org.jclouds.blobstore.functions.BlobToHttpGetOptions; import org.jclouds.blobstore.internal.BaseBlobStore; import org.jclouds.blobstore.options.ListContainerOptions; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.domain.Location; import org.jclouds.http.options.GetOptions; @@ -76,8 +75,8 @@ public class AzureBlobStore extends BaseBlobStore { ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions, ListBlobsResponseToResourceList azure2BlobStoreResourceList, AzureBlobToBlob azureBlob2Blob, BlobToAzureBlob blob2AzureBlob, BlobPropertiesToBlobMetadata blob2BlobMd, - BlobToHttpGetOptions blob2ObjectGetOptions, SignRequestForBlobStrategy signRequestForBlob) { - super(context, blobUtils, defaultLocation, locations, signRequestForBlob); + BlobToHttpGetOptions blob2ObjectGetOptions) { + super(context, blobUtils, defaultLocation, locations); this.sync = checkNotNull(sync, "sync"); this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd"); this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions, diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/config/AzureBlobStoreContextModule.java b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/config/AzureBlobStoreContextModule.java index 7cd23e5f2e..b2559f613d 100755 --- a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/config/AzureBlobStoreContextModule.java +++ b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/config/AzureBlobStoreContextModule.java @@ -26,17 +26,17 @@ import javax.inject.Singleton; import org.jclouds.azure.storage.blob.AzureBlobAsyncClient; import org.jclouds.azure.storage.blob.AzureBlobClient; 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.strategy.FindMD5InBlobProperties; -import org.jclouds.azure.storage.blob.blobstore.strategy.SignGetBlob; import org.jclouds.blobstore.AsyncBlobStore; +import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.attr.ConsistencyModel; import org.jclouds.blobstore.config.BlobStoreMapModule; import org.jclouds.blobstore.internal.BlobStoreContextImpl; import org.jclouds.blobstore.strategy.ContainsValueInListStrategy; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.domain.Location; import org.jclouds.domain.LocationScope; import org.jclouds.domain.internal.LocationImpl; @@ -66,7 +66,7 @@ public class AzureBlobStoreContextModule extends AbstractModule { bind(BlobStoreContext.class).to(new TypeLiteral>() { }).in(Scopes.SINGLETON); bind(ContainsValueInListStrategy.class).to(FindMD5InBlobProperties.class); - bind(SignRequestForBlobStrategy.class).to(SignGetBlob.class); + bind(BlobRequestSigner.class).to(AzureBlobRequestSigner.class); } @Provides diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/strategy/SignGetBlob.java b/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/strategy/SignGetBlob.java deleted file mode 100644 index 3c8ba6e30c..0000000000 --- a/azure/src/main/java/org/jclouds/azure/storage/blob/blobstore/strategy/SignGetBlob.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * - * Copyright (C) 2010 Cloud Conscious, LLC. - * - * ==================================================================== - * 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 processor; - private final Method method; - - @Inject - public SignGetBlob(RestAnnotationProcessor 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())); - } - -} \ No newline at end of file diff --git a/azure/src/test/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobBlobRequestSignerTest.java b/azure/src/test/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobBlobRequestSignerTest.java new file mode 100644 index 0000000000..dd74b0f5c5 --- /dev/null +++ b/azure/src/test/java/org/jclouds/azure/storage/blob/blobstore/AzureBlobBlobRequestSignerTest.java @@ -0,0 +1,139 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + + 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> createTypeLiteral() { + return new TypeLiteral>() { + }; + } + + @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 cache) { + return "Thu, 05 Jun 2008 16:38:19 GMT"; + } + } + + @Override + public ContextSpec createContextSpec() { + return new RestContextFactory().createContextSpec("azureblob", "identity", "credential", new Properties()); + } + +} \ No newline at end of file diff --git a/azure/src/test/java/org/jclouds/azure/storage/blob/blobstore/config/SignGetBlobTest.java b/azure/src/test/java/org/jclouds/azure/storage/blob/blobstore/config/SignGetBlobTest.java deleted file mode 100644 index 7da9826f88..0000000000 --- a/azure/src/test/java/org/jclouds/azure/storage/blob/blobstore/config/SignGetBlobTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * - * Copyright (C) 2010 Cloud Conscious, LLC. - * - * ==================================================================== - * 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 { - - 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 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> createTypeLiteral() { - return new TypeLiteral>() { - }; - } - - @Override - public ContextSpec createContextSpec() { - return new RestContextFactory().createContextSpec("azureblob", "identity", "credential", new Properties()); - } - -} \ No newline at end of file diff --git a/azure/src/test/java/org/jclouds/azure/storage/blob/blobstore/integration/AzureBlobSignerLiveTest.java b/azure/src/test/java/org/jclouds/azure/storage/blob/blobstore/integration/AzureBlobSignerLiveTest.java new file mode 100644 index 0000000000..0990cd5b72 --- /dev/null +++ b/azure/src/test/java/org/jclouds/azure/storage/blob/blobstore/integration/AzureBlobSignerLiveTest.java @@ -0,0 +1,32 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + +} \ No newline at end of file diff --git a/blobstore/src/main/clojure/org/jclouds/blobstore.clj b/blobstore/src/main/clojure/org/jclouds/blobstore.clj index 2984b6d9fc..4aa7d176a7 100644 --- a/blobstore/src/main/clojure/org/jclouds/blobstore.clj +++ b/blobstore/src/main/clojure/org/jclouds/blobstore.clj @@ -45,6 +45,7 @@ See http://code.google.com/p/jclouds for details." domain.BlobMetadata domain.StorageMetadata domain.Blob options.ListContainerOptions] [org.jclouds.io Payloads] + [org.jclouds.io.payloads PhantomPayload] [java.util Arrays] [java.security DigestOutputStream MessageDigest] [com.google.common.collect ImmutableSet])) @@ -238,13 +239,34 @@ Options can also be specified for extension modules ([container-name path #^BlobStore blobstore] (.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 in another application. ex. curl" ([container-name path] - (sign-blob-request container-name path *blobstore*)) + (sign-get-blob-request container-name path *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 "Get an inputstream from the blob at a given path" diff --git a/blobstore/src/main/java/org/jclouds/blobstore/AsyncBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/AsyncBlobStore.java index e4acc8f892..73516b2c79 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/AsyncBlobStore.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/AsyncBlobStore.java @@ -20,7 +20,6 @@ package org.jclouds.blobstore; import java.util.Set; -import com.google.common.util.concurrent.ListenableFuture; 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.ListContainerOptions; 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 @@ -49,11 +49,6 @@ public interface AsyncBlobStore { */ Blob newBlob(String name); - /** - * @see BlobStore#signRequestForBlob - */ - HttpRequest signRequestForBlob(String container, String name); - /** * @see BlobStore#listAssignableLocations */ diff --git a/blobstore/src/main/java/org/jclouds/blobstore/BlobRequestSigner.java b/blobstore/src/main/java/org/jclouds/blobstore/BlobRequestSigner.java new file mode 100644 index 0000000000..d0c65a0424 --- /dev/null +++ b/blobstore/src/main/java/org/jclouds/blobstore/BlobRequestSigner.java @@ -0,0 +1,83 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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. + * + *
+    * Blob blob = context.getBlobStore.newBlob();
+    * blob.getMetadata().setName("name");
+    * blob.setPayload(new PhantomPayload(length, md5));
+    * blob.getPayload().setContentType("text/plain");
+    * 
+ * + * @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); +} diff --git a/blobstore/src/main/java/org/jclouds/blobstore/BlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/BlobStore.java index 9739cac890..392f3c5462 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/BlobStore.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/BlobStore.java @@ -30,7 +30,6 @@ import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.options.GetOptions; import org.jclouds.blobstore.options.ListContainerOptions; import org.jclouds.domain.Location; -import org.jclouds.http.HttpRequest; /** * Synchronous access to a BlobStore such as Amazon S3 @@ -51,19 +50,6 @@ public interface BlobStore { */ 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 * scope, which is typically region or zone. A region is a general area, like eu-west, where a diff --git a/blobstore/src/main/java/org/jclouds/blobstore/BlobStoreContext.java b/blobstore/src/main/java/org/jclouds/blobstore/BlobStoreContext.java index a7d216cc1e..af14d9c48f 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/BlobStoreContext.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/BlobStoreContext.java @@ -36,6 +36,12 @@ import com.google.inject.ImplementedBy; */ @ImplementedBy(BlobStoreContextImpl.class) public interface BlobStoreContext { + /** + * + * Generates signed requests for blobs. useful in other tools such as backup utilities. + * + */ + BlobRequestSigner getSigner(); /** * Creates a Map view of the specified container. Use this for diff --git a/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java index 17b99b452d..b2687255e7 100755 --- a/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java @@ -77,7 +77,6 @@ import org.jclouds.blobstore.internal.BaseAsyncBlobStore; import org.jclouds.blobstore.options.GetOptions; import org.jclouds.blobstore.options.ListContainerOptions; import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.crypto.Crypto; import org.jclouds.crypto.CryptoStreams; @@ -125,8 +124,8 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore { HttpGetOptionsListToGetOptions httpGetOptionsConverter, IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory, BlobUtils blobUtils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier defaultLocation, - Supplier> locations, SignRequestForBlobStrategy signRequestForBlob) { - super(context, blobUtils, service, defaultLocation, locations, signRequestForBlob); + Supplier> locations) { + super(context, blobUtils, service, defaultLocation, locations); this.blobFactory = blobFactory; this.dateService = dateService; this.crypto = crypto; diff --git a/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseAsyncBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseAsyncBlobStore.java index a9cab4c0bd..2583a0648e 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseAsyncBlobStore.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseAsyncBlobStore.java @@ -37,11 +37,9 @@ import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.options.ListContainerOptions; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.blobstore.util.internal.BlobUtilsImpl; import org.jclouds.domain.Location; -import org.jclouds.http.HttpRequest; import org.jclouds.util.Utils; import com.google.common.base.Supplier; @@ -59,18 +57,16 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore { protected final ExecutorService service; protected final Supplier defaultLocation; protected final Supplier> locations; - protected final SignRequestForBlobStrategy signRequestForBlob; @Inject protected BaseAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier defaultLocation, - Supplier> locations, SignRequestForBlobStrategy signRequestForBlob) { + Supplier> locations) { this.context = checkNotNull(context, "context"); this.blobUtils = checkNotNull(blobUtils, "blobUtils"); this.service = checkNotNull(service, "service"); this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation"); this.locations = checkNotNull(locations, "locations"); - this.signRequestForBlob = checkNotNull(signRequestForBlob, "signRequestForBlob"); } @Override @@ -271,8 +267,5 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore { protected abstract boolean deleteAndVerifyContainerGone(String container); - @Override - public HttpRequest signRequestForBlob(String container, String name) { - return signRequestForBlob.apply(container, name); - } + } diff --git a/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseBlobStore.java index 4abb8c3f60..3929a63b81 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseBlobStore.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseBlobStore.java @@ -33,11 +33,9 @@ import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.options.ListContainerOptions; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.blobstore.util.internal.BlobUtilsImpl; import org.jclouds.domain.Location; -import org.jclouds.http.HttpRequest; import org.jclouds.util.Utils; import com.google.common.base.Supplier; @@ -52,16 +50,14 @@ public abstract class BaseBlobStore implements BlobStore { protected final BlobUtils blobUtils; protected final Supplier defaultLocation; protected final Supplier> locations; - protected final SignRequestForBlobStrategy signRequestForBlob; @Inject protected BaseBlobStore(BlobStoreContext context, BlobUtils blobUtils, Supplier defaultLocation, - Supplier> locations, SignRequestForBlobStrategy signRequestForBlob) { + Supplier> locations) { this.context = checkNotNull(context, "context"); this.blobUtils = checkNotNull(blobUtils, "blobUtils"); this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation"); this.locations = checkNotNull(locations, "locations"); - this.signRequestForBlob = checkNotNull(signRequestForBlob, "signRequestForBlob"); } @Override @@ -224,8 +220,4 @@ public abstract class BaseBlobStore implements BlobStore { protected abstract boolean deleteAndVerifyContainerGone(String container); - @Override - public HttpRequest signRequestForBlob(String container, String name) { - return signRequestForBlob.apply(container, name); - } } diff --git a/blobstore/src/main/java/org/jclouds/blobstore/internal/BlobStoreContextImpl.java b/blobstore/src/main/java/org/jclouds/blobstore/internal/BlobStoreContextImpl.java index 9614733c2b..080e810535 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/internal/BlobStoreContextImpl.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/internal/BlobStoreContextImpl.java @@ -26,6 +26,7 @@ import javax.inject.Singleton; import org.jclouds.blobstore.AsyncBlobStore; import org.jclouds.blobstore.BlobMap; +import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.InputStreamMap; @@ -46,22 +47,23 @@ public class BlobStoreContextImpl implements BlobStoreContext { private final RestContext providerSpecificContext; private final ConsistencyModel consistencyModel; private final Utils utils; + private final BlobRequestSigner blobRequestSigner; @SuppressWarnings("unchecked") @Inject - public BlobStoreContextImpl(BlobMap.Factory blobMapFactory, Utils utils, - ConsistencyModel consistencyModel, InputStreamMap.Factory inputStreamMapFactory, - AsyncBlobStore ablobStore, BlobStore blobStore, RestContext providerSpecificContext) { + public BlobStoreContextImpl(BlobMap.Factory blobMapFactory, Utils utils, ConsistencyModel consistencyModel, + InputStreamMap.Factory inputStreamMapFactory, AsyncBlobStore ablobStore, BlobStore blobStore, + RestContext providerSpecificContext, BlobRequestSigner blobRequestSigner) { // unravel guice and avoid passing in a million type args by not injecting generic types for // rest context - this.providerSpecificContext = checkNotNull(providerSpecificContext, - "providerSpecificContext"); + this.providerSpecificContext = checkNotNull(providerSpecificContext, "providerSpecificContext"); this.consistencyModel = checkNotNull(consistencyModel, "consistencyModel"); this.blobMapFactory = checkNotNull(blobMapFactory, "blobMapFactory"); this.inputStreamMapFactory = checkNotNull(inputStreamMapFactory, "inputStreamMapFactory"); this.ablobStore = checkNotNull(ablobStore, "ablobStore"); this.blobStore = checkNotNull(blobStore, "blobStore"); - this.utils = utils; + this.utils = checkNotNull(utils, "utils"); + this.blobRequestSigner = checkNotNull(blobRequestSigner, "blobRequestSigner"); } @Override @@ -134,4 +136,9 @@ public class BlobStoreContextImpl implements BlobStoreContext { public boolean equals(Object obj) { return providerSpecificContext.equals(obj); } + + @Override + public BlobRequestSigner getSigner() { + return blobRequestSigner; + } } diff --git a/blobstore/src/main/java/org/jclouds/blobstore/internal/RequestSigningUnsupported.java b/blobstore/src/main/java/org/jclouds/blobstore/internal/RequestSigningUnsupported.java new file mode 100644 index 0000000000..f455ae1146 --- /dev/null +++ b/blobstore/src/main/java/org/jclouds/blobstore/internal/RequestSigningUnsupported.java @@ -0,0 +1,50 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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(); + } + +} diff --git a/blobstore/src/main/java/org/jclouds/blobstore/util/BlobStoreUtils.java b/blobstore/src/main/java/org/jclouds/blobstore/util/BlobStoreUtils.java index 653aae122c..bad71f3db5 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/util/BlobStoreUtils.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/util/BlobStoreUtils.java @@ -37,14 +37,27 @@ import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.functions.ExceptionToValueOrPropagate; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpResponse; import org.jclouds.rest.internal.GeneratedHttpRequest; +import com.google.common.collect.ImmutableMultimap; + /** * * @author Adrian Cole */ public class BlobStoreUtils { + public static HttpRequest cleanRequest(GeneratedHttpRequest 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") public static final ExceptionToValueOrPropagate keyNotFoundToNullOrPropagate = new ExceptionToValueOrPropagate( @@ -131,8 +144,7 @@ public class BlobStoreUtils { } } - public static void createParentIfNeededAsync(AsyncBlobStore asyncBlobStore, String container, - Blob blob) { + public static void createParentIfNeededAsync(AsyncBlobStore asyncBlobStore, String container, Blob blob) { String name = blob.getMetadata().getName(); if (name.indexOf('/') > 0) { asyncBlobStore.createDirectory(container, parseDirectoryFromPath(name)); diff --git a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobLiveTest.java b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobLiveTest.java index 07f318005d..83072abfdd 100755 --- a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobLiveTest.java +++ b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobLiveTest.java @@ -28,8 +28,6 @@ import java.net.URLConnection; import org.jclouds.blobstore.domain.Blob; import org.jclouds.crypto.CryptoStreams; -import org.jclouds.http.HttpRequest; -import org.jclouds.util.Utils; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; 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); - } - } - } \ No newline at end of file diff --git a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobSignerLiveTest.java b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobSignerLiveTest.java new file mode 100644 index 0000000000..5c10a6a460 --- /dev/null +++ b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobSignerLiveTest.java @@ -0,0 +1,97 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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. + *

+ * 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); + } + } + +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/functions/ReturnInputStream.java b/core/src/main/java/org/jclouds/http/functions/ReturnInputStream.java index 0b554fc44a..cfad064f63 100644 --- a/core/src/main/java/org/jclouds/http/functions/ReturnInputStream.java +++ b/core/src/main/java/org/jclouds/http/functions/ReturnInputStream.java @@ -36,6 +36,6 @@ import com.google.common.base.Function; public class ReturnInputStream implements Function { public InputStream apply(HttpResponse from) { - return from.getPayload().getInput(); + return from.getPayload() != null ? from.getPayload().getInput() : null; } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/io/payloads/PhantomPayload.java b/core/src/main/java/org/jclouds/io/payloads/PhantomPayload.java new file mode 100644 index 0000000000..d6537a9701 --- /dev/null +++ b/core/src/main/java/org/jclouds/io/payloads/PhantomPayload.java @@ -0,0 +1,50 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + + 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(); + } + +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/rest/HttpAsyncClient.java b/core/src/main/java/org/jclouds/rest/HttpAsyncClient.java index ddd96b6a0a..4a2ee109b2 100644 --- a/core/src/main/java/org/jclouds/rest/HttpAsyncClient.java +++ b/core/src/main/java/org/jclouds/rest/HttpAsyncClient.java @@ -92,8 +92,9 @@ public interface HttpAsyncClient { /** * @see HttpClient#get */ + @Path("") @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture get(HttpRequest location); + ListenableFuture invoke(HttpRequest location); @GET @Path("") diff --git a/core/src/main/java/org/jclouds/rest/HttpClient.java b/core/src/main/java/org/jclouds/rest/HttpClient.java index 3cc1ddc6b8..087929a443 100644 --- a/core/src/main/java/org/jclouds/rest/HttpClient.java +++ b/core/src/main/java/org/jclouds/rest/HttpClient.java @@ -63,10 +63,7 @@ public interface HttpClient { */ InputStream get(URI location); - /** - * @return null if the resource didn't exist. - */ - InputStream get(HttpRequest location); + InputStream invoke(HttpRequest location); InputStream get(URI location, HttpRequestOptions options); diff --git a/core/src/test/java/org/jclouds/rest/BaseRestClientTest.java b/core/src/test/java/org/jclouds/rest/BaseRestClientTest.java index 39a45278b6..de0b83beea 100644 --- a/core/src/test/java/org/jclouds/rest/BaseRestClientTest.java +++ b/core/src/test/java/org/jclouds/rest/BaseRestClientTest.java @@ -84,23 +84,29 @@ public abstract class BaseRestClientTest { propagate(e); } assertEquals(payload, toMatch); - if (request.getFirstHeaderOrNull(TRANSFER_ENCODING) == null) { - 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); + Long length = new Long(payload.getBytes().length); try { - assertEquals(request.getPayload().getContentMD5(), contentMD5 ? CryptoStreams.md5(request.getPayload()) - : null); + assertContentHeadersEqual(request, contentType, length, contentMD5 ? CryptoStreams + .md5(request.getPayload()) : null); } catch (IOException 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) { assertEquals(sortAndConcatHeadersIntoString(request.getHeaders()), toMatch); } diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesAsyncBlobStore.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesAsyncBlobStore.java index 00afdcd222..16d889f13e 100644 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesAsyncBlobStore.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesAsyncBlobStore.java @@ -40,7 +40,6 @@ import org.jclouds.blobstore.domain.internal.PageSetImpl; import org.jclouds.blobstore.functions.BlobToHttpGetOptions; import org.jclouds.blobstore.internal.BaseAsyncBlobStore; import org.jclouds.blobstore.options.ListContainerOptions; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.concurrent.Futures; @@ -89,8 +88,8 @@ public class CloudFilesAsyncBlobStore extends BaseAsyncBlobStore { BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions, ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions, - Provider fetchBlobMetadataProvider, SignRequestForBlobStrategy signRequestForBlob) { - super(context, blobUtils, service, defaultLocation, locations, signRequestForBlob); + Provider fetchBlobMetadataProvider) { + super(context, blobUtils, service, defaultLocation, locations); this.sync = sync; this.async = async; this.container2ResourceMd = container2ResourceMd; diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobRequestSigner.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobRequestSigner.java new file mode 100644 index 0000000000..5dc832649e --- /dev/null +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobRequestSigner.java @@ -0,0 +1,77 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 processor; + private final BlobToObject blobToObject; + private final Method getMethod; + private final Method deleteMethod; + private final Method createMethod; + + @Inject + public CloudFilesBlobRequestSigner(RestAnnotationProcessor 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)); + } + +} \ No newline at end of file diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStore.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStore.java index 5a82b11aeb..18181226d6 100644 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStore.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStore.java @@ -37,7 +37,6 @@ import org.jclouds.blobstore.domain.internal.PageSetImpl; import org.jclouds.blobstore.functions.BlobToHttpGetOptions; import org.jclouds.blobstore.internal.BaseBlobStore; import org.jclouds.blobstore.options.ListContainerOptions; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.domain.Location; @@ -78,8 +77,8 @@ public class CloudFilesBlobStore extends BaseBlobStore { BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions, ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions, - Provider fetchBlobMetadataProvider, SignRequestForBlobStrategy signRequestForBlob) { - super(context, blobUtils, defaultLocation, locations, signRequestForBlob); + Provider fetchBlobMetadataProvider) { + super(context, blobUtils, defaultLocation, locations); this.sync = sync; this.container2ResourceMd = container2ResourceMd; this.container2ContainerListOptions = container2ContainerListOptions; diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/config/CloudFilesBlobStoreContextModule.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/config/CloudFilesBlobStoreContextModule.java index 210199bf01..d60368d013 100755 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/config/CloudFilesBlobStoreContextModule.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/config/CloudFilesBlobStoreContextModule.java @@ -24,18 +24,18 @@ import java.util.Set; import javax.inject.Singleton; import org.jclouds.blobstore.AsyncBlobStore; +import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.attr.ConsistencyModel; import org.jclouds.blobstore.config.BlobStoreMapModule; import org.jclouds.blobstore.internal.BlobStoreContextImpl; -import org.jclouds.blobstore.strategy.SignRequestForBlobStrategy; import org.jclouds.domain.Location; import org.jclouds.rackspace.cloudfiles.CloudFilesAsyncClient; import org.jclouds.rackspace.cloudfiles.CloudFilesClient; 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.strategy.SignGetObject; import org.jclouds.rackspace.config.RackspaceLocationsModule; 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(BlobStoreContext.class).to(new TypeLiteral>() { }).in(Scopes.SINGLETON); - bind(SignRequestForBlobStrategy.class).to(SignGetObject.class); + bind(BlobRequestSigner.class).to(CloudFilesBlobRequestSigner.class); } @Provides diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/strategy/SignGetObject.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/strategy/SignGetObject.java deleted file mode 100644 index 6e536b31c8..0000000000 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/strategy/SignGetObject.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * - * Copyright (C) 2010 Cloud Conscious, LLC. - * - * ==================================================================== - * 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 processor; - private final Method method; - - @Inject - public SignGetObject(RestAnnotationProcessor 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())); - } - -} \ No newline at end of file diff --git a/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobRequestSignerTest.java b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobRequestSignerTest.java new file mode 100644 index 0000000000..189f9ce847 --- /dev/null +++ b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobRequestSignerTest.java @@ -0,0 +1,116 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + + 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> createTypeLiteral() { + return new TypeLiteral>() { + }; + } + + @Override + protected Module createModule() { + return new CloudFilesRestClientModule(new TestRackspaceAuthenticationRestClientModule()); + } + + @Override + public ContextSpec createContextSpec() { + return new RestContextFactory().createContextSpec("cloudfiles", "identity", "credential", new Properties()); + } + +} \ No newline at end of file diff --git a/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobSignerLiveTest.java b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobSignerLiveTest.java new file mode 100644 index 0000000000..513a9f52f4 --- /dev/null +++ b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobSignerLiveTest.java @@ -0,0 +1,32 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + +} \ No newline at end of file diff --git a/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/strategy/SignGetBlobTest.java b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/strategy/SignGetBlobTest.java deleted file mode 100644 index 3109b03893..0000000000 --- a/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/strategy/SignGetBlobTest.java +++ /dev/null @@ -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 { - - 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> createTypeLiteral() { - return new TypeLiteral>() { - }; - } - - @Override - public ContextSpec createContextSpec() { - return new RestContextFactory().createContextSpec("cloudfiles", "identity", "credential", new Properties()); - } - -} \ No newline at end of file