mirror of https://github.com/apache/jclouds.git
corrected guice bindings for swift-based blob signatures and backfilled expect tests
This commit is contained in:
parent
99d3422b4d
commit
ffa9cd3bb0
|
@ -22,15 +22,19 @@ import java.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.apis.ApiMetadata;
|
import org.jclouds.apis.ApiMetadata;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
import org.jclouds.cloudfiles.blobstore.config.CloudFilesBlobStoreContextModule;
|
import org.jclouds.cloudfiles.blobstore.config.CloudFilesBlobStoreContextModule;
|
||||||
import org.jclouds.cloudfiles.config.CloudFilesRestClientModule;
|
import org.jclouds.cloudfiles.config.CloudFilesRestClientModule;
|
||||||
import org.jclouds.cloudfiles.config.CloudFilesRestClientModule.StorageAndCDNManagementEndpointModule;
|
import org.jclouds.cloudfiles.config.CloudFilesRestClientModule.StorageAndCDNManagementEndpointModule;
|
||||||
import org.jclouds.openstack.swift.SwiftApiMetadata;
|
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 org.jclouds.rest.RestContext;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.reflect.TypeToken;
|
import com.google.common.reflect.TypeToken;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link ApiMetadata} for Rackspace Cloud Files API
|
* Implementation of {@link ApiMetadata} for Rackspace Cloud Files API
|
||||||
|
@ -78,7 +82,11 @@ public class CloudFilesApiMetadata extends SwiftApiMetadata {
|
||||||
.documentation(URI.create("http://docs.rackspacecloud.com/files/api/v1/cfdevguide_d5/content/ch01.html"))
|
.documentation(URI.create("http://docs.rackspacecloud.com/files/api/v1/cfdevguide_d5/content/ch01.html"))
|
||||||
.defaultProperties(CloudFilesApiMetadata.defaultProperties())
|
.defaultProperties(CloudFilesApiMetadata.defaultProperties())
|
||||||
.context(CONTEXT_TOKEN)
|
.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
|
@Override
|
||||||
|
@ -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>>() {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -23,16 +23,12 @@ import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.blobstore.BlobRequestSigner;
|
|
||||||
import org.jclouds.cloudfiles.CloudFilesClient;
|
import org.jclouds.cloudfiles.CloudFilesClient;
|
||||||
import org.jclouds.openstack.swift.TemporaryUrlKey;
|
|
||||||
import org.jclouds.cloudfiles.blobstore.CloudFilesAsyncBlobStore;
|
import org.jclouds.cloudfiles.blobstore.CloudFilesAsyncBlobStore;
|
||||||
import org.jclouds.cloudfiles.blobstore.CloudFilesBlobStore;
|
import org.jclouds.cloudfiles.blobstore.CloudFilesBlobStore;
|
||||||
import org.jclouds.cloudfiles.blobstore.functions.CloudFilesObjectToBlobMetadata;
|
import org.jclouds.cloudfiles.blobstore.functions.CloudFilesObjectToBlobMetadata;
|
||||||
import org.jclouds.cloudfiles.domain.ContainerCDNMetadata;
|
import org.jclouds.cloudfiles.domain.ContainerCDNMetadata;
|
||||||
import org.jclouds.date.TimeStamp;
|
|
||||||
import org.jclouds.openstack.swift.blobstore.SwiftAsyncBlobStore;
|
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.SwiftBlobStore;
|
||||||
import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule;
|
import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule;
|
||||||
import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlobMetadata;
|
import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlobMetadata;
|
||||||
|
@ -70,6 +66,5 @@ public class CloudFilesBlobStoreContextModule extends SwiftBlobStoreContextModul
|
||||||
bind(SwiftBlobStore.class).to(CloudFilesBlobStore.class);
|
bind(SwiftBlobStore.class).to(CloudFilesBlobStore.class);
|
||||||
bind(SwiftAsyncBlobStore.class).to(CloudFilesAsyncBlobStore.class);
|
bind(SwiftAsyncBlobStore.class).to(CloudFilesAsyncBlobStore.class);
|
||||||
bind(ObjectToBlobMetadata.class).to(CloudFilesObjectToBlobMetadata.class);
|
bind(ObjectToBlobMetadata.class).to(CloudFilesObjectToBlobMetadata.class);
|
||||||
bind(BlobRequestSigner.class).to(SwiftBlobRequestSigner.class);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ public class CloudFilesRestClientModule extends SwiftRestClientModule<CloudFiles
|
||||||
.<Class<?>, Class<?>> of());
|
.<Class<?>, Class<?>> of());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected void bindResolvedClientsToCommonSwift() {
|
protected void bindResolvedClientsToCommonSwift() {
|
||||||
bind(CommonSwiftClient.class).to(CloudFilesClient.class).in(Scopes.SINGLETON);
|
bind(CommonSwiftClient.class).to(CloudFilesClient.class).in(Scopes.SINGLETON);
|
||||||
bind(CommonSwiftAsyncClient.class).to(CloudFilesAsyncClient.class).in(Scopes.SINGLETON);
|
bind(CommonSwiftAsyncClient.class).to(CloudFilesAsyncClient.class).in(Scopes.SINGLETON);
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -88,6 +88,7 @@ public class KeystoneRestClientModule<S extends KeystoneApi, A extends KeystoneA
|
||||||
.put(TenantApi.class, TenantAsyncApi.class)
|
.put(TenantApi.class, TenantAsyncApi.class)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public KeystoneRestClientModule() {
|
public KeystoneRestClientModule() {
|
||||||
super(TypeToken.class.cast(TypeToken.of(KeystoneApi.class)), TypeToken.class.cast(TypeToken.of(KeystoneAsyncApi.class)), DELEGATE_MAP);
|
super(TypeToken.class.cast(TypeToken.of(KeystoneApi.class)), TypeToken.class.cast(TypeToken.of(KeystoneAsyncApi.class)), DELEGATE_MAP);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ import java.util.Properties;
|
||||||
import org.jclouds.apis.ApiMetadata;
|
import org.jclouds.apis.ApiMetadata;
|
||||||
import org.jclouds.blobstore.BlobStoreContext;
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule;
|
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;
|
||||||
import org.jclouds.openstack.swift.config.SwiftRestClientModule.StorageEndpointModule;
|
import org.jclouds.openstack.swift.config.SwiftRestClientModule.StorageEndpointModule;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
|
@ -81,7 +82,11 @@ public class SwiftApiMetadata extends BaseRestApiMetadata {
|
||||||
.defaultProperties(SwiftApiMetadata.defaultProperties())
|
.defaultProperties(SwiftApiMetadata.defaultProperties())
|
||||||
.view(TypeToken.of(BlobStoreContext.class))
|
.view(TypeToken.of(BlobStoreContext.class))
|
||||||
.context(CONTEXT_TOKEN)
|
.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
|
@Override
|
||||||
|
|
|
@ -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.keystone.v2_0.config.KeystoneAuthenticationModule;
|
||||||
import org.jclouds.openstack.services.ServiceType;
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule;
|
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.SwiftKeystoneRestClientModule;
|
||||||
import org.jclouds.openstack.swift.config.SwiftRestClientModule.KeystoneStorageEndpointModule;
|
import org.jclouds.openstack.swift.config.SwiftRestClientModule.KeystoneStorageEndpointModule;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
|
@ -91,8 +92,12 @@ public class SwiftKeystoneApiMetadata extends SwiftApiMetadata {
|
||||||
.defaultEndpoint("http://localhost:5000/v2.0/")
|
.defaultEndpoint("http://localhost:5000/v2.0/")
|
||||||
.context(CONTEXT_TOKEN)
|
.context(CONTEXT_TOKEN)
|
||||||
.defaultProperties(SwiftKeystoneApiMetadata.defaultProperties())
|
.defaultProperties(SwiftKeystoneApiMetadata.defaultProperties())
|
||||||
.defaultModules(ImmutableSet.<Class<? extends Module>>of(KeystoneStorageEndpointModule.class, KeystoneAuthenticationModule.RegionModule.class,
|
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
|
||||||
SwiftKeystoneRestClientModule.class, SwiftBlobStoreContextModule.class));
|
.add(KeystoneStorageEndpointModule.class)
|
||||||
|
.add(KeystoneAuthenticationModule.RegionModule.class)
|
||||||
|
.add(SwiftKeystoneRestClientModule.class)
|
||||||
|
.add(SwiftBlobStoreContextModule.class)
|
||||||
|
.add(SwiftKeystoneTemporaryUrlExtensionModule.class).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -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.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
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 static org.jclouds.blobstore.util.BlobStoreUtils.cleanRequest;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
@ -30,9 +28,6 @@ import java.security.InvalidKeyException;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
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.BlobRequestSigner;
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||||
|
@ -40,21 +35,26 @@ import org.jclouds.crypto.Crypto;
|
||||||
import org.jclouds.crypto.CryptoStreams;
|
import org.jclouds.crypto.CryptoStreams;
|
||||||
import org.jclouds.date.TimeStamp;
|
import org.jclouds.date.TimeStamp;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpRequestFilter;
|
||||||
import org.jclouds.http.options.GetOptions;
|
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.CommonSwiftAsyncClient;
|
||||||
import org.jclouds.openstack.swift.TemporaryUrlKey;
|
import org.jclouds.openstack.swift.TemporaryUrlKey;
|
||||||
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
|
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
|
||||||
import org.jclouds.openstack.swift.domain.SwiftObject;
|
import org.jclouds.openstack.swift.domain.SwiftObject;
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
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
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@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 Crypto crypto;
|
||||||
|
|
||||||
private final Provider<Long> unixEpochTimestampProvider;
|
private final Provider<Long> unixEpochTimestampProvider;
|
||||||
|
@ -67,10 +67,18 @@ public class SwiftBlobRequestSigner implements BlobRequestSigner {
|
||||||
private final Method deleteMethod;
|
private final Method deleteMethod;
|
||||||
private final Method createMethod;
|
private final Method createMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create a signer for this subtype of swift
|
||||||
|
*
|
||||||
|
* @param processor
|
||||||
|
* bound to the current subclass of {@link CommonSwiftAsyncClient}
|
||||||
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
public SwiftBlobRequestSigner(RestAnnotationProcessor<CommonSwiftAsyncClient> processor, BlobToObject blobToObject,
|
protected SwiftBlobSigner(BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto,
|
||||||
BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto, @TimeStamp Provider<Long> unixEpochTimestampProvider,
|
@TimeStamp Provider<Long> unixEpochTimestampProvider,
|
||||||
@TemporaryUrlKey Supplier<String> temporaryUrlKeySupplier) throws SecurityException, NoSuchMethodException {
|
@TemporaryUrlKey Supplier<String> temporaryUrlKeySupplier,
|
||||||
|
RestAnnotationProcessor<T> processor)
|
||||||
|
throws SecurityException, NoSuchMethodException {
|
||||||
this.processor = checkNotNull(processor, "processor");
|
this.processor = checkNotNull(processor, "processor");
|
||||||
this.crypto = checkNotNull(crypto, "crypto");
|
this.crypto = checkNotNull(crypto, "crypto");
|
||||||
|
|
||||||
|
@ -80,10 +88,9 @@ public class SwiftBlobRequestSigner implements BlobRequestSigner {
|
||||||
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
|
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
|
||||||
this.blob2HttpGetOptions = checkNotNull(blob2HttpGetOptions, "blob2HttpGetOptions");
|
this.blob2HttpGetOptions = checkNotNull(blob2HttpGetOptions, "blob2HttpGetOptions");
|
||||||
|
|
||||||
this.getMethod = CommonSwiftAsyncClient.class.getMethod("getObject", String.class, String.class,
|
this.getMethod = processor.getDeclaring().getMethod("getObject", String.class, String.class, GetOptions[].class);
|
||||||
GetOptions[].class);
|
this.deleteMethod = processor.getDeclaring().getMethod("removeObject", String.class, String.class);
|
||||||
this.deleteMethod = CommonSwiftAsyncClient.class.getMethod("removeObject", String.class, String.class);
|
this.createMethod = processor.getDeclaring().getMethod("putObject", String.class, SwiftObject.class);
|
||||||
this.createMethod = CommonSwiftAsyncClient.class.getMethod("putObject", String.class, SwiftObject.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -119,8 +126,7 @@ public class SwiftBlobRequestSigner implements BlobRequestSigner {
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpRequest signForTemporaryAccess(HttpRequest request, long timeInSeconds) {
|
private HttpRequest signForTemporaryAccess(HttpRequest request, long timeInSeconds) {
|
||||||
HttpRequest.Builder builder = request.toBuilder();
|
HttpRequest.Builder<?> builder = request.toBuilder().filters(ImmutableSet.<HttpRequestFilter>of());
|
||||||
builder.filters(filter(request.getFilters(), instanceOf(AuthenticateRequest.class)));
|
|
||||||
|
|
||||||
String key = temporaryUrlKeySupplier.get();
|
String key = temporaryUrlKeySupplier.get();
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
|
@ -128,8 +134,8 @@ public class SwiftBlobRequestSigner implements BlobRequestSigner {
|
||||||
}
|
}
|
||||||
long expiresInSeconds = unixEpochTimestampProvider.get() + timeInSeconds;
|
long expiresInSeconds = unixEpochTimestampProvider.get() + timeInSeconds;
|
||||||
|
|
||||||
builder.addQueryParam("temp_url_sig", createSignature(key, createStringToSign(
|
builder.addQueryParam("temp_url_sig",
|
||||||
request.getMethod().toUpperCase(), request, expiresInSeconds)));
|
createSignature(key, createStringToSign(request.getMethod().toUpperCase(), request, expiresInSeconds)));
|
||||||
builder.addQueryParam("temp_url_expires", "" + expiresInSeconds);
|
builder.addQueryParam("temp_url_expires", "" + expiresInSeconds);
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
@ -137,14 +143,12 @@ public class SwiftBlobRequestSigner implements BlobRequestSigner {
|
||||||
|
|
||||||
private String createStringToSign(String method, HttpRequest request, long expiresInSeconds) {
|
private String createStringToSign(String method, HttpRequest request, long expiresInSeconds) {
|
||||||
checkArgument(method.equalsIgnoreCase("GET") || method.equalsIgnoreCase("PUT"));
|
checkArgument(method.equalsIgnoreCase("GET") || method.equalsIgnoreCase("PUT"));
|
||||||
return String.format("%s\n%d\n%s", method.toUpperCase(), expiresInSeconds,
|
return String.format("%s\n%d\n%s", method.toUpperCase(), expiresInSeconds, request.getEndpoint().getPath());
|
||||||
request.getEndpoint().getPath());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createSignature(String key, String stringToSign) {
|
private String createSignature(String key, String stringToSign) {
|
||||||
try {
|
try {
|
||||||
return CryptoStreams.hex(crypto.hmacSHA1(key.getBytes()).doFinal(stringToSign.getBytes()));
|
return CryptoStreams.hex(crypto.hmacSHA1(key.getBytes()).doFinal(stringToSign.getBytes()));
|
||||||
|
|
||||||
} catch (InvalidKeyException e) {
|
} catch (InvalidKeyException e) {
|
||||||
throw Throwables.propagate(e);
|
throw Throwables.propagate(e);
|
||||||
}
|
}
|
|
@ -18,57 +18,30 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.swift.blobstore.config;
|
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.AsyncBlobStore;
|
||||||
import org.jclouds.blobstore.BlobRequestSigner;
|
|
||||||
import org.jclouds.blobstore.BlobStore;
|
import org.jclouds.blobstore.BlobStore;
|
||||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||||
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
||||||
import org.jclouds.date.TimeStamp;
|
|
||||||
import org.jclouds.openstack.swift.TemporaryUrlKey;
|
|
||||||
import org.jclouds.openstack.swift.blobstore.SwiftAsyncBlobStore;
|
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.SwiftBlobStore;
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Scopes;
|
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}
|
* Configures the {@link CloudFilesBlobStoreContext}; requires
|
||||||
* bound.
|
* {@link SwiftAsyncBlobStore} bound.
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class SwiftBlobStoreContextModule extends AbstractModule {
|
public class SwiftBlobStoreContextModule extends AbstractModule {
|
||||||
|
|
||||||
@Provides
|
|
||||||
@TimeStamp
|
|
||||||
protected Long unixEpochTimestampProvider() {
|
|
||||||
return System.currentTimeMillis() / 1000; /* convert to seconds */
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
install(new BlobStoreMapModule());
|
install(new BlobStoreMapModule());
|
||||||
bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT);
|
bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT);
|
||||||
bind(AsyncBlobStore.class).to(SwiftAsyncBlobStore.class).in(Scopes.SINGLETON);
|
bind(AsyncBlobStore.class).to(SwiftAsyncBlobStore.class).in(Scopes.SINGLETON);
|
||||||
bind(BlobStore.class).to(SwiftBlobStore.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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -25,5 +25,5 @@ public class SwiftKeystoneRestClientModule extends SwiftRestClientModule<SwiftKe
|
||||||
protected void bindResolvedClientsToCommonSwift() {
|
protected void bindResolvedClientsToCommonSwift() {
|
||||||
bind(CommonSwiftClient.class).to(SwiftKeystoneClient.class).in(Scopes.SINGLETON);
|
bind(CommonSwiftClient.class).to(SwiftKeystoneClient.class).in(Scopes.SINGLETON);
|
||||||
bind(CommonSwiftAsyncClient.class).to(SwiftKeystoneAsyncClient.class).in(Scopes.SINGLETON);
|
bind(CommonSwiftAsyncClient.class).to(SwiftKeystoneAsyncClient.class).in(Scopes.SINGLETON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,16 +58,17 @@ import com.google.inject.Scopes;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@ConfiguresRestClient
|
@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")
|
@SuppressWarnings("unchecked")
|
||||||
public SwiftRestClientModule() {
|
public SwiftRestClientModule() {
|
||||||
this(TypeToken.class.cast(TypeToken.of(SwiftClient.class)), TypeToken.class.cast(TypeToken
|
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,
|
protected SwiftRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType,
|
||||||
Map<Class<?>, Class<?>> sync2Async) {
|
Map<Class<?>, Class<?>> sync2Async) {
|
||||||
super(syncClientType, asyncClientType, sync2Async);
|
super(syncClientType, asyncClientType, sync2Async);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -18,14 +18,12 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.swift.functions;
|
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 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
|
* @author Andrei Savu
|
||||||
*/
|
*/
|
||||||
|
@ -33,11 +31,6 @@ public class ParseTemporaryUrlKeyFromHeaders implements Function<HttpResponse, S
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String apply(HttpResponse httpResponse) {
|
public String apply(HttpResponse httpResponse) {
|
||||||
Multimap<String, String> headers = httpResponse.getHeaders();
|
return httpResponse.getFirstHeaderOrNull(ACCOUNT_TEMPORARY_URL_KEY);
|
||||||
if (headers.containsKey(ACCOUNT_TEMPORARY_URL_KEY)) {
|
|
||||||
return getOnlyElement(headers.get(ACCOUNT_TEMPORARY_URL_KEY));
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,33 +21,32 @@ package org.jclouds.openstack.swift;
|
||||||
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
||||||
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
||||||
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
||||||
import static org.jclouds.rest.config.BinderUtils.bindClientAndAsyncClient;
|
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
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.apis.ApiMetadata;
|
||||||
import org.jclouds.date.TimeStamp;
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.openstack.functions.URIFromAuthenticationResponseForService;
|
import org.jclouds.openstack.functions.URIFromAuthenticationResponseForService;
|
||||||
import org.jclouds.openstack.internal.TestOpenStackAuthenticationModule;
|
import org.jclouds.openstack.internal.TestOpenStackAuthenticationModule;
|
||||||
import org.jclouds.openstack.reference.AuthHeaders;
|
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.SwiftBlobStoreContextModule;
|
||||||
|
import org.jclouds.openstack.swift.blobstore.config.TemporaryUrlExtensionModule;
|
||||||
import org.jclouds.openstack.swift.config.SwiftRestClientModule;
|
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.BaseAsyncClientTest;
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.base.Suppliers;
|
||||||
import com.google.common.collect.ImmutableSet;
|
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}
|
* 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
|
@Override
|
||||||
protected Long unixEpochTimestampProvider() {
|
protected Long unixEpochTimestampProvider() {
|
||||||
return UNIX_EPOCH_TIMESTAMP;
|
return UNIX_EPOCH_TIMESTAMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configureTemporaryUrlExtension() {
|
protected void configure() {
|
||||||
bindClientAndAsyncClient(binder(), TemporaryUrlKeyApi.class, TemporaryUrlKeyAsyncApi.class);
|
bindTemporaryUrlKeyApi();
|
||||||
bind(new TypeLiteral<Supplier<String>>() {
|
bind(new TypeLiteral<Supplier<String>>() {
|
||||||
}).annotatedWith(TemporaryUrlKey.class).toInstance(Suppliers.ofInstance(TEMPORARY_URL_KEY));
|
}).annotatedWith(TemporaryUrlKey.class).toInstance(Suppliers.ofInstance(TEMPORARY_URL_KEY));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void bindRequestSigner() {
|
||||||
|
bind(BlobRequestSigner.class).to(new TypeLiteral<SwiftBlobSigner<SwiftAsyncClient>>() {
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ApiMetadata createApiMetadata() {
|
protected ApiMetadata createApiMetadata() {
|
||||||
return new SwiftApiMetadata().toBuilder().defaultModules(
|
return new SwiftApiMetadata().toBuilder()
|
||||||
ImmutableSet.<Class<? extends Module>>of(StorageEndpointModule.class, SwiftRestClientModule.class,
|
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
|
||||||
StaticTimeAndTemporaryUrlKeyModule.class)).build();
|
.add(StorageEndpointModule.class)
|
||||||
|
.add(SwiftRestClientModule.class)
|
||||||
|
.add(SwiftBlobStoreContextModule.class)
|
||||||
|
.add(StaticTimeAndTemporaryUrlKeyModule.class).build()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,16 +19,11 @@
|
||||||
package org.jclouds.openstack.swift.blobstore.integration;
|
package org.jclouds.openstack.swift.blobstore.integration;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import org.jclouds.blobstore.integration.internal.BaseBlobLiveTest;
|
import org.jclouds.blobstore.integration.internal.BaseBlobLiveTest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
||||||
import org.jclouds.openstack.swift.extensions.TemporaryUrlKeyApi;
|
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
import static org.testng.Assert.assertNotNull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author James Murty
|
* @author James Murty
|
||||||
|
|
|
@ -31,7 +31,6 @@ import java.util.concurrent.ExecutorService;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.ws.rs.HeaderParam;
|
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.blobstore.LocalAsyncBlobStore;
|
import org.jclouds.blobstore.LocalAsyncBlobStore;
|
||||||
|
@ -61,7 +60,6 @@ import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
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.
|
* Implementation of {@link SwiftAsyncClient} which keeps all data in a local Map object.
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,8 +26,6 @@ import org.jclouds.io.ContentMetadataBuilder;
|
||||||
import org.jclouds.io.MutableContentMetadata;
|
import org.jclouds.io.MutableContentMetadata;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1334,4 +1334,10 @@ public class RestAnnotationProcessor<T> {
|
||||||
return postParams;
|
return postParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the class that is being processed
|
||||||
|
*/
|
||||||
|
public Class<T> getDeclaring(){
|
||||||
|
return declaring;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,20 +18,28 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.hpcloud.objectstorage;
|
package org.jclouds.hpcloud.objectstorage;
|
||||||
|
|
||||||
|
import static org.jclouds.rest.config.BinderUtils.bindClientAndAsyncClient;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.apis.ApiMetadata;
|
import org.jclouds.apis.ApiMetadata;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
import org.jclouds.hpcloud.objectstorage.blobstore.config.HPCloudObjectStorageBlobStoreContextModule;
|
import org.jclouds.hpcloud.objectstorage.blobstore.config.HPCloudObjectStorageBlobStoreContextModule;
|
||||||
import org.jclouds.hpcloud.objectstorage.config.HPCloudObjectStorageRestClientModule;
|
import org.jclouds.hpcloud.objectstorage.config.HPCloudObjectStorageRestClientModule;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule;
|
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule;
|
||||||
import org.jclouds.openstack.swift.SwiftKeystoneApiMetadata;
|
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.config.SwiftRestClientModule.KeystoneStorageEndpointModule;
|
||||||
|
import org.jclouds.openstack.swift.extensions.KeystoneTemporaryUrlKeyAsyncApi;
|
||||||
|
import org.jclouds.openstack.swift.extensions.TemporaryUrlKeyApi;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.reflect.TypeToken;
|
import com.google.common.reflect.TypeToken;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link org.jclouds.providers.ProviderMetadata} for HP Cloud Services Object Storage
|
* Implementation of {@link org.jclouds.providers.ProviderMetadata} for HP Cloud Services Object Storage
|
||||||
*
|
*
|
||||||
|
@ -82,7 +90,8 @@ public class HPCloudObjectStorageApiMetadata extends SwiftKeystoneApiMetadata {
|
||||||
.add(KeystoneStorageEndpointModule.class)
|
.add(KeystoneStorageEndpointModule.class)
|
||||||
.add(RegionModule.class)
|
.add(RegionModule.class)
|
||||||
.add(HPCloudObjectStorageRestClientModule.class)
|
.add(HPCloudObjectStorageRestClientModule.class)
|
||||||
.add(HPCloudObjectStorageBlobStoreContextModule.class).build());
|
.add(HPCloudObjectStorageBlobStoreContextModule.class)
|
||||||
|
.add(HPCloudObjectStorageTemporaryUrlExtensionModule.class).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -96,4 +105,24 @@ public class HPCloudObjectStorageApiMetadata extends SwiftKeystoneApiMetadata {
|
||||||
return this;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -29,13 +29,11 @@ import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.blobstore.AsyncBlobStore;
|
import org.jclouds.blobstore.AsyncBlobStore;
|
||||||
import org.jclouds.blobstore.BlobRequestSigner;
|
|
||||||
import org.jclouds.blobstore.BlobStore;
|
import org.jclouds.blobstore.BlobStore;
|
||||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||||
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
||||||
import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageApi;
|
import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageApi;
|
||||||
import org.jclouds.hpcloud.objectstorage.blobstore.HPCloudObjectStorageAsyncBlobStore;
|
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.HPCloudObjectStorageBlobStore;
|
||||||
import org.jclouds.hpcloud.objectstorage.blobstore.functions.HPCloudObjectStorageObjectToBlobMetadata;
|
import org.jclouds.hpcloud.objectstorage.blobstore.functions.HPCloudObjectStorageObjectToBlobMetadata;
|
||||||
import org.jclouds.hpcloud.objectstorage.domain.CDNContainer;
|
import org.jclouds.hpcloud.objectstorage.domain.CDNContainer;
|
||||||
|
@ -107,6 +105,5 @@ public class HPCloudObjectStorageBlobStoreContextModule extends SwiftBlobStoreCo
|
||||||
bind(AsyncBlobStore.class).to(HPCloudObjectStorageAsyncBlobStore.class);
|
bind(AsyncBlobStore.class).to(HPCloudObjectStorageAsyncBlobStore.class);
|
||||||
bind(BlobStore.class).to(HPCloudObjectStorageBlobStore.class);
|
bind(BlobStore.class).to(HPCloudObjectStorageBlobStore.class);
|
||||||
bind(ObjectToBlobMetadata.class).to(HPCloudObjectStorageObjectToBlobMetadata.class);
|
bind(ObjectToBlobMetadata.class).to(HPCloudObjectStorageObjectToBlobMetadata.class);
|
||||||
bind(BlobRequestSigner.class).to(HPCloudObjectStorageBlobRequestSigner.class);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,10 @@ import java.util.Map;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageAsyncApi;
|
|
||||||
import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageApi;
|
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.CDNContainerApi;
|
||||||
|
import org.jclouds.hpcloud.objectstorage.extensions.CDNContainerAsyncApi;
|
||||||
import org.jclouds.hpcloud.services.HPExtensionCDN;
|
import org.jclouds.hpcloud.services.HPExtensionCDN;
|
||||||
import org.jclouds.hpcloud.services.HPExtensionServiceType;
|
import org.jclouds.hpcloud.services.HPExtensionServiceType;
|
||||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,7 +18,10 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.hpcloud.objectstorage.blobstore.integration;
|
package org.jclouds.hpcloud.objectstorage.blobstore.integration;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.jclouds.openstack.swift.blobstore.integration.SwiftBlobSignerLiveTest;
|
import org.jclouds.openstack.swift.blobstore.integration.SwiftBlobSignerLiveTest;
|
||||||
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,4 +33,20 @@ public class HPCloudObjectStorageBlobSignerLiveTest extends SwiftBlobSignerLiveT
|
||||||
provider = "hpcloud-objectstorage";
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue