Merge pull request #889 from jclouds/issue-1096

Issue 1096: Guice errors when trying to get a signer for a keystone v2 password-auth BlobStore
This commit is contained in:
Adrian Cole 2012-10-10 04:06:33 -07:00
commit b49a3d555a
32 changed files with 1140 additions and 550 deletions

View File

@ -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<RestContext<CloudFilesClient, CloudFilesAsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<CloudFilesClient, CloudFilesAsyncClient>>() {
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.<Class<? extends Module>>of(StorageAndCDNManagementEndpointModule.class, CloudFilesRestClientModule.class, CloudFilesBlobStoreContextModule.class));
.defaultModules(ImmutableSet.<Class<? extends Module>>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<CloudFilesAsyncClient> {
@Override
protected void bindRequestSigner() {
bind(BlobRequestSigner.class).to(new TypeLiteral<SwiftBlobSigner<CloudFilesAsyncClient>>() {
});
}
}
}

View File

@ -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);
}
}

View File

@ -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<CloudFiles
.<Class<?>, Class<?>> of());
}
@Override
protected void bindResolvedClientsToCommonSwift() {
bind(CommonSwiftClient.class).to(CloudFilesClient.class).in(Scopes.SINGLETON);
bind(CommonSwiftAsyncClient.class).to(CloudFilesAsyncClient.class).in(Scopes.SINGLETON);

View File

@ -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<HttpRequest, HttpResponse> 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.<HttpRequest, HttpResponse> 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.<Class<? extends Module>> builder()
.add(StorageAndCDNManagementEndpointModule.class)
.add(CloudFilesRestClientModule.class)
.add(CloudFilesBlobStoreContextModule.class)
.add(StaticTimeAndTemporaryUrlKeyModule.class).build()).build();
}
}

View File

@ -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<S extends KeystoneApi, A extends KeystoneA
.put(TenantApi.class, TenantAsyncApi.class)
.build();
@SuppressWarnings("unchecked")
public KeystoneRestClientModule() {
super(TypeToken.class.cast(TypeToken.of(KeystoneApi.class)), TypeToken.class.cast(TypeToken.of(KeystoneAsyncApi.class)), DELEGATE_MAP);
}
@ -128,7 +129,7 @@ public class KeystoneRestClientModule<S extends KeystoneApi, A extends KeystoneA
bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
super.configure();
}
@Provides
@Singleton
public Multimap<URI, URI> aliases() {

View File

@ -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<S3AsyncClient> {
@Override
protected TypeLiteral<RestAnnotationProcessor<S3AsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<S3AsyncClient>>() {
};
}
private BlobRequestSigner signer;
private Provider<BlobBuilder> 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<S3Client, S3AsyncClient> {
@Override
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return "Thu, 05 Jun 2008 16:38:19 GMT";
}
}
}

View File

@ -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<S3Client, S3AsyncClient> {
@Override
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return "Thu, 05 Jun 2008 16:38:19 GMT";
}
}
}

View File

@ -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<RestContext<SwiftClient, SwiftAsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<SwiftClient, SwiftAsyncClient>>() {
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.<Class<? extends Module>>of(StorageEndpointModule.class, SwiftRestClientModule.class, SwiftBlobStoreContextModule.class));
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(StorageEndpointModule.class)
.add(SwiftRestClientModule.class)
.add(SwiftBlobStoreContextModule.class)
.add(SwiftTemporaryUrlExtensionModule.class).build());
}
@Override

View File

@ -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<RestContext<SwiftKeystoneClient, SwiftKeystoneAsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<SwiftKeystoneClient, SwiftKeystoneAsyncClient>>() {
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.<Class<? extends Module>>of(KeystoneStorageEndpointModule.class, KeystoneAuthenticationModule.RegionModule.class,
SwiftKeystoneRestClientModule.class, SwiftBlobStoreContextModule.class));
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(KeystoneStorageEndpointModule.class)
.add(KeystoneAuthenticationModule.RegionModule.class)
.add(SwiftKeystoneRestClientModule.class)
.add(SwiftBlobStoreContextModule.class)
.add(SwiftKeystoneTemporaryUrlExtensionModule.class).build());
}
@Override

View File

@ -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<T extends CommonSwiftAsyncClient> implements BlobRequestSigner {
private final RestAnnotationProcessor<CommonSwiftAsyncClient> processor;
private final RestAnnotationProcessor<T> processor;
private final Crypto crypto;
private final Provider<Long> 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<CommonSwiftAsyncClient> processor, BlobToObject blobToObject,
BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto, @TimeStamp Provider<Long> unixEpochTimestampProvider,
@TemporaryUrlKey Supplier<String> temporaryUrlKeySupplier) throws SecurityException, NoSuchMethodException {
protected SwiftBlobSigner(BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto,
@TimeStamp Provider<Long> unixEpochTimestampProvider,
@TemporaryUrlKey Supplier<String> temporaryUrlKeySupplier,
RestAnnotationProcessor<T> 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.<HttpRequestFilter>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);
}

View File

@ -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<Supplier<String>>() {
}).annotatedWith(TemporaryUrlKey.class).to(ReturnOrFetchTemporaryUrlKey.class);
}
}

View File

@ -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<A extends CommonSwiftAsyncClient> extends AbstractModule {
public static class SwiftTemporaryUrlExtensionModule extends TemporaryUrlExtensionModule<SwiftAsyncClient> {
@Override
protected void bindRequestSigner() {
bind(BlobRequestSigner.class).to(new TypeLiteral<SwiftBlobSigner<SwiftAsyncClient>>() {
});
}
}
/**
* Ensures keystone auth is used instead of swift auth
*
*/
public static class SwiftKeystoneTemporaryUrlExtensionModule extends
TemporaryUrlExtensionModule<SwiftKeystoneAsyncClient> {
protected void bindTemporaryUrlKeyApi() {
bindClientAndAsyncClient(binder(), TemporaryUrlKeyApi.class, KeystoneTemporaryUrlKeyAsyncApi.class);
}
@Override
protected void bindRequestSigner() {
bind(BlobRequestSigner.class).to(new TypeLiteral<SwiftBlobSigner<SwiftKeystoneAsyncClient>>() {
});
}
}
@Provides
@TimeStamp
protected Long unixEpochTimestampProvider() {
return System.currentTimeMillis() / 1000; /* convert to seconds */
}
@Override
protected void configure() {
bindRequestSigner();
bindTemporaryUrlKeyApi();
bind(new TypeLiteral<Supplier<String>>() {
}).annotatedWith(TemporaryUrlKey.class).to(ReturnOrFetchTemporaryUrlKey.class);
}
protected abstract void bindRequestSigner();
protected void bindTemporaryUrlKeyApi() {
bindClientAndAsyncClient(binder(), TemporaryUrlKeyApi.class, TemporaryUrlKeyAsyncApi.class);
}
}

View File

@ -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<SwiftKe
super(TypeToken.of(SwiftKeystoneClient.class), TypeToken.of(SwiftKeystoneAsyncClient.class), ImmutableMap
.<Class<?>, Class<?>> of());
}
protected void bindResolvedClientsToCommonSwift() {
bind(CommonSwiftClient.class).to(SwiftKeystoneClient.class).in(Scopes.SINGLETON);
bind(CommonSwiftAsyncClient.class).to(SwiftKeystoneAsyncClient.class).in(Scopes.SINGLETON);
}
}
}

View File

@ -54,23 +54,24 @@ import com.google.inject.Provides;
import com.google.inject.Scopes;
/**
*
*
* @author Adrian Cole
*/
@ConfiguresRestClient
public class SwiftRestClientModule<S extends CommonSwiftClient, A extends CommonSwiftAsyncClient> extends RestClientModule<S, A> {
public class SwiftRestClientModule<S extends CommonSwiftClient, A extends CommonSwiftAsyncClient> extends
RestClientModule<S, A> {
@SuppressWarnings("unchecked")
public SwiftRestClientModule() {
this(TypeToken.class.cast(TypeToken.of(SwiftClient.class)), TypeToken.class.cast(TypeToken
.of(SwiftAsyncClient.class)), ImmutableMap.<Class<?>, Class<?>> of());
.of(SwiftAsyncClient.class)), ImmutableMap.<Class<?>, Class<?>> of());
}
protected SwiftRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType,
Map<Class<?>, Class<?>> sync2Async) {
Map<Class<?>, Class<?>> sync2Async) {
super(syncClientType, asyncClientType, sync2Async);
}
public static class StorageEndpointModule extends OpenStackAuthenticationModule {
@Provides
@Singleton

View File

@ -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 {
}

View File

@ -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<HttpResponse, S
@Override
public String apply(HttpResponse httpResponse) {
Multimap<String, String> 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);
}
}

View File

@ -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<SwiftAsy
}
}
public static class StaticTimeAndTemporaryUrlKeyModule extends SwiftBlobStoreContextModule {
public static class StaticTimeAndTemporaryUrlKeyModule extends TemporaryUrlExtensionModule<SwiftAsyncClient> {
@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<Supplier<String>>() {
}).annotatedWith(TemporaryUrlKey.class).toInstance(Suppliers.ofInstance(TEMPORARY_URL_KEY));
}
@Override
protected void bindRequestSigner() {
bind(BlobRequestSigner.class).to(new TypeLiteral<SwiftBlobSigner<SwiftAsyncClient>>() {
});
}
}
@Override
protected ApiMetadata createApiMetadata() {
return new SwiftApiMetadata().toBuilder().defaultModules(
ImmutableSet.<Class<? extends Module>>of(StorageEndpointModule.class, SwiftRestClientModule.class,
StaticTimeAndTemporaryUrlKeyModule.class)).build();
return new SwiftApiMetadata().toBuilder()
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(StorageEndpointModule.class)
.add(SwiftRestClientModule.class)
.add(SwiftBlobStoreContextModule.class)
.add(StaticTimeAndTemporaryUrlKeyModule.class).build()).build();
}
@Override

View File

@ -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);
}
}

View File

