tuned timestamp logic

git-svn-id: http://jclouds.googlecode.com/svn/trunk@1982 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-10-14 04:59:51 +00:00
parent b4a4bedcc3
commit e939114702
37 changed files with 671 additions and 250 deletions

View File

@ -26,6 +26,7 @@ package org.jclouds.aws.s3;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SESSIONINTERVAL;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import java.net.URI;
@ -76,6 +77,8 @@ public class S3ContextBuilder extends
}, props);
properties.setProperty(S3Constants.PROPERTY_S3_ENDPOINT, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "x-amz-meta-");
if (!properties.containsKey(PROPERTY_S3_SESSIONINTERVAL))
this.withTimeStampExpiration(60);
}
public S3ContextBuilder(String id, String secret) {
@ -162,4 +165,8 @@ public class S3ContextBuilder extends
modules.add(new RestS3ConnectionModule());
}
public S3ContextBuilder withTimeStampExpiration(long seconds) {
getProperties().setProperty(PROPERTY_S3_SESSIONINTERVAL, seconds + "");
return this;
}
}

View File

@ -24,6 +24,8 @@
package org.jclouds.aws.s3.config;
import java.net.URI;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
@ -48,7 +50,11 @@ import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.rest.RestClientFactory;
import org.jclouds.util.DateService;
import org.jclouds.util.TimeStamp;
import com.google.common.base.Function;
import com.google.common.collect.MapMaker;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Scopes;
@ -62,6 +68,28 @@ import com.google.inject.Scopes;
@RequiresHttp
public class RestS3ConnectionModule extends AbstractModule {
@Provides
@TimeStamp
protected String provideTimeStamp(@TimeStamp ConcurrentMap<String, String> cache) {
return cache.get("doesn't matter");
}
/**
* borrowing concurrency code to ensure that caching takes place properly
*/
@Provides
@TimeStamp
ConcurrentMap<String, String> provideTimeStampCache(
@Named(S3Constants.PROPERTY_S3_SESSIONINTERVAL) long seconds,
final DateService dateService) {
return new MapMaker().expiration(seconds, TimeUnit.SECONDS).makeComputingMap(
new Function<String, String>() {
public String apply(String key) {
return dateService.rfc822DateFormat();
}
});
}
@Override
protected void configure() {
bind(RequestAuthorizeSignature.class).in(Scopes.SINGLETON);
@ -78,7 +106,8 @@ public class RestS3ConnectionModule extends AbstractModule {
@Provides
@Singleton
protected BlobStore<BucketMetadata, ObjectMetadata, S3Object> provideS3BlobStore(RestClientFactory factory) {
protected BlobStore<BucketMetadata, ObjectMetadata, S3Object> provideS3BlobStore(
RestClientFactory factory) {
return factory.create(S3BlobStore.class);
}

View File

@ -29,11 +29,10 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;
@ -42,12 +41,12 @@ import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils;
import org.jclouds.util.DateService;
import org.jclouds.util.TimeStamp;
import com.google.common.annotations.VisibleForTesting;
/**
* Signs the S3 request. This will update timestamps at most once per second.
* Signs the S3 request.
*
* @see <a href= "http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html" />
* @author Adrian Cole
@ -60,46 +59,15 @@ public class RequestAuthorizeSignature implements HttpRequestFilter {
private final String accessKey;
private final String secretKey;
private final DateService dateService;
public final long BILLION = 1000000000;
private final AtomicReference<String> timeStamp;
private final AtomicLong trigger = new AtomicLong(System.nanoTime() + 1 * BILLION);
/**
* Start the time update service. Amazon clocks need to be within 900 seconds of the request
* time. This method updates the clock every second. This is not performed per-request, as
* creation of the date object is a slow, synchronized command.
*/
synchronized void updateIfTimeOut() {
if (trigger.get() - System.nanoTime() <= 0) {
timeStamp.set(createNewStamp());
trigger.set(System.nanoTime() + 1 * BILLION);
}
}
// this is a hotspot when submitted concurrently, so be lazy.
// amazon is ok with up to 15 minutes off their time, so let's
// be as lazy as possible.
String createNewStamp() {
return dateService.rfc822DateFormat();
}
public String timestampAsHeaderString() {
updateIfTimeOut();
return timeStamp.get();
}
private final Provider<String> timeStampProvider;
@Inject
public RequestAuthorizeSignature(@Named(S3Constants.PROPERTY_AWS_ACCESSKEYID) String accessKey,
@Named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY) String secretKey,
DateService dateService) {
@TimeStamp Provider<String> timeStampProvider) {
this.accessKey = accessKey;
this.secretKey = secretKey;
this.dateService = dateService;
timeStamp = new AtomicReference<String>(createNewStamp());
this.timeStampProvider = timeStampProvider;
}
public void filter(HttpRequest request) throws HttpException {
@ -142,7 +110,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter {
private void replaceDateHeader(HttpRequest request) {
request.getHeaders().replaceValues(HttpHeaders.DATE,
Collections.singletonList(timestampAsHeaderString()));
Collections.singletonList(timeStampProvider.get()));
}
private void appendAmzHeaders(HttpRequest request, StringBuilder toSign) {

View File

@ -42,7 +42,10 @@ public interface S3Constants extends AWSConstants, S3Headers, BlobStoreConstants
public static final String MARKER = "marker";
public static final String MAX_KEYS = "max-keys";
public static final String DELIMITER = "delimiter";
public static final String PROPERTY_S3_ENDPOINT = "https://s3.amazonaws.com";
public static final String PROPERTY_S3_ENDPOINT = "jclouds.s3.endpoint";
/**
* how long do we wait before obtaining a new timestamp for requests.
*/
public static final String PROPERTY_S3_SESSIONINTERVAL = "jclouds.s3.sessioninterval";
}

View File

@ -24,6 +24,9 @@
package org.jclouds.aws.s3.config;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import java.util.concurrent.ConcurrentMap;
import org.jclouds.aws.s3.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.s3.handlers.AWSRedirectionRetryHandler;
@ -32,6 +35,7 @@ import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.http.handlers.DelegatingErrorHandler;
import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.util.DateService;
import org.jclouds.util.Jsr330;
import org.testng.annotations.Test;
@ -46,19 +50,35 @@ import com.google.inject.Injector;
public class RestS3ConnectionModuleTest {
Injector createInjector() {
return Guice.createInjector(new RestS3ConnectionModule(), new ParserModule(), new AbstractModule() {
return Guice.createInjector(new RestS3ConnectionModule(), new ParserModule(),
new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
"user");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY))
.to("key");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT)).to(
"http://localhost");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to("user");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)).to("key");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT))
.to("http://localhost");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_S3_SESSIONINTERVAL)).to("2");
}
});
}
@Test
void testUpdatesOnlyOncePerSecond() throws NoSuchMethodException, InterruptedException {
RestS3ConnectionModule module = new RestS3ConnectionModule();
ConcurrentMap<String, String> map = module.provideTimeStampCache(1, new DateService());
String timeStamp = map.get("foo");
for (int i = 0; i < 10; i++)
map.get("foo");
assertEquals(timeStamp, map.get("foo"));
Thread.sleep(1001);
assertFalse(timeStamp.equals(map.get("foo")));
}
@Test
void testServerErrorHandler() {
DelegatingErrorHandler handler = createInjector().getInstance(DelegatingErrorHandler.class);

View File

@ -30,9 +30,10 @@ import java.net.URI;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.aws.s3.config.RestS3ConnectionModule;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.http.HttpRequest;
import org.jclouds.util.DateService;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.util.Jsr330;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
@ -132,34 +133,24 @@ public class RequestAuthorizeSignatureTest {
assertEquals(builder.toString(), "/adriancole.s3int5");
}
@Test
void testUpdatesOnlyOncePerSecond() throws NoSuchMethodException, InterruptedException {
// filter.createNewStamp();
String timeStamp = filter.timestampAsHeaderString();
// replay(filter);
for (int i = 0; i < 10; i++)
filter.updateIfTimeOut();
assert timeStamp.equals(filter.timestampAsHeaderString());
Thread.sleep(1000);
assert !timeStamp.equals(filter.timestampAsHeaderString());
// verify(filter);
}
/**
* before class, as we need to ensure that the filter is threadsafe.
*
*/
@BeforeClass
protected void createFilter() {
injector = Guice.createInjector(new AbstractModule() {
injector = Guice.createInjector(new RestS3ConnectionModule(), new ParserModule(),
new AbstractModule() {
protected void configure() {
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
"foo");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY))
.to("bar");
bind(DateService.class);
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to("foo");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)).to("bar");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_S3_SESSIONINTERVAL)).to("2");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT))
.to("https://s3.amazonaws.com");
}
});
filter = injector.getInstance(RequestAuthorizeSignature.class);

View File

@ -29,6 +29,7 @@ import java.io.IOException;
import java.io.InputStream;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.config.RestS3ConnectionModule;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.http.HttpCommand;
@ -59,14 +60,19 @@ public class S3UtilsTest {
@BeforeTest
protected void setUpInjector() {
Injector injector = Guice.createInjector(new ParserModule(), new AbstractModule() {
Injector injector = Guice.createInjector(new RestS3ConnectionModule(), new ParserModule(),
new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
"user");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY))
.to("key");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to("user");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)).to("key");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_S3_SESSIONINTERVAL)).to("2");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT))
.to("https://s3.amazonaws.com");
}
});

View File

@ -24,6 +24,7 @@
package org.jclouds.azure.storage.blob;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import java.net.URI;
@ -76,14 +77,10 @@ public class AzureBlobContextBuilder extends
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "x-ms-meta-");
properties.setProperty(AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT,
"https://{account}.blob.core.windows.net");
if (!properties.containsKey(PROPERTY_AZURESTORAGE_SESSIONINTERVAL))
this.withTimeStampExpiration(60);
}
// @Override
// protected void addBlobStoreModule(List<Module> modules) {
// modules.add(BlobStoreMapsModule.Builder.newBuilder(containerMetadataType, blobMetadataType,
// blobType).withClearContainerStrategy(RecreateClearContainerStrategy.class).build());
// }
public AzureBlobContextBuilder(String id, String secret) {
this(new Properties());
properties.setProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT, checkNotNull(id,
@ -173,4 +170,8 @@ public class AzureBlobContextBuilder extends
modules.add(new RestAzureBlobStoreModule());
}
public AzureBlobContextBuilder withTimeStampExpiration(long seconds) {
getProperties().setProperty(PROPERTY_AZURESTORAGE_SESSIONINTERVAL, seconds + "");
return this;
}
}

View File

@ -40,6 +40,7 @@ import org.jclouds.azure.storage.blob.functions.ParseContainerMetadataFromHeader
import org.jclouds.azure.storage.blob.functions.ReturnTrueIfContainerAlreadyExists;
import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
import org.jclouds.azure.storage.config.RestAzureStorageConnectionModule;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
@ -81,7 +82,8 @@ public class AzureBlobConnectionTest {
Method method = AzureBlobConnection.class.getMethod("listContainers", Array.newInstance(
ListOptions.class, 0).getClass());
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] {});
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] {});
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/");
assertEquals(httpMethod.getEndpoint().getQuery(), "comp=list");
@ -89,8 +91,7 @@ public class AzureBlobConnectionTest {
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ParseSax.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null);
}
@ -99,8 +100,8 @@ public class AzureBlobConnectionTest {
Method method = AzureBlobConnection.class.getMethod("listContainers", Array.newInstance(
ListOptions.class, 0).getClass());
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] { maxResults(1).marker(
"marker").prefix("prefix") });
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] { maxResults(1).marker("marker").prefix("prefix") });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/");
assert httpMethod.getEndpoint().getQuery().contains("comp=list");
@ -111,8 +112,7 @@ public class AzureBlobConnectionTest {
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ParseSax.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null);
}
@ -121,7 +121,8 @@ public class AzureBlobConnectionTest {
Method method = AzureBlobConnection.class.getMethod("createContainer", String.class, Array
.newInstance(CreateContainerOptions.class, 0).getClass());
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] { "container" });
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] { "container" });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/container");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container");
@ -140,7 +141,8 @@ public class AzureBlobConnectionTest {
public void testDeleteContainer() throws SecurityException, NoSuchMethodException {
Method method = AzureBlobConnection.class.getMethod("deleteContainer", String.class);
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] { "container" });
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] { "container" });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/container");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container");
@ -159,7 +161,8 @@ public class AzureBlobConnectionTest {
Method method = AzureBlobConnection.class.getMethod("createContainer", String.class, Array
.newInstance(CreateContainerOptions.class, 0).getClass());
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] { "container",
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] { "container",
withPublicAcl().withMetadata(ImmutableMultimap.of("foo", "bar")) });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/container");
@ -183,7 +186,8 @@ public class AzureBlobConnectionTest {
Method method = AzureBlobConnection.class.getMethod("createRootContainer", Array.newInstance(
CreateContainerOptions.class, 0).getClass());
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] {});
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] {});
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/$root");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container");
@ -202,7 +206,8 @@ public class AzureBlobConnectionTest {
public void testDeleteRootContainer() throws SecurityException, NoSuchMethodException {
Method method = AzureBlobConnection.class.getMethod("deleteRootContainer");
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] {});
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] {});
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/$root");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container");
@ -221,8 +226,8 @@ public class AzureBlobConnectionTest {
Method method = AzureBlobConnection.class.getMethod("createRootContainer", Array.newInstance(
CreateContainerOptions.class, 0).getClass());
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] { withPublicAcl()
.withMetadata(ImmutableMultimap.of("foo", "bar")) });
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] { withPublicAcl().withMetadata(ImmutableMultimap.of("foo", "bar")) });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/$root");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container");
@ -245,7 +250,8 @@ public class AzureBlobConnectionTest {
Method method = AzureBlobConnection.class.getMethod("listBlobs", String.class, Array
.newInstance(ListBlobsOptions.class, 0).getClass());
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] { "container" });
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] { "container" });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/container");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container&comp=list");
@ -253,8 +259,7 @@ public class AzureBlobConnectionTest {
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ParseSax.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null);
}
@ -263,7 +268,8 @@ public class AzureBlobConnectionTest {
Method method = AzureBlobConnection.class.getMethod("listBlobs", Array.newInstance(
ListBlobsOptions.class, 0).getClass());
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] {});
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] {});
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/$root");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container&comp=list");
@ -271,8 +277,7 @@ public class AzureBlobConnectionTest {
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ParseSax.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null);
}
@ -280,7 +285,8 @@ public class AzureBlobConnectionTest {
public void testContainerProperties() throws SecurityException, NoSuchMethodException {
Method method = AzureBlobConnection.class.getMethod("getContainerProperties", String.class);
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] { "container" });
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] { "container" });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/container");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container");
@ -297,8 +303,8 @@ public class AzureBlobConnectionTest {
Method method = AzureBlobConnection.class.getMethod("setContainerMetadata", String.class,
Multimap.class);
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] { "container",
ImmutableMultimap.of("key", "value") });
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] { "container", ImmutableMultimap.of("key", "value") });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/container");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container&comp=metadata");
@ -318,8 +324,8 @@ public class AzureBlobConnectionTest {
public void testSetBlobMetadata() throws SecurityException, NoSuchMethodException {
Method method = AzureBlobConnection.class.getMethod("setBlobMetadata", String.class,
String.class, Multimap.class);
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method, new Object[] { "container", "blob",
ImmutableMultimap.of("key", "value") });
GeneratedHttpRequest<AzureBlobConnection> httpMethod = processor.createRequest(method,
new Object[] { "container", "blob", ImmutableMultimap.of("key", "value") });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/container/blob");
assertEquals(httpMethod.getEndpoint().getQuery(), "comp=metadata");
@ -357,9 +363,12 @@ public class AzureBlobConnectionTest {
return Logger.NULL;
}
});
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL)).to(
1l);
}
}, new RestModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule());
}, new RestAzureStorageConnectionModule(), new RestModule(), new ExecutorServiceModule(
new WithinThreadExecutorService()), new JavaUrlHttpCommandExecutorServiceModule());
processor = injector.getInstance(Key
.get(new TypeLiteral<RestAnnotationProcessor<AzureBlobConnection>>() {
}));

