removed mapmaker expiration as it is incompatible with google appengine. replaced with ExpirableSupplier

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2032 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-10-31 09:07:57 +00:00
parent af2fa174d1
commit 3d030cfac0
46 changed files with 435 additions and 379 deletions

View File

@ -27,7 +27,6 @@ import static org.jclouds.atmosonline.saas.reference.AtmosStorageConstants.PROPE
import static org.jclouds.atmosonline.saas.reference.AtmosStorageConstants.PROPERTY_EMCSAAS_SESSIONINTERVAL;
import java.net.URI;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
@ -37,6 +36,7 @@ import org.jclouds.atmosonline.saas.AtmosStorage;
import org.jclouds.atmosonline.saas.AtmosStorageClient;
import org.jclouds.atmosonline.saas.handlers.AtmosStorageClientErrorRetryHandler;
import org.jclouds.atmosonline.saas.handlers.ParseAtmosStorageErrorFromXmlContent;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.RequiresHttp;
@ -48,8 +48,7 @@ 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.common.base.Supplier;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
@ -82,8 +81,8 @@ public class AtmosStorageRestClientModule extends AbstractModule {
@Provides
@TimeStamp
protected String provideTimeStamp(@TimeStamp ConcurrentMap<String, String> cache) {
return cache.get("doesn't matter");
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return cache.get();
}
/**
@ -91,14 +90,13 @@ public class AtmosStorageRestClientModule extends AbstractModule {
*/
@Provides
@TimeStamp
ConcurrentMap<String, String> provideTimeStampCache(
@Named(PROPERTY_EMCSAAS_SESSIONINTERVAL) long seconds, final DateService dateService) {
return new MapMaker().expiration(seconds, TimeUnit.SECONDS).makeComputingMap(
new Function<String, String>() {
public String apply(String key) {
Supplier<String> provideTimeStampCache(@Named(PROPERTY_EMCSAAS_SESSIONINTERVAL) long seconds,
final DateService dateService) {
return new ExpirableSupplier<String>(new Supplier<String>() {
public String get() {
return dateService.rfc822DateFormat();
}
});
}, seconds, TimeUnit.SECONDS);
}
protected void bindErrorHandlers() {

View File

@ -26,8 +26,6 @@ package org.jclouds.atmosonline.saas.config;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import java.util.concurrent.ConcurrentMap;
import org.bouncycastle.util.encoders.Base64;
import org.jclouds.atmosonline.saas.handlers.AtmosStorageClientErrorRetryHandler;
import org.jclouds.atmosonline.saas.handlers.ParseAtmosStorageErrorFromXmlContent;
@ -42,6 +40,7 @@ import org.jclouds.util.DateService;
import org.jclouds.util.Jsr330;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -74,13 +73,13 @@ public class AtmosStorageRestClientModuleTest {
void testUpdatesOnlyOncePerSecond() throws NoSuchMethodException, InterruptedException {
AtmosStorageRestClientModule module = new AtmosStorageRestClientModule();
ConcurrentMap<String, String> map = module.provideTimeStampCache(1, new DateService());
String timeStamp = map.get("foo");
Supplier<String> map = module.provideTimeStampCache(1, new DateService());
String timeStamp = map.get();
for (int i = 0; i < 10; i++)
map.get("foo");
assertEquals(timeStamp, map.get("foo"));
map.get();
assertEquals(timeStamp, map.get());
Thread.sleep(1001);
assertFalse(timeStamp.equals(map.get("foo")));
assertFalse(timeStamp.equals(map.get()));
}
@Test

View File

@ -26,8 +26,11 @@ 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_ENDPOINT;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_METADATA_PREFIX;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_RETRY;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SESSIONINTERVAL;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_TIMEOUT;
import java.net.URI;
import java.util.Properties;
@ -44,7 +47,7 @@ public class S3PropertiesBuilder extends HttpPropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(S3Constants.PROPERTY_S3_ENDPOINT, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_S3_ENDPOINT, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_S3_METADATA_PREFIX, "x-amz-meta-");
properties.setProperty(PROPERTY_S3_SESSIONINTERVAL, "60");
return properties;
@ -77,4 +80,24 @@ public class S3PropertiesBuilder extends HttpPropertiesBuilder {
return this;
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public S3PropertiesBuilder withRequestTimeout(long milliseconds) {
properties.setProperty(PROPERTY_S3_TIMEOUT, Long.toString(milliseconds));
return this;
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public S3PropertiesBuilder withMaxRetries(int retries) {
properties.setProperty(PROPERTY_S3_RETRY, Integer.toString(retries));
return this;
}
protected S3PropertiesBuilder withMetaPrefix(String prefix) {
properties.setProperty(PROPERTY_S3_METADATA_PREFIX, prefix);
return this;
}
}

View File

@ -23,8 +23,11 @@
*/
package org.jclouds.aws.s3.blobstore;
import static org.jclouds.aws.s3.reference.S3Constants.*;
import static org.jclouds.blobstore.reference.BlobStoreConstants.*;
import java.util.List;
import java.util.Properties;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import org.jclouds.aws.s3.S3Client;
@ -34,6 +37,7 @@ import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
@ -55,7 +59,17 @@ public class S3BlobStoreContextBuilder extends BlobStoreContextBuilder<S3Client>
public S3BlobStoreContextBuilder(Properties props) {
super(new TypeLiteral<S3Client>() {
}, props);
}, convert(props));
}
private static Properties convert(Properties props) {
for (Entry<String, String> entry : ImmutableMap.of(PROPERTY_S3_METADATA_PREFIX,
PROPERTY_USER_METADATA_PREFIX, PROPERTY_S3_RETRY, PROPERTY_BLOBSTORE_RETRY,
PROPERTY_S3_TIMEOUT, PROPERTY_USER_METADATA_PREFIX).entrySet()) {
if (props.containsKey(entry.getKey()))
props.setProperty(entry.getValue(), props.getProperty(entry.getKey()));
}
return props;
}
@Override

View File

@ -27,6 +27,7 @@ import java.net.URI;
import java.util.Properties;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.S3PropertiesBuilder;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
@ -47,19 +48,19 @@ import com.google.inject.Module;
*/
public class S3BlobStoreContextFactory {
public static BlobStoreContext<S3Client> createContext(Properties properties, Module... modules) {
return new S3BlobStoreContextBuilder(new S3BlobStorePropertiesBuilder(properties).build())
return new S3BlobStoreContextBuilder(new S3PropertiesBuilder(properties).build())
.withModules(modules).buildContext();
}
public static BlobStoreContext<S3Client> createContext(String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new S3BlobStoreContextBuilder(new S3BlobStorePropertiesBuilder(awsAccessKeyId,
return new S3BlobStoreContextBuilder(new S3PropertiesBuilder(awsAccessKeyId,
awsSecretAccessKey).build()).withModules(modules).buildContext();
}
public static BlobStoreContext<S3Client> createContext(URI endpoint, String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new S3BlobStoreContextBuilder(new S3BlobStorePropertiesBuilder(awsAccessKeyId,
return new S3BlobStoreContextBuilder(new S3PropertiesBuilder(awsAccessKeyId,
awsSecretAccessKey).withEndpoint(endpoint).build()).withModules(modules)
.buildContext();
}

View File

@ -1,63 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.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.aws.s3.blobstore;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import java.util.Properties;
import org.jclouds.aws.s3.S3PropertiesBuilder;
import org.jclouds.blobstore.reference.BlobStoreConstants;
/**
* Builds properties used in S3 Blob Stores
*
* @author Adrian Cole, Andrew Newdigate
*/
public class S3BlobStorePropertiesBuilder extends S3PropertiesBuilder {
public S3BlobStorePropertiesBuilder(String id, String secret) {
super(id, secret);
}
public S3BlobStorePropertiesBuilder(Properties properties) {
super(properties);
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public S3BlobStorePropertiesBuilder withRequestTimeout(long milliseconds) {
properties.setProperty(BlobStoreConstants.PROPERTY_BLOBSTORE_TIMEOUT, Long
.toString(milliseconds));
return this;
}
@Override
protected Properties defaultProperties() {
Properties props = super.defaultProperties();
props.setProperty(PROPERTY_USER_METADATA_PREFIX, "x-amz-meta-");
return props;
}
}

View File

@ -24,7 +24,6 @@
package org.jclouds.aws.s3.config;
import java.net.URI;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
@ -37,6 +36,7 @@ import org.jclouds.aws.s3.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.s3.handlers.AWSRedirectionRetryHandler;
import org.jclouds.aws.s3.handlers.ParseAWSErrorFromXmlContent;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.RequiresHttp;
@ -48,8 +48,7 @@ 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.common.base.Supplier;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Scopes;
@ -65,8 +64,8 @@ public class S3RestClientModule extends AbstractModule {
@Provides
@TimeStamp
protected String provideTimeStamp(@TimeStamp ConcurrentMap<String, String> cache) {
return cache.get("doesn't matter");
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return cache.get();
}
/**
@ -74,15 +73,14 @@ public class S3RestClientModule extends AbstractModule {
*/
@Provides
@TimeStamp
ConcurrentMap<String, String> provideTimeStampCache(
Supplier<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 new ExpirableSupplier<String>(new Supplier<String>() {
public String get() {
return dateService.rfc822DateFormat();
}
});
}, seconds, TimeUnit.SECONDS);
}
@Override

View File

@ -23,6 +23,8 @@
*/
package org.jclouds.aws.s3.functions;
import javax.inject.Singleton;
import org.jclouds.aws.s3.domain.S3Object;
import com.google.common.base.Function;
@ -31,6 +33,7 @@ import com.google.common.base.Function;
*
* @author Adrian Cole
*/
@Singleton
public class ObjectKey implements Function<Object, String> {
public String apply(Object from) {

View File

@ -46,6 +46,19 @@ public interface S3Constants extends AWSConstants, S3Headers {
* how long do we wait before obtaining a new timestamp for requests.
*/
public static final String PROPERTY_S3_SESSIONINTERVAL = "jclouds.s3.sessioninterval";
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public static final String PROPERTY_S3_TIMEOUT = "jclouds.s3.timeout";
/**
* time to pause before retrying a transient failure
*/
public static final String PROPERTY_S3_RETRY = "jclouds.s3.retry";
/**
* Any header starting with this prefix is considered user metadata. It will be stored with the
* object and returned when you retrieve the object/
*/
public static final String PROPERTY_S3_METADATA_PREFIX = "jclouds.s3.metaprefix";
}

View File

@ -33,6 +33,7 @@ import java.util.ArrayList;
import java.util.List;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.S3PropertiesBuilder;
import org.jclouds.aws.s3.blobstore.config.S3BlobStoreContextModule;
import org.jclouds.aws.s3.config.S3RestClientModule;
import org.jclouds.aws.s3.config.S3StubClientModule;
@ -59,8 +60,8 @@ import com.google.inject.TypeLiteral;
public class S3BlobStoreContextBuilderTest {
public void testNewBuilder() {
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(
new S3BlobStorePropertiesBuilder("id", "secret").build());
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(new S3PropertiesBuilder(
"id", "secret").build());
assertEquals(builder.getProperties().getProperty(PROPERTY_USER_METADATA_PREFIX),
"x-amz-meta-");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_ACCESSKEYID), "id");
@ -68,9 +69,8 @@ public class S3BlobStoreContextBuilderTest {
}
public void testBuildContext() {
BlobStoreContext<S3Client> context = new S3BlobStoreContextBuilder(
new S3BlobStorePropertiesBuilder("id", "secret").build()).withModules(
new S3StubClientModule()).buildContext();
BlobStoreContext<S3Client> context = new S3BlobStoreContextBuilder(new S3PropertiesBuilder(
"id", "secret").build()).withModules(new S3StubClientModule()).buildContext();
assertEquals(context.getClass(), BlobStoreContextImpl.class);
assertEquals(context.getApi().getClass(), StubS3Client.class);
assertEquals(context.getBlobStore().getClass(), S3BlobStore.class);
@ -81,8 +81,8 @@ public class S3BlobStoreContextBuilderTest {
}
public void testBuildInjector() {
Injector i = new S3BlobStoreContextBuilder(new S3BlobStorePropertiesBuilder("id", "secret")
.build()).withModules(new S3StubClientModule()).buildInjector();
Injector i = new S3BlobStoreContextBuilder(new S3PropertiesBuilder("id", "secret").build())
.withModules(new S3StubClientModule()).buildInjector();
assert i.getInstance(Key.get(new TypeLiteral<BlobStoreContext<S3Client>>() {
})) != null;
assert i.getInstance(S3Object.class) != null;
@ -91,8 +91,8 @@ public class S3BlobStoreContextBuilderTest {
protected void testAddContextModule() {
List<Module> modules = new ArrayList<Module>();
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(
new S3BlobStorePropertiesBuilder("id", "secret").build());
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(new S3PropertiesBuilder(
"id", "secret").build());
builder.addContextModule(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), S3BlobStoreContextModule.class);
@ -100,8 +100,8 @@ public class S3BlobStoreContextBuilderTest {
protected void addClientModule() {
List<Module> modules = new ArrayList<Module>();
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(
new S3BlobStorePropertiesBuilder("id", "secret").build());
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(new S3PropertiesBuilder(
"id", "secret").build());
builder.addClientModule(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), S3RestClientModule.class);

View File

@ -24,9 +24,9 @@
package org.jclouds.aws.s3.blobstore.integration;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.S3PropertiesBuilder;
import org.jclouds.aws.s3.blobstore.S3BlobStoreContextBuilder;
import org.jclouds.aws.s3.blobstore.S3BlobStoreContextFactory;
import org.jclouds.aws.s3.blobstore.S3BlobStorePropertiesBuilder;
import org.jclouds.aws.s3.config.S3StubClientModule;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
@ -45,9 +45,8 @@ public class S3TestInitializer extends BaseTestInitializer<S3Client> {
protected BlobStoreContext<S3Client> createLiveContext(Module configurationModule, String url,
String app, String account, String key) {
BaseBlobStoreIntegrationTest.SANITY_CHECK_RETURNED_BUCKET_NAME = true;
return new S3BlobStoreContextBuilder(new S3BlobStorePropertiesBuilder(account, key)
.relaxSSLHostname().build()).withModules(configurationModule,
new Log4JLoggingModule()).buildContext();
return new S3BlobStoreContextBuilder(new S3PropertiesBuilder(account, key).relaxSSLHostname()
.build()).withModules(configurationModule, new Log4JLoggingModule()).buildContext();
}
@Override

View File

@ -26,8 +26,6 @@ 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;
import org.jclouds.aws.s3.handlers.ParseAWSErrorFromXmlContent;
@ -41,6 +39,7 @@ import org.jclouds.util.DateService;
import org.jclouds.util.Jsr330;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -72,13 +71,13 @@ public class S3RestClientModuleTest {
void testUpdatesOnlyOncePerSecond() throws NoSuchMethodException, InterruptedException {
S3RestClientModule module = new S3RestClientModule();
ConcurrentMap<String, String> map = module.provideTimeStampCache(1, new DateService());
String timeStamp = map.get("foo");
Supplier<String> map = module.provideTimeStampCache(1, new DateService());
String timeStamp = map.get();
for (int i = 0; i < 10; i++)
map.get("foo");
assertEquals(timeStamp, map.get("foo"));
map.get();
assertEquals(timeStamp, map.get());
Thread.sleep(1001);
assertFalse(timeStamp.equals(map.get("foo")));
assertFalse(timeStamp.equals(map.get()));
}
@Test

View File

@ -24,14 +24,19 @@
package org.jclouds.azure.storage.blob;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_RETRY;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_SESSIONINTERVAL;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_TIMEOUT;
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT;
import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY;
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;
import java.util.Properties;
import org.jclouds.azure.storage.blob.reference.AzureBlobConstants;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.http.HttpPropertiesBuilder;
/**
@ -43,10 +48,10 @@ public class AzureBlobPropertiesBuilder extends HttpPropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT,
"https://{account}.blob.core.windows.net");
properties.setProperty(AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX, "x-ms-meta-");
properties.setProperty(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX, "x-ms-meta-");
properties
.setProperty(PROPERTY_AZUREBLOB_ENDPOINT, "https://{account}.blob.core.windows.net");
properties.setProperty(PROPERTY_AZUREBLOB_METADATA_PREFIX, "x-ms-meta-");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "x-ms-meta-");
properties.setProperty(PROPERTY_AZURESTORAGE_SESSIONINTERVAL, 60 + "");
return properties;
}
@ -61,29 +66,48 @@ public class AzureBlobPropertiesBuilder extends HttpPropertiesBuilder {
}
public AzureBlobPropertiesBuilder withCredentials(String id, String secret) {
properties.setProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT, checkNotNull(id,
"azureStorageAccount"));
properties.setProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY, checkNotNull(secret,
"azureStorageKey"));
String endpoint = properties.getProperty(AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT);
properties.setProperty(AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT, endpoint.replaceAll(
"\\{account\\}", id));
properties
.setProperty(PROPERTY_AZURESTORAGE_ACCOUNT, checkNotNull(id, "azureStorageAccount"));
properties.setProperty(PROPERTY_AZURESTORAGE_KEY, checkNotNull(secret, "azureStorageKey"));
String endpoint = properties.getProperty(PROPERTY_AZUREBLOB_ENDPOINT);
properties.setProperty(PROPERTY_AZUREBLOB_ENDPOINT, endpoint.replaceAll("\\{account\\}", id));
return this;
}
public AzureBlobPropertiesBuilder withEndpoint(URI endpoint) {
String account = checkNotNull(properties
.getProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT),
String account = checkNotNull(properties.getProperty(PROPERTY_AZURESTORAGE_ACCOUNT),
"azureStorageAccount");
properties.setProperty(AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT, checkNotNull(endpoint,
"endpoint").toString());
properties.setProperty(AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT, endpoint.toString()
.replaceAll("\\{account\\}", account));
properties.setProperty(PROPERTY_AZUREBLOB_ENDPOINT, checkNotNull(endpoint, "endpoint")
.toString());
properties.setProperty(PROPERTY_AZUREBLOB_ENDPOINT, endpoint.toString().replaceAll(
"\\{account\\}", account));
return this;
}
public AzureBlobPropertiesBuilder withTimeStampExpiration(long seconds) {
properties.setProperty(PROPERTY_AZURESTORAGE_SESSIONINTERVAL, seconds + "");
properties.setProperty(PROPERTY_AZUREBLOB_SESSIONINTERVAL, seconds + "");
return this;
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public AzureBlobPropertiesBuilder withRequestTimeout(long milliseconds) {
properties.setProperty(PROPERTY_AZUREBLOB_TIMEOUT, Long.toString(milliseconds));
return this;
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public AzureBlobPropertiesBuilder withMaxRetries(int retries) {
properties.setProperty(PROPERTY_AZUREBLOB_RETRY, Integer.toString(retries));
return this;
}
protected AzureBlobPropertiesBuilder withMetaPrefix(String prefix) {
properties.setProperty(PROPERTY_AZUREBLOB_METADATA_PREFIX, prefix);
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, prefix);
return this;
}

View File

@ -23,26 +23,27 @@
*/
package org.jclouds.azure.storage.blob.binders;
import static com.google.common.base.Preconditions.*;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.azure.storage.blob.blobstore.functions.AzureBlobToBlob;
import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.reference.AzureBlobConstants;
import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
public class BindAzureBlobToEntity implements Binder {
public class BindAzureBlobToEntity extends BindBlobToEntityAndUserMetadataToHeadersWithPrefix {
private final BindBlobToEntityAndUserMetadataToHeadersWithPrefix blobBinder;
private final AzureBlobToBlob azureBlob2Blob;
@Inject
public BindAzureBlobToEntity(AzureBlobToBlob azureBlob2Blob,
BindBlobToEntityAndUserMetadataToHeadersWithPrefix blobBinder) {
this.blobBinder = blobBinder;
@Named(AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX) String prefix) {
super(prefix);
this.azureBlob2Blob = azureBlob2Blob;
}
@ -52,7 +53,7 @@ public class BindAzureBlobToEntity implements Binder {
checkArgument(
checkNotNull(object.getContentLength(), "object.getContentLength()") <= 64 * 1024 * 1024,
"maximum size for put Blob is 64MB");
blobBinder.bindToRequest(request, azureBlob2Blob.apply(object));
super.bindToRequest(request, azureBlob2Blob.apply(object));
if (object.getProperties().getContentLanguage() != null) {
request.getHeaders().put(HttpHeaders.CONTENT_LANGUAGE,

View File

@ -23,8 +23,15 @@
*/
package org.jclouds.azure.storage.blob.blobstore;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_RETRY;
import static org.jclouds.azure.storage.blob.reference.AzureBlobConstants.PROPERTY_AZUREBLOB_TIMEOUT;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_BLOBSTORE_RETRY;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import java.util.List;
import java.util.Properties;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import org.jclouds.azure.storage.blob.AzureBlobClient;
@ -34,6 +41,7 @@ import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
@ -55,7 +63,17 @@ public class AzureBlobStoreContextBuilder extends BlobStoreContextBuilder<AzureB
public AzureBlobStoreContextBuilder(Properties props) {
super(new TypeLiteral<AzureBlobClient>() {
}, props);
}, convert(props));
}
private static Properties convert(Properties props) {
for (Entry<String, String> entry : ImmutableMap.of(PROPERTY_AZUREBLOB_METADATA_PREFIX,
PROPERTY_USER_METADATA_PREFIX, PROPERTY_AZUREBLOB_RETRY, PROPERTY_BLOBSTORE_RETRY,
PROPERTY_AZUREBLOB_TIMEOUT, PROPERTY_USER_METADATA_PREFIX).entrySet()) {
if (props.containsKey(entry.getKey()))
props.setProperty(entry.getValue(), props.getProperty(entry.getKey()));
}
return props;
}
@Override

View File

@ -27,6 +27,7 @@ import java.net.URI;
import java.util.Properties;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.AzureBlobPropertiesBuilder;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
@ -34,8 +35,7 @@ import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.inject.Module;
/**
* Creates {@link AzureBlobStoreContext} instances based on the most commonly requested
* arguments.
* Creates {@link AzureBlobStoreContext} instances based on the most commonly requested arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
@ -49,20 +49,19 @@ import com.google.inject.Module;
public class AzureBlobStoreContextFactory {
public static BlobStoreContext<AzureBlobClient> createContext(Properties properties,
Module... modules) {
return new AzureBlobStoreContextBuilder(new AzureBlobStorePropertiesBuilder(
properties).build()).withModules(modules).buildContext();
return new AzureBlobStoreContextBuilder(new AzureBlobPropertiesBuilder(properties).build())
.withModules(modules).buildContext();
}
public static BlobStoreContext<AzureBlobClient> createContext(String user,
public static BlobStoreContext<AzureBlobClient> createContext(String user, String encodedKey,
Module... modules) {
return new AzureBlobStoreContextBuilder(new AzureBlobPropertiesBuilder(user, encodedKey)
.build()).withModules(modules).buildContext();
}
public static BlobStoreContext<AzureBlobClient> createContext(URI endpoint, String user,
String encodedKey, Module... modules) {
return new AzureBlobStoreContextBuilder(new AzureBlobStorePropertiesBuilder(
user, encodedKey).build()).withModules(modules).buildContext();
}
public static BlobStoreContext<AzureBlobClient> createContext(URI endpoint,
String user, String encodedKey, Module... modules) {
return new AzureBlobStoreContextBuilder(new AzureBlobStorePropertiesBuilder(
user, encodedKey).withEndpoint(endpoint).build()).withModules(
modules).buildContext();
return new AzureBlobStoreContextBuilder(new AzureBlobPropertiesBuilder(user, encodedKey)
.withEndpoint(endpoint).build()).withModules(modules).buildContext();
}
}

View File

@ -1,55 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.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.azure.storage.blob.blobstore;
import java.util.Properties;
import org.jclouds.azure.storage.blob.AzureBlobPropertiesBuilder;
import org.jclouds.blobstore.reference.BlobStoreConstants;
/**
* Builds properties used in AzureBlob Blob Stores
*
* @author Adrian Cole, Andrew Newdigate
*/
public class AzureBlobStorePropertiesBuilder extends AzureBlobPropertiesBuilder {
public AzureBlobStorePropertiesBuilder(String id, String secret) {
super(id, secret);
}
public AzureBlobStorePropertiesBuilder(Properties properties) {
super(properties);
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public AzureBlobStorePropertiesBuilder withRequestTimeout(long milliseconds) {
properties.setProperty(BlobStoreConstants.PROPERTY_BLOBSTORE_TIMEOUT, Long
.toString(milliseconds));
return this;
}
}

View File

@ -32,6 +32,24 @@ import org.jclouds.azure.storage.reference.AzureStorageConstants;
*/
public interface AzureBlobConstants extends AzureStorageConstants {
public static final String PROPERTY_AZUREBLOB_ENDPOINT = "jclouds.azureblob.endpoint";
/**
* how long do we wait before obtaining a new timestamp for requests.
*/
public static final String PROPERTY_AZUREBLOB_SESSIONINTERVAL = "jclouds.azureblob.sessioninterval";
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public static final String PROPERTY_AZUREBLOB_TIMEOUT = "jclouds.azureblob.timeout";
/**
* time to pause before retrying a transient failure
*/
public static final String PROPERTY_AZUREBLOB_RETRY = "jclouds.azureblob.retry";
/**
* Any header starting with this prefix is considered user metadata. It will be stored with the
* object and returned when you retrieve the object/
*/
public static final String PROPERTY_AZUREBLOB_METADATA_PREFIX = "jclouds.azureblob.metaprefix";
}

View File

@ -23,7 +23,6 @@
*/
package org.jclouds.azure.storage.blob;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.testng.Assert.assertEquals;
import java.net.URI;
@ -35,6 +34,7 @@ import org.jclouds.azure.storage.blob.config.AzureBlobRestClientModule;
import org.jclouds.azure.storage.blob.config.AzureBlobStubClientModule;
import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.internal.StubAzureBlobClient;
import org.jclouds.azure.storage.blob.reference.AzureBlobConstants;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.rest.RestContext;
@ -57,7 +57,8 @@ public class AzureBlobContextBuilderTest {
public void testNewBuilder() {
AzureBlobContextBuilder builder = new AzureBlobContextBuilder(new AzureBlobPropertiesBuilder(
"id", "secret").build()).withModules(new AzureBlobStubClientModule());
assertEquals(builder.getProperties().getProperty(PROPERTY_USER_METADATA_PREFIX), "x-ms-meta-");
assertEquals(builder.getProperties().getProperty(
AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX), "x-ms-meta-");
assertEquals(builder.getProperties().getProperty(
AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT), "id");
assertEquals(builder.getProperties().getProperty(
@ -65,8 +66,9 @@ public class AzureBlobContextBuilderTest {
}
public void testBuildContext() {
RestContext<AzureBlobClient> context = new AzureBlobContextBuilder(new AzureBlobPropertiesBuilder("id",
"secret").build()).withModules(new AzureBlobStubClientModule()).buildContext();
RestContext<AzureBlobClient> context = new AzureBlobContextBuilder(
new AzureBlobPropertiesBuilder("id", "secret").build()).withModules(
new AzureBlobStubClientModule()).buildContext();
assertEquals(context.getClass(), RestContextImpl.class);
assertEquals(context.getApi().getClass(), StubAzureBlobClient.class);
assertEquals(context.getAccount(), "id");
@ -79,7 +81,8 @@ public class AzureBlobContextBuilderTest {
assert i.getInstance(Key.get(new TypeLiteral<RestContext<AzureBlobClient>>() {
})) != null;
assert i.getInstance(AzureBlob.class) != null;
assert i.getInstance(Blob.class) != null; }
assert i.getInstance(Blob.class) != null;
}
protected void testAddContextModule() {
List<Module> modules = new ArrayList<Module>();

View File

@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.List;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.AzureBlobPropertiesBuilder;
import org.jclouds.azure.storage.blob.blobstore.config.AzureBlobStoreContextModule;
import org.jclouds.azure.storage.blob.config.AzureBlobRestClientModule;
import org.jclouds.azure.storage.blob.config.AzureBlobStubClientModule;
@ -68,7 +69,7 @@ public class AzureBlobStoreContextBuilderTest {
}
private AzureBlobStoreContextBuilder newBuilder() {
return new AzureBlobStoreContextBuilder(new AzureBlobStorePropertiesBuilder("id",
return new AzureBlobStoreContextBuilder(new AzureBlobPropertiesBuilder("id",
"secret").build()).withModules(new AzureBlobStubClientModule());
}

View File

@ -24,9 +24,9 @@
package org.jclouds.azure.storage.blob.blobstore.integration;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.AzureBlobPropertiesBuilder;
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStoreContextBuilder;
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStoreContextFactory;
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStorePropertiesBuilder;
import org.jclouds.azure.storage.blob.config.AzureBlobStubClientModule;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.integration.internal.BaseTestInitializer;
@ -43,7 +43,7 @@ public class AzureBlobTestInitializer extends BaseTestInitializer<AzureBlobClien
@Override
protected BlobStoreContext<AzureBlobClient> createLiveContext(Module configurationModule,
String url, String app, String account, String key) {
return new AzureBlobStoreContextBuilder(new AzureBlobStorePropertiesBuilder(
return new AzureBlobStoreContextBuilder(new AzureBlobPropertiesBuilder(
account, key).relaxSSLHostname().build()).withModules(configurationModule,
new Log4JLoggingModule()).buildContext();
}

View File

@ -25,12 +25,12 @@ 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.concurrent.ExpirableSupplier;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.RequiresHttp;
import org.jclouds.http.annotation.ClientError;
@ -40,8 +40,7 @@ import org.jclouds.rest.ConfiguresRestClient;
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.common.base.Supplier;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
@ -56,8 +55,8 @@ public class AzureStorageRestClientModule extends AbstractModule {
@Provides
@TimeStamp
protected String provideTimeStamp(@TimeStamp ConcurrentMap<String, String> cache) {
return cache.get("doesn't matter");
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return cache.get();
}
/**
@ -65,15 +64,14 @@ public class AzureStorageRestClientModule extends AbstractModule {
*/
@Provides
@TimeStamp
ConcurrentMap<String, String> provideTimeStampCache(
Supplier<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 new ExpirableSupplier<String>(new Supplier<String>() {
public String get() {
return dateService.rfc822DateFormat();
}
});
}, seconds, TimeUnit.SECONDS);
}
@Override

View File

@ -29,8 +29,6 @@ import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import java.util.concurrent.ConcurrentMap;
import org.jclouds.azure.storage.handlers.ParseAzureStorageErrorFromXmlContent;
import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
@ -43,6 +41,7 @@ import org.jclouds.util.DateService;
import org.jclouds.util.Jsr330;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -70,13 +69,13 @@ public class AzureStorageRestClientModuleTest {
void testUpdatesOnlyOncePerSecond() throws NoSuchMethodException, InterruptedException {
AzureStorageRestClientModule module = new AzureStorageRestClientModule();
ConcurrentMap<String, String> map = module.provideTimeStampCache(1, new DateService());
String timeStamp = map.get("foo");
Supplier<String> map = module.provideTimeStampCache(1, new DateService());
String timeStamp = map.get();
for (int i = 0; i < 10; i++)
map.get("foo");
assertEquals(timeStamp, map.get("foo"));
map.get();
assertEquals(timeStamp, map.get());
Thread.sleep(1001);
assertFalse(timeStamp.equals(map.get("foo")));
assertFalse(timeStamp.equals(map.get()));
}
@Test

View File

@ -29,6 +29,11 @@ package org.jclouds.blobstore.reference;
* @author Adrian Cole
*/
public interface BlobStoreConstants {
/**
* comma-separated, fully qualified class names of implementations of BlobStoreContextBuilder
*
*/
public static final String PROPERTY_BLOBSTORE_CONTEXTBUILDERS = "jclouds.blobstore.contextbuilders";
/**
* longest time a single synchronous operation can take before throwing an exception.

View File

@ -79,7 +79,7 @@ public class ParseBlobFromHeadersAndHttpContentTest {
metadataParser, blobProvider);
Multimap<String, String> allHeaders = ImmutableMultimap.of("key", "value");
HttpResponse from = new HttpResponse();
from.setHeaders(allHeaders);
from.getHeaders().putAll(allHeaders);
Blob object = blobProvider.create(null);
callable.addAllHeadersTo(from, object);
assertEquals(object.getAllHeaders().get("key"), Collections.singletonList("value"));

View File

@ -142,7 +142,7 @@ public class ParseBlobMetadataFromHeadersTest {
public void testAddUserMetadataTo() {
Multimap<String, String> allHeaders = ImmutableMultimap.of("prefix" + "key", "value");
HttpResponse from = new HttpResponse();
from.setHeaders(allHeaders);
from.getHeaders().putAll(allHeaders);
MutableBlobMetadata metadata = blobMetadataProvider.get();
parser.addUserMetadataTo(from, metadata);
assertEquals(metadata.getUserMetadata().get("key"), "value");

View File

@ -82,7 +82,7 @@ public class BaseBlobStoreIntegrationTest<S> {
protected static volatile AtomicInteger containerIndex = new AtomicInteger(0);
protected volatile BlobStoreContext<S> context;
protected static volatile int containerCount = 20;
protected static volatile int containerCount = 10;
public static final String CONTAINER_PREFIX = System.getProperty("user.name") + "-blobstore";
/**
* two test groups integration and live.

View File

@ -0,0 +1,64 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.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.concurrent;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import com.google.common.base.Supplier;
/**
* Works in google app engine since it doesn't use threads.
*
* @author Adrian Cole
*/
public class ExpirableSupplier<V> implements Supplier<V> {
private final Supplier<V> supplier;
private final AtomicReference<V> currentValue;
private final AtomicLong trigger;
private final long expirationNanos;
public ExpirableSupplier(Supplier<V> supplier, long duration, TimeUnit unit) {
this.supplier = supplier;
this.expirationNanos = unit.toNanos(duration);
this.currentValue = new AtomicReference<V>(null);
trigger = new AtomicLong(System.nanoTime() + expirationNanos);
}
void updateIfExpired() {
V current = currentValue.get();
if (current == null || trigger.get() - System.nanoTime() <= 0) {
trigger.set(System.nanoTime() + expirationNanos);
// we always want the last one to win. think login session
currentValue.set(supplier.get());
}
}
public V get() {
updateIfExpired();
return currentValue.get();
}
}

View File

@ -47,13 +47,14 @@ public class HttpMessage {
return headers;
}
public void setHeaders(Multimap<String, String> headers) {
this.headers = Multimaps.synchronizedMultimap(headers);
}
/**
* try to get the value, then try as lowercase.
*/
public String getFirstHeaderOrNull(String string) {
Collection<String> values = headers.get(string);
return (values != null && values.size() >= 1) ? values.iterator().next() : null;
if (values.size() == 0)
values = headers.get(string.toLowerCase());
return (values.size() >= 1) ? values.iterator().next() : null;
}
}

View File

@ -71,7 +71,7 @@ public class HttpRequest extends HttpMessage implements Request<URI> {
*/
public HttpRequest(String method, URI endPoint, Multimap<String, String> headers) {
this(method, endPoint);
setHeaders(checkNotNull(headers, "headers"));
getHeaders().putAll(checkNotNull(headers, "headers"));
}
/**
@ -84,7 +84,7 @@ public class HttpRequest extends HttpMessage implements Request<URI> {
protected HttpRequest(String method, URI endPoint, Multimap<String, String> headers,
@Nullable Object entity) {
this(method, endPoint);
setHeaders(checkNotNull(headers, "headers"));
getHeaders().putAll(checkNotNull(headers, "headers"));
setEntity(entity);
}

View File

@ -23,6 +23,8 @@
*/
package org.jclouds.rest.binders;
import java.util.Collections;
import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;
@ -40,7 +42,7 @@ public class BindToStringEntity implements Binder {
String stringEntity = entity.toString();
if (request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE) == null)
request.getHeaders().put(HttpHeaders.CONTENT_TYPE, "application/unknown");
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, stringEntity.getBytes().length + "");
request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,Collections.singletonList(stringEntity.getBytes().length + ""));
request.setEntity(stringEntity);
}
}

View File

@ -354,7 +354,6 @@ public class RestAnnotationProcessor<T> {
GeneratedHttpRequest<T> request = new GeneratedHttpRequest<T>(httpMethod, endPoint, this,
declaring, method, args);
request.setHeaders(headers);
addHostHeaderIfAnnotatedWithVirtualHost(headers, request.getEndpoint().getHost(), method);
addFiltersIfAnnotated(method, request);
if (stringEntity != null) {
@ -362,6 +361,7 @@ public class RestAnnotationProcessor<T> {
if (headers.get(HttpHeaders.CONTENT_TYPE) != null)
headers.put(HttpHeaders.CONTENT_TYPE, "application/unknown");
}
request.getHeaders().putAll(headers);
decorateRequest(request);
return request;
}

View File

@ -149,7 +149,7 @@ public abstract class BaseJettyTest {
} else {
handleAction(request, response);
}
} else if (request.getHeader("Range") != null) {
} else if (request.getHeader("range") != null) {
response.sendError(404, "no content");
} else if (request.getHeader("test") != null) {
response.setContentType("text/plain");

View File

@ -23,6 +23,8 @@
*/
package org.jclouds.mezeo.pcs2.functions;
import javax.inject.Singleton;
import org.jclouds.blobstore.ContainerNotFoundException;
import com.google.common.base.Function;
@ -31,6 +33,7 @@ import com.google.common.base.Function;
*
* @author Adrian Cole
*/
@Singleton
public class ReturnFalseIfContainerNotFound implements Function<Exception, Boolean> {
public Boolean apply(Exception from) {

View File

@ -23,6 +23,8 @@
*/
package org.jclouds.mezeo.pcs2.functions;
import javax.inject.Singleton;
import org.jclouds.http.HttpResponseException;
import com.google.common.base.Function;
@ -31,6 +33,7 @@ import com.google.common.base.Function;
*
* @author Adrian Cole
*/
@Singleton
public class ReturnTrueIfContainerAlreadyExists implements Function<Exception, Boolean> {
public Boolean apply(Exception from) {

View File

@ -23,8 +23,9 @@
*/
package org.jclouds.rackspace.cloudfiles;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.rackspace.cloudfiles.reference.CloudFilesConstants.PROPERTY_CLOUDFILES_METADATA_PREFIX;
import static org.jclouds.rackspace.cloudfiles.reference.CloudFilesConstants.PROPERTY_CLOUDFILES_RETRY;
import static org.jclouds.rackspace.cloudfiles.reference.CloudFilesConstants.PROPERTY_CLOUDFILES_TIMEOUT;
import java.util.Properties;
@ -40,7 +41,6 @@ public class CloudFilesPropertiesBuilder extends RackspacePropertiesBuilder {
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_CLOUDFILES_METADATA_PREFIX, "X-Object-Meta-");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "X-Object-Meta-");
return properties;
}
@ -52,4 +52,24 @@ public class CloudFilesPropertiesBuilder extends RackspacePropertiesBuilder {
super(id, secret);
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public CloudFilesPropertiesBuilder withRequestTimeout(long milliseconds) {
properties.setProperty(PROPERTY_CLOUDFILES_TIMEOUT, Long.toString(milliseconds));
return this;
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public CloudFilesPropertiesBuilder withMaxRetries(int retries) {
properties.setProperty(PROPERTY_CLOUDFILES_RETRY, Integer.toString(retries));
return this;
}
protected CloudFilesPropertiesBuilder withMetaPrefix(String prefix) {
properties.setProperty(PROPERTY_CLOUDFILES_METADATA_PREFIX, prefix);
return this;
}
}

View File

@ -26,6 +26,7 @@ package org.jclouds.rackspace.cloudfiles.binders;
import static com.google.common.base.Preconditions.checkArgument;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
@ -33,16 +34,15 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils;
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ObjectToBlob;
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
import org.jclouds.rest.Binder;
import org.jclouds.rackspace.cloudfiles.reference.CloudFilesConstants;
public class BindCFObjectToEntity implements Binder {
private final BindBlobToEntityAndUserMetadataToHeadersWithPrefix blobBinder;
public class BindCFObjectToEntity extends BindBlobToEntityAndUserMetadataToHeadersWithPrefix {
private final ObjectToBlob object2Blob;
@Inject
public BindCFObjectToEntity(ObjectToBlob object2Blob,
BindBlobToEntityAndUserMetadataToHeadersWithPrefix blobBinder) {
this.blobBinder = blobBinder;
@Named(CloudFilesConstants.PROPERTY_CLOUDFILES_METADATA_PREFIX) String prefix) {
super(prefix);
this.object2Blob = object2Blob;
}
@ -57,7 +57,7 @@ public class BindCFObjectToEntity implements Binder {
request.getHeaders().put("Transfer-Encoding", "chunked");
}
blobBinder.bindToRequest(request, object2Blob.apply(object));
super.bindToRequest(request, object2Blob.apply(object));
if (object.getInfo().getHash() != null) {
request.getHeaders().put(HttpHeaders.ETAG,
HttpUtils.toHexString(object.getInfo().getHash()));

View File

@ -23,8 +23,15 @@
*/
package org.jclouds.rackspace.cloudfiles.blobstore;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_BLOBSTORE_RETRY;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.rackspace.cloudfiles.reference.CloudFilesConstants.PROPERTY_CLOUDFILES_METADATA_PREFIX;
import static org.jclouds.rackspace.cloudfiles.reference.CloudFilesConstants.PROPERTY_CLOUDFILES_RETRY;
import static org.jclouds.rackspace.cloudfiles.reference.CloudFilesConstants.PROPERTY_CLOUDFILES_TIMEOUT;
import java.util.List;
import java.util.Properties;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import org.jclouds.blobstore.BlobStoreContextBuilder;
@ -35,13 +42,14 @@ import org.jclouds.rackspace.cloudfiles.blobstore.config.CloudFilesBlobStoreCont
import org.jclouds.rackspace.cloudfiles.config.CloudFilesRestClientModule;
import org.jclouds.rackspace.config.RackspaceAuthenticationRestModule;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Creates {@link CloudFilesBlobStoreContext} or {@link Injector} instances based on the most commonly
* requested arguments.
* Creates {@link CloudFilesBlobStoreContext} or {@link Injector} instances based on the most
* commonly requested arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
@ -56,7 +64,17 @@ public class CloudFilesBlobStoreContextBuilder extends BlobStoreContextBuilder<C
public CloudFilesBlobStoreContextBuilder(Properties props) {
super(new TypeLiteral<CloudFilesClient>() {
}, props);
}, convert(props));
}
private static Properties convert(Properties props) {
for (Entry<String, String> entry : ImmutableMap.of(PROPERTY_CLOUDFILES_METADATA_PREFIX,
PROPERTY_USER_METADATA_PREFIX, PROPERTY_CLOUDFILES_RETRY, PROPERTY_BLOBSTORE_RETRY,
PROPERTY_CLOUDFILES_TIMEOUT, PROPERTY_USER_METADATA_PREFIX).entrySet()) {
if (props.containsKey(entry.getKey()))
props.setProperty(entry.getValue(), props.getProperty(entry.getKey()));
}
return props;
}
@Override

View File

@ -30,6 +30,7 @@ import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
import org.jclouds.rackspace.cloudfiles.CloudFilesPropertiesBuilder;
import com.google.inject.Module;
@ -49,20 +50,19 @@ import com.google.inject.Module;
public class CloudFilesBlobStoreContextFactory {
public static BlobStoreContext<CloudFilesClient> createContext(Properties properties,
Module... modules) {
return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder(
properties).build()).withModules(modules).buildContext();
return new CloudFilesBlobStoreContextBuilder(new CloudFilesPropertiesBuilder(properties)
.build()).withModules(modules).buildContext();
}
public static BlobStoreContext<CloudFilesClient> createContext(String user,
public static BlobStoreContext<CloudFilesClient> createContext(String user, String key,
Module... modules) {
return new CloudFilesBlobStoreContextBuilder(new CloudFilesPropertiesBuilder(user, key)
.build()).withModules(modules).buildContext();
}
public static BlobStoreContext<CloudFilesClient> createContext(URI endpoint, String user,
String key, Module... modules) {
return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder(
user, key).build()).withModules(modules).buildContext();
}
public static BlobStoreContext<CloudFilesClient> createContext(URI endpoint,
String user, String key, Module... modules) {
return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder(
user, key).withEndpoint(endpoint).build()).withModules(
modules).buildContext();
return new CloudFilesBlobStoreContextBuilder(new CloudFilesPropertiesBuilder(user, key)
.withEndpoint(endpoint).build()).withModules(modules).buildContext();
}
}

View File

@ -1,55 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.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.rackspace.cloudfiles.blobstore;
import java.util.Properties;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.rackspace.cloudfiles.CloudFilesPropertiesBuilder;
/**
* Builds properties used in CloudFiles Blob Stores
*
* @author Adrian Cole, Andrew Newdigate
*/
public class CloudFilesBlobStorePropertiesBuilder extends CloudFilesPropertiesBuilder {
public CloudFilesBlobStorePropertiesBuilder(String id, String secret) {
super(id, secret);
}
public CloudFilesBlobStorePropertiesBuilder(Properties properties) {
super(properties);
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public CloudFilesBlobStorePropertiesBuilder withRequestTimeout(long milliseconds) {
properties.setProperty(BlobStoreConstants.PROPERTY_BLOBSTORE_TIMEOUT, Long
.toString(milliseconds));
return this;
}
}

View File

@ -50,6 +50,17 @@ public interface CloudFilesConstants extends RackspaceConstants {
*/
String PATH = "path";
String PROPERTY_CLOUDFILES_METADATA_PREFIX = "jclouds.cloudfiles.metaprefix";
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public static final String PROPERTY_CLOUDFILES_TIMEOUT = "jclouds.cloudfiles.timeout";
/**
* time to pause before retrying a transient failure
*/
public static final String PROPERTY_CLOUDFILES_RETRY = "jclouds.cloudfiles.retry";
/**
* Any header starting with this prefix is considered user metadata. It will be stored with the
* object and returned when you retrieve the object/
*/
public static final String PROPERTY_CLOUDFILES_METADATA_PREFIX = "jclouds.cloudfiles.metaprefix";
}

View File

@ -36,6 +36,7 @@ import org.jclouds.blobstore.domain.internal.BlobImpl;
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
import org.jclouds.rackspace.StubRackspaceAuthenticationModule;
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
import org.jclouds.rackspace.cloudfiles.CloudFilesPropertiesBuilder;
import org.jclouds.rackspace.cloudfiles.blobstore.config.CloudFilesBlobStoreContextModule;
import org.jclouds.rackspace.cloudfiles.config.CloudFilesRestClientModule;
import org.jclouds.rackspace.cloudfiles.config.CloudFilesStubClientModule;
@ -69,7 +70,7 @@ public class CloudFilesBlobStoreContextBuilderTest {
}
private CloudFilesBlobStoreContextBuilder newBuilder() {
return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder("id",
return new CloudFilesBlobStoreContextBuilder(new CloudFilesPropertiesBuilder("id",
"secret").build()).withModules(new CloudFilesStubClientModule(),
new StubRackspaceAuthenticationModule());
}

View File

@ -28,9 +28,9 @@ import org.jclouds.blobstore.integration.internal.BaseTestInitializer;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rackspace.StubRackspaceAuthenticationModule;
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
import org.jclouds.rackspace.cloudfiles.CloudFilesPropertiesBuilder;
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextBuilder;
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextFactory;
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStorePropertiesBuilder;
import org.jclouds.rackspace.cloudfiles.config.CloudFilesStubClientModule;
import com.google.inject.Module;
@ -44,8 +44,8 @@ public class CloudFilesTestInitializer extends BaseTestInitializer<CloudFilesCli
@Override
protected BlobStoreContext<CloudFilesClient> createLiveContext(Module configurationModule,
String url, String app, String account, String key) {
return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder(
account, key).relaxSSLHostname().build()).withModules(configurationModule,
return new CloudFilesBlobStoreContextBuilder(new CloudFilesPropertiesBuilder(account, key)
.relaxSSLHostname().build()).withModules(configurationModule,
new Log4JLoggingModule()).buildContext();
}

View File

@ -51,32 +51,27 @@ public class ParseAuthenticationResponseFromHeaders implements
* parses the http response headers to create a new {@link AuthenticationResponse} object.
*/
public AuthenticationResponse apply(final HttpResponse from) {
return new AuthenticationResponse() {
public String getAuthToken() {
return checkNotNull(from.getFirstHeaderOrNull(AUTH_TOKEN),
AUTH_TOKEN);
return checkNotNull(from.getFirstHeaderOrNull(AUTH_TOKEN), AUTH_TOKEN);
}
public URI getCDNManagementUrl() {
String cdnManagementUrl = checkNotNull(from
.getFirstHeaderOrNull(CDN_MANAGEMENT_URL),
String cdnManagementUrl = checkNotNull(from.getFirstHeaderOrNull(CDN_MANAGEMENT_URL),
CDN_MANAGEMENT_URL);
return URI.create(cdnManagementUrl);
}
public URI getServerManagementUrl() {
String serverManagementUrl = checkNotNull(from
.getFirstHeaderOrNull(SERVER_MANAGEMENT_URL),
SERVER_MANAGEMENT_URL);
.getFirstHeaderOrNull(SERVER_MANAGEMENT_URL), SERVER_MANAGEMENT_URL);
return URI.create(serverManagementUrl);
}
public URI getStorageUrl() {
String storageUrl = checkNotNull(from
.getFirstHeaderOrNull(STORAGE_URL),
STORAGE_URL);
String storageUrl = checkNotNull(from.getFirstHeaderOrNull(STORAGE_URL), STORAGE_URL
+ " not found in headers:" + from.getStatusLine() + " - " + from.getHeaders());
return URI.create(storageUrl);
}

View File

@ -30,29 +30,27 @@ import static org.jclouds.vcloudx.reference.VCloudXConstants.PROPERTY_VCLOUDX_US
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.http.RequiresHttp;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.rest.RestClientFactory;
import org.jclouds.vcloudx.VCloudXLogin;
import org.jclouds.vcloudx.VCloudToken;
import org.jclouds.vcloudx.VCloudXLogin;
import org.jclouds.vcloudx.VCloudXLogin.VCloudXSession;
import org.jclouds.vcloudx.endpoints.Org;
import org.jclouds.vcloudx.endpoints.VCloudX;
import com.google.common.base.Function;
import com.google.common.collect.MapMaker;
import com.google.common.base.Supplier;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
* Configures the VCloudX authentication service connection, including logging and http
* transport.
* Configures the VCloudX authentication service connection, including logging and http transport.
*
* @author Adrian Cole
*/
@ -65,28 +63,28 @@ public class RestVCloudXAuthenticationModule extends AbstractModule {
@VCloudToken
@Provides
String provideVCloudToken(ConcurrentMap<String, VCloudXSession> cache) {
return cache.get("doesn't matter").getVCloudToken();
String provideVCloudToken(Supplier<VCloudXSession> cache) {
return cache.get().getVCloudToken();
}
@Provides
@Org
protected URI provideOrg(ConcurrentMap<String, VCloudXSession> cache) {
return cache.get("doesn't matter").getOrg();
protected URI provideOrg(Supplier<VCloudXSession> cache) {
return cache.get().getOrg();
}
/**
* borrowing concurrency code to ensure that caching takes place properly
*/
@Provides
ConcurrentMap<String, VCloudXSession> provideVCloudTokenCache(
@Singleton
Supplier<VCloudXSession> provideVCloudTokenCache(
@Named(PROPERTY_VCLOUDX_SESSIONINTERVAL) long seconds, final VCloudXLogin login) {
return new MapMaker().expiration(seconds, TimeUnit.SECONDS).makeComputingMap(
new Function<String, VCloudXSession>() {
public VCloudXSession apply(String key) {
return new ExpirableSupplier<VCloudXSession>(new Supplier<VCloudXSession>() {
public VCloudXSession get() {
return login.login();
}
});
}, seconds, TimeUnit.SECONDS);
}
@Provides

View File

@ -30,7 +30,6 @@ import static org.jclouds.vcloudx.reference.VCloudXConstants.PROPERTY_VCLOUDX_US
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.jclouds.http.HttpRetryHandler;
@ -44,6 +43,7 @@ import org.jclouds.vcloudx.VCloudXLogin;
import org.jclouds.vcloudx.VCloudXLogin.VCloudXSession;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -91,12 +91,12 @@ public class RestVCloudXAuthenticationModuleTest {
}
};
ConcurrentMap<String, VCloudXSession> map = module.provideVCloudTokenCache(1, login);
Supplier<VCloudXSession> map = module.provideVCloudTokenCache(1, login);
for (int i = 0; i < 10; i++)
map.get("foo");
assert "1".equals(map.get("foo").getVCloudToken());
map.get();
assert "1".equals(map.get().getVCloudToken());
Thread.sleep(1001);
assert "2".equals(map.get("foo").getVCloudToken());
assert "2".equals(map.get().getVCloudToken());
}
@Test