@ -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<HttpRequest, HttpResponse> 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.<HttpRequest, HttpResponse> 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.<Class<? extends Module>> builder()
.add(StorageEndpointModule.class)
.add(SwiftRestClientModule.class)
.add(SwiftBlobStoreContextModule.class)
.add(StaticTimeAndTemporaryUrlKeyModule.class).build()).build();
}
}

View File

@ -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<HttpRequest, HttpResponse> 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.<HttpRequest, HttpResponse> 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.<Class<? extends Module>>builder()
.add(KeystoneStorageEndpointModule.class)
.add(KeystoneAuthenticationModule.RegionModule.class)
.add(SwiftKeystoneRestClientModule.class)
.add(SwiftBlobStoreContextModule.class)
.add(StaticTimeAndTemporaryUrlKeyModule.class).build()).build();
}
}

View File

@ -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");
}

View File

@ -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

View File

@ -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<BlobStore> {
/**
* 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<HttpRequest, HttpResponse> init() {
return ImmutableMap.<HttpRequest, HttpResponse> 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<HttpRequest, HttpResponse> fn, Module module, Properties props) {
return createInjector(fn, module, props).getInstance(BlobStore.class);
}
}

View File

@ -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
*/

View File

@ -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<T> {
@ -192,7 +192,7 @@ public class RestAnnotationProcessor<T> {
static final LoadingCache<Method, LoadingCache<Integer, Set<Annotation>>> methodToIndexOfParamToPostParamAnnotations = createMethodToIndexOfParamToAnnotation(PayloadParam.class);
static final LoadingCache<Method, LoadingCache<Integer, Set<Annotation>>> methodToIndexOfParamToPartParamAnnotations = createMethodToIndexOfParamToAnnotation(PartParam.class);
static final LoadingCache<Method, LoadingCache<Integer, Set<Annotation>>> methodToIndexOfParamToParamParserAnnotations = createMethodToIndexOfParamToAnnotation(ParamParser.class);
final Cache<MethodKey, Method> delegationMap;
static LoadingCache<Method, LoadingCache<Integer, Set<Annotation>>> createMethodToIndexOfParamToAnnotation(
@ -322,7 +322,7 @@ public class RestAnnotationProcessor<T> {
@SuppressWarnings("unchecked")
@Inject
public RestAnnotationProcessor(Injector injector, LoadingCache<Class<?>, Boolean> seedAnnotationCache, Cache<MethodKey, Method> delegationMap,
public RestAnnotationProcessor(Injector injector, LoadingCache<Class<?>, Boolean> seedAnnotationCache, Cache<MethodKey, Method> delegationMap,
@ApiVersion String apiVersion, @BuildVersion String buildVersion, ParseSax.Factory parserFactory,
HttpUtils utils, ContentMetadataCodec contentMetadataCodec, TypeLiteral<T> typeLiteral) throws ExecutionException {
this.declaring = (Class<T>) typeLiteral.getRawType();
@ -343,7 +343,7 @@ public class RestAnnotationProcessor<T> {
this.buildVersion = buildVersion;
}
public Method getDelegateOrNull(Method in) {
return delegationMap.getIfPresent(new MethodKey(in));
}
@ -364,7 +364,7 @@ public class RestAnnotationProcessor<T> {
&& 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<T> {
Type returnVal = getReturnTypeForMethod(method);
return getJsonParserKeyForMethodAnType(method, returnVal);
}
@SuppressWarnings("unchecked")
public static Key<? extends Function<HttpResponse, ?>> getJAXBParserKeyForMethod(Method method) {
Type returnVal = getReturnTypeForMethod(method);
@ -1334,4 +1334,10 @@ public class RestAnnotationProcessor<T> {
return postParams;
}
/**
* the class that is being processed
*/
public Class<T> getDeclaring(){
return declaring;
}
}

View File

@ -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<RestContext<HPCloudObjectStorageApi, HPCloudObjectStorageAsyncApi>> CONTEXT_TOKEN = new TypeToken<RestContext<HPCloudObjectStorageApi, HPCloudObjectStorageAsyncApi>>() {
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<HPCloudObjectStorageAsyncApi> {
@Override
protected void bindRequestSigner() {
bind(BlobRequestSigner.class).to(new TypeLiteral<SwiftBlobSigner<HPCloudObjectStorageAsyncApi>>() {
});
}
@Override
protected void bindTemporaryUrlKeyApi() {
bindClientAndAsyncClient(binder(), TemporaryUrlKeyApi.class, KeystoneTemporaryUrlKeyAsyncApi.class);
}
}
}

View File

@ -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<HPCloudObjectStorageAsyncApi> 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<HPCloudObjectStorageAsyncApi> 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)));
}
}

View File

@ -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<String, URI> 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);
}
}

View File

@ -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

View File

@ -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<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> 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);
}
}

View File

@ -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<HttpRequest, HttpResponse> 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.<HttpRequest, HttpResponse> builder()
.put(authenticate, authenticationResponse)
.put(temporaryKeyRequest, temporaryKeyResponse).build();
}
@Override
protected ApiMetadata createApiMetadata() {
return new HPCloudObjectStorageApiMetadata().toBuilder()
.defaultModules(ImmutableSet.<Class<? extends Module>>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;
}
}
}

View File

@ -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();
}
}