View File

@ -37,6 +37,7 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.azure.storage.AzureBlob;
import org.jclouds.azure.storage.blob.domain.Blob;
import org.jclouds.azure.storage.blob.functions.ReturnTrueIfContainerAlreadyExists;
import org.jclouds.azure.storage.config.RestAzureStorageConnectionModule;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.reference.BlobStoreConstants;
@ -75,7 +76,8 @@ public class AzureBlobStoreTest {
public void testListContainers() throws SecurityException, NoSuchMethodException {
Method method = AzureBlobStore.class.getMethod("listContainers");
GeneratedHttpRequest<AzureBlobStore> httpMethod = processor.createRequest(method, new Object[] {});
GeneratedHttpRequest<AzureBlobStore> httpMethod = processor.createRequest(method,
new Object[] {});
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/");
assertEquals(httpMethod.getEndpoint().getQuery(), "comp=list");
@ -83,8 +85,7 @@ public class AzureBlobStoreTest {
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ParseSax.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null);
}
@ -92,7 +93,8 @@ public class AzureBlobStoreTest {
public void testCreateContainer() throws SecurityException, NoSuchMethodException {
Method method = AzureBlobStore.class.getMethod("createContainer", String.class);
GeneratedHttpRequest<AzureBlobStore> httpMethod = processor.createRequest(method, new Object[] { "container" });
GeneratedHttpRequest<AzureBlobStore> httpMethod = processor.createRequest(method,
new Object[] { "container" });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/container");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container");
@ -111,7 +113,8 @@ public class AzureBlobStoreTest {
public void testDeleteContainer() throws SecurityException, NoSuchMethodException {
Method method = AzureBlobStore.class.getMethod("deleteContainer", String.class);
GeneratedHttpRequest<AzureBlobStore> httpMethod = processor.createRequest(method, new Object[] { "container" });
GeneratedHttpRequest<AzureBlobStore> httpMethod = processor.createRequest(method,
new Object[] { "container" });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/container");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container");
@ -129,7 +132,8 @@ public class AzureBlobStoreTest {
public void testListBlobs() throws SecurityException, NoSuchMethodException {
Method method = AzureBlobStore.class.getMethod("listBlobs", String.class);
GeneratedHttpRequest<AzureBlobStore> httpMethod = processor.createRequest(method, new Object[] { "container" });
GeneratedHttpRequest<AzureBlobStore> httpMethod = processor.createRequest(method,
new Object[] { "container" });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/container");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=container&comp=list");
@ -137,8 +141,7 @@ public class AzureBlobStoreTest {
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ParseSax.class);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null);
}
@ -148,8 +151,8 @@ public class AzureBlobStoreTest {
Blob blob = new Blob("test");
blob.setData("test");
GeneratedHttpRequest<AzureBlobStore> httpMethod = processor
.createRequest(method, new Object[] { "mycontainer", blob });
GeneratedHttpRequest<AzureBlobStore> httpMethod = processor.createRequest(method,
new Object[] { "mycontainer", blob });
assertEquals(httpMethod.getEndpoint().getHost(), "myaccount.blob.core.windows.net");
assertEquals(httpMethod.getEndpoint().getPath(), "/mycontainer/test");
assertEquals(httpMethod.getEndpoint().getQuery(), null);
@ -188,6 +191,9 @@ public class AzureBlobStoreTest {
return Logger.NULL;
}
});
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL)).to(
1l);
}
@SuppressWarnings("unused")
@ -202,8 +208,8 @@ public class AzureBlobStoreTest {
};
}
}, new RestModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule());
}, new RestAzureStorageConnectionModule(), new RestModule(), new ExecutorServiceModule(
new WithinThreadExecutorService()), new JavaUrlHttpCommandExecutorServiceModule());
processor = injector.getInstance(Key
.get(new TypeLiteral<RestAnnotationProcessor<AzureBlobStore>>() {
}));

