From ffa9cd3bb0805a11c1496f30af6ab35e209b33b5 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Wed, 10 Oct 2012 12:03:23 +0200 Subject: [PATCH] corrected guice bindings for swift-based blob signatures and backfilled expect tests --- .../cloudfiles/CloudFilesApiMetadata.java | 31 +++- .../CloudFilesBlobStoreContextModule.java | 5 - .../config/CloudFilesRestClientModule.java | 3 +- .../CloudFilesBlobSignerExpectTest.java | 145 +++++++++++++++++ .../v2_0/config/KeystoneRestClientModule.java | 5 +- .../s3/blobstore/S3BlobRequestSignerTest.java | 128 --------------- .../s3/blobstore/S3BlobSignerExpectTest.java | 129 ++++++++++++++++ .../openstack/swift/SwiftApiMetadata.java | 11 +- .../swift/SwiftKeystoneApiMetadata.java | 11 +- ...equestSigner.java => SwiftBlobSigner.java} | 48 +++--- .../config/SwiftBlobStoreContextModule.java | 33 +--- .../config/TemporaryUrlExtensionModule.java | 97 ++++++++++++ .../config/SwiftKeystoneRestClientModule.java | 6 +- .../swift/config/SwiftRestClientModule.java | 11 +- .../KeystoneTemporaryUrlKeyAsyncApi.java | 38 +++++ .../ParseTemporaryUrlKeyFromHeaders.java | 17 +- .../swift/CommonSwiftClientTest.java | 36 +++-- .../blobstore/SwiftBlobRequestSignerTest.java | 124 --------------- .../blobstore/SwiftBlobSignerExpectTest.java | 140 +++++++++++++++++ .../SwiftKeystoneBlobSignerExpectTest.java | 142 +++++++++++++++++ .../integration/SwiftBlobLiveTest.java | 9 +- .../swift/internal/StubSwiftAsyncClient.java | 4 +- .../internal/BaseBlobSignerExpectTest.java | 121 +++++++++++++++ .../payloads/BaseMutableContentMetadata.java | 2 - .../internal/RestAnnotationProcessor.java | 18 ++- .../HPCloudObjectStorageApiMetadata.java | 35 ++++- ...HPCloudObjectStorageBlobRequestSigner.java | 75 --------- ...udObjectStorageBlobStoreContextModule.java | 7 +- .../HPCloudObjectStorageRestClientModule.java | 8 +- ...oudObjectStorageBlobRequestSignerTest.java | 86 ----------- ...loudObjectStorageBlobSignerExpectTest.java | 146 ++++++++++++++++++ ...PCloudObjectStorageBlobSignerLiveTest.java | 19 +++ 32 files changed, 1140 insertions(+), 550 deletions(-) create mode 100644 apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/blobstore/CloudFilesBlobSignerExpectTest.java delete mode 100644 apis/s3/src/test/java/org/jclouds/s3/blobstore/S3BlobRequestSignerTest.java create mode 100644 apis/s3/src/test/java/org/jclouds/s3/blobstore/S3BlobSignerExpectTest.java rename apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/{SwiftBlobRequestSigner.java => SwiftBlobSigner.java} (77%) create mode 100644 apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/TemporaryUrlExtensionModule.java create mode 100644 apis/swift/src/main/java/org/jclouds/openstack/swift/extensions/KeystoneTemporaryUrlKeyAsyncApi.java delete mode 100644 apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftBlobRequestSignerTest.java create mode 100644 apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftBlobSignerExpectTest.java create mode 100644 apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftKeystoneBlobSignerExpectTest.java create mode 100644 blobstore/src/test/java/org/jclouds/blobstore/internal/BaseBlobSignerExpectTest.java delete mode 100644 providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobRequestSigner.java delete mode 100644 providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobRequestSignerTest.java create mode 100644 providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobSignerExpectTest.java diff --git a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/CloudFilesApiMetadata.java b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/CloudFilesApiMetadata.java index eea9a09b28..25540f9cd1 100644 --- a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/CloudFilesApiMetadata.java +++ b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/CloudFilesApiMetadata.java @@ -22,30 +22,34 @@ import java.net.URI; import java.util.Properties; import org.jclouds.apis.ApiMetadata; +import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.cloudfiles.blobstore.config.CloudFilesBlobStoreContextModule; import org.jclouds.cloudfiles.config.CloudFilesRestClientModule; import org.jclouds.cloudfiles.config.CloudFilesRestClientModule.StorageAndCDNManagementEndpointModule; import org.jclouds.openstack.swift.SwiftApiMetadata; +import org.jclouds.openstack.swift.blobstore.SwiftBlobSigner; +import org.jclouds.openstack.swift.blobstore.config.TemporaryUrlExtensionModule; import org.jclouds.rest.RestContext; import com.google.common.collect.ImmutableSet; import com.google.common.reflect.TypeToken; import com.google.inject.Module; +import com.google.inject.TypeLiteral; /** * Implementation of {@link ApiMetadata} for Rackspace Cloud Files API - * + * * @author Adrian Cole */ public class CloudFilesApiMetadata extends SwiftApiMetadata { - + /** The serialVersionUID */ private static final long serialVersionUID = -1572520638079261710L; - + public static final TypeToken> CONTEXT_TOKEN = new TypeToken>() { private static final long serialVersionUID = -5070937833892503232L; }; - + private static Builder builder() { return new Builder(); } @@ -62,7 +66,7 @@ public class CloudFilesApiMetadata extends SwiftApiMetadata { protected CloudFilesApiMetadata(Builder builder) { super(builder); } - + public static Properties defaultProperties() { Properties properties = SwiftApiMetadata.defaultProperties(); return properties; @@ -78,9 +82,13 @@ public class CloudFilesApiMetadata extends SwiftApiMetadata { .documentation(URI.create("http://docs.rackspacecloud.com/files/api/v1/cfdevguide_d5/content/ch01.html")) .defaultProperties(CloudFilesApiMetadata.defaultProperties()) .context(CONTEXT_TOKEN) - .defaultModules(ImmutableSet.>of(StorageAndCDNManagementEndpointModule.class, CloudFilesRestClientModule.class, CloudFilesBlobStoreContextModule.class)); + .defaultModules(ImmutableSet.>builder() + .add(StorageAndCDNManagementEndpointModule.class) + .add(CloudFilesRestClientModule.class) + .add(CloudFilesBlobStoreContextModule.class) + .add(CloudFilesTemporaryUrlExtensionModule.class).build()); } - + @Override public CloudFilesApiMetadata build() { return new CloudFilesApiMetadata(this); @@ -93,4 +101,13 @@ public class CloudFilesApiMetadata extends SwiftApiMetadata { } } + public static class CloudFilesTemporaryUrlExtensionModule extends TemporaryUrlExtensionModule { + + @Override + protected void bindRequestSigner() { + bind(BlobRequestSigner.class).to(new TypeLiteral>() { + }); + } + + } } \ No newline at end of file diff --git a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/blobstore/config/CloudFilesBlobStoreContextModule.java b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/blobstore/config/CloudFilesBlobStoreContextModule.java index edacb1d321..b9282dc995 100644 --- a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/blobstore/config/CloudFilesBlobStoreContextModule.java +++ b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/blobstore/config/CloudFilesBlobStoreContextModule.java @@ -23,16 +23,12 @@ import java.util.concurrent.TimeUnit; import javax.inject.Singleton; -import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.cloudfiles.CloudFilesClient; -import org.jclouds.openstack.swift.TemporaryUrlKey; import org.jclouds.cloudfiles.blobstore.CloudFilesAsyncBlobStore; import org.jclouds.cloudfiles.blobstore.CloudFilesBlobStore; import org.jclouds.cloudfiles.blobstore.functions.CloudFilesObjectToBlobMetadata; import org.jclouds.cloudfiles.domain.ContainerCDNMetadata; -import org.jclouds.date.TimeStamp; import org.jclouds.openstack.swift.blobstore.SwiftAsyncBlobStore; -import org.jclouds.openstack.swift.blobstore.SwiftBlobRequestSigner; import org.jclouds.openstack.swift.blobstore.SwiftBlobStore; import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule; import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlobMetadata; @@ -70,6 +66,5 @@ public class CloudFilesBlobStoreContextModule extends SwiftBlobStoreContextModul bind(SwiftBlobStore.class).to(CloudFilesBlobStore.class); bind(SwiftAsyncBlobStore.class).to(CloudFilesAsyncBlobStore.class); bind(ObjectToBlobMetadata.class).to(CloudFilesObjectToBlobMetadata.class); - bind(BlobRequestSigner.class).to(SwiftBlobRequestSigner.class); } } diff --git a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/config/CloudFilesRestClientModule.java b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/config/CloudFilesRestClientModule.java index f927e9ee80..7273a4a2ec 100644 --- a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/config/CloudFilesRestClientModule.java +++ b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/config/CloudFilesRestClientModule.java @@ -43,7 +43,7 @@ import com.google.inject.Provides; import com.google.inject.Scopes; /** - * + * * @author Adrian Cole */ @ConfiguresRestClient @@ -53,6 +53,7 @@ public class CloudFilesRestClientModule extends SwiftRestClientModule, Class> of()); } + @Override protected void bindResolvedClientsToCommonSwift() { bind(CommonSwiftClient.class).to(CloudFilesClient.class).in(Scopes.SINGLETON); bind(CommonSwiftAsyncClient.class).to(CloudFilesAsyncClient.class).in(Scopes.SINGLETON); diff --git a/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/blobstore/CloudFilesBlobSignerExpectTest.java b/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/blobstore/CloudFilesBlobSignerExpectTest.java new file mode 100644 index 0000000000..8b9c2f2ae5 --- /dev/null +++ b/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/blobstore/CloudFilesBlobSignerExpectTest.java @@ -0,0 +1,145 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you 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.cloudfiles.blobstore; + +import static org.jclouds.openstack.swift.reference.SwiftHeaders.ACCOUNT_TEMPORARY_URL_KEY; + +import java.util.Map; + +import org.jclouds.apis.ApiMetadata; +import org.jclouds.blobstore.internal.BaseBlobSignerExpectTest; +import org.jclouds.cloudfiles.CloudFilesApiMetadata; +import org.jclouds.cloudfiles.CloudFilesApiMetadata.CloudFilesTemporaryUrlExtensionModule; +import org.jclouds.cloudfiles.blobstore.config.CloudFilesBlobStoreContextModule; +import org.jclouds.cloudfiles.config.CloudFilesRestClientModule; +import org.jclouds.cloudfiles.config.CloudFilesRestClientModule.StorageAndCDNManagementEndpointModule; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.net.HttpHeaders; +import com.google.inject.Module; + +/** + * Tests behavior of {@code SwiftBlobSigner} + * + * @author Adrian Cole + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during +// surefire +@Test(groups = "unit", testName = "CloudFilesBlobSignerExpectTest") +public class CloudFilesBlobSignerExpectTest extends BaseBlobSignerExpectTest { + + public CloudFilesBlobSignerExpectTest() { + identity = "user@jclouds.org"; + credential = "Password1234"; + } + + @Override + protected HttpRequest getBlob() { + return HttpRequest.builder().method("GET") + .endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container/name") + .addHeader("X-Auth-Token", authToken).build(); + } + + @Override + protected HttpRequest getBlobWithTime() { + return HttpRequest.builder().method("GET") + .endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container/name?temp_url_sig=9d62a4a15076699b3f7c60c2d021609990f24115&temp_url_expires=123456792").build(); + } + + @Override + protected HttpRequest getBlobWithOptions() { + return HttpRequest.builder().method("GET") + .endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container/name") + .addHeader("X-Auth-Token", authToken) + .addHeader("Range", "bytes=0-1").build(); + } + + @Override + protected HttpRequest putBlob() { + return HttpRequest.builder().method("PUT") + .endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container/name") + .addHeader("X-Auth-Token", authToken).build(); + } + + @Override + protected HttpRequest putBlobWithTime() { + return HttpRequest.builder().method("PUT") + .endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container/name?temp_url_sig=f83fa711f353f6f0bab3a66c56e35a972b9b3922&temp_url_expires=123456792").build(); + } + + @Override + protected HttpRequest removeBlob() { + return HttpRequest.builder().method("DELETE") + .endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container/name") + .addHeader("X-Auth-Token", authToken).build(); + } + + protected String authToken = "118fb907-0786-4799-88f0-9a5b7963d1ab"; + + @Override + protected Map init() { + + HttpRequest authRequest = HttpRequest.builder().method("POST") + .endpoint("https://auth.api.rackspacecloud.com/v1.1/auth") + .addHeader(HttpHeaders.ACCEPT, "application/json") + .payload( + payloadFromStringWithContentType( + "{\"credentials\":{\"username\":\"user@jclouds.org\",\"key\":\"Password1234\"}}", + "application/json")).build(); + + HttpResponse authResponse = HttpResponse.builder().statusCode(200).message("HTTP/1.1 200") + .payload(payloadFromResourceWithContentType("/auth1_1.json", "application/json")).build(); + + HttpRequest temporaryKeyRequest = HttpRequest.builder().method("HEAD") + .endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/") + .addHeader("X-Auth-Token", authToken).build(); + + HttpResponse temporaryKeyResponse = HttpResponse.builder().statusCode(200) + .addHeader(ACCOUNT_TEMPORARY_URL_KEY, "TEMPORARY_KEY").build(); + + return ImmutableMap. builder() + .put(authRequest, authResponse) + .put(temporaryKeyRequest, temporaryKeyResponse).build(); + } + + public static class StaticTimeAndTemporaryUrlKeyModule extends CloudFilesTemporaryUrlExtensionModule { + + @Override + protected Long unixEpochTimestampProvider() { + return 123456789L; + } + } + + @Override + protected ApiMetadata createApiMetadata() { + return new CloudFilesApiMetadata() + .toBuilder() + .defaultEndpoint("https://auth.api.rackspacecloud.com") + .defaultModules( + ImmutableSet.> builder() + .add(StorageAndCDNManagementEndpointModule.class) + .add(CloudFilesRestClientModule.class) + .add(CloudFilesBlobStoreContextModule.class) + .add(StaticTimeAndTemporaryUrlKeyModule.class).build()).build(); + } +} diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneRestClientModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneRestClientModule.java index ac8d3433dd..c77f70b1f9 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneRestClientModule.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneRestClientModule.java @@ -73,7 +73,7 @@ import com.google.inject.assistedinject.FactoryModuleBuilder; /** * Configures the Keystone connection. - * + * * @author Adam Lowe */ @ConfiguresRestClient @@ -88,6 +88,7 @@ public class KeystoneRestClientModule aliases() { diff --git a/apis/s3/src/test/java/org/jclouds/s3/blobstore/S3BlobRequestSignerTest.java b/apis/s3/src/test/java/org/jclouds/s3/blobstore/S3BlobRequestSignerTest.java deleted file mode 100644 index 06b43d3949..0000000000 --- a/apis/s3/src/test/java/org/jclouds/s3/blobstore/S3BlobRequestSignerTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds licenses this file - * to you 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.s3.blobstore; - -import static org.testng.Assert.assertEquals; - -import java.io.IOException; -import java.util.Date; - -import javax.inject.Provider; - -import org.jclouds.blobstore.BlobRequestSigner; -import org.jclouds.blobstore.domain.Blob; -import org.jclouds.blobstore.domain.BlobBuilder; -import org.jclouds.date.TimeStamp; -import org.jclouds.http.HttpRequest; -import org.jclouds.rest.ConfiguresRestClient; -import org.jclouds.rest.internal.RestAnnotationProcessor; -import org.jclouds.s3.S3AsyncClient; -import org.jclouds.s3.S3Client; -import org.jclouds.s3.config.S3RestClientModule; -import org.jclouds.s3.internal.BaseS3AsyncClientTest; -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; - -/** - * Tests behavior of {@code S3BlobRequestSigner} - * - * @author Adrian Cole - */ -// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire -@Test(groups = "unit", testName = "S3BlobRequestSignerTest") -public class S3BlobRequestSignerTest extends BaseS3AsyncClientTest { - - @Override - protected TypeLiteral> createTypeLiteral() { - return new TypeLiteral>() { - }; - } - - private BlobRequestSigner signer; - private Provider 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.get().name("name").forSigning().contentLength(2l).contentMD5(new byte[] { 0, 2, 4, 8 }).contentType( - "text/plain").expires(new Date(1000)).build(); - - 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", null, null, null, (long) 2l, new byte[] { 0, 2, 4, 8 }, new Date(1000)); - - assertEquals(request.getFilters().size(), 0); - } - - @BeforeClass - protected void setupFactory() throws IOException { - super.setupFactory(); - this.blobFactory = injector.getProvider(BlobBuilder.class); - this.signer = injector.getInstance(BlobRequestSigner.class); - } - - @Override - protected Module createModule() { - return new TestS3RestClientModule(); - } - - @ConfiguresRestClient - private static final class TestS3RestClientModule extends S3RestClientModule { - - @Override - protected String provideTimeStamp(@TimeStamp Supplier cache) { - return "Thu, 05 Jun 2008 16:38:19 GMT"; - } - } - -} diff --git a/apis/s3/src/test/java/org/jclouds/s3/blobstore/S3BlobSignerExpectTest.java b/apis/s3/src/test/java/org/jclouds/s3/blobstore/S3BlobSignerExpectTest.java new file mode 100644 index 0000000000..2d074d2b43 --- /dev/null +++ b/apis/s3/src/test/java/org/jclouds/s3/blobstore/S3BlobSignerExpectTest.java @@ -0,0 +1,129 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you 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.s3.blobstore; + +import org.jclouds.blobstore.internal.BaseBlobSignerExpectTest; +import org.jclouds.date.TimeStamp; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.s3.S3AsyncClient; +import org.jclouds.s3.S3Client; +import org.jclouds.s3.config.S3RestClientModule; +import org.testng.SkipException; +import org.testng.annotations.Test; + +import com.google.common.base.Supplier; +import com.google.inject.Module; + +/** + * Tests behavior of {@code S3BlobRequestSigner} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "S3BlobSignerExpectTest") +public class S3BlobSignerExpectTest extends BaseBlobSignerExpectTest { + + public S3BlobSignerExpectTest() { + provider = "s3"; + } + + @Override + protected HttpRequest getBlob() { + return HttpRequest.builder().method("GET") + .endpoint("https://container.s3.amazonaws.com/name") + .addHeader("Host", "container.s3.amazonaws.com") + .addHeader("Date", "Thu, 05 Jun 2008 16:38:19 GMT") + .addHeader("Authorization", "AWS identity:0uvBv1wEskuhFHYJF/L6kEV9A7o=").build(); + } + + @Override + @Test + public void testSignGetBlobWithTime() { + throw new SkipException("not yet implemented"); + } + + //TODO + @Override + protected HttpRequest getBlobWithTime() { + return HttpRequest.builder().method("GET") + .endpoint("https://container.s3.amazonaws.com/name") + .addHeader("Host", "container.s3.amazonaws.com") + .addHeader("Date", "Thu, 05 Jun 2008 16:38:19 GMT") + .addHeader("Authorization", "AWS identity:0uvBv1wEskuhFHYJF/L6kEV9A7o=").build(); + } + + @Override + protected HttpRequest getBlobWithOptions() { + return HttpRequest.builder().method("GET") + .endpoint("https://container.s3.amazonaws.com/name") + .addHeader("Range", "bytes=0-1") + .addHeader("Host", "container.s3.amazonaws.com") + .addHeader("Date", "Thu, 05 Jun 2008 16:38:19 GMT") + .addHeader("Authorization", "AWS identity:0uvBv1wEskuhFHYJF/L6kEV9A7o=").build(); + } + + @Override + protected HttpRequest putBlob() { + return HttpRequest.builder().method("PUT") + .endpoint("https://container.s3.amazonaws.com/name") + .addHeader("Host", "container.s3.amazonaws.com") + .addHeader("Date", "Thu, 05 Jun 2008 16:38:19 GMT") + .addHeader("Authorization", "AWS identity:j9Dy/lmmvlCKjA4lkqZenLxMkR4=").build(); + } + + @Override + @Test + public void testSignPutBlobWithTime() throws Exception { + throw new SkipException("not yet implemented"); + } + + //TODO + @Override + protected HttpRequest putBlobWithTime() { + return HttpRequest.builder().method("PUT") + .endpoint("https://container.s3.amazonaws.com/name") + .addHeader("Host", "container.s3.amazonaws.com") + .addHeader("Date", "Thu, 05 Jun 2008 16:38:19 GMT") + .addHeader("Authorization", "AWS identity:0uvBv1wEskuhFHYJF/L6kEV9A7o=").build(); + } + + @Override + protected HttpRequest removeBlob() { + return HttpRequest.builder().method("DELETE") + .endpoint("https://container.s3.amazonaws.com/name") + .addHeader("Host", "container.s3.amazonaws.com") + .addHeader("Date", "Thu, 05 Jun 2008 16:38:19 GMT") + .addHeader("Authorization", "AWS identity:4FnyjdX/ULdDMRbVlLNjZfEo9RQ=").build(); + } + + @Override + protected Module createModule() { + return new TestS3RestClientModule(); + } + + @ConfiguresRestClient + private static final class TestS3RestClientModule extends S3RestClientModule { + + @Override + protected String provideTimeStamp(@TimeStamp Supplier cache) { + return "Thu, 05 Jun 2008 16:38:19 GMT"; + } + } + +} diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftApiMetadata.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftApiMetadata.java index 34fa5479de..ca59b003d9 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftApiMetadata.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftApiMetadata.java @@ -27,6 +27,7 @@ import java.util.Properties; import org.jclouds.apis.ApiMetadata; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule; +import org.jclouds.openstack.swift.blobstore.config.TemporaryUrlExtensionModule.SwiftTemporaryUrlExtensionModule; import org.jclouds.openstack.swift.config.SwiftRestClientModule; import org.jclouds.openstack.swift.config.SwiftRestClientModule.StorageEndpointModule; import org.jclouds.rest.RestContext; @@ -38,13 +39,13 @@ import com.google.inject.Module; /** * Implementation of {@link ApiMetadata} for OpenStack Swift - * + * * @author Adrian Cole */ public class SwiftApiMetadata extends BaseRestApiMetadata { /** The serialVersionUID */ private static final long serialVersionUID = 6725672099385580694L; - + public static final TypeToken> CONTEXT_TOKEN = new TypeToken>() { private static final long serialVersionUID = -5070937833892503232L; }; @@ -81,7 +82,11 @@ public class SwiftApiMetadata extends BaseRestApiMetadata { .defaultProperties(SwiftApiMetadata.defaultProperties()) .view(TypeToken.of(BlobStoreContext.class)) .context(CONTEXT_TOKEN) - .defaultModules(ImmutableSet.>of(StorageEndpointModule.class, SwiftRestClientModule.class, SwiftBlobStoreContextModule.class)); + .defaultModules(ImmutableSet.>builder() + .add(StorageEndpointModule.class) + .add(SwiftRestClientModule.class) + .add(SwiftBlobStoreContextModule.class) + .add(SwiftTemporaryUrlExtensionModule.class).build()); } @Override diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneApiMetadata.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneApiMetadata.java index ba6f4c6ffc..f205b02298 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneApiMetadata.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneApiMetadata.java @@ -29,6 +29,7 @@ import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; import org.jclouds.openstack.services.ServiceType; import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule; +import org.jclouds.openstack.swift.blobstore.config.TemporaryUrlExtensionModule.SwiftKeystoneTemporaryUrlExtensionModule; import org.jclouds.openstack.swift.config.SwiftKeystoneRestClientModule; import org.jclouds.openstack.swift.config.SwiftRestClientModule.KeystoneStorageEndpointModule; import org.jclouds.rest.RestContext; @@ -46,7 +47,7 @@ public class SwiftKeystoneApiMetadata extends SwiftApiMetadata { /** The serialVersionUID */ private static final long serialVersionUID = 820062881469203616L; - + public static final TypeToken> CONTEXT_TOKEN = new TypeToken>() { private static final long serialVersionUID = -5070937833892503232L; }; @@ -91,8 +92,12 @@ public class SwiftKeystoneApiMetadata extends SwiftApiMetadata { .defaultEndpoint("http://localhost:5000/v2.0/") .context(CONTEXT_TOKEN) .defaultProperties(SwiftKeystoneApiMetadata.defaultProperties()) - .defaultModules(ImmutableSet.>of(KeystoneStorageEndpointModule.class, KeystoneAuthenticationModule.RegionModule.class, - SwiftKeystoneRestClientModule.class, SwiftBlobStoreContextModule.class)); + .defaultModules(ImmutableSet.>builder() + .add(KeystoneStorageEndpointModule.class) + .add(KeystoneAuthenticationModule.RegionModule.class) + .add(SwiftKeystoneRestClientModule.class) + .add(SwiftBlobStoreContextModule.class) + .add(SwiftKeystoneTemporaryUrlExtensionModule.class).build()); } @Override diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/SwiftBlobRequestSigner.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/SwiftBlobSigner.java similarity index 77% rename from apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/SwiftBlobRequestSigner.java rename to apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/SwiftBlobSigner.java index b14d0f87fc..688527ce8d 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/SwiftBlobRequestSigner.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/SwiftBlobSigner.java @@ -20,8 +20,6 @@ package org.jclouds.openstack.swift.blobstore; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Predicates.instanceOf; -import static com.google.common.collect.Iterables.filter; import static org.jclouds.blobstore.util.BlobStoreUtils.cleanRequest; import java.lang.reflect.Method; @@ -30,9 +28,6 @@ import java.security.InvalidKeyException; import javax.inject.Inject; import javax.inject.Singleton; -import com.google.common.base.Supplier; -import com.google.common.base.Throwables; -import com.google.inject.Provider; import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.functions.BlobToHttpGetOptions; @@ -40,21 +35,26 @@ import org.jclouds.crypto.Crypto; import org.jclouds.crypto.CryptoStreams; import org.jclouds.date.TimeStamp; import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.options.GetOptions; -import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; import org.jclouds.openstack.swift.CommonSwiftAsyncClient; import org.jclouds.openstack.swift.TemporaryUrlKey; import org.jclouds.openstack.swift.blobstore.functions.BlobToObject; import org.jclouds.openstack.swift.domain.SwiftObject; import org.jclouds.rest.internal.RestAnnotationProcessor; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Provider; + /** * @author Adrian Cole */ @Singleton -public class SwiftBlobRequestSigner implements BlobRequestSigner { +public class SwiftBlobSigner implements BlobRequestSigner { - private final RestAnnotationProcessor processor; + private final RestAnnotationProcessor processor; private final Crypto crypto; private final Provider unixEpochTimestampProvider; @@ -67,10 +67,18 @@ public class SwiftBlobRequestSigner implements BlobRequestSigner { private final Method deleteMethod; private final Method createMethod; + /** + * create a signer for this subtype of swift + * + * @param processor + * bound to the current subclass of {@link CommonSwiftAsyncClient} + */ @Inject - public SwiftBlobRequestSigner(RestAnnotationProcessor processor, BlobToObject blobToObject, - BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto, @TimeStamp Provider unixEpochTimestampProvider, - @TemporaryUrlKey Supplier temporaryUrlKeySupplier) throws SecurityException, NoSuchMethodException { + protected SwiftBlobSigner(BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto, + @TimeStamp Provider unixEpochTimestampProvider, + @TemporaryUrlKey Supplier temporaryUrlKeySupplier, + RestAnnotationProcessor processor) + throws SecurityException, NoSuchMethodException { this.processor = checkNotNull(processor, "processor"); this.crypto = checkNotNull(crypto, "crypto"); @@ -80,10 +88,9 @@ public class SwiftBlobRequestSigner implements BlobRequestSigner { this.blobToObject = checkNotNull(blobToObject, "blobToObject"); this.blob2HttpGetOptions = checkNotNull(blob2HttpGetOptions, "blob2HttpGetOptions"); - this.getMethod = CommonSwiftAsyncClient.class.getMethod("getObject", String.class, String.class, - GetOptions[].class); - this.deleteMethod = CommonSwiftAsyncClient.class.getMethod("removeObject", String.class, String.class); - this.createMethod = CommonSwiftAsyncClient.class.getMethod("putObject", String.class, SwiftObject.class); + this.getMethod = processor.getDeclaring().getMethod("getObject", String.class, String.class, GetOptions[].class); + this.deleteMethod = processor.getDeclaring().getMethod("removeObject", String.class, String.class); + this.createMethod = processor.getDeclaring().getMethod("putObject", String.class, SwiftObject.class); } @Override @@ -119,8 +126,7 @@ public class SwiftBlobRequestSigner implements BlobRequestSigner { } private HttpRequest signForTemporaryAccess(HttpRequest request, long timeInSeconds) { - HttpRequest.Builder builder = request.toBuilder(); - builder.filters(filter(request.getFilters(), instanceOf(AuthenticateRequest.class))); + HttpRequest.Builder builder = request.toBuilder().filters(ImmutableSet.of()); String key = temporaryUrlKeySupplier.get(); if (key == null) { @@ -128,8 +134,8 @@ public class SwiftBlobRequestSigner implements BlobRequestSigner { } long expiresInSeconds = unixEpochTimestampProvider.get() + timeInSeconds; - builder.addQueryParam("temp_url_sig", createSignature(key, createStringToSign( - request.getMethod().toUpperCase(), request, expiresInSeconds))); + builder.addQueryParam("temp_url_sig", + createSignature(key, createStringToSign(request.getMethod().toUpperCase(), request, expiresInSeconds))); builder.addQueryParam("temp_url_expires", "" + expiresInSeconds); return builder.build(); @@ -137,14 +143,12 @@ public class SwiftBlobRequestSigner implements BlobRequestSigner { private String createStringToSign(String method, HttpRequest request, long expiresInSeconds) { checkArgument(method.equalsIgnoreCase("GET") || method.equalsIgnoreCase("PUT")); - return String.format("%s\n%d\n%s", method.toUpperCase(), expiresInSeconds, - request.getEndpoint().getPath()); + return String.format("%s\n%d\n%s", method.toUpperCase(), expiresInSeconds, request.getEndpoint().getPath()); } private String createSignature(String key, String stringToSign) { try { return CryptoStreams.hex(crypto.hmacSHA1(key.getBytes()).doFinal(stringToSign.getBytes())); - } catch (InvalidKeyException e) { throw Throwables.propagate(e); } diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java index fc93747625..051cc8c882 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java @@ -18,57 +18,30 @@ */ package org.jclouds.openstack.swift.blobstore.config; -import com.google.common.base.Supplier; -import com.google.inject.Provides; -import com.google.inject.TypeLiteral; + import org.jclouds.blobstore.AsyncBlobStore; -import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.attr.ConsistencyModel; import org.jclouds.blobstore.config.BlobStoreMapModule; -import org.jclouds.date.TimeStamp; -import org.jclouds.openstack.swift.TemporaryUrlKey; import org.jclouds.openstack.swift.blobstore.SwiftAsyncBlobStore; -import org.jclouds.openstack.swift.blobstore.SwiftBlobRequestSigner; import org.jclouds.openstack.swift.blobstore.SwiftBlobStore; import com.google.inject.AbstractModule; import com.google.inject.Scopes; -import org.jclouds.openstack.swift.extensions.TemporaryUrlKeyApi; -import org.jclouds.openstack.swift.extensions.TemporaryUrlKeyAsyncApi; -import org.jclouds.openstack.swift.suppliers.ReturnOrFetchTemporaryUrlKey; - -import java.util.UUID; - -import static org.jclouds.rest.config.BinderUtils.bindClientAndAsyncClient; /** - * Configures the {@link CloudFilesBlobStoreContext}; requires {@link SwiftAsyncBlobStore} - * bound. + * Configures the {@link CloudFilesBlobStoreContext}; requires + * {@link SwiftAsyncBlobStore} bound. * * @author Adrian Cole */ public class SwiftBlobStoreContextModule extends AbstractModule { - @Provides - @TimeStamp - protected Long unixEpochTimestampProvider() { - return System.currentTimeMillis() / 1000; /* convert to seconds */ - } - @Override protected void configure() { install(new BlobStoreMapModule()); bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT); bind(AsyncBlobStore.class).to(SwiftAsyncBlobStore.class).in(Scopes.SINGLETON); bind(BlobStore.class).to(SwiftBlobStore.class).in(Scopes.SINGLETON); - bind(BlobRequestSigner.class).to(SwiftBlobRequestSigner.class); - configureTemporaryUrlExtension(); - } - - protected void configureTemporaryUrlExtension() { - bindClientAndAsyncClient(binder(), TemporaryUrlKeyApi.class, TemporaryUrlKeyAsyncApi.class); - bind(new TypeLiteral>() { - }).annotatedWith(TemporaryUrlKey.class).to(ReturnOrFetchTemporaryUrlKey.class); } } diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/TemporaryUrlExtensionModule.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/TemporaryUrlExtensionModule.java new file mode 100644 index 0000000000..71bcd40c20 --- /dev/null +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/TemporaryUrlExtensionModule.java @@ -0,0 +1,97 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you 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.openstack.swift.blobstore.config; + +import static org.jclouds.rest.config.BinderUtils.bindClientAndAsyncClient; + +import org.jclouds.blobstore.BlobRequestSigner; +import org.jclouds.date.TimeStamp; +import org.jclouds.openstack.swift.CommonSwiftAsyncClient; +import org.jclouds.openstack.swift.SwiftAsyncClient; +import org.jclouds.openstack.swift.SwiftKeystoneAsyncClient; +import org.jclouds.openstack.swift.TemporaryUrlKey; +import org.jclouds.openstack.swift.blobstore.SwiftBlobSigner; +import org.jclouds.openstack.swift.extensions.KeystoneTemporaryUrlKeyAsyncApi; +import org.jclouds.openstack.swift.extensions.TemporaryUrlKeyApi; +import org.jclouds.openstack.swift.extensions.TemporaryUrlKeyAsyncApi; +import org.jclouds.openstack.swift.suppliers.ReturnOrFetchTemporaryUrlKey; + +import com.google.common.base.Supplier; +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.TypeLiteral; + +/** + * Isolates dependencies needed for {@link SwiftBlobSigner} + * + * @author Adrian Cole + * + */ +public abstract class TemporaryUrlExtensionModule extends AbstractModule { + + public static class SwiftTemporaryUrlExtensionModule extends TemporaryUrlExtensionModule { + + @Override + protected void bindRequestSigner() { + bind(BlobRequestSigner.class).to(new TypeLiteral>() { + }); + } + + } + + /** + * Ensures keystone auth is used instead of swift auth + * + */ + public static class SwiftKeystoneTemporaryUrlExtensionModule extends + TemporaryUrlExtensionModule { + + protected void bindTemporaryUrlKeyApi() { + bindClientAndAsyncClient(binder(), TemporaryUrlKeyApi.class, KeystoneTemporaryUrlKeyAsyncApi.class); + } + + @Override + protected void bindRequestSigner() { + bind(BlobRequestSigner.class).to(new TypeLiteral>() { + }); + } + + } + + @Provides + @TimeStamp + protected Long unixEpochTimestampProvider() { + return System.currentTimeMillis() / 1000; /* convert to seconds */ + } + + @Override + protected void configure() { + bindRequestSigner(); + bindTemporaryUrlKeyApi(); + bind(new TypeLiteral>() { + }).annotatedWith(TemporaryUrlKey.class).to(ReturnOrFetchTemporaryUrlKey.class); + } + + protected abstract void bindRequestSigner(); + + protected void bindTemporaryUrlKeyApi() { + bindClientAndAsyncClient(binder(), TemporaryUrlKeyApi.class, TemporaryUrlKeyAsyncApi.class); + } + +} \ No newline at end of file diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/config/SwiftKeystoneRestClientModule.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/config/SwiftKeystoneRestClientModule.java index e5b355762b..deff5d995d 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/config/SwiftKeystoneRestClientModule.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/config/SwiftKeystoneRestClientModule.java @@ -11,7 +11,7 @@ import com.google.common.reflect.TypeToken; import com.google.inject.Scopes; /** - * + * * @author Adrian Cole */ @ConfiguresRestClient @@ -21,9 +21,9 @@ public class SwiftKeystoneRestClientModule extends SwiftRestClientModule, Class> of()); } - + protected void bindResolvedClientsToCommonSwift() { bind(CommonSwiftClient.class).to(SwiftKeystoneClient.class).in(Scopes.SINGLETON); bind(CommonSwiftAsyncClient.class).to(SwiftKeystoneAsyncClient.class).in(Scopes.SINGLETON); - } + } } diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/config/SwiftRestClientModule.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/config/SwiftRestClientModule.java index 830aafb650..5cc3fa31a3 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/config/SwiftRestClientModule.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/config/SwiftRestClientModule.java @@ -54,23 +54,24 @@ import com.google.inject.Provides; import com.google.inject.Scopes; /** - * + * * @author Adrian Cole */ @ConfiguresRestClient -public class SwiftRestClientModule extends RestClientModule { +public class SwiftRestClientModule extends + RestClientModule { @SuppressWarnings("unchecked") public SwiftRestClientModule() { this(TypeToken.class.cast(TypeToken.of(SwiftClient.class)), TypeToken.class.cast(TypeToken - .of(SwiftAsyncClient.class)), ImmutableMap., Class> of()); + .of(SwiftAsyncClient.class)), ImmutableMap., Class> of()); } protected SwiftRestClientModule(TypeToken syncClientType, TypeToken asyncClientType, - Map, Class> sync2Async) { + Map, Class> sync2Async) { super(syncClientType, asyncClientType, sync2Async); } - + public static class StorageEndpointModule extends OpenStackAuthenticationModule { @Provides @Singleton diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/extensions/KeystoneTemporaryUrlKeyAsyncApi.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/extensions/KeystoneTemporaryUrlKeyAsyncApi.java new file mode 100644 index 0000000000..7fb51d8dc2 --- /dev/null +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/extensions/KeystoneTemporaryUrlKeyAsyncApi.java @@ -0,0 +1,38 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you 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.openstack.swift.extensions; + +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.openstack.swift.Storage; +import org.jclouds.rest.annotations.Endpoint; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SkipEncoding; + +/** + * Only purpose is to override the auth filter with one that works in keystone + * + * @author Adrian Cole + * @see TemporaryUrlKeyApi + */ +@SkipEncoding('/') +@RequestFilters(AuthenticateRequest.class) +@Endpoint(Storage.class) +public interface KeystoneTemporaryUrlKeyAsyncApi extends TemporaryUrlKeyAsyncApi { + +} diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/functions/ParseTemporaryUrlKeyFromHeaders.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/functions/ParseTemporaryUrlKeyFromHeaders.java index c126fca7ee..349dab3334 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/functions/ParseTemporaryUrlKeyFromHeaders.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/functions/ParseTemporaryUrlKeyFromHeaders.java @@ -18,14 +18,12 @@ */ package org.jclouds.openstack.swift.functions; -import com.google.common.base.Function; -import com.google.common.collect.Multimap; -import org.jclouds.http.HttpResponse; -import org.jclouds.openstack.swift.reference.SwiftHeaders; - -import static com.google.common.collect.Iterables.getOnlyElement; import static org.jclouds.openstack.swift.reference.SwiftHeaders.ACCOUNT_TEMPORARY_URL_KEY; +import org.jclouds.http.HttpResponse; + +import com.google.common.base.Function; + /** * @author Andrei Savu */ @@ -33,11 +31,6 @@ public class ParseTemporaryUrlKeyFromHeaders implements Function headers = httpResponse.getHeaders(); - if (headers.containsKey(ACCOUNT_TEMPORARY_URL_KEY)) { - return getOnlyElement(headers.get(ACCOUNT_TEMPORARY_URL_KEY)); - } else { - return null; - } + return httpResponse.getFirstHeaderOrNull(ACCOUNT_TEMPORARY_URL_KEY); } } diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/CommonSwiftClientTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/CommonSwiftClientTest.java index 667f3d0c0e..3023e5e551 100644 --- a/apis/swift/src/test/java/org/jclouds/openstack/swift/CommonSwiftClientTest.java +++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/CommonSwiftClientTest.java @@ -21,33 +21,32 @@ package org.jclouds.openstack.swift; import static org.jclouds.Constants.PROPERTY_API_VERSION; import static org.jclouds.Constants.PROPERTY_ENDPOINT; import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS; -import static org.jclouds.rest.config.BinderUtils.bindClientAndAsyncClient; import java.net.URI; import java.util.Properties; import javax.inject.Singleton; -import com.google.common.base.Suppliers; -import com.google.inject.*; -import com.google.inject.util.Modules; import org.jclouds.apis.ApiMetadata; -import org.jclouds.date.TimeStamp; +import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.http.HttpRequest; import org.jclouds.openstack.functions.URIFromAuthenticationResponseForService; import org.jclouds.openstack.internal.TestOpenStackAuthenticationModule; import org.jclouds.openstack.reference.AuthHeaders; +import org.jclouds.openstack.swift.blobstore.SwiftBlobSigner; import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule; +import org.jclouds.openstack.swift.blobstore.config.TemporaryUrlExtensionModule; import org.jclouds.openstack.swift.config.SwiftRestClientModule; -import org.jclouds.openstack.swift.extensions.TemporaryUrlKeyApi; -import org.jclouds.openstack.swift.extensions.TemporaryUrlKeyAsyncApi; -import org.jclouds.openstack.swift.suppliers.ReturnOrFetchTemporaryUrlKey; import org.jclouds.rest.internal.BaseAsyncClientTest; import org.jclouds.rest.internal.RestAnnotationProcessor; import org.testng.annotations.Test; import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; +import com.google.inject.Provides; +import com.google.inject.TypeLiteral; /** * Tests behavior of {@code BindSwiftObjectMetadataToRequest} @@ -83,25 +82,34 @@ public abstract class CommonSwiftClientTest extends BaseAsyncClientTest { @Override protected Long unixEpochTimestampProvider() { return UNIX_EPOCH_TIMESTAMP; } @Override - protected void configureTemporaryUrlExtension() { - bindClientAndAsyncClient(binder(), TemporaryUrlKeyApi.class, TemporaryUrlKeyAsyncApi.class); + protected void configure() { + bindTemporaryUrlKeyApi(); bind(new TypeLiteral>() { }).annotatedWith(TemporaryUrlKey.class).toInstance(Suppliers.ofInstance(TEMPORARY_URL_KEY)); } + + @Override + protected void bindRequestSigner() { + bind(BlobRequestSigner.class).to(new TypeLiteral>() { + }); + } } @Override protected ApiMetadata createApiMetadata() { - return new SwiftApiMetadata().toBuilder().defaultModules( - ImmutableSet.>of(StorageEndpointModule.class, SwiftRestClientModule.class, - StaticTimeAndTemporaryUrlKeyModule.class)).build(); + return new SwiftApiMetadata().toBuilder() + .defaultModules(ImmutableSet.>builder() + .add(StorageEndpointModule.class) + .add(SwiftRestClientModule.class) + .add(SwiftBlobStoreContextModule.class) + .add(StaticTimeAndTemporaryUrlKeyModule.class).build()).build(); } @Override diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftBlobRequestSignerTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftBlobRequestSignerTest.java deleted file mode 100644 index f16199ec10..0000000000 --- a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftBlobRequestSignerTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds licenses this file - * to you 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.openstack.swift.blobstore; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; - -import java.io.IOException; -import java.util.Date; - -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.openstack.swift.CommonSwiftClientTest; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -/** - * Tests behavior of {@code CommonSwiftBlobRequestSigner} - * - * @author Adrian Cole - */ -// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire -@Test(groups = "unit", testName = "SwiftBlobRequestSignerTest") -public class SwiftBlobRequestSignerTest extends CommonSwiftClientTest { - - private BlobRequestSigner signer; - private Factory blobFactory; - - public void testSignGetBlob() throws Exception { - HttpRequest request = signer.signGetBlob("container", "name"); - - assertRequestLineEquals(request, "GET http://storage/container/name HTTP/1.1"); - assertNonPayloadHeadersEqual(request, "X-Auth-Token: testtoken\n"); - assertPayloadEquals(request, null, null, false); - - assertEquals(request.getFilters().size(), 0); - } - - public void testSignGetBlobWithTime() { - HttpRequest request = signer.signGetBlob("container", "name", 120); - - assertRequestLineEquals(request, "GET http://storage/container/name?" + - "temp_url_sig=4759d99d13c826bba0af2c9f0c526ca53c95abaf&temp_url_expires=123456909 HTTP/1.1"); - assertFalse(request.getHeaders().containsKey("X-Auth-Token")); - assertPayloadEquals(request, null, null, false); - - assertEquals(request.getFilters().size(), 0); - } - - public void testSignPutBlob() throws Exception { - Blob blob = blobFactory.create(null); - blob.getMetadata().setName("name"); - blob.setPayload(""); - blob.getPayload().getContentMetadata().setContentLength(2l); - blob.getPayload().getContentMetadata().setContentMD5(new byte[] { 0, 2, 4, 8 }); - blob.getPayload().getContentMetadata().setContentType("text/plain"); - blob.getPayload().getContentMetadata().setExpires(new Date(1000)); - - HttpRequest request = signer.signPutBlob("container", blob); - - assertRequestLineEquals(request, "PUT http://storage/container/name HTTP/1.1"); - assertNonPayloadHeadersEqual(request, "X-Auth-Token: testtoken\n"); - assertContentHeadersEqual(request, "text/plain", null, null, null, (long) 2l, new byte[] { 0, 2, 4, 8 }, new Date(1000)); - - assertEquals(request.getFilters().size(), 0); - } - - public void testSignPutBlobWithTime() throws Exception { - Blob blob = blobFactory.create(null); - - blob.getMetadata().setName("name"); - blob.setPayload(""); - blob.getPayload().getContentMetadata().setContentLength(2l); - blob.getPayload().getContentMetadata().setContentMD5(new byte[]{0, 2, 4, 8}); - blob.getPayload().getContentMetadata().setContentType("text/plain"); - blob.getPayload().getContentMetadata().setExpires(new Date(1000)); - - HttpRequest request = signer.signPutBlob("container", blob, 120 /* seconds */); - - assertRequestLineEquals(request, "PUT http://storage/container/name?" + - "temp_url_sig=490690286130adac9e7144d85b320a00b1bf9e2b&temp_url_expires=123456909 HTTP/1.1"); - - assertFalse(request.getHeaders().containsKey("X-Auth-Token")); - assertContentHeadersEqual(request, "text/plain", null, null, null, (long) 2l, new byte[]{0, 2, 4, 8}, new Date(1000)); - - assertEquals(request.getFilters().size(), 0); - } - - public void testSignRemoveBlob() throws Exception { - HttpRequest request = signer.signRemoveBlob("container", "name"); - - assertRequestLineEquals(request, "DELETE http://storage/container/name HTTP/1.1"); - assertNonPayloadHeadersEqual(request, "X-Auth-Token: testtoken\n"); - assertPayloadEquals(request, null, null, false); - - 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); - } - -} diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftBlobSignerExpectTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftBlobSignerExpectTest.java new file mode 100644 index 0000000000..d67448cbda --- /dev/null +++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftBlobSignerExpectTest.java @@ -0,0 +1,140 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you 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.openstack.swift.blobstore; + +import static org.jclouds.openstack.swift.reference.SwiftHeaders.ACCOUNT_TEMPORARY_URL_KEY; + +import java.util.Map; + +import org.jclouds.apis.ApiMetadata; +import org.jclouds.blobstore.internal.BaseBlobSignerExpectTest; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.swift.CommonSwiftClientTest.StorageEndpointModule; +import org.jclouds.openstack.swift.SwiftApiMetadata; +import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule; +import org.jclouds.openstack.swift.blobstore.config.TemporaryUrlExtensionModule.SwiftTemporaryUrlExtensionModule; +import org.jclouds.openstack.swift.config.SwiftRestClientModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; + +/** + * Tests behavior of {@code SwiftBlobRequestSigner} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "SwiftBlobSignerExpectTest") +public class SwiftBlobSignerExpectTest extends BaseBlobSignerExpectTest { + + public SwiftBlobSignerExpectTest() { + identity = "test:tester"; + credential = "testing"; + } + + @Override + protected HttpRequest getBlob() { + return HttpRequest.builder().method("GET") + .endpoint("http://storage/container/name") + .addHeader("X-Auth-Token", "testtoken").build(); + } + + @Override + protected HttpRequest getBlobWithTime() { + return HttpRequest.builder().method("GET") + .endpoint("http://storage/container/name?temp_url_sig=2abd47f6b1c159fe9a45c873aaade8eeeb36a2e1&temp_url_expires=123456792").build(); + } + + @Override + protected HttpRequest getBlobWithOptions() { + return HttpRequest.builder().method("GET") + .endpoint("http://storage/container/name") + .addHeader("X-Auth-Token", "testtoken") + .addHeader("Range", "bytes=0-1").build(); + } + + @Override + protected HttpRequest putBlob() { + return HttpRequest.builder().method("PUT") + .endpoint("http://storage/container/name") + .addHeader("X-Auth-Token", "testtoken").build(); + } + + @Override + protected HttpRequest putBlobWithTime() { + return HttpRequest.builder().method("PUT") + .endpoint("http://storage/container/name?temp_url_sig=e894c60fa1284cc575cf22d7786bab07b8c33610&temp_url_expires=123456792").build(); + } + + @Override + protected HttpRequest removeBlob() { + return HttpRequest.builder().method("DELETE") + .endpoint("http://storage/container/name") + .addHeader("X-Auth-Token", "testtoken").build(); + } + + @Override + protected Map init() { + HttpRequest authRequest = HttpRequest.builder().method("GET") + .endpoint("http://auth/v1.0") + .addHeader("X-Auth-User", identity) + .addHeader("X-Auth-Key", credential) + .addHeader("Accept", "*/*") + .addHeader("Host", "myhost:8080").build(); + + HttpResponse authResponse = HttpResponse.builder().statusCode(200) + .message("HTTP/1.1 200 OK") + .addHeader("X-Storage-Url", "http://storage") + .addHeader("X-Auth-Token", "testtoken").build(); + + HttpRequest temporaryKeyRequest = HttpRequest.builder().method("HEAD") + .endpoint("http://storage/") + .addHeader("X-Auth-Token", "testtoken").build(); + + HttpResponse temporaryKeyResponse = HttpResponse.builder().statusCode(200) + .addHeader(ACCOUNT_TEMPORARY_URL_KEY, "TEMPORARY_KEY").build(); + + return ImmutableMap. builder() + .put(authRequest, authResponse) + .put(temporaryKeyRequest, temporaryKeyResponse).build(); + } + + public static class StaticTimeAndTemporaryUrlKeyModule extends SwiftTemporaryUrlExtensionModule { + + @Override + protected Long unixEpochTimestampProvider() { + return 123456789L; + } + } + + @Override + protected ApiMetadata createApiMetadata() { + return new SwiftApiMetadata() + .toBuilder() + .defaultEndpoint("http://auth") + .defaultModules( + ImmutableSet.> builder() + .add(StorageEndpointModule.class) + .add(SwiftRestClientModule.class) + .add(SwiftBlobStoreContextModule.class) + .add(StaticTimeAndTemporaryUrlKeyModule.class).build()).build(); + } +} diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftKeystoneBlobSignerExpectTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftKeystoneBlobSignerExpectTest.java new file mode 100644 index 0000000000..130ea8b017 --- /dev/null +++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftKeystoneBlobSignerExpectTest.java @@ -0,0 +1,142 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you 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.openstack.swift.blobstore; + +import static org.jclouds.openstack.swift.reference.SwiftHeaders.ACCOUNT_TEMPORARY_URL_KEY; + +import java.util.Map; + +import org.jclouds.apis.ApiMetadata; +import org.jclouds.blobstore.internal.BaseBlobSignerExpectTest; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; +import org.jclouds.openstack.swift.SwiftKeystoneApiMetadata; +import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule; +import org.jclouds.openstack.swift.blobstore.config.TemporaryUrlExtensionModule.SwiftKeystoneTemporaryUrlExtensionModule; +import org.jclouds.openstack.swift.config.SwiftKeystoneRestClientModule; +import org.jclouds.openstack.swift.config.SwiftRestClientModule.KeystoneStorageEndpointModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; + +/** + * Tests behavior of {@code SwiftBlobRequestSigner} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "SwiftKeystoneBlobSignerExpectTest") +public class SwiftKeystoneBlobSignerExpectTest extends BaseBlobSignerExpectTest { + + @Override + protected HttpRequest getBlob() { + return HttpRequest.builder().method("GET") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name") + .addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").build(); + } + + @Override + protected HttpRequest getBlobWithTime() { + return HttpRequest.builder().method("GET") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name?temp_url_sig=fd9b09acbc3ce71182240503c803dda4902098a9&temp_url_expires=123456792").build(); + } + + @Override + protected HttpRequest getBlobWithOptions() { + return HttpRequest.builder().method("GET") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name") + .addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").addHeader("Range", "bytes=0-1").build(); + } + + @Override + protected HttpRequest putBlob() { + return HttpRequest.builder().method("PUT") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name") + .addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").build(); + } + + @Override + protected HttpRequest putBlobWithTime() { + return HttpRequest.builder().method("PUT") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name?temp_url_sig=72e5f6ebafab2b3da0586198797e58fb7478211e&temp_url_expires=123456792").build(); + } + + @Override + protected HttpRequest removeBlob() { + return HttpRequest.builder().method("DELETE") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name") + .addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").build(); + } + + /** + * add the keystone commands + */ + @Override + protected Map init() { + + HttpRequest authenticate = HttpRequest + .builder() + .method("POST") + .endpoint("http://localhost:5000/v2.0/tokens") + .addHeader("Accept", "application/json") + .payload( + payloadFromStringWithContentType( + "{\"auth\":{\"passwordCredentials\":{\"username\":\"identity\",\"password\":\"credential\"}}}", + "application/json")).build(); + + HttpResponse authenticationResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/keystoneAuthResponse.json", "application/json")) + .build(); + + HttpRequest temporaryKeyRequest = HttpRequest + .builder() + .method("HEAD") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/") + .addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").build(); + + HttpResponse temporaryKeyResponse = HttpResponse.builder().statusCode(200) + .addHeader(ACCOUNT_TEMPORARY_URL_KEY, "TEMPORARY_KEY").build(); + + return ImmutableMap. builder() + .put(authenticate, authenticationResponse) + .put(temporaryKeyRequest, temporaryKeyResponse).build(); + } + + public static class StaticTimeAndTemporaryUrlKeyModule extends SwiftKeystoneTemporaryUrlExtensionModule { + public static final long UNIX_EPOCH_TIMESTAMP = 123456789L; + + @Override + protected Long unixEpochTimestampProvider() { + return UNIX_EPOCH_TIMESTAMP; + } + } + + @Override + protected ApiMetadata createApiMetadata() { + return new SwiftKeystoneApiMetadata().toBuilder() + .defaultModules(ImmutableSet.>builder() + .add(KeystoneStorageEndpointModule.class) + .add(KeystoneAuthenticationModule.RegionModule.class) + .add(SwiftKeystoneRestClientModule.class) + .add(SwiftBlobStoreContextModule.class) + .add(StaticTimeAndTemporaryUrlKeyModule.class).build()).build(); + } +} diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/integration/SwiftBlobLiveTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/integration/SwiftBlobLiveTest.java index c1b0ff7a67..e18e85fd34 100644 --- a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/integration/SwiftBlobLiveTest.java +++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/integration/SwiftBlobLiveTest.java @@ -19,18 +19,13 @@ package org.jclouds.openstack.swift.blobstore.integration; import java.util.Properties; -import java.util.UUID; import org.jclouds.blobstore.integration.internal.BaseBlobLiveTest; import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties; -import org.jclouds.openstack.swift.extensions.TemporaryUrlKeyApi; import org.testng.annotations.Test; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; - /** - * + * * @author James Murty * @author Adrian Cole */ @@ -42,7 +37,7 @@ public class SwiftBlobLiveTest extends BaseBlobLiveTest { setIfTestSystemPropertyPresent(props, KeystoneProperties.CREDENTIAL_TYPE); return props; } - + public SwiftBlobLiveTest() { provider = System.getProperty("test.swift.provider", "swift"); } diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/internal/StubSwiftAsyncClient.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/internal/StubSwiftAsyncClient.java index 2d0fb1584a..477c53628c 100644 --- a/apis/swift/src/test/java/org/jclouds/openstack/swift/internal/StubSwiftAsyncClient.java +++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/internal/StubSwiftAsyncClient.java @@ -31,7 +31,6 @@ import java.util.concurrent.ExecutorService; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import javax.ws.rs.HeaderParam; import org.jclouds.Constants; import org.jclouds.blobstore.LocalAsyncBlobStore; @@ -61,11 +60,10 @@ import com.google.common.base.Throwables; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.common.util.concurrent.ListenableFuture; -import org.jclouds.openstack.swift.reference.SwiftHeaders; /** * Implementation of {@link SwiftAsyncClient} which keeps all data in a local Map object. - * + * * @author Adrian Cole */ @Singleton diff --git a/blobstore/src/test/java/org/jclouds/blobstore/internal/BaseBlobSignerExpectTest.java b/blobstore/src/test/java/org/jclouds/blobstore/internal/BaseBlobSignerExpectTest.java new file mode 100644 index 0000000000..c28fc3168d --- /dev/null +++ b/blobstore/src/test/java/org/jclouds/blobstore/internal/BaseBlobSignerExpectTest.java @@ -0,0 +1,121 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you 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 static org.jclouds.blobstore.options.GetOptions.Builder.range; +import static org.testng.Assert.assertEquals; + +import java.util.Date; +import java.util.Map; +import java.util.Properties; + +import org.jclouds.blobstore.BlobStore; +import org.jclouds.blobstore.domain.Blob; +import org.jclouds.blobstore.options.GetOptions; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.rest.internal.BaseRestClientExpectTest; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.inject.Module; + +/** + * @author Adrian Cole + */ +public abstract class BaseBlobSignerExpectTest extends BaseRestClientExpectTest { + + /** + * define the requests and responses needed to initialize the blobstore. For + * example, you may need to add in discovery requests needed (ex. KeyStone in + */ + protected Map init() { + return ImmutableMap. of(); + } + + protected String container = "container"; + protected String name = "name"; + protected String text = "fooooooooooooooooooooooo"; + protected GetOptions options = range(0, 1); + + @Test + public void testSignGetBlob() { + BlobStore getBlob = requestsSendResponses(init()); + assertEquals(getBlob.getContext().getSigner().signGetBlob(container, name), getBlob()); + } + + protected abstract HttpRequest getBlob(); + + @Test + public void testSignGetBlobWithTime() { + BlobStore getBlobWithTime = requestsSendResponses(init()); + HttpRequest compare = getBlobWithTime(); + assertEquals(getBlobWithTime.getContext().getSigner().signGetBlob(container, name, 3l /* seconds */), + compare); + } + + protected abstract HttpRequest getBlobWithTime(); + + @Test + public void testSignGetBlobWithOptions() { + BlobStore getBlobWithOptions = requestsSendResponses(init()); + assertEquals(getBlobWithOptions.getContext().getSigner().signGetBlob(container, name, options), + getBlobWithOptions()); + } + + protected abstract HttpRequest getBlobWithOptions(); + + @Test + public void testSignRemoveBlob() { + BlobStore removeBlob = requestsSendResponses(init()); + assertEquals(removeBlob.getContext().getSigner().signRemoveBlob(container, name), removeBlob()); + } + + @Test + public void testSignPutBlob() throws Exception { + BlobStore signPutBlob = requestsSendResponses(init()); + Blob blob = signPutBlob.blobBuilder("name").forSigning().contentLength(2l).contentMD5(new byte[] { 0, 2, 4, 8 }) + .contentType("text/plain").expires(new Date(1000)).build(); + HttpRequest compare = putBlob(); + compare.setPayload(blob.getPayload()); + assertEquals(signPutBlob.getContext().getSigner().signPutBlob(container, blob), compare); + } + + protected abstract HttpRequest putBlob(); + + @Test + public void testSignPutBlobWithTime() throws Exception { + BlobStore signPutBloblWithTime = requestsSendResponses(init()); + Blob blob = signPutBloblWithTime.blobBuilder(name).payload(text).contentType("text/plain").build(); + HttpRequest compare = putBlobWithTime(); + compare.setPayload(blob.getPayload()); + assertEquals(signPutBloblWithTime.getContext().getSigner().signPutBlob(container, blob, 3l /* seconds */), + compare); + } + + protected abstract HttpRequest putBlobWithTime(); + + protected abstract HttpRequest removeBlob(); + + @Override + public BlobStore createClient(Function fn, Module module, Properties props) { + return createInjector(fn, module, props).getInstance(BlobStore.class); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/io/payloads/BaseMutableContentMetadata.java b/core/src/main/java/org/jclouds/io/payloads/BaseMutableContentMetadata.java index ac2045e966..a4db8f1fd6 100644 --- a/core/src/main/java/org/jclouds/io/payloads/BaseMutableContentMetadata.java +++ b/core/src/main/java/org/jclouds/io/payloads/BaseMutableContentMetadata.java @@ -26,8 +26,6 @@ import org.jclouds.io.ContentMetadataBuilder; import org.jclouds.io.MutableContentMetadata; import org.jclouds.javax.annotation.Nullable; -import com.google.common.collect.Multimap; - /** * @author Adrian Cole */ diff --git a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java index 38d2dbe0ff..6086eff825 100644 --- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java +++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java @@ -169,7 +169,7 @@ import com.google.inject.util.Types; /** * Creates http methods based on annotations on a class or interface. - * + * * @author Adrian Cole */ public class RestAnnotationProcessor { @@ -192,7 +192,7 @@ public class RestAnnotationProcessor { static final LoadingCache>> methodToIndexOfParamToPostParamAnnotations = createMethodToIndexOfParamToAnnotation(PayloadParam.class); static final LoadingCache>> methodToIndexOfParamToPartParamAnnotations = createMethodToIndexOfParamToAnnotation(PartParam.class); static final LoadingCache>> methodToIndexOfParamToParamParserAnnotations = createMethodToIndexOfParamToAnnotation(ParamParser.class); - + final Cache delegationMap; static LoadingCache>> createMethodToIndexOfParamToAnnotation( @@ -322,7 +322,7 @@ public class RestAnnotationProcessor { @SuppressWarnings("unchecked") @Inject - public RestAnnotationProcessor(Injector injector, LoadingCache, Boolean> seedAnnotationCache, Cache delegationMap, + public RestAnnotationProcessor(Injector injector, LoadingCache, Boolean> seedAnnotationCache, Cache delegationMap, @ApiVersion String apiVersion, @BuildVersion String buildVersion, ParseSax.Factory parserFactory, HttpUtils utils, ContentMetadataCodec contentMetadataCodec, TypeLiteral typeLiteral) throws ExecutionException { this.declaring = (Class) typeLiteral.getRawType(); @@ -343,7 +343,7 @@ public class RestAnnotationProcessor { this.buildVersion = buildVersion; } - + public Method getDelegateOrNull(Method in) { return delegationMap.getIfPresent(new MethodKey(in)); } @@ -364,7 +364,7 @@ public class RestAnnotationProcessor { && Objects.equal(this.name, that.name) && Objects.equal(this.parametersTypeHashCode, that.parametersTypeHashCode); } - + private final String name; private final int parametersTypeHashCode; private final Class declaringClass; @@ -838,7 +838,7 @@ public class RestAnnotationProcessor { Type returnVal = getReturnTypeForMethod(method); return getJsonParserKeyForMethodAnType(method, returnVal); } - + @SuppressWarnings("unchecked") public static Key> getJAXBParserKeyForMethod(Method method) { Type returnVal = getReturnTypeForMethod(method); @@ -1334,4 +1334,10 @@ public class RestAnnotationProcessor { return postParams; } + /** + * the class that is being processed + */ + public Class getDeclaring(){ + return declaring; + } } diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageApiMetadata.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageApiMetadata.java index 4586f48b19..e444f92c6c 100644 --- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageApiMetadata.java +++ b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageApiMetadata.java @@ -18,30 +18,38 @@ */ package org.jclouds.hpcloud.objectstorage; +import static org.jclouds.rest.config.BinderUtils.bindClientAndAsyncClient; + import java.net.URI; import java.util.Properties; import org.jclouds.apis.ApiMetadata; +import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.hpcloud.objectstorage.blobstore.config.HPCloudObjectStorageBlobStoreContextModule; import org.jclouds.hpcloud.objectstorage.config.HPCloudObjectStorageRestClientModule; import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule; import org.jclouds.openstack.swift.SwiftKeystoneApiMetadata; +import org.jclouds.openstack.swift.blobstore.SwiftBlobSigner; +import org.jclouds.openstack.swift.blobstore.config.TemporaryUrlExtensionModule; import org.jclouds.openstack.swift.config.SwiftRestClientModule.KeystoneStorageEndpointModule; +import org.jclouds.openstack.swift.extensions.KeystoneTemporaryUrlKeyAsyncApi; +import org.jclouds.openstack.swift.extensions.TemporaryUrlKeyApi; import org.jclouds.rest.RestContext; import com.google.common.collect.ImmutableSet; import com.google.common.reflect.TypeToken; import com.google.inject.Module; +import com.google.inject.TypeLiteral; /** * Implementation of {@link org.jclouds.providers.ProviderMetadata} for HP Cloud Services Object Storage - * + * * @author Jeremy Daggett */ public class HPCloudObjectStorageApiMetadata extends SwiftKeystoneApiMetadata { /** The serialVersionUID */ private static final long serialVersionUID = 820062881469203616L; - + public static final TypeToken> CONTEXT_TOKEN = new TypeToken>() { private static final long serialVersionUID = -5070937833892503232L; }; @@ -82,7 +90,8 @@ public class HPCloudObjectStorageApiMetadata extends SwiftKeystoneApiMetadata { .add(KeystoneStorageEndpointModule.class) .add(RegionModule.class) .add(HPCloudObjectStorageRestClientModule.class) - .add(HPCloudObjectStorageBlobStoreContextModule.class).build()); + .add(HPCloudObjectStorageBlobStoreContextModule.class) + .add(HPCloudObjectStorageTemporaryUrlExtensionModule.class).build()); } @Override @@ -96,4 +105,24 @@ public class HPCloudObjectStorageApiMetadata extends SwiftKeystoneApiMetadata { return this; } } + + /** + * Ensures keystone auth is used instead of swift auth + * + */ + public static class HPCloudObjectStorageTemporaryUrlExtensionModule extends + TemporaryUrlExtensionModule { + + @Override + protected void bindRequestSigner() { + bind(BlobRequestSigner.class).to(new TypeLiteral>() { + }); + } + + @Override + protected void bindTemporaryUrlKeyApi() { + bindClientAndAsyncClient(binder(), TemporaryUrlKeyApi.class, KeystoneTemporaryUrlKeyAsyncApi.class); + } + + } } diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobRequestSigner.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobRequestSigner.java deleted file mode 100644 index b2f6ffa392..0000000000 --- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobRequestSigner.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.jclouds.hpcloud.objectstorage.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.blobstore.functions.BlobToHttpGetOptions; -import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageAsyncApi; -import org.jclouds.http.HttpRequest; -import org.jclouds.http.options.GetOptions; -import org.jclouds.openstack.swift.blobstore.functions.BlobToObject; -import org.jclouds.openstack.swift.domain.SwiftObject; -import org.jclouds.rest.internal.RestAnnotationProcessor; - -/** - * @author Adrian Cole - */ -@Singleton -public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner { - private final RestAnnotationProcessor processor; - private final BlobToObject blobToObject; - private final BlobToHttpGetOptions blob2HttpGetOptions; - - private final Method getMethod; - private final Method deleteMethod; - private final Method createMethod; - - @Inject - public HPCloudObjectStorageBlobRequestSigner(RestAnnotationProcessor processor, BlobToObject blobToObject, - BlobToHttpGetOptions blob2HttpGetOptions) throws SecurityException, NoSuchMethodException { - this.processor = checkNotNull(processor, "processor"); - this.blobToObject = checkNotNull(blobToObject, "blobToObject"); - this.blob2HttpGetOptions = checkNotNull(blob2HttpGetOptions, "blob2HttpGetOptions"); - this.getMethod = HPCloudObjectStorageAsyncApi.class.getMethod("getObject", String.class, String.class, - GetOptions[].class); - this.deleteMethod = HPCloudObjectStorageAsyncApi.class.getMethod("removeObject", String.class, String.class); - this.createMethod = HPCloudObjectStorageAsyncApi.class.getMethod("putObject", String.class, SwiftObject.class); - } - - @Override - public HttpRequest signGetBlob(String container, String name) { - return cleanRequest(processor.createRequest(getMethod, container, name)); - } - - @Override - public HttpRequest signGetBlob(String container, String name, long timeInSeconds) { - throw new UnsupportedOperationException(); - } - - @Override - public HttpRequest signPutBlob(String container, Blob blob) { - return cleanRequest(processor.createRequest(createMethod, container, blobToObject.apply(blob))); - } - - @Override - public HttpRequest signPutBlob(String container, Blob blob, long timeInSeconds) { - throw new UnsupportedOperationException(); - } - - @Override - public HttpRequest signRemoveBlob(String container, String name) { - return cleanRequest(processor.createRequest(deleteMethod, container, name)); - } - - @Override - public HttpRequest signGetBlob(String container, String name, org.jclouds.blobstore.options.GetOptions options) { - return cleanRequest(processor.createRequest(getMethod, container, name, blob2HttpGetOptions.apply(options))); - } -} diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/config/HPCloudObjectStorageBlobStoreContextModule.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/config/HPCloudObjectStorageBlobStoreContextModule.java index 5b91f497d7..e02cfe0500 100644 --- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/config/HPCloudObjectStorageBlobStoreContextModule.java +++ b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/config/HPCloudObjectStorageBlobStoreContextModule.java @@ -29,13 +29,11 @@ import javax.inject.Inject; import javax.inject.Singleton; import org.jclouds.blobstore.AsyncBlobStore; -import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.attr.ConsistencyModel; import org.jclouds.blobstore.config.BlobStoreMapModule; import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageApi; import org.jclouds.hpcloud.objectstorage.blobstore.HPCloudObjectStorageAsyncBlobStore; -import org.jclouds.hpcloud.objectstorage.blobstore.HPCloudObjectStorageBlobRequestSigner; import org.jclouds.hpcloud.objectstorage.blobstore.HPCloudObjectStorageBlobStore; import org.jclouds.hpcloud.objectstorage.blobstore.functions.HPCloudObjectStorageObjectToBlobMetadata; import org.jclouds.hpcloud.objectstorage.domain.CDNContainer; @@ -53,7 +51,7 @@ import com.google.common.cache.LoadingCache; import com.google.inject.Provides; /** - * + * * @author Adrian Cole */ public class HPCloudObjectStorageBlobStoreContextModule extends SwiftBlobStoreContextModule { @@ -99,7 +97,7 @@ public class HPCloudObjectStorageBlobStoreContextModule extends SwiftBlobStoreCo protected LoadingCache cdnContainer(GetCDNMetadata loader) { return CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.SECONDS).build(loader); } - + @Override protected void configure() { install(new BlobStoreMapModule()); @@ -107,6 +105,5 @@ public class HPCloudObjectStorageBlobStoreContextModule extends SwiftBlobStoreCo bind(AsyncBlobStore.class).to(HPCloudObjectStorageAsyncBlobStore.class); bind(BlobStore.class).to(HPCloudObjectStorageBlobStore.class); bind(ObjectToBlobMetadata.class).to(HPCloudObjectStorageObjectToBlobMetadata.class); - bind(BlobRequestSigner.class).to(HPCloudObjectStorageBlobRequestSigner.class); } } diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/config/HPCloudObjectStorageRestClientModule.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/config/HPCloudObjectStorageRestClientModule.java index dc28e2fb72..4db5bda2a5 100644 --- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/config/HPCloudObjectStorageRestClientModule.java +++ b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/config/HPCloudObjectStorageRestClientModule.java @@ -25,10 +25,10 @@ import java.util.Map; import javax.inject.Singleton; -import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageAsyncApi; import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageApi; -import org.jclouds.hpcloud.objectstorage.extensions.CDNContainerAsyncApi; +import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageAsyncApi; import org.jclouds.hpcloud.objectstorage.extensions.CDNContainerApi; +import org.jclouds.hpcloud.objectstorage.extensions.CDNContainerAsyncApi; import org.jclouds.hpcloud.services.HPExtensionCDN; import org.jclouds.hpcloud.services.HPExtensionServiceType; import org.jclouds.location.suppliers.RegionIdToURISupplier; @@ -45,7 +45,7 @@ import com.google.inject.Provides; import com.google.inject.Scopes; /** - * + * * @author Adrian Cole */ @ConfiguresRestClient @@ -63,7 +63,7 @@ public class HPCloudObjectStorageRestClientModule extends bind(CommonSwiftClient.class).to(HPCloudObjectStorageApi.class).in(Scopes.SINGLETON); bind(CommonSwiftAsyncClient.class).to(HPCloudObjectStorageAsyncApi.class).in(Scopes.SINGLETON); } - + @Provides @Singleton @HPExtensionCDN diff --git a/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobRequestSignerTest.java b/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobRequestSignerTest.java deleted file mode 100644 index ab0351bb59..0000000000 --- a/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobRequestSignerTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds licenses this file - * to you 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.hpcloud.objectstorage.blobstore; - -import static org.testng.Assert.assertEquals; - -import java.util.Date; -import java.util.Map; - -import org.jclouds.blobstore.BlobRequestSigner; -import org.jclouds.blobstore.BlobStore; -import org.jclouds.blobstore.domain.Blob; -import org.jclouds.hpcloud.objectstorage.internal.BaseHPCloudObjectStorageBlobStoreExpectTest; -import org.jclouds.http.HttpRequest; -import org.jclouds.http.HttpResponse; -import org.testng.annotations.Test; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMultimap; - -/** - * Tests behavior of {@code HPCloudObjectStorageBlobRequestSigner} - * - * @author Adrian Cole - */ -// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire -@Test(groups = "unit", testName = "HPCloudObjectStorageBlobRequestSignerTest") -public class HPCloudObjectStorageBlobRequestSignerTest extends BaseHPCloudObjectStorageBlobStoreExpectTest { - - Map requestResponseMap = ImmutableMap. builder().put( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess).build(); - - public void testSignGetBlob() { - - BlobRequestSigner signGetBlob = requestsSendResponses(requestResponseMap).getContext().getSigner(); - - HttpRequest request = signGetBlob.signGetBlob("container", "name"); - - assertEquals(request.getRequestLine(), - "GET https://objects.jclouds.org/v1.0/40806637803162/container/name HTTP/1.1"); - assertEquals(request.getHeaders(), ImmutableMultimap.of("X-Auth-Token", "Auth_4f173437e4b013bee56d1007")); - } - - public void testSignRemoveBlob() { - BlobRequestSigner signRemoveBlob = requestsSendResponses(requestResponseMap).getContext().getSigner(); - - HttpRequest request = signRemoveBlob.signRemoveBlob("container", "name"); - assertEquals(request.getRequestLine(), - "DELETE https://objects.jclouds.org/v1.0/40806637803162/container/name HTTP/1.1"); - assertEquals(request.getHeaders(), ImmutableMultimap.of("X-Auth-Token", "Auth_4f173437e4b013bee56d1007")); - - } - - public void testSignPutBlob() { - BlobStore blobStore = requestsSendResponses(requestResponseMap); - BlobRequestSigner signPutBlob = blobStore.getContext().getSigner(); - Blob blob = blobStore.blobBuilder("name").forSigning().contentLength(2l).contentMD5(new byte[] { 0, 2, 4, 8 }) - .contentType("text/plain").expires(new Date(1000)).build(); - - HttpRequest request = signPutBlob.signPutBlob("container", blob); - - assertEquals(request.getRequestLine(), - "PUT https://objects.jclouds.org/v1.0/40806637803162/container/name HTTP/1.1"); - assertEquals(request.getHeaders(), ImmutableMultimap.of("X-Auth-Token", "Auth_4f173437e4b013bee56d1007")); - // TODO: - // assertEquals(request.getPayload(), blob); - - } - -} diff --git a/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobSignerExpectTest.java b/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobSignerExpectTest.java new file mode 100644 index 0000000000..497f24aaf7 --- /dev/null +++ b/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobSignerExpectTest.java @@ -0,0 +1,146 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you 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.hpcloud.objectstorage.blobstore; + +import static org.jclouds.openstack.swift.reference.SwiftHeaders.ACCOUNT_TEMPORARY_URL_KEY; + +import java.util.Map; + +import org.jclouds.apis.ApiMetadata; +import org.jclouds.blobstore.internal.BaseBlobSignerExpectTest; +import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageApiMetadata; +import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageApiMetadata.HPCloudObjectStorageTemporaryUrlExtensionModule; +import org.jclouds.hpcloud.objectstorage.blobstore.config.HPCloudObjectStorageBlobStoreContextModule; +import org.jclouds.hpcloud.objectstorage.config.HPCloudObjectStorageRestClientModule; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule; +import org.jclouds.openstack.swift.config.SwiftRestClientModule.KeystoneStorageEndpointModule; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; + +/** + * Tests behavior of {@code SwiftBlobRequestSigner} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "HPCloudObjectStorageBlobSignerExpectTest") +public class HPCloudObjectStorageBlobSignerExpectTest extends BaseBlobSignerExpectTest { + + public HPCloudObjectStorageBlobSignerExpectTest() { + identity = "12346637803162:identity"; + } + + @Override + protected HttpRequest getBlob() { + return HttpRequest.builder().method("GET") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name") + .addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").build(); + } + + @Override + protected HttpRequest getBlobWithTime() { + return HttpRequest.builder().method("GET") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name?temp_url_sig=fd9b09acbc3ce71182240503c803dda4902098a9&temp_url_expires=123456792").build(); + } + + @Override + protected HttpRequest getBlobWithOptions() { + return HttpRequest.builder().method("GET") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name") + .addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").addHeader("Range", "bytes=0-1").build(); + } + + @Override + protected HttpRequest putBlob() { + return HttpRequest.builder().method("PUT") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name") + .addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").build(); + } + + @Override + protected HttpRequest putBlobWithTime() { + return HttpRequest.builder().method("PUT") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name?temp_url_sig=72e5f6ebafab2b3da0586198797e58fb7478211e&temp_url_expires=123456792").build(); + } + + @Override + protected HttpRequest removeBlob() { + return HttpRequest.builder().method("DELETE") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/container/name") + .addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").build(); + } + + /** + * add the keystone commands + */ + @Override + protected Map init() { + + HttpRequest authenticate = HttpRequest + .builder() + .method("POST") + .endpoint("https://region-a.geo-1.identity.hpcloudsvc.com:35357/v2.0/tokens") + .addHeader("Accept", "application/json") + .payload( + payloadFromStringWithContentType( + "{\"auth\":{\"passwordCredentials\":{\"username\":\"identity\",\"password\":\"credential\"},\"tenantName\":\"12346637803162\"}}", + "application/json")).build(); + + HttpResponse authenticationResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/keystoneAuthResponseWithCDN.json", "application/json")) + .build(); + + HttpRequest temporaryKeyRequest = HttpRequest + .builder() + .method("HEAD") + .endpoint("https://objects.jclouds.org/v1.0/40806637803162/") + .addHeader("X-Auth-Token", "Auth_4f173437e4b013bee56d1007").build(); + + HttpResponse temporaryKeyResponse = HttpResponse.builder().statusCode(200) + .addHeader(ACCOUNT_TEMPORARY_URL_KEY, "TEMPORARY_KEY").build(); + + return ImmutableMap. builder() + .put(authenticate, authenticationResponse) + .put(temporaryKeyRequest, temporaryKeyResponse).build(); + } + + @Override + protected ApiMetadata createApiMetadata() { + return new HPCloudObjectStorageApiMetadata().toBuilder() + .defaultModules(ImmutableSet.>builder() + .add(KeystoneStorageEndpointModule.class) + .add(RegionModule.class) + .add(HPCloudObjectStorageRestClientModule.class) + .add(HPCloudObjectStorageBlobStoreContextModule.class) + .add(StaticTimeAndTemporaryUrlKeyModule.class).build()).build(); + } + + public static class StaticTimeAndTemporaryUrlKeyModule extends HPCloudObjectStorageTemporaryUrlExtensionModule { + public static final long UNIX_EPOCH_TIMESTAMP = 123456789L; + + @Override + protected Long unixEpochTimestampProvider() { + return UNIX_EPOCH_TIMESTAMP; + } + } +} diff --git a/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/integration/HPCloudObjectStorageBlobSignerLiveTest.java b/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/integration/HPCloudObjectStorageBlobSignerLiveTest.java index f78fa2436b..3f429f2a63 100644 --- a/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/integration/HPCloudObjectStorageBlobSignerLiveTest.java +++ b/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/integration/HPCloudObjectStorageBlobSignerLiveTest.java @@ -18,7 +18,10 @@ */ package org.jclouds.hpcloud.objectstorage.blobstore.integration; +import java.io.IOException; + import org.jclouds.openstack.swift.blobstore.integration.SwiftBlobSignerLiveTest; +import org.jclouds.rest.AuthorizationException; import org.testng.annotations.Test; /** @@ -30,4 +33,20 @@ public class HPCloudObjectStorageBlobSignerLiveTest extends SwiftBlobSignerLiveT provider = "hpcloud-objectstorage"; } + // hp doesn't yet support time-bound request signing + // https://api-docs.hpcloud.com/hpcloud-object-storage/1.0/content/ch_object-storage-dev-overview.html + @Override + @Test(expectedExceptions = AuthorizationException.class) + public void testSignGetUrlWithTime() throws InterruptedException, IOException { + super.testSignGetUrlWithTime(); + } + + // hp doesn't yet support time-bound request signing + // https://api-docs.hpcloud.com/hpcloud-object-storage/1.0/content/ch_object-storage-dev-overview.html + @Override + @Test(expectedExceptions = AuthorizationException.class) + public void testSignPutUrlWithTime() throws Exception { + super.testSignPutUrlWithTime(); + } + }