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 static org.jclouds.atmosonline.saas.reference.AtmosStorageConstants.PROPERTY_EMCSAAS_SESSIONINTERVAL;
import java.net.URI; import java.net.URI;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.inject.Named; 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.AtmosStorageClient;
import org.jclouds.atmosonline.saas.handlers.AtmosStorageClientErrorRetryHandler; import org.jclouds.atmosonline.saas.handlers.AtmosStorageClientErrorRetryHandler;
import org.jclouds.atmosonline.saas.handlers.ParseAtmosStorageErrorFromXmlContent; import org.jclouds.atmosonline.saas.handlers.ParseAtmosStorageErrorFromXmlContent;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
@ -48,8 +48,7 @@ import org.jclouds.rest.RestClientFactory;
import org.jclouds.util.DateService; import org.jclouds.util.DateService;
import org.jclouds.util.TimeStamp; import org.jclouds.util.TimeStamp;
import com.google.common.base.Function; import com.google.common.base.Supplier;
import com.google.common.collect.MapMaker;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -82,8 +81,8 @@ public class AtmosStorageRestClientModule extends AbstractModule {
@Provides @Provides
@TimeStamp @TimeStamp
protected String provideTimeStamp(@TimeStamp ConcurrentMap<String, String> cache) { protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return cache.get("doesn't matter"); return cache.get();
} }
/** /**
@ -91,14 +90,13 @@ public class AtmosStorageRestClientModule extends AbstractModule {
*/ */
@Provides @Provides
@TimeStamp @TimeStamp
ConcurrentMap<String, String> provideTimeStampCache( Supplier<String> provideTimeStampCache(@Named(PROPERTY_EMCSAAS_SESSIONINTERVAL) long seconds,
@Named(PROPERTY_EMCSAAS_SESSIONINTERVAL) long seconds, final DateService dateService) { final DateService dateService) {
return new MapMaker().expiration(seconds, TimeUnit.SECONDS).makeComputingMap( return new ExpirableSupplier<String>(new Supplier<String>() {
new Function<String, String>() { public String get() {
public String apply(String key) {
return dateService.rfc822DateFormat(); return dateService.rfc822DateFormat();
} }
}); }, seconds, TimeUnit.SECONDS);
} }
protected void bindErrorHandlers() { 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.assertEquals;
import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertFalse;
import java.util.concurrent.ConcurrentMap;
import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Base64;
import org.jclouds.atmosonline.saas.handlers.AtmosStorageClientErrorRetryHandler; import org.jclouds.atmosonline.saas.handlers.AtmosStorageClientErrorRetryHandler;
import org.jclouds.atmosonline.saas.handlers.ParseAtmosStorageErrorFromXmlContent; import org.jclouds.atmosonline.saas.handlers.ParseAtmosStorageErrorFromXmlContent;
@ -42,6 +40,7 @@ import org.jclouds.util.DateService;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
@ -74,13 +73,13 @@ public class AtmosStorageRestClientModuleTest {
void testUpdatesOnlyOncePerSecond() throws NoSuchMethodException, InterruptedException { void testUpdatesOnlyOncePerSecond() throws NoSuchMethodException, InterruptedException {
AtmosStorageRestClientModule module = new AtmosStorageRestClientModule(); AtmosStorageRestClientModule module = new AtmosStorageRestClientModule();
ConcurrentMap<String, String> map = module.provideTimeStampCache(1, new DateService()); Supplier<String> map = module.provideTimeStampCache(1, new DateService());
String timeStamp = map.get("foo"); String timeStamp = map.get();
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
map.get("foo"); map.get();
assertEquals(timeStamp, map.get("foo")); assertEquals(timeStamp, map.get());
Thread.sleep(1001); Thread.sleep(1001);
assertFalse(timeStamp.equals(map.get("foo"))); assertFalse(timeStamp.equals(map.get()));
} }
@Test @Test

View File

@ -26,8 +26,11 @@ package org.jclouds.aws.s3;
import static com.google.common.base.Preconditions.checkNotNull; 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_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY; 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_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_SESSIONINTERVAL;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_TIMEOUT;
import java.net.URI; import java.net.URI;
import java.util.Properties; import java.util.Properties;
@ -44,7 +47,7 @@ public class S3PropertiesBuilder extends HttpPropertiesBuilder {
@Override @Override
protected Properties defaultProperties() { protected Properties defaultProperties() {
Properties properties = super.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_METADATA_PREFIX, "x-amz-meta-");
properties.setProperty(PROPERTY_S3_SESSIONINTERVAL, "60"); properties.setProperty(PROPERTY_S3_SESSIONINTERVAL, "60");
return properties; return properties;
@ -77,4 +80,24 @@ public class S3PropertiesBuilder extends HttpPropertiesBuilder {
return this; 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; 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.List;
import java.util.Properties; import java.util.Properties;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import org.jclouds.aws.s3.S3Client; import org.jclouds.aws.s3.S3Client;
@ -34,6 +37,7 @@ import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule; import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -55,7 +59,17 @@ public class S3BlobStoreContextBuilder extends BlobStoreContextBuilder<S3Client>
public S3BlobStoreContextBuilder(Properties props) { public S3BlobStoreContextBuilder(Properties props) {
super(new TypeLiteral<S3Client>() { 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 @Override

View File

@ -27,6 +27,7 @@ import java.net.URI;
import java.util.Properties; import java.util.Properties;
import org.jclouds.aws.s3.S3Client; import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.S3PropertiesBuilder;
import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule; import org.jclouds.logging.jdk.config.JDKLoggingModule;
@ -47,19 +48,19 @@ import com.google.inject.Module;
*/ */
public class S3BlobStoreContextFactory { public class S3BlobStoreContextFactory {
public static BlobStoreContext<S3Client> createContext(Properties properties, Module... modules) { 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(); .withModules(modules).buildContext();
} }
public static BlobStoreContext<S3Client> createContext(String awsAccessKeyId, public static BlobStoreContext<S3Client> createContext(String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) { String awsSecretAccessKey, Module... modules) {
return new S3BlobStoreContextBuilder(new S3BlobStorePropertiesBuilder(awsAccessKeyId, return new S3BlobStoreContextBuilder(new S3PropertiesBuilder(awsAccessKeyId,
awsSecretAccessKey).build()).withModules(modules).buildContext(); awsSecretAccessKey).build()).withModules(modules).buildContext();
} }
public static BlobStoreContext<S3Client> createContext(URI endpoint, String awsAccessKeyId, public static BlobStoreContext<S3Client> createContext(URI endpoint, String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) { String awsSecretAccessKey, Module... modules) {
return new S3BlobStoreContextBuilder(new S3BlobStorePropertiesBuilder(awsAccessKeyId, return new S3BlobStoreContextBuilder(new S3PropertiesBuilder(awsAccessKeyId,
awsSecretAccessKey).withEndpoint(endpoint).build()).withModules(modules) awsSecretAccessKey).withEndpoint(endpoint).build()).withModules(modules)
.buildContext(); .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; package org.jclouds.aws.s3.config;
import java.net.URI; import java.net.URI;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.inject.Named; 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.AWSRedirectionRetryHandler;
import org.jclouds.aws.s3.handlers.ParseAWSErrorFromXmlContent; import org.jclouds.aws.s3.handlers.ParseAWSErrorFromXmlContent;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
@ -48,8 +48,7 @@ import org.jclouds.rest.RestClientFactory;
import org.jclouds.util.DateService; import org.jclouds.util.DateService;
import org.jclouds.util.TimeStamp; import org.jclouds.util.TimeStamp;
import com.google.common.base.Function; import com.google.common.base.Supplier;
import com.google.common.collect.MapMaker;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.Scopes; import com.google.inject.Scopes;
@ -65,8 +64,8 @@ public class S3RestClientModule extends AbstractModule {
@Provides @Provides
@TimeStamp @TimeStamp
protected String provideTimeStamp(@TimeStamp ConcurrentMap<String, String> cache) { protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return cache.get("doesn't matter"); return cache.get();
} }
/** /**
@ -74,15 +73,14 @@ public class S3RestClientModule extends AbstractModule {
*/ */
@Provides @Provides
@TimeStamp @TimeStamp
ConcurrentMap<String, String> provideTimeStampCache( Supplier<String> provideTimeStampCache(
@Named(S3Constants.PROPERTY_S3_SESSIONINTERVAL) long seconds, @Named(S3Constants.PROPERTY_S3_SESSIONINTERVAL) long seconds,
final DateService dateService) { final DateService dateService) {
return new MapMaker().expiration(seconds, TimeUnit.SECONDS).makeComputingMap( return new ExpirableSupplier<String>(new Supplier<String>() {
new Function<String, String>() { public String get() {
public String apply(String key) {
return dateService.rfc822DateFormat(); return dateService.rfc822DateFormat();
} }
}); }, seconds, TimeUnit.SECONDS);
} }
@Override @Override

View File

@ -23,6 +23,8 @@
*/ */
package org.jclouds.aws.s3.functions; package org.jclouds.aws.s3.functions;
import javax.inject.Singleton;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -31,6 +33,7 @@ import com.google.common.base.Function;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton
public class ObjectKey implements Function<Object, String> { public class ObjectKey implements Function<Object, String> {
public String apply(Object from) { 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. * how long do we wait before obtaining a new timestamp for requests.
*/ */
public static final String PROPERTY_S3_SESSIONINTERVAL = "jclouds.s3.sessioninterval"; 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"; 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 java.util.List;
import org.jclouds.aws.s3.S3Client; 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.blobstore.config.S3BlobStoreContextModule;
import org.jclouds.aws.s3.config.S3RestClientModule; import org.jclouds.aws.s3.config.S3RestClientModule;
import org.jclouds.aws.s3.config.S3StubClientModule; import org.jclouds.aws.s3.config.S3StubClientModule;
@ -59,8 +60,8 @@ import com.google.inject.TypeLiteral;
public class S3BlobStoreContextBuilderTest { public class S3BlobStoreContextBuilderTest {
public void testNewBuilder() { public void testNewBuilder() {
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder( S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(new S3PropertiesBuilder(
new S3BlobStorePropertiesBuilder("id", "secret").build()); "id", "secret").build());
assertEquals(builder.getProperties().getProperty(PROPERTY_USER_METADATA_PREFIX), assertEquals(builder.getProperties().getProperty(PROPERTY_USER_METADATA_PREFIX),
"x-amz-meta-"); "x-amz-meta-");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_ACCESSKEYID), "id"); assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_ACCESSKEYID), "id");
@ -68,9 +69,8 @@ public class S3BlobStoreContextBuilderTest {
} }
public void testBuildContext() { public void testBuildContext() {
BlobStoreContext<S3Client> context = new S3BlobStoreContextBuilder( BlobStoreContext<S3Client> context = new S3BlobStoreContextBuilder(new S3PropertiesBuilder(
new S3BlobStorePropertiesBuilder("id", "secret").build()).withModules( "id", "secret").build()).withModules(new S3StubClientModule()).buildContext();
new S3StubClientModule()).buildContext();
assertEquals(context.getClass(), BlobStoreContextImpl.class); assertEquals(context.getClass(), BlobStoreContextImpl.class);
assertEquals(context.getApi().getClass(), StubS3Client.class); assertEquals(context.getApi().getClass(), StubS3Client.class);
assertEquals(context.getBlobStore().getClass(), S3BlobStore.class); assertEquals(context.getBlobStore().getClass(), S3BlobStore.class);
@ -81,8 +81,8 @@ public class S3BlobStoreContextBuilderTest {
} }
public void testBuildInjector() { public void testBuildInjector() {
Injector i = new S3BlobStoreContextBuilder(new S3BlobStorePropertiesBuilder("id", "secret") Injector i = new S3BlobStoreContextBuilder(new S3PropertiesBuilder("id", "secret").build())
.build()).withModules(new S3StubClientModule()).buildInjector(); .withModules(new S3StubClientModule()).buildInjector();
assert i.getInstance(Key.get(new TypeLiteral<BlobStoreContext<S3Client>>() { assert i.getInstance(Key.get(new TypeLiteral<BlobStoreContext<S3Client>>() {
})) != null; })) != null;
assert i.getInstance(S3Object.class) != null; assert i.getInstance(S3Object.class) != null;
@ -91,8 +91,8 @@ public class S3BlobStoreContextBuilderTest {
protected void testAddContextModule() { protected void testAddContextModule() {
List<Module> modules = new ArrayList<Module>(); List<Module> modules = new ArrayList<Module>();
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder( S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(new S3PropertiesBuilder(
new S3BlobStorePropertiesBuilder("id", "secret").build()); "id", "secret").build());
builder.addContextModule(modules); builder.addContextModule(modules);
assertEquals(modules.size(), 1); assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), S3BlobStoreContextModule.class); assertEquals(modules.get(0).getClass(), S3BlobStoreContextModule.class);
@ -100,8 +100,8 @@ public class S3BlobStoreContextBuilderTest {
protected void addClientModule() { protected void addClientModule() {
List<Module> modules = new ArrayList<Module>(); List<Module> modules = new ArrayList<Module>();
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder( S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(new S3PropertiesBuilder(
new S3BlobStorePropertiesBuilder("id", "secret").build()); "id", "secret").build());
builder.addClientModule(modules); builder.addClientModule(modules);
assertEquals(modules.size(), 1); assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), S3RestClientModule.class); assertEquals(modules.get(0).getClass(), S3RestClientModule.class);

View File

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

View File

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

View File

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

View File

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

View File

@ -23,8 +23,15 @@
*/ */
package org.jclouds.azure.storage.blob.blobstore; 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.List;
import java.util.Properties; import java.util.Properties;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import org.jclouds.azure.storage.blob.AzureBlobClient; 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.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule; import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -55,7 +63,17 @@ public class AzureBlobStoreContextBuilder extends BlobStoreContextBuilder<AzureB
public AzureBlobStoreContextBuilder(Properties props) { public AzureBlobStoreContextBuilder(Properties props) {
super(new TypeLiteral<AzureBlobClient>() { 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 @Override

View File

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

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 interface AzureBlobConstants extends AzureStorageConstants {
public static final String PROPERTY_AZUREBLOB_ENDPOINT = "jclouds.azureblob.endpoint"; 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"; public static final String PROPERTY_AZUREBLOB_METADATA_PREFIX = "jclouds.azureblob.metaprefix";
} }

View File

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

View File

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

View File

@ -24,9 +24,9 @@
package org.jclouds.azure.storage.blob.blobstore.integration; package org.jclouds.azure.storage.blob.blobstore.integration;
import org.jclouds.azure.storage.blob.AzureBlobClient; 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.AzureBlobStoreContextBuilder;
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStoreContextFactory; 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.azure.storage.blob.config.AzureBlobStubClientModule;
import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.integration.internal.BaseTestInitializer; import org.jclouds.blobstore.integration.internal.BaseTestInitializer;
@ -43,7 +43,7 @@ public class AzureBlobTestInitializer extends BaseTestInitializer<AzureBlobClien
@Override @Override
protected BlobStoreContext<AzureBlobClient> createLiveContext(Module configurationModule, protected BlobStoreContext<AzureBlobClient> createLiveContext(Module configurationModule,
String url, String app, String account, String key) { String url, String app, String account, String key) {
return new AzureBlobStoreContextBuilder(new AzureBlobStorePropertiesBuilder( return new AzureBlobStoreContextBuilder(new AzureBlobPropertiesBuilder(
account, key).relaxSSLHostname().build()).withModules(configurationModule, account, key).relaxSSLHostname().build()).withModules(configurationModule,
new Log4JLoggingModule()).buildContext(); 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 static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.inject.Named; import javax.inject.Named;
import org.jclouds.azure.storage.handlers.ParseAzureStorageErrorFromXmlContent; import org.jclouds.azure.storage.handlers.ParseAzureStorageErrorFromXmlContent;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.ClientError;
@ -40,8 +40,7 @@ import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.util.DateService; import org.jclouds.util.DateService;
import org.jclouds.util.TimeStamp; import org.jclouds.util.TimeStamp;
import com.google.common.base.Function; import com.google.common.base.Supplier;
import com.google.common.collect.MapMaker;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -56,8 +55,8 @@ public class AzureStorageRestClientModule extends AbstractModule {
@Provides @Provides
@TimeStamp @TimeStamp
protected String provideTimeStamp(@TimeStamp ConcurrentMap<String, String> cache) { protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return cache.get("doesn't matter"); return cache.get();
} }
/** /**
@ -65,15 +64,14 @@ public class AzureStorageRestClientModule extends AbstractModule {
*/ */
@Provides @Provides
@TimeStamp @TimeStamp
ConcurrentMap<String, String> provideTimeStampCache( Supplier<String> provideTimeStampCache(
@Named(PROPERTY_AZURESTORAGE_SESSIONINTERVAL) long seconds, @Named(PROPERTY_AZURESTORAGE_SESSIONINTERVAL) long seconds,
final DateService dateService) { final DateService dateService) {
return new MapMaker().expiration(seconds, TimeUnit.SECONDS).makeComputingMap( return new ExpirableSupplier<String>(new Supplier<String>() {
new Function<String, String>() { public String get() {
public String apply(String key) {
return dateService.rfc822DateFormat(); return dateService.rfc822DateFormat();
} }
}); }, seconds, TimeUnit.SECONDS);
} }
@Override @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.assertEquals;
import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertFalse;
import java.util.concurrent.ConcurrentMap;
import org.jclouds.azure.storage.handlers.ParseAzureStorageErrorFromXmlContent; import org.jclouds.azure.storage.handlers.ParseAzureStorageErrorFromXmlContent;
import org.jclouds.concurrent.WithinThreadExecutorService; import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.concurrent.config.ExecutorServiceModule;
@ -43,6 +41,7 @@ import org.jclouds.util.DateService;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
@ -70,13 +69,13 @@ public class AzureStorageRestClientModuleTest {
void testUpdatesOnlyOncePerSecond() throws NoSuchMethodException, InterruptedException { void testUpdatesOnlyOncePerSecond() throws NoSuchMethodException, InterruptedException {
AzureStorageRestClientModule module = new AzureStorageRestClientModule(); AzureStorageRestClientModule module = new AzureStorageRestClientModule();
ConcurrentMap<String, String> map = module.provideTimeStampCache(1, new DateService()); Supplier<String> map = module.provideTimeStampCache(1, new DateService());
String timeStamp = map.get("foo"); String timeStamp = map.get();
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
map.get("foo"); map.get();
assertEquals(timeStamp, map.get("foo")); assertEquals(timeStamp, map.get());
Thread.sleep(1001); Thread.sleep(1001);
assertFalse(timeStamp.equals(map.get("foo"))); assertFalse(timeStamp.equals(map.get()));
} }
@Test @Test

View File

@ -29,6 +29,11 @@ package org.jclouds.blobstore.reference;
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface BlobStoreConstants { 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. * longest time a single synchronous operation can take before throwing an exception.

View File

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

View File

@ -142,7 +142,7 @@ public class ParseBlobMetadataFromHeadersTest {
public void testAddUserMetadataTo() { public void testAddUserMetadataTo() {
Multimap<String, String> allHeaders = ImmutableMultimap.of("prefix" + "key", "value"); Multimap<String, String> allHeaders = ImmutableMultimap.of("prefix" + "key", "value");
HttpResponse from = new HttpResponse(); HttpResponse from = new HttpResponse();
from.setHeaders(allHeaders); from.getHeaders().putAll(allHeaders);
MutableBlobMetadata metadata = blobMetadataProvider.get(); MutableBlobMetadata metadata = blobMetadataProvider.get();
parser.addUserMetadataTo(from, metadata); parser.addUserMetadataTo(from, metadata);
assertEquals(metadata.getUserMetadata().get("key"), "value"); 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 static volatile AtomicInteger containerIndex = new AtomicInteger(0);
protected volatile BlobStoreContext<S> context; 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"; public static final String CONTAINER_PREFIX = System.getProperty("user.name") + "-blobstore";
/** /**
* two test groups integration and live. * 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; 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) { public String getFirstHeaderOrNull(String string) {
Collection<String> values = headers.get(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) { public HttpRequest(String method, URI endPoint, Multimap<String, String> headers) {
this(method, endPoint); 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, protected HttpRequest(String method, URI endPoint, Multimap<String, String> headers,
@Nullable Object entity) { @Nullable Object entity) {
this(method, endPoint); this(method, endPoint);
setHeaders(checkNotNull(headers, "headers")); getHeaders().putAll(checkNotNull(headers, "headers"));
setEntity(entity); setEntity(entity);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,8 +23,9 @@
*/ */
package org.jclouds.rackspace.cloudfiles; 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_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; import java.util.Properties;
@ -40,7 +41,6 @@ public class CloudFilesPropertiesBuilder extends RackspacePropertiesBuilder {
protected Properties defaultProperties() { protected Properties defaultProperties() {
Properties properties = super.defaultProperties(); Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_CLOUDFILES_METADATA_PREFIX, "X-Object-Meta-"); properties.setProperty(PROPERTY_CLOUDFILES_METADATA_PREFIX, "X-Object-Meta-");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "X-Object-Meta-");
return properties; return properties;
} }
@ -52,4 +52,24 @@ public class CloudFilesPropertiesBuilder extends RackspacePropertiesBuilder {
super(id, secret); 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 static com.google.common.base.Preconditions.checkArgument;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix; import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
@ -33,16 +34,15 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ObjectToBlob; import org.jclouds.rackspace.cloudfiles.blobstore.functions.ObjectToBlob;
import org.jclouds.rackspace.cloudfiles.domain.CFObject; import org.jclouds.rackspace.cloudfiles.domain.CFObject;
import org.jclouds.rest.Binder; import org.jclouds.rackspace.cloudfiles.reference.CloudFilesConstants;
public class BindCFObjectToEntity implements Binder { public class BindCFObjectToEntity extends BindBlobToEntityAndUserMetadataToHeadersWithPrefix {
private final BindBlobToEntityAndUserMetadataToHeadersWithPrefix blobBinder;
private final ObjectToBlob object2Blob; private final ObjectToBlob object2Blob;
@Inject @Inject
public BindCFObjectToEntity(ObjectToBlob object2Blob, public BindCFObjectToEntity(ObjectToBlob object2Blob,
BindBlobToEntityAndUserMetadataToHeadersWithPrefix blobBinder) { @Named(CloudFilesConstants.PROPERTY_CLOUDFILES_METADATA_PREFIX) String prefix) {
this.blobBinder = blobBinder; super(prefix);
this.object2Blob = object2Blob; this.object2Blob = object2Blob;
} }
@ -57,7 +57,7 @@ public class BindCFObjectToEntity implements Binder {
request.getHeaders().put("Transfer-Encoding", "chunked"); request.getHeaders().put("Transfer-Encoding", "chunked");
} }
blobBinder.bindToRequest(request, object2Blob.apply(object)); super.bindToRequest(request, object2Blob.apply(object));
if (object.getInfo().getHash() != null) { if (object.getInfo().getHash() != null) {
request.getHeaders().put(HttpHeaders.ETAG, request.getHeaders().put(HttpHeaders.ETAG,
HttpUtils.toHexString(object.getInfo().getHash())); HttpUtils.toHexString(object.getInfo().getHash()));

View File

@ -23,8 +23,15 @@
*/ */
package org.jclouds.rackspace.cloudfiles.blobstore; 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.List;
import java.util.Properties; import java.util.Properties;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import org.jclouds.blobstore.BlobStoreContextBuilder; 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.cloudfiles.config.CloudFilesRestClientModule;
import org.jclouds.rackspace.config.RackspaceAuthenticationRestModule; import org.jclouds.rackspace.config.RackspaceAuthenticationRestModule;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
/** /**
* Creates {@link CloudFilesBlobStoreContext} or {@link Injector} instances based on the most commonly * Creates {@link CloudFilesBlobStoreContext} or {@link Injector} instances based on the most
* requested arguments. * commonly requested arguments.
* <p/> * <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided. * Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/> * <p/>
@ -56,7 +64,17 @@ public class CloudFilesBlobStoreContextBuilder extends BlobStoreContextBuilder<C
public CloudFilesBlobStoreContextBuilder(Properties props) { public CloudFilesBlobStoreContextBuilder(Properties props) {
super(new TypeLiteral<CloudFilesClient>() { 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 @Override

View File

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

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 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.blobstore.internal.BlobStoreContextImpl;
import org.jclouds.rackspace.StubRackspaceAuthenticationModule; import org.jclouds.rackspace.StubRackspaceAuthenticationModule;
import org.jclouds.rackspace.cloudfiles.CloudFilesClient; 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.blobstore.config.CloudFilesBlobStoreContextModule;
import org.jclouds.rackspace.cloudfiles.config.CloudFilesRestClientModule; import org.jclouds.rackspace.cloudfiles.config.CloudFilesRestClientModule;
import org.jclouds.rackspace.cloudfiles.config.CloudFilesStubClientModule; import org.jclouds.rackspace.cloudfiles.config.CloudFilesStubClientModule;
@ -69,7 +70,7 @@ public class CloudFilesBlobStoreContextBuilderTest {
} }
private CloudFilesBlobStoreContextBuilder newBuilder() { private CloudFilesBlobStoreContextBuilder newBuilder() {
return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder("id", return new CloudFilesBlobStoreContextBuilder(new CloudFilesPropertiesBuilder("id",
"secret").build()).withModules(new CloudFilesStubClientModule(), "secret").build()).withModules(new CloudFilesStubClientModule(),
new StubRackspaceAuthenticationModule()); 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.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rackspace.StubRackspaceAuthenticationModule; import org.jclouds.rackspace.StubRackspaceAuthenticationModule;
import org.jclouds.rackspace.cloudfiles.CloudFilesClient; 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.CloudFilesBlobStoreContextBuilder;
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextFactory; import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextFactory;
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStorePropertiesBuilder;
import org.jclouds.rackspace.cloudfiles.config.CloudFilesStubClientModule; import org.jclouds.rackspace.cloudfiles.config.CloudFilesStubClientModule;
import com.google.inject.Module; import com.google.inject.Module;
@ -44,8 +44,8 @@ public class CloudFilesTestInitializer extends BaseTestInitializer<CloudFilesCli
@Override @Override
protected BlobStoreContext<CloudFilesClient> createLiveContext(Module configurationModule, protected BlobStoreContext<CloudFilesClient> createLiveContext(Module configurationModule,
String url, String app, String account, String key) { String url, String app, String account, String key) {
return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder( return new CloudFilesBlobStoreContextBuilder(new CloudFilesPropertiesBuilder(account, key)
account, key).relaxSSLHostname().build()).withModules(configurationModule, .relaxSSLHostname().build()).withModules(configurationModule,
new Log4JLoggingModule()).buildContext(); 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. * parses the http response headers to create a new {@link AuthenticationResponse} object.
*/ */
public AuthenticationResponse apply(final HttpResponse from) { public AuthenticationResponse apply(final HttpResponse from) {
return new AuthenticationResponse() { return new AuthenticationResponse() {
public String getAuthToken() { public String getAuthToken() {
return checkNotNull(from.getFirstHeaderOrNull(AUTH_TOKEN), return checkNotNull(from.getFirstHeaderOrNull(AUTH_TOKEN), AUTH_TOKEN);
AUTH_TOKEN);
} }
public URI getCDNManagementUrl() { public URI getCDNManagementUrl() {
String cdnManagementUrl = checkNotNull(from String cdnManagementUrl = checkNotNull(from.getFirstHeaderOrNull(CDN_MANAGEMENT_URL),
.getFirstHeaderOrNull(CDN_MANAGEMENT_URL),
CDN_MANAGEMENT_URL); CDN_MANAGEMENT_URL);
return URI.create(cdnManagementUrl); return URI.create(cdnManagementUrl);
} }
public URI getServerManagementUrl() { public URI getServerManagementUrl() {
String serverManagementUrl = checkNotNull(from String serverManagementUrl = checkNotNull(from
.getFirstHeaderOrNull(SERVER_MANAGEMENT_URL), .getFirstHeaderOrNull(SERVER_MANAGEMENT_URL), SERVER_MANAGEMENT_URL);
SERVER_MANAGEMENT_URL);
return URI.create(serverManagementUrl); return URI.create(serverManagementUrl);
} }
public URI getStorageUrl() { public URI getStorageUrl() {
String storageUrl = checkNotNull(from String storageUrl = checkNotNull(from.getFirstHeaderOrNull(STORAGE_URL), STORAGE_URL
.getFirstHeaderOrNull(STORAGE_URL), + " not found in headers:" + from.getStatusLine() + " - " + from.getHeaders());
STORAGE_URL);
return URI.create(storageUrl); 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.io.UnsupportedEncodingException;
import java.net.URI; import java.net.URI;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.rest.RestClientFactory; import org.jclouds.rest.RestClientFactory;
import org.jclouds.vcloudx.VCloudXLogin;
import org.jclouds.vcloudx.VCloudToken; import org.jclouds.vcloudx.VCloudToken;
import org.jclouds.vcloudx.VCloudXLogin;
import org.jclouds.vcloudx.VCloudXLogin.VCloudXSession; import org.jclouds.vcloudx.VCloudXLogin.VCloudXSession;
import org.jclouds.vcloudx.endpoints.Org; import org.jclouds.vcloudx.endpoints.Org;
import org.jclouds.vcloudx.endpoints.VCloudX; import org.jclouds.vcloudx.endpoints.VCloudX;
import com.google.common.base.Function; import com.google.common.base.Supplier;
import com.google.common.collect.MapMaker;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
/** /**
* Configures the VCloudX authentication service connection, including logging and http * Configures the VCloudX authentication service connection, including logging and http transport.
* transport.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@ -65,28 +63,28 @@ public class RestVCloudXAuthenticationModule extends AbstractModule {
@VCloudToken @VCloudToken
@Provides @Provides
String provideVCloudToken(ConcurrentMap<String, VCloudXSession> cache) { String provideVCloudToken(Supplier<VCloudXSession> cache) {
return cache.get("doesn't matter").getVCloudToken(); return cache.get().getVCloudToken();
} }
@Provides @Provides
@Org @Org
protected URI provideOrg(ConcurrentMap<String, VCloudXSession> cache) { protected URI provideOrg(Supplier<VCloudXSession> cache) {
return cache.get("doesn't matter").getOrg(); return cache.get().getOrg();
} }
/** /**
* borrowing concurrency code to ensure that caching takes place properly * borrowing concurrency code to ensure that caching takes place properly
*/ */
@Provides @Provides
ConcurrentMap<String, VCloudXSession> provideVCloudTokenCache( @Singleton
Supplier<VCloudXSession> provideVCloudTokenCache(
@Named(PROPERTY_VCLOUDX_SESSIONINTERVAL) long seconds, final VCloudXLogin login) { @Named(PROPERTY_VCLOUDX_SESSIONINTERVAL) long seconds, final VCloudXLogin login) {
return new MapMaker().expiration(seconds, TimeUnit.SECONDS).makeComputingMap( return new ExpirableSupplier<VCloudXSession>(new Supplier<VCloudXSession>() {
new Function<String, VCloudXSession>() { public VCloudXSession get() {
public VCloudXSession apply(String key) {
return login.login(); return login.login();
} }
}); }, seconds, TimeUnit.SECONDS);
} }
@Provides @Provides

View File

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