View File

@ -28,6 +28,7 @@ import static org.testng.Assert.assertEquals;
import org.jclouds.azure.storage.blob.handlers.AzureBlobClientErrorRetryHandler;
import org.jclouds.azure.storage.blob.reference.AzureBlobConstants;
import org.jclouds.azure.storage.handlers.ParseAzureStorageErrorFromXmlContent;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.http.handlers.DelegatingErrorHandler;
@ -60,6 +61,9 @@ public class RestAzureBlobConnectionModuleTest {
bindConstant().annotatedWith(
Jsr330.named(AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT)).to(
"http://localhost");
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL)).to(
1l);
}
});
}

View File

@ -23,6 +23,13 @@
*/
package org.jclouds.azure.storage.config;
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import org.jclouds.azure.storage.handlers.ParseAzureStorageErrorFromXmlContent;
import org.jclouds.cloud.ConfiguresCloudConnection;
import org.jclouds.http.HttpErrorHandler;
@ -30,8 +37,13 @@ import org.jclouds.http.RequiresHttp;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.util.DateService;
import org.jclouds.util.TimeStamp;
import com.google.common.base.Function;
import com.google.common.collect.MapMaker;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
* Configures the AzureStorage connection, including logging and http transport.
@ -42,6 +54,28 @@ import com.google.inject.AbstractModule;
@RequiresHttp
public class RestAzureStorageConnectionModule extends AbstractModule {
@Provides
@TimeStamp
protected String provideTimeStamp(@TimeStamp ConcurrentMap<String, String> cache) {
return cache.get("doesn't matter");
}
/**
* borrowing concurrency code to ensure that caching takes place properly
*/
@Provides
@TimeStamp
ConcurrentMap<String, String> provideTimeStampCache(
@Named(PROPERTY_AZURESTORAGE_SESSIONINTERVAL) long seconds,
final DateService dateService) {
return new MapMaker().expiration(seconds, TimeUnit.SECONDS).makeComputingMap(
new Function<String, String>() {
public String apply(String key) {
return dateService.rfc822DateFormat();
}
});
}
@Override
protected void configure() {
bindErrorHandlers();

View File

@ -27,11 +27,10 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;
@ -40,12 +39,12 @@ import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils;
import org.jclouds.util.DateService;
import org.jclouds.util.TimeStamp;
import com.google.common.annotations.VisibleForTesting;
/**
* Signs the Azure Storage request. This will update timestamps at most once per second.
* Signs the Azure Storage request.
*
* @see <a href= "http://msdn.microsoft.com/en-us/library/dd179428.aspx" />
* @author Adrian Cole
@ -57,48 +56,17 @@ public class SharedKeyAuthentication implements HttpRequestFilter {
HttpHeaders.CONTENT_TYPE, HttpHeaders.DATE };
private final String account;
private byte[] key;
private final DateService dateService;
public final long BILLION = 1000000000;
private final AtomicReference<String> timeStamp;
private final AtomicLong trigger = new AtomicLong(System.nanoTime() + 1 * BILLION);
/**
* Start the time update service. Azure clocks need to be within 900 seconds of the request time.
* This method updates the clock every second. This is not performed per-request, as creation of
* the date object is a slow, synchronized command.
*/
synchronized void updateIfTimeOut() {
if (trigger.get() - System.nanoTime() <= 0) {
timeStamp.set(createNewStamp());
trigger.set(System.nanoTime() + 1 * BILLION);
}
}
// this is a hotspot when submitted concurrently, so be lazy.
// amazon is ok with up to 15 minutes off their time, so let's
// be as lazy as possible.
String createNewStamp() {
return dateService.rfc822DateFormat();
}
public String timestampAsHeaderString() {
updateIfTimeOut();
return timeStamp.get();
}
private final byte[] key;
private final Provider<String> timeStampProvider;
@Inject
public SharedKeyAuthentication(
@Named(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT) String account,
@Named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY) String encodedKey,
DateService dateService) {
@TimeStamp Provider<String> timeStampProvider) {
this.account = account;
this.key = HttpUtils.fromBase64String(encodedKey);
this.dateService = dateService;
timeStamp = new AtomicReference<String>(createNewStamp());
this.timeStampProvider = timeStampProvider;
}
public void filter(HttpRequest request) throws HttpException {
@ -140,7 +108,7 @@ public class SharedKeyAuthentication implements HttpRequestFilter {
private void replaceDateHeader(HttpRequest request) {
request.getHeaders().replaceValues(HttpHeaders.DATE,
Collections.singletonList(timestampAsHeaderString()));
Collections.singletonList(timeStampProvider.get()));
}
private void appendCanonicalizedHeaders(HttpRequest request, StringBuilder toSign) {
@ -153,45 +121,6 @@ public class SharedKeyAuthentication implements HttpRequestFilter {
toSign.deleteCharAt(toSign.lastIndexOf(","));
toSign.append("\n");
}
// }
// // Retrieve all headers for the resource that begin with x-ms-, including the x-ms-date
// // header.
// Set<String> matchingHeaders = Sets.filter(request.getHeaders().keySet(),
// new Predicate<String>() {
// public boolean apply(String input) {
// return input.startsWith("x-ms-");
// }
// });
//
// // Convert each HTTP header name to lowercase.
// // Sort the container of headers lexicographically by header name, in ascending order.
// SortedSet<String> lowercaseHeaders =
// Sets.newTreeSet(Iterables.transform(matchingHeaders,
// new Function<String, String>() {
// public String apply(String from) {
// return from.toLowerCase();
// }
// }));
//
// for (String header : lowercaseHeaders) {
// // Combine headers with the same name into one header. The resulting header should be a
// // name-value pair of the format "header-name:comma-separated-value-list", without any
// // white
// // space between values.
// toSign.append(header).append(":");
// // Trim any white space around the colon in the header.
// // TODO: not sure why there would be...
// for (String value : request.getHeaders().get(header))
// // Replace any breaking white space with a single space.
// toSign.append(value.replaceAll("\r?\n", " ")).append(",");
// toSign.deleteCharAt(toSign.lastIndexOf(","));
// // Finally, append a new line character to each canonicalized header in the resulting
// list.
// // Construct the CanonicalizedHeaders string by concatenating all headers in this list
// into
// // a
// // single string.
// toSign.append("\n");
}
}

View File

@ -31,4 +31,8 @@ package org.jclouds.azure.storage.reference;
public interface AzureStorageConstants {
public static final String PROPERTY_AZURESTORAGE_ACCOUNT = "jclouds.azure.storage.account";
public static final String PROPERTY_AZURESTORAGE_KEY = "jclouds.azure.storage.key";
/**
* how long do we wait before obtaining a new timestamp for requests.
*/
public static final String PROPERTY_AZURESTORAGE_SESSIONINTERVAL = "jclouds.azure.storage.sessioninterval";
}

View File

@ -32,6 +32,7 @@ import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.jclouds.azure.storage.AzureBlob;
import org.jclouds.azure.storage.config.RestAzureStorageConnectionModule;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
@ -85,19 +86,29 @@ public class SharedKeyAuthenticationLiveTest {
"jclouds.test.user");
final String key = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
uri = "http://" + account + ".blob.core.windows.net";
injector = Guice.createInjector(new AbstractModule() {
injector = Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
bind(URI.class).annotatedWith(AzureBlob.class).toInstance(URI.create(uri));
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT)).to(account);
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT))
.to(account);
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY)).to(key);
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY))
.to(key);
bindConstant()
.annotatedWith(
Jsr330
.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL))
.to(1l);
}
}, new RestModule(), new Log4JLoggingModule(), new ExecutorServiceModule(
new WithinThreadExecutorService()), new JavaUrlHttpCommandExecutorServiceModule());
}, new RestAzureStorageConnectionModule(), new RestModule(),
new Log4JLoggingModule(),
new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule());
RestClientFactory factory = injector.getInstance(RestClientFactory.class);
client = factory.create(IntegrationTestClient.class);
}

View File

@ -23,6 +23,7 @@
*/
package org.jclouds.azure.storage.filters;
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL;
import static org.testng.Assert.assertEquals;
import java.net.URI;
@ -30,10 +31,11 @@ import java.net.URI;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.azure.storage.config.RestAzureStorageConnectionModule;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils;
import org.jclouds.util.DateService;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.util.Jsr330;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
@ -127,35 +129,26 @@ public class SharedKeyAuthenticationTest {
assertEquals(builder.toString(), "/mycontainer?comp=list");
}
@Test
void testUpdatesOnlyOncePerSecond() throws NoSuchMethodException, InterruptedException {
// filter.createNewStamp();
String timeStamp = filter.timestampAsHeaderString();
// replay(filter);
for (int i = 0; i < 10; i++)
filter.updateIfTimeOut();
assert timeStamp.equals(filter.timestampAsHeaderString());
Thread.sleep(1000);
assert !timeStamp.equals(filter.timestampAsHeaderString());
// verify(filter);
}
/**
* before class, as we need to ensure that the filter is threadsafe.
*
*/
@BeforeClass
protected void createFilter() {
injector = Guice.createInjector(new AbstractModule() {
injector = Guice.createInjector(new ParserModule(), new RestAzureStorageConnectionModule(),
new AbstractModule() {
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT)).to(ACCOUNT);
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT))
.to(ACCOUNT);
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY)).to(KEY);
bind(DateService.class);
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY))
.to(KEY);
bindConstant().annotatedWith(
Jsr330.named(PROPERTY_AZURESTORAGE_SESSIONINTERVAL)).to("1");
}
});
filter = injector.getInstance(SharedKeyAuthentication.class);
}

View File

@ -24,6 +24,7 @@
package org.jclouds.azure.storage.queue;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL;
import java.net.URI;
import java.util.List;
@ -68,6 +69,8 @@ public class AzureQueueContextBuilder extends CloudContextBuilder<AzureQueueConn
String endpoint = properties.getProperty(AzureQueueConstants.PROPERTY_AZUREQUEUE_ENDPOINT);
properties.setProperty(AzureQueueConstants.PROPERTY_AZUREQUEUE_ENDPOINT, endpoint.replaceAll(
"\\{account\\}", id));
if (!properties.containsKey(PROPERTY_AZURESTORAGE_SESSIONINTERVAL))
this.withTimeStampExpiration(60);
}
public AzureQueueContextBuilder(Properties properties) {
@ -161,4 +164,9 @@ public class AzureQueueContextBuilder extends CloudContextBuilder<AzureQueueConn
return (AzureQueueContextBuilder) super
.withPoolRequestInvokerThreads(poolRequestInvokerThreads);
}
public AzureQueueContextBuilder withTimeStampExpiration(long seconds) {
getProperties().setProperty(PROPERTY_AZURESTORAGE_SESSIONINTERVAL, seconds + "");
return this;
}
}

View File

@ -34,6 +34,7 @@ import java.util.Collections;
import javax.ws.rs.HttpMethod;
import org.jclouds.azure.storage.AzureQueue;
import org.jclouds.azure.storage.config.RestAzureStorageConnectionModule;
import org.jclouds.azure.storage.options.CreateOptions;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
@ -184,9 +185,12 @@ public class AzureQueueConnectionTest {
return Logger.NULL;
}
});
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL)).to(
1l);
}
}, new RestModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule());
}, new RestAzureStorageConnectionModule(), new RestModule(), new ExecutorServiceModule(
new WithinThreadExecutorService()), new JavaUrlHttpCommandExecutorServiceModule());
processor = injector.getInstance(Key
.get(new TypeLiteral<RestAnnotationProcessor<AzureQueueConnection>>() {
}));

View File

@ -38,7 +38,6 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.DateService;
import org.testng.annotations.BeforeTest;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.util;
import static org.testng.Assert.assertEquals;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.http.internal;
import static com.google.common.base.Preconditions.checkNotNull;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.rest.internal;
import java.lang.reflect.Method;

View File

@ -0,0 +1,44 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Related to a TimeStamp
*
* @author Adrian Cole
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface TimeStamp {
}

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.mezeo.pcs2.binders;
import static com.google.common.base.Preconditions.checkNotNull;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.mezeo.pcs2.functions;
import static com.google.common.base.Preconditions.checkState;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.mezeo.pcs2.options;
import static com.google.common.base.Preconditions.checkArgument;

View File

@ -40,13 +40,14 @@ import org.testng.annotations.Test;
@Test(groups = { "integration", "live" }, testName = "cloudfiles.PCSBlobMapIntegrationTest")
public class PCSBlobMapIntegrationTest extends
BaseBlobMapIntegrationTest<PCSConnection, ContainerMetadata, FileMetadata, PCSFile> {
@Test(enabled = false)
@Override
public void testEntrySet() throws IOException, InterruptedException, ExecutionException,
TimeoutException {
// fails on 400 errors
}
@Test(enabled = false)
@Override
public void testContains() throws InterruptedException, ExecutionException, TimeoutException {
// not supported

View File

@ -41,30 +41,35 @@ import org.testng.annotations.Test;
public class PCSInputStreamMapIntegrationTest extends
BaseInputStreamMapIntegrationTest<PCSConnection, ContainerMetadata, FileMetadata, PCSFile> {
@Test(enabled = false)
@Override
public void testEntrySet() throws IOException, InterruptedException, ExecutionException,
TimeoutException {
// fails on 400 errors
}
@Test(enabled = false)
@Override
public void testContainsBytesValue() throws InterruptedException, ExecutionException,
TimeoutException {
// not supported
}
@Test(enabled = false)
@Override
public void testContainsFileValue() throws InterruptedException, ExecutionException,
TimeoutException {
// not supported
}
@Test(enabled = false)
@Override
public void testContainsInputStreamValue() throws InterruptedException, ExecutionException,
TimeoutException {
// not supported
}
@Test(enabled = false)
@Override
public void testContainsStringValue() throws InterruptedException, ExecutionException,
TimeoutException {

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.mezeo.pcs2.options;
import static org.jclouds.mezeo.pcs2.options.PutBlockOptions.Builder.range;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.nirvanix.sdn;
import org.jclouds.cloud.CloudContext;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.nirvanix.sdn.binders;
import static com.google.common.base.Preconditions.checkArgument;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.nirvanix.sdn.config;
import java.net.URI;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.nirvanix.sdn.domain;
import java.net.URI;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.nirvanix.sdn.filters;
import static com.google.common.base.Preconditions.checkArgument;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.nirvanix.sdn.filters;
import static com.google.common.base.Preconditions.checkArgument;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.nirvanix.sdn;
import static com.google.common.base.Preconditions.checkNotNull;

View File

@ -1,3 +1,26 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.nirvanix.sdn.binders;
import static org.easymock.classextension.EasyMock.createMock;