Issue 826:support api-generated location metadata across service types, note this ensures authenticationexceptions propagate even after context creation

This commit is contained in:
Adrian Cole 2012-02-02 07:22:46 -08:00
parent d4fb6bb802
commit bdd739ad04
66 changed files with 2081 additions and 1015 deletions

View File

@ -27,10 +27,12 @@ import org.jclouds.byon.Node;
import org.jclouds.byon.internal.BYONComputeServiceAdapter; import org.jclouds.byon.internal.BYONComputeServiceAdapter;
import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty; import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty;
import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule; import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.concurrent.SingleThreaded; import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.location.Provider; import org.jclouds.location.Provider;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
@ -60,14 +62,12 @@ public class BYONComputeServiceContextModule extends
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
bind(new TypeLiteral<Supplier<Location>>() {
}).to(OnlyLocationOrFirstZone.class);
bind(new TypeLiteral<Function<URI, InputStream>>() { bind(new TypeLiteral<Function<URI, InputStream>>() {
}).to(SupplyFromProviderURIOrNodesProperty.class); }).to(SupplyFromProviderURIOrNodesProperty.class);
bind(new TypeLiteral<Supplier<InputStream>>() { bind(new TypeLiteral<Supplier<InputStream>>() {
}).annotatedWith(Provider.class).to(SupplyFromProviderURIOrNodesProperty.class); }).annotatedWith(Provider.class).to(SupplyFromProviderURIOrNodesProperty.class);
bind(new TypeLiteral<Function<URI, InputStream>>() { bind(new TypeLiteral<Function<URI, InputStream>>() {
}).to(SupplyFromProviderURIOrNodesProperty.class); }).to(SupplyFromProviderURIOrNodesProperty.class);
install(new LocationsFromComputeServiceAdapterModule<NodeMetadata, Hardware, Image, Location>(){});
} }
} }

View File

@ -35,7 +35,7 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder; import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.location.suppliers.JustProvider; import org.jclouds.location.suppliers.all.JustProvider;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;

View File

@ -31,7 +31,6 @@ import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.internal.BlobStoreContextImpl; import org.jclouds.blobstore.internal.BlobStoreContextImpl;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.location.config.JustProviderLocationModule;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Scopes; import com.google.inject.Scopes;
@ -59,7 +58,6 @@ public class TransientBlobStoreContextModule extends AbstractModule {
}).toInstance(containerToLocation); }).toInstance(containerToLocation);
install(new BlobStoreObjectModule()); install(new BlobStoreObjectModule());
install(new BlobStoreMapModule()); install(new BlobStoreMapModule());
install(new JustProviderLocationModule());
bind(BlobStore.class).to(TransientBlobStore.class); bind(BlobStore.class).to(TransientBlobStore.class);
bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT); bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT);
bind(BlobRequestSigner.class).to(TransientBlobRequestSigner.class); bind(BlobRequestSigner.class).to(TransientBlobRequestSigner.class);

View File

@ -55,7 +55,6 @@ import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.domain.LoginCredentials; import org.jclouds.domain.LoginCredentials;
import org.jclouds.json.Json; import org.jclouds.json.Json;
import org.jclouds.location.Provider; import org.jclouds.location.Provider;
import org.jclouds.location.config.LocationModule;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier; import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statement;
@ -81,7 +80,6 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
configureLocationModule();
install(new ComputeServiceTimeoutsModule()); install(new ComputeServiceTimeoutsModule());
bind(new TypeLiteral<Function<NodeMetadata, SshClient>>() { bind(new TypeLiteral<Function<NodeMetadata, SshClient>>() {
}).to(CreateSshClientOncePortIsListeningOnNode.class); }).to(CreateSshClientOncePortIsListeningOnNode.class);
@ -115,10 +113,6 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
install(new FactoryModuleBuilder().build(BlockUntilInitScriptStatusIsZeroThenReturnOutput.Factory.class)); install(new FactoryModuleBuilder().build(BlockUntilInitScriptStatusIsZeroThenReturnOutput.Factory.class));
} }
protected void configureLocationModule() {
install(new LocationModule(authException));
}
@Singleton @Singleton
static class RunScriptOnNodeFactoryImpl implements RunScriptOnNode.Factory { static class RunScriptOnNodeFactoryImpl implements RunScriptOnNode.Factory {
@ -210,8 +204,6 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
return "%s-%s"; return "%s-%s";
} }
protected AtomicReference<AuthorizationException> authException = new AtomicReference<AuthorizationException>();
@Provides @Provides
@Singleton @Singleton
protected Supplier<Map<String, ? extends Image>> provideImageMap(@Memoized Supplier<Set<? extends Image>> images) { protected Supplier<Map<String, ? extends Image>> provideImageMap(@Memoized Supplier<Set<? extends Image>> images) {
@ -235,12 +227,12 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
@Memoized @Memoized
protected Supplier<Set<? extends Image>> supplyImageCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds, protected Supplier<Set<? extends Image>> supplyImageCache(AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds,
final Supplier<Set<? extends Image>> imageSupplier, Injector injector) { final Supplier<Set<? extends Image>> imageSupplier, Injector injector) {
if (shouldParseImagesOnDemand(injector)) { if (shouldParseImagesOnDemand(injector)) {
return supplyImageCache(seconds, imageSupplier); return supplyImageCache(authException, seconds, imageSupplier);
} else { } else {
return supplyNonParsingImageCache(seconds, imageSupplier, injector); return supplyNonParsingImageCache(authException, seconds, imageSupplier, injector);
} }
} }
@ -248,7 +240,7 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
return true; return true;
} }
protected Supplier<Set<? extends Image>> supplyImageCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds, protected Supplier<Set<? extends Image>> supplyImageCache(AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds,
final Supplier<Set<? extends Image>> imageSupplier) { final Supplier<Set<? extends Image>> imageSupplier) {
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Set<? extends Image>>(authException, return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Set<? extends Image>>(authException,
seconds, new Supplier<Set<? extends Image>>() { seconds, new Supplier<Set<? extends Image>>() {
@ -262,9 +254,9 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
/** /**
* For overriding; default impl is same as {@link supplyImageCache(seconds, imageSupplier)} * For overriding; default impl is same as {@link supplyImageCache(seconds, imageSupplier)}
*/ */
protected Supplier<Set<? extends Image>> supplyNonParsingImageCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds, protected Supplier<Set<? extends Image>> supplyNonParsingImageCache(AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds,
final Supplier<Set<? extends Image>> imageSupplier, Injector injector) { final Supplier<Set<? extends Image>> imageSupplier, Injector injector) {
return supplyImageCache(seconds, imageSupplier); return supplyImageCache(authException, seconds, imageSupplier);
} }
@Provides @Provides
@ -290,7 +282,7 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
@Memoized @Memoized
protected Supplier<Set<? extends Hardware>> supplySizeCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds, protected Supplier<Set<? extends Hardware>> supplySizeCache(AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds,
final Supplier<Set<? extends Hardware>> hardwareSupplier) { final Supplier<Set<? extends Hardware>> hardwareSupplier) {
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Set<? extends Hardware>>(authException, return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Set<? extends Hardware>>(authException,
seconds, new Supplier<Set<? extends Hardware>>() { seconds, new Supplier<Set<? extends Hardware>>() {

View File

@ -20,13 +20,8 @@ package org.jclouds.compute.config;
import java.util.Set; import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
@ -41,54 +36,18 @@ public abstract class BindComputeSuppliersByClass extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
bindImageSupplier(defineImageSupplier()); bindImageSupplier(defineImageSupplier());
bindLocationSupplier(defineLocationSupplier());
bindHardwareSupplier(defineHardwareSupplier()); bindHardwareSupplier(defineHardwareSupplier());
bindDefaultLocationSupplier(defineDefaultLocationSupplier());
} }
protected abstract Class<? extends Supplier<Set<? extends Image>>> defineImageSupplier(); protected abstract Class<? extends Supplier<Set<? extends Image>>> defineImageSupplier();
protected abstract Class<? extends Supplier<Set<? extends Hardware>>> defineHardwareSupplier(); protected abstract Class<? extends Supplier<Set<? extends Hardware>>> defineHardwareSupplier();
protected Class<? extends Supplier<Set<? extends Location>>> defineLocationSupplier() {
return SupplierOfLocationSet.class;
}
@Singleton
static class SupplierOfLocationSet implements Supplier<Set<? extends Location>> {
private final Set<? extends Location> locations;
@Inject
SupplierOfLocationSet(Set<? extends Location> locations) {
this.locations = locations;
}
@Override
public Set<? extends Location> get() {
return locations;
}
}
protected Class<? extends Supplier<Location>> defineDefaultLocationSupplier() {
return OnlyLocationOrFirstZone.class;
}
protected void bindImageSupplier(Class<? extends Supplier<Set<? extends Image>>> clazz) { protected void bindImageSupplier(Class<? extends Supplier<Set<? extends Image>>> clazz) {
bind(new TypeLiteral<Supplier<Set<? extends Image>>>() { bind(new TypeLiteral<Supplier<Set<? extends Image>>>() {
}).to(clazz).in(Scopes.SINGLETON); }).to(clazz).in(Scopes.SINGLETON);
} }
protected void bindLocationSupplier(Class<? extends Supplier<Set<? extends Location>>> clazz) {
bind(new TypeLiteral<Supplier<Set<? extends Location>>>() {
}).to(clazz).in(Scopes.SINGLETON);
}
protected void bindDefaultLocationSupplier(Class<? extends Supplier<Location>> clazz) {
bind(new TypeLiteral<Supplier<Location>>() {
}).to(clazz).in(Scopes.SINGLETON);
}
protected void bindHardwareSupplier(Class<? extends Supplier<Set<? extends Hardware>>> clazz) { protected void bindHardwareSupplier(Class<? extends Supplier<Set<? extends Hardware>>> clazz) {
bind(new TypeLiteral<Supplier<Set<? extends Hardware>>>() { bind(new TypeLiteral<Supplier<Set<? extends Hardware>>>() {
}).to(clazz).in(Scopes.SINGLETON); }).to(clazz).in(Scopes.SINGLETON);

View File

@ -23,15 +23,12 @@ import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
import static com.google.inject.util.Types.newParameterizedType; import static com.google.inject.util.Types.newParameterizedType;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import java.util.Set; import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.collect.TransformingSetSupplier; import org.jclouds.collect.TransformingSetSupplier;
import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
@ -50,11 +47,12 @@ import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.compute.strategy.impl.AdaptingComputeServiceStrategies; import org.jclouds.compute.strategy.impl.AdaptingComputeServiceStrategies;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials; import org.jclouds.domain.LoginCredentials;
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier; import org.jclouds.location.suppliers.LocationsSupplier;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
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;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -83,24 +81,37 @@ public class ComputeServiceAdapterContextModule<S, A, N, H, I, L> extends BaseCo
asyncClientType))).in(Scopes.SINGLETON); asyncClientType))).in(Scopes.SINGLETON);
} }
/**
* install this, if you want to use your computeservice adapter to handle locations. Note that if
* you do this, you'll want to instantiate a subclass to prevent type erasure.
*
* ex.
* <pre>
* install(new LocationsFromComputeServiceAdapterModule<NodeMetadata, Hardware, Image, Location>(){});
* </pre>
* not
* <pre>
* install(new LocationsFromComputeServiceAdapterModule<NodeMetadata, Hardware, Image, Location>());
* </pre>
*/
public static class LocationsFromComputeServiceAdapterModule<N, H, I, L> extends AbstractModule {
@Override @Override
protected void configureLocationModule() { protected void configure() {
// configuring below
} }
@Provides @Provides
@Singleton @Singleton
@Memoized protected LocationsSupplier supplyLocationsFromComputeServiceAdapter(
protected Supplier<Set<? extends Location>> supplyLocationCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
final ComputeServiceAdapter<N, H, I, L> adapter, final Function<L, Location> transformer) { final ComputeServiceAdapter<N, H, I, L> adapter, final Function<L, Location> transformer) {
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Set<? extends Location>>(authException, return new LocationsSupplier() {
seconds, new Supplier<Set<? extends Location>>() {
@Override @Override
public Set<? extends Location> get() { public Set<? extends Location> get() {
return ImmutableSet.<Location> copyOf(transform(filter(adapter.listLocations(), notNull()), Iterable<L> locations = filter(adapter.listLocations(), notNull());
transformer)); return ImmutableSet.<Location> copyOf(transform(locations, transformer));
}
};
} }
});
} }
@Provides @Provides
@ -111,7 +122,7 @@ public class ComputeServiceAdapterContextModule<S, A, N, H, I, L> extends BaseCo
@Override @Override
public Iterable<H> get() { public Iterable<H> get() {
return filter(adapter.listHardwareProfiles(), notNull()); return adapter.listHardwareProfiles();
} }
}, transformer); }, transformer);

View File

@ -42,7 +42,7 @@ import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials; import org.jclouds.domain.LoginCredentials;
import org.jclouds.location.suppliers.JustProvider; import org.jclouds.location.suppliers.all.JustProvider;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;

View File

@ -25,12 +25,8 @@ import javax.inject.Singleton;
import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule; import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.concurrent.SingleThreaded; import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import com.google.common.base.Supplier;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/** /**
* *
@ -54,8 +50,6 @@ public class StubComputeServiceContextModule extends
@Override @Override
protected void configure() { protected void configure() {
install(new StubComputeServiceDependenciesModule()); install(new StubComputeServiceDependenciesModule());
bind(new TypeLiteral<Supplier<Location>>() {
}).to(OnlyLocationOrFirstZone.class);
super.configure(); super.configure();
} }
} }

View File

@ -18,7 +18,12 @@
*/ */
package org.jclouds.concurrent; package org.jclouds.concurrent;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Maps.newHashMap; import static com.google.common.collect.Maps.newHashMap;
import static org.jclouds.util.Throwables2.containsThrowable;
import static org.jclouds.util.Throwables2.propagateAuthorizationOrOriginalException;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
@ -29,20 +34,18 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import org.jclouds.javax.annotation.Nullable;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.inject.Inject; import com.google.inject.Inject;
/** /**
@ -82,6 +85,7 @@ public class FutureIterables {
return transformParallel(fromIterable, function, exec, maxTime, logger, logPrefix, retryHandler, maxRetries); return transformParallel(fromIterable, function, exec, maxTime, logger, logPrefix, retryHandler, maxRetries);
} }
@SuppressWarnings("unchecked")
public static <F, T> Iterable<T> transformParallel(Iterable<F> fromIterable, public static <F, T> Iterable<T> transformParallel(Iterable<F> fromIterable,
Function<? super F, Future<T>> function, ExecutorService exec, @Nullable Long maxTime, Logger logger, Function<? super F, Future<T>> function, ExecutorService exec, @Nullable Long maxTime, Logger logger,
String logPrefix, BackoffLimitedRetryHandler retryHandler, int maxRetries) { String logPrefix, BackoffLimitedRetryHandler retryHandler, int maxRetries) {
@ -93,7 +97,7 @@ public class FutureIterables {
responses.put(from, function.apply(from)); responses.put(from, function.apply(from));
} }
exceptions = awaitCompletion(responses, exec, maxTime, logger, logPrefix); exceptions = awaitCompletion(responses, exec, maxTime, logger, logPrefix);
if (exceptions.size() > 0) { if (exceptions.size() > 0 && !any(exceptions.values(), containsThrowable(AuthorizationException.class))) {
fromIterable = exceptions.keySet(); fromIterable = exceptions.keySet();
retryHandler.imposeBackoffExponentialDelay(delayStart, 2, i + 1, maxRetries, retryHandler.imposeBackoffExponentialDelay(delayStart, 2, i + 1, maxRetries,
String.format("error %s: %s: %s", logPrefix, fromIterable, exceptions)); String.format("error %s: %s: %s", logPrefix, fromIterable, exceptions));
@ -101,8 +105,10 @@ public class FutureIterables {
break; break;
} }
} }
//make sure we propagate any authorization exception so that we don't lock out accounts
if (exceptions.size() > 0) if (exceptions.size() > 0)
throw new RuntimeException(String.format("error %s: %s: %s", logPrefix, fromIterable, exceptions)); return propagateAuthorizationOrOriginalException(new TransformParallelException((Map) responses, exceptions,
logPrefix));
return unwrap(responses.values()); return unwrap(responses.values());
} }
@ -116,7 +122,7 @@ public class FutureIterables {
final AtomicInteger complete = new AtomicInteger(0); final AtomicInteger complete = new AtomicInteger(0);
final AtomicInteger errors = new AtomicInteger(0); final AtomicInteger errors = new AtomicInteger(0);
final long start = System.currentTimeMillis(); final long start = System.currentTimeMillis();
final Map<T, Exception> errorMap = Maps.newHashMap(); final Map<T, Exception> errorMap = newHashMap();
for (final java.util.Map.Entry<T, ? extends Future<?>> future : responses.entrySet()) { for (final java.util.Map.Entry<T, ? extends Future<?>> future : responses.entrySet()) {
Futures.makeListenable(future.getValue(), exec).addListener(new Runnable() { Futures.makeListenable(future.getValue(), exec).addListener(new Runnable() {
@ -157,21 +163,21 @@ public class FutureIterables {
String message = message(logPrefix, total, complete.get(), errors.get(), start); String message = message(logPrefix, total, complete.get(), errors.get(), start);
TimeoutException exception = new TimeoutException(message); TimeoutException exception = new TimeoutException(message);
logger.error(exception, message); logger.error(exception, message);
Throwables.propagate(exception); propagate(exception);
} }
return errorMap; return errorMap;
} }
public static <T> Iterable<T> unwrap(Iterable<Future<T>> values) { public static <T> Iterable<T> unwrap(Iterable<Future<T>> values) {
return Iterables.transform(values, new Function<Future<T>, T>() { return transform(values, new Function<Future<T>, T>() {
@Override @Override
public T apply(Future<T> from) { public T apply(Future<T> from) {
try { try {
return from.get(); return from.get();
} catch (InterruptedException e) { } catch (InterruptedException e) {
Throwables.propagate(e); propagate(e);
} catch (ExecutionException e) { } catch (ExecutionException e) {
Throwables.propagate(e); propagate(e);
} }
return null; return null;
} }

View File

@ -0,0 +1,61 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.concurrent;
import java.util.Map;
import java.util.concurrent.Future;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
/**
* A failure occurred while concurrently operating on an Iterable
*
* @author Adrian Cole
*/
public final class TransformParallelException extends RuntimeException {
/** The serialVersionUID */
private static final long serialVersionUID = 1L;
private final Map<?, Future<?>> success;
private final Map<?, Exception> exceptions;
public TransformParallelException(Map<?, Future<?>> success, Map<?, Exception> exceptions, String messagePrefix) {
super(String.format("error %s: %s", messagePrefix, exceptions));
this.success = ImmutableMap.copyOf(success);
this.exceptions = ImmutableMap.copyOf(exceptions);
initCause(Iterables.get(exceptions.values(), 0));
}
/**
* @return Elements that performed the transform without error
*/
public Map<?, Future<?>> getSuccessfulToValue() {
return success;
}
/**
* @return Elements that failed during the transform
*/
public Map<?, Exception> getFromToException() {
return exceptions;
}
}

View File

@ -0,0 +1,48 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.functions;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
public class JoinOnK2<K, K2, V> implements Function<Map<K, Supplier<Set<K2>>>, Map<K2, Supplier<V>>> {
private final Supplier<Map<K2, Supplier<V>>> regionToEndpointSupplier;
public JoinOnK2(Supplier<Map<K2, Supplier<V>>> regionToEndpointSupplier) {
this.regionToEndpointSupplier = regionToEndpointSupplier;
}
@Override
public Map<K2, Supplier<V>> apply(Map<K, Supplier<Set<K2>>> regionToZones) {
Map<K2, Supplier<V>> regionToEndpoint = regionToEndpointSupplier.get();
Builder<K2, Supplier<V>> builder = ImmutableMap.<K2, Supplier<V>> builder();
for (Entry<K, Supplier<Set<K2>>> entry : regionToZones.entrySet()) {
for (K2 zone : entry.getValue().get()) {
builder.put(zone, regionToEndpoint.get(entry.getKey()));
}
}
return builder.build();
}
}

View File

@ -20,6 +20,8 @@ package org.jclouds.location.config;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import java.net.URI;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -28,6 +30,20 @@ import javax.inject.Singleton;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.location.Iso3166;
import org.jclouds.location.Provider;
import org.jclouds.location.Region;
import org.jclouds.location.Zone;
import org.jclouds.location.suppliers.ImplicitLocationSupplier;
import org.jclouds.location.suppliers.ImplicitRegionIdSupplier;
import org.jclouds.location.suppliers.LocationIdToIso3166CodesSupplier;
import org.jclouds.location.suppliers.LocationsSupplier;
import org.jclouds.location.suppliers.ProviderURISupplier;
import org.jclouds.location.suppliers.RegionIdToURISupplier;
import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
import org.jclouds.location.suppliers.RegionIdsSupplier;
import org.jclouds.location.suppliers.ZoneIdToURISupplier;
import org.jclouds.location.suppliers.ZoneIdsSupplier;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier; import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
@ -36,35 +52,100 @@ import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
/** /**
* All of these are memoized as locations do not change often at runtime. Note that we take care to
* propagate authorization exceptions. this is so that we do not lock out the account.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class LocationModule extends AbstractModule { public class LocationModule extends AbstractModule {
protected final AtomicReference<AuthorizationException> authException;
public LocationModule() {
this(new AtomicReference<AuthorizationException>());
}
public LocationModule(AtomicReference<AuthorizationException> authException) {
this.authException = authException;
}
@Provides
@Singleton
@Memoized
protected Supplier<Set<? extends Location>> supplyLocationCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
final Supplier<Set<? extends Location>> locationSupplier) {
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Set<? extends Location>>(authException, seconds,
new Supplier<Set<? extends Location>>() {
@Override
public Set<? extends Location> get() {
return locationSupplier.get();
}
});
}
@Override @Override
protected void configure() { protected void configure() {
} }
@Provides
@Singleton
@Iso3166
protected Supplier<Map<String, Supplier<Set<String>>>> isoCodesSupplier(
AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds,
LocationIdToIso3166CodesSupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds, uncached);
}
@Provides
@Singleton
@Provider
protected Supplier<URI> provideProvider(AtomicReference<AuthorizationException> authException,
@Named(PROPERTY_SESSION_INTERVAL) long seconds, ProviderURISupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds, uncached);
}
@Provides
@Singleton
protected Supplier<Location> implicitLocationSupplier(AtomicReference<AuthorizationException> authException,
@Named(PROPERTY_SESSION_INTERVAL) long seconds, ImplicitLocationSupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds, uncached);
}
@Provides
@Singleton
// TODO: we should eventually get rid of memoized as an annotation, as it is confusing
@Memoized
protected Supplier<Set<? extends Location>> memoizedLocationsSupplier(
AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds,
LocationsSupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds, uncached);
}
@Provides
@Singleton
@Region
protected Supplier<Set<String>> regionIdsSupplier(AtomicReference<AuthorizationException> authException,
@Named(PROPERTY_SESSION_INTERVAL) long seconds, RegionIdsSupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds, uncached);
}
@Provides
@Singleton
@Region
protected Supplier<Map<String, Supplier<URI>>> regionIdToURISupplier(
AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds,
RegionIdToURISupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds, uncached);
}
@Provides
@Singleton
@Region
protected Supplier<String> implicitRegionIdSupplier(AtomicReference<AuthorizationException> authException,
@Named(PROPERTY_SESSION_INTERVAL) long seconds, ImplicitRegionIdSupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds, uncached);
}
@Provides
@Singleton
@Zone
protected Supplier<Set<String>> regionIdsSupplier(
AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds,
ZoneIdsSupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds, uncached);
}
@Provides
@Singleton
@Zone
protected Supplier<Map<String, Supplier<Set<String>>>> regionIdToZoneIdsSupplier(
AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds,
RegionIdToZoneIdsSupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds, uncached);
}
@Provides
@Singleton
@Zone
protected Supplier<Map<String, Supplier<URI>>> zoneIdToURISupplier(
AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds,
ZoneIdToURISupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds, uncached);
}
} }

View File

@ -1,81 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.config;
import static org.jclouds.location.reference.LocationConstants.ENDPOINT;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.net.URI;
import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.location.Region;
import org.jclouds.logging.Logger;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.inject.ConfigurationException;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
/**
*
* looks for properties bound to the naming convention jclouds.region.{@code regionId}.endpoint
*
* @author Adrian Cole
*/
@Singleton
public class ProvideRegionToURIViaProperties implements javax.inject.Provider<Map<String, URI>> {
private final Injector injector;
@Resource
protected Logger logger = Logger.NULL;
@Inject
protected ProvideRegionToURIViaProperties(Injector injector) {
this.injector = injector;
}
@Singleton
@Region
@Override
public Map<String, URI> get() {
try {
String regionString = injector.getInstance(Key.get(String.class, Names.named(PROPERTY_REGIONS)));
Builder<String, URI> regions = ImmutableMap.<String, URI> builder();
for (String region : Splitter.on(',').split(regionString)) {
String regionUri = injector.getInstance(Key.get(String.class, Names.named(PROPERTY_REGION + "." + region
+ "." + ENDPOINT)));
regions.put(region, URI.create(regionUri));
}
return regions.build();
} catch (ConfigurationException e) {
logger.warn("no region name to endpoint mappings configured!");
return ImmutableMap.of();
}
}
}

View File

@ -1,77 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.config;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.location.Region;
import org.jclouds.location.Zone;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.inject.ConfigurationException;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
/**
*
* looks for properties bound to the naming convention jclouds.location.region.{@code regionId}.zones
*
* @author Adrian Cole
*/
@Singleton
public class ProvideZonesViaProperties implements javax.inject.Provider<Map<String, String>> {
private final Injector injector;
private final Set<String> regions;
@Inject
ProvideZonesViaProperties(Injector injector, @Region Set<String> regions) {
this.injector = injector;
this.regions = regions;
}
@Singleton
@Zone
@Override
public Map<String, String> get() {
try {
Builder<String, String> zones = ImmutableMap.<String, String> builder();
for (String region : regions) {
for (String zone : Splitter.on(',').split(
injector.getInstance(Key.get(String.class, Names.named(PROPERTY_REGION + "." + region + ".zones"))))) {
zones.put(zone, region);
}
}
return zones.build();
} catch (ConfigurationException e) {
// this happens if regions property isn't set
// services not run by AWS may not have zones, so this is ok.
return ImmutableMap.<String, String> of();
}
}
}

View File

@ -32,6 +32,7 @@ import org.jclouds.location.Provider;
import org.jclouds.location.Region; import org.jclouds.location.Region;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Supplier;
/** /**
* Return a uri corresponding to the name of the region (passed argument). * Return a uri corresponding to the name of the region (passed argument).
@ -41,25 +42,26 @@ import com.google.common.base.Function;
*/ */
@Singleton @Singleton
public class RegionToEndpointOrProviderIfNull implements Function<Object, URI> { public class RegionToEndpointOrProviderIfNull implements Function<Object, URI> {
private final URI defaultUri; private final Supplier<URI> defaultUri;
private final String defaultProvider; private final String defaultProvider;
private final Map<String, URI> regionToEndpoint; private final Supplier<Map<String, Supplier<URI>>> regionToEndpointSupplier;
@Inject @Inject
public RegionToEndpointOrProviderIfNull(@Provider String defaultProvider, @Provider URI defaultUri, public RegionToEndpointOrProviderIfNull(@Provider String defaultProvider, @Provider Supplier<URI> defaultUri,
@Region Map<String, URI> regionToEndpoint) { @Region Supplier<Map<String, Supplier<URI>>> regionToEndpointSupplier) {
this.defaultProvider = checkNotNull(defaultProvider, "defaultProvider"); this.defaultProvider = checkNotNull(defaultProvider, "defaultProvider");
this.defaultUri = checkNotNull(defaultUri, "defaultUri"); this.defaultUri = checkNotNull(defaultUri, "defaultUri");
this.regionToEndpoint = checkNotNull(regionToEndpoint, "regionToEndpoint"); this.regionToEndpointSupplier = checkNotNull(regionToEndpointSupplier, "regionToEndpointSupplier");
} }
@Override @Override
public URI apply(@Nullable Object from) { public URI apply(@Nullable Object from) {
if (from == null || from.equals(defaultProvider)) if (from == null || from.equals(defaultProvider))
return defaultUri; return defaultUri.get();
checkArgument(from instanceof String, "region is a String argument"); checkArgument(from instanceof String, "region is a String argument");
Map<String, Supplier<URI>> regionToEndpoint = regionToEndpointSupplier.get();
checkArgument(regionToEndpoint.containsKey(from), checkArgument(regionToEndpoint.containsKey(from),
"requested location %s, which is not in the configured locations: %s", from, regionToEndpoint); "requested location %s, which is not in the configured locations: %s", from, regionToEndpoint);
return regionToEndpoint.get(from); return regionToEndpoint.get(from).get();
} }
} }

View File

@ -18,8 +18,8 @@
*/ */
package org.jclouds.location.functions; package org.jclouds.location.functions;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.*;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
@ -31,6 +31,7 @@ import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Zone; import org.jclouds.location.Zone;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Supplier;
/** /**
* *
@ -39,17 +40,20 @@ import com.google.common.base.Function;
@Singleton @Singleton
public class ZoneToEndpoint implements Function<Object, URI> { public class ZoneToEndpoint implements Function<Object, URI> {
private final Map<String, URI> zoneToEndpoint; private final Supplier<Map<String, Supplier<URI>>> zoneToEndpointSupplier;
@Inject @Inject
public ZoneToEndpoint(@Zone Map<String, URI> zoneToEndpoint) { public ZoneToEndpoint(@Zone Supplier<Map<String, Supplier<URI>>> zoneToEndpointSupplier) {
this.zoneToEndpoint = checkNotNull(zoneToEndpoint, "zoneToEndpoint"); this.zoneToEndpointSupplier = checkNotNull(zoneToEndpointSupplier, "zoneToEndpointSupplier");
checkArgument(zoneToEndpoint.size() > 0, "no zone name to endpoint mappings configured!");
} }
@Override @Override
public URI apply(@Nullable Object from) { public URI apply(@Nullable Object from) {
checkArgument(from != null && from instanceof String, "you must specify a zone, as a String argument"); checkArgument(from != null && from instanceof String, "you must specify a zone, as a String argument");
return zoneToEndpoint.get(from); Map<String, Supplier<URI>> zoneToEndpoint = zoneToEndpointSupplier.get();
checkState(zoneToEndpoint.size() > 0, "no zone name to endpoint mappings configured!");
checkArgument(zoneToEndpoint.containsKey(from),
"requested location %s, which is not in the configured locations: %s", from, zoneToEndpoint);
return zoneToEndpoint.get(from).get();
} }
} }

View File

@ -33,6 +33,24 @@ import com.google.common.base.Predicate;
*/ */
public class LocationPredicates { public class LocationPredicates {
public static Predicate<Location> isProvider() {
return IsProvider.INSTANCE;
}
@Singleton
static enum IsProvider implements Predicate<Location> {
INSTANCE;
@Override
public boolean apply(Location input) {
return input.getScope() == LocationScope.PROVIDER;
}
@Override
public String toString() {
return "isProvider()";
}
}
public static Predicate<Location> isZone() { public static Predicate<Location> isZone() {
return IsZone.INSTANCE; return IsZone.INSTANCE;
} }

View File

@ -16,40 +16,19 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.jclouds.location.config; package org.jclouds.location.suppliers;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.JustProvider; import org.jclouds.location.suppliers.implicit.OnlyLocationOrFirstRegionOptionallyMatchingRegionId;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import org.jclouds.rest.AuthorizationException;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.inject.TypeLiteral; import com.google.inject.ImplementedBy;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
public class JustProviderLocationModule extends LocationModule { @ImplementedBy(OnlyLocationOrFirstRegionOptionallyMatchingRegionId.class)
public JustProviderLocationModule() { public interface ImplicitLocationSupplier extends Supplier<Location> {
super();
}
public JustProviderLocationModule(AtomicReference<AuthorizationException> authException) {
super(authException);
}
@Override
protected void configure() {
bind(new TypeLiteral<Supplier<Set<? extends Location>>>() {
}).to(JustProvider.class);
bind(new TypeLiteral<Supplier<Location>>() {
}).to(OnlyLocationOrFirstZone.class);
super.configure();
}
} }

View File

@ -0,0 +1,33 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers;
import org.jclouds.location.suppliers.implicit.GetRegionIdMatchingProviderURIOrNull;
import com.google.common.base.Supplier;
import com.google.inject.ImplementedBy;
/**
*
* @author Adrian Cole
*/
@ImplementedBy(GetRegionIdMatchingProviderURIOrNull.class)
public interface ImplicitRegionIdSupplier extends Supplier<String> {
}

View File

@ -0,0 +1,38 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers;
import java.util.Map;
import java.util.Set;
import org.jclouds.location.suppliers.fromconfig.LocationIdToIso3166CodesFromConfiguration;
import com.google.common.base.Supplier;
import com.google.inject.ImplementedBy;
/**
*
*
* @author Adrian Cole
*/
@ImplementedBy(LocationIdToIso3166CodesFromConfiguration.class)
public interface LocationIdToIso3166CodesSupplier extends Supplier<Map<String, Supplier<Set<String>>>> {
}

View File

@ -16,31 +16,21 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.jclouds.location.config; package org.jclouds.location.suppliers;
import java.util.Set; import java.util.Set;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.OnlyLocationOrFirstRegionOptionallyMatchingRegionId; import org.jclouds.location.suppliers.all.ZoneToRegionToProviderOrJustProvider;
import org.jclouds.location.suppliers.RegionToProviderOrJustProvider;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.inject.TypeLiteral; import com.google.inject.ImplementedBy;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*
*/ */
public class RegionsLocationModule extends LocationModule { @ImplementedBy(ZoneToRegionToProviderOrJustProvider.class)
public interface LocationsSupplier extends Supplier<Set<? extends Location>> {
@Override
protected void configure() {
bind(new TypeLiteral<Supplier<Set<? extends Location>>>() {
}).to(RegionToProviderOrJustProvider.class);
bind(new TypeLiteral<Supplier<Location>>() {
}).to(OnlyLocationOrFirstRegionOptionallyMatchingRegionId.class);
super.configure();
}
} }

View File

@ -0,0 +1,31 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers;
import java.net.URI;
import org.jclouds.location.suppliers.fromconfig.ProviderURIFromConfiguration;
import com.google.common.base.Supplier;
import com.google.inject.ImplementedBy;
@ImplementedBy(ProviderURIFromConfiguration.class)
public interface ProviderURISupplier extends Supplier<URI> {
}

View File

@ -0,0 +1,37 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers;
import java.net.URI;
import java.util.Map;
import org.jclouds.location.suppliers.fromconfig.RegionIdToURIFromConfigurationOrDefaultToProvider;
import com.google.common.base.Supplier;
import com.google.inject.ImplementedBy;
/**
*
*
* @author Adrian Cole
*/
@ImplementedBy(RegionIdToURIFromConfigurationOrDefaultToProvider.class)
public interface RegionIdToURISupplier extends Supplier<Map<String, Supplier<URI>>> {
}

View File

@ -0,0 +1,36 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers;
import java.util.Map;
import java.util.Set;
import org.jclouds.location.suppliers.fromconfig.RegionIdToZoneIdsFromConfiguration;
import com.google.common.base.Supplier;
import com.google.inject.ImplementedBy;
/**
* @author Adrian Cole
*/
@ImplementedBy(RegionIdToZoneIdsFromConfiguration.class)
public interface RegionIdToZoneIdsSupplier extends Supplier<Map<String, Supplier<Set<String>>>> {
}

View File

@ -0,0 +1,35 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers;
import java.util.Set;
import org.jclouds.location.suppliers.fromconfig.RegionIdsFromConfiguration;
import com.google.common.base.Supplier;
import com.google.inject.ImplementedBy;
/**
* @author Adrian Cole
*/
@ImplementedBy(RegionIdsFromConfiguration.class)
public interface RegionIdsSupplier extends Supplier<Set<String>> {
}

View File

@ -0,0 +1,37 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers;
import java.net.URI;
import java.util.Map;
import org.jclouds.location.suppliers.fromconfig.ZoneIdToURIFromConfigurationOrDefaultToProvider;
import com.google.common.base.Supplier;
import com.google.inject.ImplementedBy;
/**
*
*
* @author Adrian Cole
*/
@ImplementedBy(ZoneIdToURIFromConfigurationOrDefaultToProvider.class)
public interface ZoneIdToURISupplier extends Supplier<Map<String, Supplier<URI>>> {
}

View File

@ -0,0 +1,35 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers;
import java.util.Set;
import org.jclouds.location.suppliers.fromconfig.ZoneIdsFromConfiguration;
import com.google.common.base.Supplier;
import com.google.inject.ImplementedBy;
/**
*
* @author Adrian Cole
*/
@ImplementedBy(ZoneIdsFromConfiguration.class)
public interface ZoneIdsSupplier extends Supplier<Set<String>> {
}

View File

@ -1,89 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Maps.uniqueIndex;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.location.Iso3166;
import org.jclouds.location.Provider;
import org.jclouds.location.Zone;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
/**
*
* @author Adrian Cole
*/
@Singleton
public class ZoneToRegionToProviderOrJustProvider extends RegionToProviderOrJustProvider {
private final Map<String, String> zoneToRegion;
private Map<String, Set<String>> isoCodesById;
@Inject
ZoneToRegionToProviderOrJustProvider(@Iso3166 Set<String> isoCodes, @Provider String providerName,
@Provider URI endpoint, @Iso3166 Map<String, Set<String>> isoCodesById,
@Zone Map<String, String> zoneToRegion) {
super(isoCodes, providerName, endpoint, ImmutableSet.copyOf(checkNotNull(zoneToRegion, "zoneToRegion").values()),
isoCodesById);
this.zoneToRegion = zoneToRegion;
this.isoCodesById = checkNotNull(isoCodesById, "isoCodesById");
}
@Override
public Set<? extends Location> get() {
Builder<Location> locations = buildJustProviderOrRegions();
ImmutableMap<String, Location> idToLocation = uniqueIndex(locations.build(), new Function<Location, String>() {
@Override
public String apply(Location from) {
return from.getId();
}
});
if (zoneToRegion.size() == 1)
return locations.build();
for (String zone : zoneToRegion.keySet()) {
Location parent = idToLocation.get(zoneToRegion.get(zone));
LocationBuilder builder = new LocationBuilder().scope(LocationScope.ZONE).id(zone).description(zone).parent(
parent);
if (isoCodesById.containsKey(zone))
builder.iso3166Codes(isoCodesById.get(zone));
// be cautious.. only inherit iso codes if the parent is a region
// regions may be added dynamically, and we prefer to inherit an
// empty set of codes from a region, then a provider, whose code
// are likely hard-coded.
else if (parent.getScope() == LocationScope.REGION)
builder.iso3166Codes(parent.getIso3166Codes());
locations.add(builder.build());
}
return locations.build();
}
}

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.jclouds.location.suppliers; package org.jclouds.location.suppliers.all;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -42,20 +42,20 @@ import com.google.common.collect.ImmutableSet;
@Singleton @Singleton
public class JustProvider implements Supplier<Set<? extends Location>> { public class JustProvider implements Supplier<Set<? extends Location>> {
private final String providerName; private final String providerName;
private final URI endpoint; private final URI endpointSupplier;
private final Set<String> isoCodes; private final Set<String> isoCodesSupplier;
@Inject @Inject
public JustProvider(@Provider String providerName, @Provider URI endpoint, @Iso3166 Set<String> isoCodes) { public JustProvider(@Provider String providerName, @Provider URI endpointSupplier, @Iso3166 Set<String> isoCodesSupplier) {
this.providerName = checkNotNull(providerName, "providerName"); this.providerName = checkNotNull(providerName, "providerName");
this.endpoint = checkNotNull(endpoint, "endpoint"); this.endpointSupplier = checkNotNull(endpointSupplier, "endpoint");
this.isoCodes = checkNotNull(isoCodes, "isoCodes"); this.isoCodesSupplier = checkNotNull(isoCodesSupplier, "isoCodes");
} }
@Override @Override
public Set<? extends Location> get() { public Set<? extends Location> get() {
return ImmutableSet.of(new LocationBuilder().scope(LocationScope.PROVIDER).id(providerName) return ImmutableSet.of(new LocationBuilder().scope(LocationScope.PROVIDER).id(providerName)
.description(endpoint.toASCIIString()).iso3166Codes(isoCodes).build()); .description(endpointSupplier.toASCIIString()).iso3166Codes(isoCodesSupplier).build());
} }
} }

View File

@ -16,11 +16,10 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.jclouds.location.suppliers; package org.jclouds.location.suppliers.all;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -31,9 +30,9 @@ import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder; import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.location.Iso3166; import org.jclouds.location.Iso3166;
import org.jclouds.location.Provider;
import org.jclouds.location.Region; import org.jclouds.location.Region;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableSet.Builder; import com.google.common.collect.ImmutableSet.Builder;
@ -43,37 +42,36 @@ import com.google.common.collect.ImmutableSet.Builder;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class RegionToProviderOrJustProvider extends JustProvider { public class RegionToProviderOrJustProvider implements Supplier<Set<? extends Location>> {
private final Set<String> regions; private final JustProvider justProvider;
private final Map<String, Set<String>> isoCodesById; private final Supplier<Set<String>> regionsSupplier;
private final Supplier<Map<String, Supplier<Set<String>>>> isoCodesByIdSupplier;
@Inject @Inject
public RegionToProviderOrJustProvider(@Iso3166 Set<String> isoCodes, @Provider String providerName, public RegionToProviderOrJustProvider(JustProvider justProvider, @Region Supplier<Set<String>> regionsSupplier,
@Provider URI endpoint, @Region Set<String> regions, @Iso3166 Map<String, Set<String>> isoCodesById) { @Iso3166 Supplier<Map<String, Supplier<Set<String>>>> isoCodesByIdSupplier) {
super(providerName, endpoint, isoCodes); this.justProvider = checkNotNull(justProvider, "justProvider");
this.regions = checkNotNull(regions, "regions"); this.regionsSupplier = checkNotNull(regionsSupplier, "regionsSupplier");
this.isoCodesById = checkNotNull(isoCodesById, "isoCodesById"); this.isoCodesByIdSupplier = checkNotNull(isoCodesByIdSupplier, "isoCodesByIdSupplier");
} }
@Override @Override
public Set<? extends Location> get() { public Set<? extends Location> get() {
return buildJustProviderOrRegions().build();
}
protected Builder<Location> buildJustProviderOrRegions() {
Builder<Location> locations = ImmutableSet.builder(); Builder<Location> locations = ImmutableSet.builder();
Location provider = Iterables.getOnlyElement(super.get()); Location provider = Iterables.getOnlyElement(justProvider.get());
Set<String> regions = regionsSupplier.get();
Map<String, Supplier<Set<String>>> isoCodesById = isoCodesByIdSupplier.get();
if (regions.size() == 0) if (regions.size() == 0)
return locations.add(provider); return locations.add(provider).build();
else else
for (String region : regions) { for (String region : regions) {
LocationBuilder builder = new LocationBuilder().scope(LocationScope.REGION).id(region).description(region) LocationBuilder builder = new LocationBuilder().scope(LocationScope.REGION).id(region).description(region)
.parent(provider); .parent(provider);
if (isoCodesById.containsKey(region)) if (isoCodesById.containsKey(region))
builder.iso3166Codes(isoCodesById.get(region)); builder.iso3166Codes(isoCodesById.get(region).get());
locations.add(builder.build()); locations.add(builder.build());
} }
return locations; return locations.build();
} }
} }

View File

@ -0,0 +1,142 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers.all;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.location.Iso3166;
import org.jclouds.location.Zone;
import org.jclouds.location.predicates.LocationPredicates;
import org.jclouds.location.suppliers.LocationsSupplier;
import org.jclouds.logging.Logger;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.collect.Sets.SetView;
/**
*
* @author Adrian Cole
*/
@Singleton
public class ZoneToRegionToProviderOrJustProvider implements LocationsSupplier {
@Resource
protected Logger logger = Logger.NULL;
private final RegionToProviderOrJustProvider regionToProviderOrJustProvider;
private final Supplier<Set<String>> zoneIdsSupplier;
private final Supplier<Map<String, Supplier<Set<String>>>> isoCodesByIdSupplier;
private final Supplier<Map<String, Supplier<Set<String>>>> regionIdToZoneIdsSupplier;
@Inject
ZoneToRegionToProviderOrJustProvider(RegionToProviderOrJustProvider regionToProviderOrJustProvider,
@Zone Supplier<Set<String>> zoneIdsSupplier,
@Iso3166 Supplier<Map<String, Supplier<Set<String>>>> isoCodesByIdSupplier,
@Zone Supplier<Map<String, Supplier<Set<String>>>> regionIdToZoneIdsSupplier) {
this.regionToProviderOrJustProvider = checkNotNull(regionToProviderOrJustProvider,
"regionToProviderOrJustProvider");
this.zoneIdsSupplier = checkNotNull(zoneIdsSupplier, "zoneIdsSupplier");
this.regionIdToZoneIdsSupplier = checkNotNull(regionIdToZoneIdsSupplier, "regionIdToZoneIdsSupplier");
this.isoCodesByIdSupplier = checkNotNull(isoCodesByIdSupplier, "isoCodesByIdSupplier");
}
@Override
public Set<? extends Location> get() {
Set<? extends Location> regionsOrJustProvider = regionToProviderOrJustProvider.get();
Set<String> zoneIds = zoneIdsSupplier.get();
if (zoneIds.size() == 0)
return regionsOrJustProvider;
Map<String, Location> zoneIdToParent = setParentOfZoneToRegionOrProvider(zoneIds, regionsOrJustProvider);
Map<String, Supplier<Set<String>>> isoCodesById = isoCodesByIdSupplier.get();
Builder<Location> locations = ImmutableSet.builder();
locations.addAll(regionsOrJustProvider);
for (String zoneId : zoneIdToParent.keySet()) {
Location parent = zoneIdToParent.get(zoneId);
LocationBuilder builder = new LocationBuilder().scope(LocationScope.ZONE).id(zoneId).description(zoneId)
.parent(parent);
if (isoCodesById.containsKey(zoneId))
builder.iso3166Codes(isoCodesById.get(zoneId).get());
// be cautious.. only inherit iso codes if the parent is a region
// regions may be added dynamically, and we prefer to inherit an
// empty set of codes from a region, then a provider, whose code
// are likely hard-coded.
else if (parent.getScope() == LocationScope.REGION)
builder.iso3166Codes(parent.getIso3166Codes());
locations.add(builder.build());
}
return locations.build();
}
private Map<String, Location> setParentOfZoneToRegionOrProvider(Set<String> zoneIds,
Set<? extends Location> locations) {
// mutable, so that we can query current state when adding. safe as its temporary
Map<String, Location> zoneIdToParent = Maps.newLinkedHashMap();
Location provider = Iterables.find(locations, LocationPredicates.isProvider(), null);
if (locations.size() == 1 && provider != null) {
for (String zone : zoneIds)
zoneIdToParent.put(zone, provider);
} else {
// note that we only call regionIdToZoneIdsSupplier if there are region locations present
// they cannot be, if the above is true
Map<String, Supplier<Set<String>>> regionIdToZoneIds = regionIdToZoneIdsSupplier.get();
for (Location region : Iterables.filter(locations, LocationPredicates.isRegion())) {
provider = region.getParent();
if (regionIdToZoneIds.containsKey(region.getId())) {
for (String zoneId : regionIdToZoneIds.get(region.getId()).get())
zoneIdToParent.put(zoneId, region);
} else {
logger.debug("no zones configured for region: %s", region);
}
}
}
SetView<String> orphans = Sets.difference(zoneIds, zoneIdToParent.keySet());
if (orphans.size() > 0) {
// any unmatched zones should have their parents set to the provider
checkState(
provider != null,
"cannot configure zones %s as we need a parent, and the only available location [%s] is not a provider",
zoneIds, locations);
for (String orphanedZoneId : orphans)
zoneIdToParent.put(orphanedZoneId, provider);
}
checkState(zoneIdToParent.keySet().containsAll(zoneIds), "orphaned zones: %s ", Sets.difference(zoneIds,
zoneIdToParent.keySet()));
return zoneIdToParent;
}
}

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.jclouds.location.config; package org.jclouds.location.suppliers.fromconfig;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.location.reference.LocationConstants.ISO3166_CODES; import static org.jclouds.location.reference.LocationConstants.ISO3166_CODES;
@ -30,28 +30,31 @@ import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.location.Iso3166; import org.jclouds.location.Iso3166;
import org.jclouds.location.suppliers.LocationIdToIso3166CodesSupplier;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableMap.Builder;
/** /**
* *
* looks for properties bound to the naming conventions jclouds.region. * looks for properties bound to the naming conventions jclouds.region. {@code regionId}
* {@code regionId} .iso3166-codes and jclouds.zone.{@code zoneId}.iso3166-codes * .iso3166-codes and jclouds.zone.{@code zoneId}.iso3166-codes
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class ProvideIso3166CodesByLocationIdViaProperties implements javax.inject.Provider<Map<String, Set<String>>> { public class LocationIdToIso3166CodesFromConfiguration implements LocationIdToIso3166CodesSupplier {
private final Function<Predicate<String>, Map<String, String>> filterStringsBoundByName; private final Function<Predicate<String>, Map<String, String>> filterStringsBoundByName;
@Inject @Inject
ProvideIso3166CodesByLocationIdViaProperties( public LocationIdToIso3166CodesFromConfiguration(
Function<Predicate<String>, Map<String, String>> filterStringsBoundByName) { Function<Predicate<String>, Map<String, String>> filterStringsBoundByName) {
this.filterStringsBoundByName = checkNotNull(filterStringsBoundByName, "filterStringsBoundByName"); this.filterStringsBoundByName = checkNotNull(filterStringsBoundByName, "filterStringsBoundByName");
} }
@ -59,16 +62,16 @@ public class ProvideIso3166CodesByLocationIdViaProperties implements javax.injec
@Singleton @Singleton
@Iso3166 @Iso3166
@Override @Override
public Map<String, Set<String>> get() { public Map<String, Supplier<Set<String>>> get() {
Map<String, String> stringsBoundWithRegionOrZonePrefix = filterStringsBoundByName.apply(new Predicate<String>() { Map<String, String> stringsBoundWithRegionOrZonePrefix = filterStringsBoundByName.apply(new Predicate<String>() {
@Override @Override
public boolean apply(String input) { public boolean apply(String input) {
return input.startsWith(PROPERTY_REGION) || input.startsWith(PROPERTY_ZONE); return (input.startsWith(PROPERTY_REGION) || input.startsWith(PROPERTY_ZONE));
} }
}); });
Builder<String, Set<String>> codes = ImmutableMap.<String, Set<String>> builder(); Builder<String, Supplier<Set<String>>> codes = ImmutableMap.<String, Supplier<Set<String>>> builder();
for (String key : ImmutableSet.of(PROPERTY_REGION, PROPERTY_ZONE)) { for (String key : ImmutableSet.of(PROPERTY_REGION, PROPERTY_ZONE)) {
String regionOrZoneString = stringsBoundWithRegionOrZonePrefix.get(key + "s"); String regionOrZoneString = stringsBoundWithRegionOrZonePrefix.get(key + "s");
if (regionOrZoneString == null) if (regionOrZoneString == null)
@ -76,7 +79,8 @@ public class ProvideIso3166CodesByLocationIdViaProperties implements javax.injec
for (String region : Splitter.on(',').split(regionOrZoneString)) { for (String region : Splitter.on(',').split(regionOrZoneString)) {
String isoCodes = stringsBoundWithRegionOrZonePrefix.get(key + "." + region + "." + ISO3166_CODES); String isoCodes = stringsBoundWithRegionOrZonePrefix.get(key + "." + region + "." + ISO3166_CODES);
if (isoCodes != null) if (isoCodes != null)
codes.put(region, ImmutableSet.copyOf(Splitter.on(',').split(isoCodes))); codes.put(region, Suppliers.<Set<String>> ofInstance(ImmutableSet.copyOf(Splitter.on(',')
.split(isoCodes))));
} }
} }
return codes.build(); return codes.build();

View File

@ -0,0 +1,78 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers.fromconfig;
import static org.jclouds.location.reference.LocationConstants.ENDPOINT;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.location.Provider;
import org.jclouds.logging.Logger;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.inject.assistedinject.Assisted;
@Singleton
public class LocationIdToURIFromConfigurationOrDefaultToProvider implements Supplier<Map<String, Supplier<URI>>>{
@Resource
protected Logger logger = Logger.NULL;
protected final ValueOfConfigurationKeyOrNull config;
protected final Supplier<Set<String>> locationIds;
protected final Supplier<URI> providerURI;
protected final String configPrefix;
@Inject
public LocationIdToURIFromConfigurationOrDefaultToProvider(ValueOfConfigurationKeyOrNull config, @Provider Supplier<URI> providerURI, @Assisted Supplier<Set<String>> locationIds,
@Assisted String configPrefix) {
this.config = config;
this.locationIds = locationIds;
this.providerURI = providerURI;
this.configPrefix = configPrefix;
}
@Override
public Map<String, Supplier<URI>> get() {
Builder<String, Supplier<URI>> locations = ImmutableMap.<String, Supplier<URI>> builder();
for (String location : locationIds.get()) {
String configKey = configPrefix + "." + location + "." + ENDPOINT;
String locationUri = config.apply(configKey);
if (locationUri == null) {
logger.debug("config key %s not present, defaulting to %s", configKey, providerURI);
locations.put(location, providerURI);
} else {
locations.put(location, Suppliers.ofInstance(URI.create(locationUri)));
}
}
return locations.build();
}
}

View File

@ -0,0 +1,39 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers.fromconfig;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.location.suppliers.ProviderURISupplier;
import org.jclouds.rest.suppliers.URIFromStringSupplier;
@Singleton
public class ProviderURIFromConfiguration extends URIFromStringSupplier implements
ProviderURISupplier {
@Inject
protected ProviderURIFromConfiguration(@Named(PROPERTY_ENDPOINT) String endpoint) {
super(checkNotNull(endpoint, PROPERTY_ENDPOINT));
}
}

View File

@ -0,0 +1,51 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers.fromconfig;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION;
import java.net.URI;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.location.Provider;
import org.jclouds.location.Region;
import org.jclouds.location.suppliers.RegionIdToURISupplier;
import com.google.common.base.Supplier;
/**
*
* looks for properties bound to the naming convention jclouds.region.{@code regionId}.endpoint
*
* @author Adrian Cole
*/
@Singleton
public class RegionIdToURIFromConfigurationOrDefaultToProvider extends LocationIdToURIFromConfigurationOrDefaultToProvider implements RegionIdToURISupplier {
@Inject
protected RegionIdToURIFromConfigurationOrDefaultToProvider(ValueOfConfigurationKeyOrNull config, @Provider Supplier<URI> providerURI,
@Region Supplier<Set<String>> regionIds) {
super(config, providerURI, regionIds, PROPERTY_REGION);
}
}

View File

@ -0,0 +1,91 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers.fromconfig;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.location.Provider;
import org.jclouds.location.Region;
import org.jclouds.location.Zone;
import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
import org.jclouds.logging.Logger;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableMap.Builder;
/**
*
* looks for properties bound to the naming convention jclouds.location.region.{@code regionId}
* .zones
*
* @author Adrian Cole
*/
@Singleton
public class RegionIdToZoneIdsFromConfiguration implements RegionIdToZoneIdsSupplier {
@Resource
protected Logger logger = Logger.NULL;
private final ValueOfConfigurationKeyOrNull config;
private final String provider;
private final Supplier<Set<String>> regionsSupplier;
@Inject
protected RegionIdToZoneIdsFromConfiguration(ValueOfConfigurationKeyOrNull config, @Provider String provider,
@Region Supplier<Set<String>> regionsSupplier) {
this.config = config;
this.provider = provider;
this.regionsSupplier = regionsSupplier;
}
@Singleton
@Zone
@Override
public Map<String, Supplier<Set<String>>> get() {
Set<String> regions = regionsSupplier.get();
if (regions.size() == 0) {
logger.debug("no regions configured for provider %s", provider);
return ImmutableMap.of();
}
Builder<String, Supplier<Set<String>>> regionToZones = ImmutableMap.<String, Supplier<Set<String>>> builder();
for (String region : regions) {
String configKey = PROPERTY_REGION + "." + region + ".zones";
String zones = config.apply(configKey);
if (zones == null)
logger.debug("config key %s not present", configKey);
else
regionToZones.put(region, Suppliers.<Set<String>> ofInstance(ImmutableSet.copyOf(Splitter.on(',').split(
zones))));
}
return regionToZones.build();
}
}

View File

@ -0,0 +1,45 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers.fromconfig;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.location.Provider;
import org.jclouds.location.suppliers.RegionIdsSupplier;
/**
*
* looks for properties bound to the naming convention jclouds.regions
*
* @author Adrian Cole
*/
@Singleton
public class RegionIdsFromConfiguration extends SplitConfigurationKey implements RegionIdsSupplier {
@Inject
protected RegionIdsFromConfiguration(ValueOfConfigurationKeyOrNull config, @Provider String provider) {
super(config, provider, PROPERTY_REGIONS);
}
}

View File

@ -0,0 +1,63 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers.fromconfig;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.location.Provider;
import org.jclouds.logging.Logger;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.inject.assistedinject.Assisted;
@Singleton
public class SplitConfigurationKey implements Supplier<Set<String>> {
@Resource
protected Logger logger = Logger.NULL;
protected final ValueOfConfigurationKeyOrNull config;
protected final String provider;
protected final String configKey;
public SplitConfigurationKey(ValueOfConfigurationKeyOrNull config, @Provider String provider,
@Assisted String configKey) {
this.config = config;
this.provider = provider;
this.configKey = configKey;
}
@Override
public Set<String> get() {
String regionString = config.apply(configKey);
if (regionString == null) {
logger.debug("no %s configured for provider %s", configKey, provider);
return ImmutableSet.of();
} else {
return ImmutableSet.copyOf(Splitter.on(',').split(regionString));
}
}
}

View File

@ -0,0 +1,51 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers.fromconfig;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_ZONE;
import java.net.URI;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.location.Provider;
import org.jclouds.location.Zone;
import org.jclouds.location.suppliers.ZoneIdToURISupplier;
import com.google.common.base.Supplier;
/**
*
* looks for properties bound to the naming convention jclouds.zone.{@code zoneId}.endpoint
*
* @author Adrian Cole
*/
@Singleton
public class ZoneIdToURIFromConfigurationOrDefaultToProvider extends LocationIdToURIFromConfigurationOrDefaultToProvider implements ZoneIdToURISupplier {
@Inject
protected ZoneIdToURIFromConfigurationOrDefaultToProvider(ValueOfConfigurationKeyOrNull config, @Provider Supplier<URI> providerURI,
@Zone Supplier<Set<String>> zoneIds) {
super(config, providerURI, zoneIds, PROPERTY_ZONE);
}
}

View File

@ -0,0 +1,45 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers.fromconfig;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_ZONES;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.location.Provider;
import org.jclouds.location.suppliers.ZoneIdsSupplier;
/**
*
* looks for properties bound to the naming convention jclouds.zones
*
* @author Adrian Cole
*/
@Singleton
public class ZoneIdsFromConfiguration extends SplitConfigurationKey implements ZoneIdsSupplier {
@Inject
protected ZoneIdsFromConfiguration(ValueOfConfigurationKeyOrNull config, @Provider String provider) {
super(config, provider, PROPERTY_ZONES);
}
}

View File

@ -0,0 +1,44 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.location.suppliers.implicit;
import java.net.URI;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.location.Provider;
import org.jclouds.location.Region;
import org.jclouds.location.suppliers.ImplicitRegionIdSupplier;
import org.jclouds.suppliers.SupplyKeyMatchingValueOrNull;
import com.google.common.base.Supplier;
@Singleton
public class GetRegionIdMatchingProviderURIOrNull extends SupplyKeyMatchingValueOrNull<String, URI> implements
ImplicitRegionIdSupplier {
@Inject
public GetRegionIdMatchingProviderURIOrNull(@Region Supplier<Map<String, Supplier<URI>>> supplier,
@Provider Supplier<URI> providerUri) {
super(supplier, providerUri);
}
}

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.jclouds.location.suppliers; package org.jclouds.location.suppliers.implicit;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.collect.Iterables.getOnlyElement;
@ -34,9 +34,9 @@ import javax.inject.Singleton;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Region; import org.jclouds.location.Region;
import org.jclouds.location.functions.ToIdAndScope; import org.jclouds.location.functions.ToIdAndScope;
import org.jclouds.location.suppliers.ImplicitLocationSupplier;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
@ -47,22 +47,23 @@ import com.google.common.collect.Iterables;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class OnlyLocationOrFirstRegionOptionallyMatchingRegionId implements Supplier<Location> { public class OnlyLocationOrFirstRegionOptionallyMatchingRegionId implements ImplicitLocationSupplier {
private final Supplier<String> regionSupplier;
private final Predicate<Location> locationPredicate;
private final Supplier<Set<? extends Location>> locationsSupplier; private final Supplier<Set<? extends Location>> locationsSupplier;
@Inject @Inject
OnlyLocationOrFirstRegionOptionallyMatchingRegionId(@Nullable @Region String region, OnlyLocationOrFirstRegionOptionallyMatchingRegionId(@Region Supplier<String> regionSupplier,
@Memoized Supplier<Set<? extends Location>> locationsSupplier) { @Memoized Supplier<Set<? extends Location>> locationsSupplier) {
this.locationPredicate = region == null ? Predicates.<Location>or(isZone(), isRegion()) this.regionSupplier = checkNotNull(regionSupplier, "regionSupplier");
: isZoneOrRegionWhereRegionIdEquals(region);
this.locationsSupplier = checkNotNull(locationsSupplier, "locationsSupplier"); this.locationsSupplier = checkNotNull(locationsSupplier, "locationsSupplier");
} }
@Override @Override
@Singleton @Singleton
public Location get() { public Location get() {
String region = regionSupplier.get();
Predicate<Location> locationPredicate = region == null ? Predicates.<Location>or(isZone(), isRegion())
: isZoneOrRegionWhereRegionIdEquals(region);
Set<? extends Location> locations = locationsSupplier.get(); Set<? extends Location> locations = locationsSupplier.get();
if (locationsSupplier.get().size() == 1) if (locationsSupplier.get().size() == 1)
return getOnlyElement(locationsSupplier.get()); return getOnlyElement(locationsSupplier.get());

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.jclouds.location.suppliers; package org.jclouds.location.suppliers.implicit;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Iterables.find;
@ -33,6 +33,7 @@ import javax.inject.Singleton;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.location.functions.ToIdAndScope; import org.jclouds.location.functions.ToIdAndScope;
import org.jclouds.location.suppliers.ImplicitLocationSupplier;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
@ -42,7 +43,7 @@ import com.google.common.base.Supplier;
* *
*/ */
@Singleton @Singleton
public class OnlyLocationOrFirstZone implements Supplier<Location> { public class OnlyLocationOrFirstZone implements ImplicitLocationSupplier {
private final Supplier<Set<? extends Location>> locationsSupplier; private final Supplier<Set<? extends Location>> locationsSupplier;

View File

@ -19,78 +19,44 @@
package org.jclouds.rest; package org.jclouds.rest;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.equalTo;
import static com.google.common.base.Predicates.instanceOf; import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.base.Predicates.not;
import static com.google.common.base.Splitter.on;
import static com.google.common.collect.Iterables.addAll; import static com.google.common.collect.Iterables.addAll;
import static com.google.common.collect.Iterables.any; import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.filter;
import static com.google.inject.Scopes.SINGLETON; import static com.google.inject.Scopes.SINGLETON;
import static com.google.inject.util.Types.newParameterizedType; import static com.google.inject.util.Types.newParameterizedType;
import static org.jclouds.Constants.PROPERTY_API;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_BUILD_VERSION;
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_IDENTITY;
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
import static org.jclouds.Constants.PROPERTY_PROVIDER;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.concurrent.MoreExecutors; import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.concurrent.SingleThreaded; import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.concurrent.config.ConfiguresExecutorService; import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.domain.Credentials;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService; import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.lifecycle.config.LifeCycleModule; import org.jclouds.lifecycle.config.LifeCycleModule;
import org.jclouds.location.Iso3166;
import org.jclouds.location.Provider;
import org.jclouds.location.config.ProvideIso3166CodesByLocationIdViaProperties;
import org.jclouds.logging.config.LoggingModule; import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule; import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.annotations.Api; import org.jclouds.rest.config.BindPropertiesToAnnotations;
import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.BuildVersion;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.rest.config.CredentialStoreModule; import org.jclouds.rest.config.CredentialStoreModule;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rest.config.RestModule; import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.internal.RestContextImpl; import org.jclouds.rest.internal.RestContextImpl;
import org.jclouds.util.Maps2;
import org.nnsoft.guice.rocoto.Rocoto; import org.nnsoft.guice.rocoto.Rocoto;
import org.nnsoft.guice.rocoto.configuration.ConfigurationModule; import org.nnsoft.guice.rocoto.configuration.ConfigurationModule;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ExecutionList; import com.google.common.util.concurrent.ExecutionList;
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;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.Provides;
import com.google.inject.Stage; import com.google.inject.Stage;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -108,115 +74,6 @@ import com.google.inject.TypeLiteral;
* @see RestContext * @see RestContext
*/ */
public class RestContextBuilder<S, A> { public class RestContextBuilder<S, A> {
static class BindPropertiesToAnnotations extends ConfigurationModule {
@Provides
@Singleton
@Named("TIMEOUTS")
protected Map<String, Long> timeouts(Function<Predicate<String>, Map<String, String>> filterStringsBoundByName) {
Map<String, String> stringBoundWithTimeoutPrefix = filterStringsBoundByName.apply(new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.startsWith(PROPERTY_TIMEOUTS_PREFIX);
}
});
Map<String, Long> longsByName = Maps.transformValues(stringBoundWithTimeoutPrefix, new Function<String, Long>() {
@Override
public Long apply(String input) {
return Long.valueOf(String.valueOf(input));
}
});
return Maps2.transformKeys(longsByName, new Function<String, String>() {
@Override
public String apply(String input) {
return input.replaceFirst(PROPERTY_TIMEOUTS_PREFIX, "");
}
});
}
@Provides
@Singleton
@Provider
protected String bindProvider(@Named(PROPERTY_PROVIDER) String in){
return in;
}
@Provides
@Singleton
@Provider
protected URI bindProviderEndpoint(@Named(PROPERTY_ENDPOINT) String in){
return URI.create(in);
}
@Provides
@Singleton
@Iso3166
protected Set<String> bindIsoCodes(@Named(PROPERTY_ISO3166_CODES) String in){
return ImmutableSet.copyOf(filter(on(',').split( in),
not(equalTo(""))));
}
@Provides
@Singleton
@Api
protected String bindApi(@Named(PROPERTY_API) String in){
return in;
}
@Provides
@Singleton
@ApiVersion
protected String bindApiVersion(@Named(PROPERTY_API_VERSION) String in){
return in;
}
@Provides
@Singleton
@BuildVersion
protected String bindBuildVersion(@Named(PROPERTY_BUILD_VERSION) String in){
return in;
}
@Provides
@Singleton
@Identity
protected String bindIdentity(@Named(PROPERTY_IDENTITY) String in){
return in;
}
@Provides
@Singleton
@Credential
@Nullable
protected String bindCredential(ValueOfConfigurationKeyOrNull config){
return config.apply(PROPERTY_CREDENTIAL);
}
@Provides
@Singleton
@Provider
protected Credentials bindProviderCredentials(@Identity String identity, @Nullable @Credential String credential){
return new Credentials(identity, credential);
}
@Override
protected void bindConfigurations() {
bind(new TypeLiteral<Function<Predicate<String>, Map<String, String>>>() {
}).to(FilterStringsBoundToInjectorByName.class);
bind(new TypeLiteral<Map<String, Set<String>>>() {
}).annotatedWith(Iso3166.class).toProvider(ProvideIso3166CodesByLocationIdViaProperties.class);
}
}
protected Properties properties; protected Properties properties;
protected List<Module> modules = new ArrayList<Module>(3); protected List<Module> modules = new ArrayList<Module>(3);
protected Class<A> asyncClientType; protected Class<A> asyncClientType;

View File

@ -0,0 +1,168 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.config;
import static com.google.common.base.Predicates.equalTo;
import static com.google.common.base.Predicates.not;
import static com.google.common.base.Splitter.on;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.Constants.PROPERTY_API;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_BUILD_VERSION;
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_IDENTITY;
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
import static org.jclouds.Constants.PROPERTY_PROVIDER;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.domain.Credentials;
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Iso3166;
import org.jclouds.location.Provider;
import org.jclouds.rest.annotations.Api;
import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.BuildVersion;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.util.Maps2;
import org.nnsoft.guice.rocoto.configuration.ConfigurationModule;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
public class BindPropertiesToAnnotations extends ConfigurationModule {
@Provides
@Singleton
@Named("TIMEOUTS")
protected Map<String, Long> timeouts(Function<Predicate<String>, Map<String, String>> filterStringsBoundByName) {
Map<String, String> stringBoundWithTimeoutPrefix = filterStringsBoundByName.apply(new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.startsWith(PROPERTY_TIMEOUTS_PREFIX);
}
});
Map<String, Long> longsByName = Maps.transformValues(stringBoundWithTimeoutPrefix, new Function<String, Long>() {
@Override
public Long apply(String input) {
return Long.valueOf(String.valueOf(input));
}
});
return Maps2.transformKeys(longsByName, new Function<String, String>() {
@Override
public String apply(String input) {
return input.replaceFirst(PROPERTY_TIMEOUTS_PREFIX, "");
}
});
}
@Provides
@Singleton
@Provider
protected String bindProvider(@Named(PROPERTY_PROVIDER) String in){
return in;
}
@Provides
@Singleton
@Provider
protected URI bindProviderEndpoint(@Named(PROPERTY_ENDPOINT) String in){
return URI.create(in);
}
@Provides
@Singleton
@Iso3166
protected Set<String> bindIsoCodes(@Named(PROPERTY_ISO3166_CODES) String in){
return ImmutableSet.copyOf(filter(on(',').split( in),
not(equalTo(""))));
}
@Provides
@Singleton
@Api
protected String bindApi(@Named(PROPERTY_API) String in){
return in;
}
@Provides
@Singleton
@ApiVersion
protected String bindApiVersion(@Named(PROPERTY_API_VERSION) String in){
return in;
}
@Provides
@Singleton
@BuildVersion
protected String bindBuildVersion(@Named(PROPERTY_BUILD_VERSION) String in){
return in;
}
@Provides
@Singleton
@Identity
protected String bindIdentity(@Named(PROPERTY_IDENTITY) String in){
return in;
}
@Provides
@Singleton
@Credential
@Nullable
protected String bindCredential(ValueOfConfigurationKeyOrNull config){
return config.apply(PROPERTY_CREDENTIAL);
}
@Provides
@Singleton
@Provider
protected Credentials bindProviderCredentials(@Identity String identity, @Nullable @Credential String credential){
return new Credentials(identity, credential);
}
@Override
protected void bindConfigurations() {
bind(new TypeLiteral<Function<Predicate<String>, Map<String, String>>>() {
}).to(FilterStringsBoundToInjectorByName.class);
}
}

View File

@ -18,21 +18,22 @@
*/ */
package org.jclouds.rest.config; package org.jclouds.rest.config;
import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.domain.Credentials;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.internal.ClassMethodArgs; import org.jclouds.internal.ClassMethodArgs;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.config.LocationModule;
import org.jclouds.location.Provider; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl; import org.jclouds.rest.internal.RestContextImpl;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -49,10 +50,13 @@ import com.google.inject.util.Types;
@ConfiguresRestClient @ConfiguresRestClient
@RequiresHttp @RequiresHttp
public class RestClientModule<S, A> extends AbstractModule { public class RestClientModule<S, A> extends AbstractModule {
public final static TypeLiteral<Supplier<URI>> URI_SUPPLIER_TYPE = new TypeLiteral<Supplier<URI>>() {
};
protected final Class<A> asyncClientType; protected final Class<A> asyncClientType;
protected final Class<S> syncClientType; protected final Class<S> syncClientType;
protected final Map<Class<?>, Class<?>> delegates; protected final Map<Class<?>, Class<?>> delegates;
protected final AtomicReference<AuthorizationException> authException = new AtomicReference<AuthorizationException>();
public RestClientModule(Class<S> syncClientType, Class<A> asyncClientType, public RestClientModule(Class<S> syncClientType, Class<A> asyncClientType,
Map<Class<?>, Class<?>> delegates) { Map<Class<?>, Class<?>> delegates) {
@ -66,9 +70,15 @@ public class RestClientModule<S, A> extends AbstractModule {
.<Class<?>, Class<?>> of(syncClientType, asyncClientType)); .<Class<?>, Class<?>> of(syncClientType, asyncClientType));
} }
protected void installLocations() {
install(new LocationModule());
}
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({ "unchecked", "rawtypes" })
@Override @Override
protected void configure() { protected void configure() {
// this will help short circuit scenarios that can otherwise lock out users
bind(new TypeLiteral<AtomicReference<AuthorizationException>>(){}).toInstance(authException);
// Ensures the restcontext can be looked up without generic types. // Ensures the restcontext can be looked up without generic types.
bind(new TypeLiteral<RestContext>() { bind(new TypeLiteral<RestContext>() {
}).to( }).to(
@ -82,6 +92,7 @@ public class RestClientModule<S, A> extends AbstractModule {
bindClient(); bindClient();
bindErrorHandlers(); bindErrorHandlers();
bindRetryHandlers(); bindRetryHandlers();
installLocations();
} }
/** /**

View File

@ -139,6 +139,7 @@ import com.google.common.base.Functions;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
@ -759,7 +760,10 @@ public class RestAnnotationProcessor<T> {
return null; return null;
} }
//TODO: change to LoadingCache<ClassMethodArgs, URI> and move this logic to the CacheLoader. private final static TypeLiteral<Supplier<URI>> uriSupplierLiteral = new TypeLiteral<Supplier<URI>>() {
};
// TODO: change to LoadingCache<ClassMethodArgs, URI> and move this logic to the CacheLoader.
public static URI getEndpointFor(Method method, Object[] args, Injector injector) throws ExecutionException { public static URI getEndpointFor(Method method, Object[] args, Injector injector) throws ExecutionException {
URI endpoint = getEndpointInParametersOrNull(method, args, injector); URI endpoint = getEndpointInParametersOrNull(method, args, injector);
if (endpoint == null) { if (endpoint == null) {
@ -771,17 +775,21 @@ public class RestAnnotationProcessor<T> {
} else { } else {
throw new IllegalStateException("no annotations on class or method: " + method); throw new IllegalStateException("no annotations on class or method: " + method);
} }
endpoint = injector.getInstance(Key.get(URI.class, annotation.value())); endpoint = injector.getInstance(Key.get(uriSupplierLiteral, annotation.value())).get();
} }
return addHostIfMissing(endpoint, injector.getInstance(Key.get(URI.class, org.jclouds.location.Provider.class))); URI providerEndpoint = injector.getInstance(Key.get(uriSupplierLiteral, org.jclouds.location.Provider.class))
.get();
return addHostIfMissing(endpoint, providerEndpoint);
} }
public static URI addHostIfMissing(URI original, URI withHost) { public static URI addHostIfMissing(URI original, URI withHost) {
checkNotNull(withHost,"URI witHost cannot be null"); checkNotNull(withHost, "URI witHost cannot be null");
checkArgument(withHost.getHost()!=null, "URI withHost must have host:"+withHost); checkArgument(withHost.getHost() != null, "URI withHost must have host:" + withHost);
if(original == null) return null; if (original == null)
if (original.getHost() != null) return original; return null;
if (original.getHost() != null)
return original;
return withHost.resolve(original); return withHost.resolve(original);
} }

View File

@ -47,6 +47,11 @@ public class MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<T> imp
private final Supplier<T> delegate; private final Supplier<T> delegate;
private final long seconds; private final long seconds;
public static <T> MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<T> create(
AtomicReference<AuthorizationException> authException, long seconds, Supplier<T> delegate) {
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<T>(authException, seconds, delegate);
}
public MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier( public MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier(
AtomicReference<AuthorizationException> authException, long seconds, Supplier<T> delegate) { AtomicReference<AuthorizationException> authException, long seconds, Supplier<T> delegate) {
this.delegate = memoizeWithExpirationOnAbsoluteInterval(new RetryOnTimeOutExceptionSupplier<T>( this.delegate = memoizeWithExpirationOnAbsoluteInterval(new RetryOnTimeOutExceptionSupplier<T>(

View File

@ -0,0 +1,43 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.suppliers;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import javax.inject.Inject;
import com.google.common.base.Supplier;
public class URIFromStringSupplier implements Supplier<URI> {
private final URI endpoint;
@Inject
protected URIFromStringSupplier(String uri) {
this.endpoint = URI.create(checkNotNull(uri, "uri"));
}
@Override
public URI get() {
return endpoint;
}
}

View File

@ -0,0 +1,64 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.suppliers;
import java.util.Map;
import javax.annotation.Resource;
import org.jclouds.logging.Logger;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
/**
* Allows you to lazy discover a key by value. This is useful for example in service discovery,
* where you need to see what the "current" service name is based on a map of service names to
* endpoints. <h3>note</h3> take care to memoize this using {@link Suppliers#memoize(Supplier)}
*
* @author Adrian Cole
*/
public class SupplyKeyMatchingValueOrNull<K, V> implements Supplier<K> {
@Resource
protected Logger logger = Logger.NULL;
private final Supplier<Map<K, Supplier<V>>> supplier;
private final Supplier<V> valueSupplier;
public SupplyKeyMatchingValueOrNull(Supplier<Map<K, Supplier<V>>> supplier, Supplier<V> valueSupplier) {
this.valueSupplier = valueSupplier;
this.supplier = supplier;
}
@Override
public K get() {
V uri = valueSupplier.get();
// eagerly get all the values, so we can see which is default
Map<K, V> map = Maps.transformValues(supplier.get(), Suppliers.<V> supplierFunction());
K region = ImmutableBiMap.copyOf(map).inverse().get(uri);
if (region == null && map.size() > 0) {
logger.warn("failed to find key for value %s in %s; choosing first: %s", uri, map, region);
region = Iterables.get(map.keySet(), 0);
}
return region;
}
}

View File

@ -41,6 +41,19 @@ import com.google.common.collect.Multimap;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class Maps2 { public class Maps2 {
public static <K> Function<Map<K, ?>, Set<K>> keySetFunction() {
return new Function<Map<K, ?>, Set<K>>() {
@Override
public Set<K> apply(Map<K, ?> arg0) {
return arg0.keySet();
}
public String toString() {
return "keySet()";
}
};
}
public static <K, V> Map<K, V> convertUnsafe(Multimap<K, V> in) { public static <K, V> Map<K, V> convertUnsafe(Multimap<K, V> in) {
LinkedHashMap<K, V> out = Maps.newLinkedHashMap(); LinkedHashMap<K, V> out = Maps.newLinkedHashMap();

View File

@ -26,8 +26,10 @@ import java.io.Serializable;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.io.OutputSupplier; import com.google.common.io.OutputSupplier;
/** /**
@ -36,6 +38,21 @@ import com.google.common.io.OutputSupplier;
*/ */
public class Suppliers2 { public class Suppliers2 {
public static <X> Function<X, Supplier<X>> ofInstanceFunction() {
return new Function<X, Supplier<X>>(){
@Override
public Supplier<X> apply(X arg0) {
return Suppliers.ofInstance(arg0);
}
@Override
public String toString(){
return "Suppliers.ofInstance()";
}
};
}
/** /**
* converts an {@link OutputStream} to an {@link OutputSupplier} * converts an {@link OutputStream} to an {@link OutputSupplier}
* *
@ -52,9 +69,11 @@ public class Suppliers2 {
/** /**
* See Supplier.memoizeWithExpiration. * See Supplier.memoizeWithExpiration.
* *
* Difference between this impl and v11.0 is that we fix http://code.google.com/p/guava-libraries/issues/detail?id=857. * Difference between this impl and v11.0 is that we fix
* http://code.google.com/p/guava-libraries/issues/detail?id=857.
*/ */
public static <T> Supplier<T> memoizeWithExpirationOnAbsoluteInterval(Supplier<T> delegate, long duration, TimeUnit unit) { public static <T> Supplier<T> memoizeWithExpirationOnAbsoluteInterval(Supplier<T> delegate, long duration,
TimeUnit unit) {
return new ExpiringMemoizingSupplier<T>(delegate, duration, unit); return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
} }
@ -86,7 +105,8 @@ public class Suppliers2 {
synchronized (this) { synchronized (this) {
if (nanos == expirationNanos) { // recheck for lost race if (nanos == expirationNanos) { // recheck for lost race
// Set value to null prior to retrieving new val, so old and new are not held in memory simultaneously // Set value to null prior to retrieving new val, so old and new are not held in
// memory simultaneously
value = null; value = null;
T t = delegate.get(); T t = delegate.get();

View File

@ -25,11 +25,13 @@ import static com.google.common.collect.Iterables.find;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import org.jclouds.concurrent.TransformParallelException;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.InsufficientResourcesException; import org.jclouds.rest.InsufficientResourcesException;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Predicate;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.inject.CreationException; import com.google.inject.CreationException;
import com.google.inject.ProvisionException; import com.google.inject.ProvisionException;
@ -42,10 +44,26 @@ import com.google.inject.spi.Message;
*/ */
public class Throwables2 { public class Throwables2 {
public static <T extends Throwable> Predicate<Throwable> containsThrowable(final Class<T> throwableType) {
return new Predicate<Throwable>() {
@Override
public boolean apply(Throwable input) {
return getFirstThrowableOfType(input, throwableType) != null;
}
public String toString() {
return "containsThrowable()";
}
};
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T extends Throwable> T getFirstThrowableOfType(Throwable from, Class<T> clazz) { public static <T extends Throwable> T getFirstThrowableOfType(Throwable from, Class<T> clazz) {
if (from instanceof ProvisionException) if (from instanceof ProvisionException)
return getFirstThrowableOfType(ProvisionException.class.cast(from), clazz); return getFirstThrowableOfType(ProvisionException.class.cast(from), clazz);
else if (from instanceof TransformParallelException)
return getFirstThrowableOfType(TransformParallelException.class.cast(from), clazz);
else if (from instanceof CreationException) else if (from instanceof CreationException)
return getFirstThrowableOfType(CreationException.class.cast(from), clazz); return getFirstThrowableOfType(CreationException.class.cast(from), clazz);
try { try {
@ -55,12 +73,23 @@ public class Throwables2 {
} }
} }
public static <T extends Throwable> T getFirstThrowableOfType(TransformParallelException e, Class<T> clazz) {
for (Exception exception : e.getFromToException().values()) {
T cause = getFirstThrowableOfType(exception, clazz);
if (cause != null)
return cause;
}
return null;
}
public static <T extends Throwable> T getFirstThrowableOfType(ProvisionException e, Class<T> clazz) { public static <T extends Throwable> T getFirstThrowableOfType(ProvisionException e, Class<T> clazz) {
for (Message message : e.getErrorMessages()) { for (Message message : e.getErrorMessages()) {
if (message.getCause() != null) { if (message.getCause() != null) {
T cause = getFirstThrowableOfType(message.getCause(), clazz); T cause = getFirstThrowableOfType(message.getCause(), clazz);
if (cause instanceof ProvisionException) if (cause instanceof ProvisionException)
return getFirstThrowableOfType(ProvisionException.class.cast(cause), clazz); return getFirstThrowableOfType(ProvisionException.class.cast(cause), clazz);
else if (cause instanceof TransformParallelException)
return getFirstThrowableOfType(TransformParallelException.class.cast(cause), clazz);
else if (cause instanceof CreationException) else if (cause instanceof CreationException)
return getFirstThrowableOfType(CreationException.class.cast(cause), clazz); return getFirstThrowableOfType(CreationException.class.cast(cause), clazz);
return cause; return cause;
@ -75,6 +104,8 @@ public class Throwables2 {
T cause = getFirstThrowableOfType(message.getCause(), clazz); T cause = getFirstThrowableOfType(message.getCause(), clazz);
if (cause instanceof ProvisionException) if (cause instanceof ProvisionException)
return getFirstThrowableOfType(ProvisionException.class.cast(cause), clazz); return getFirstThrowableOfType(ProvisionException.class.cast(cause), clazz);
else if (cause instanceof TransformParallelException)
return getFirstThrowableOfType(TransformParallelException.class.cast(cause), clazz);
else if (cause instanceof CreationException) else if (cause instanceof CreationException)
return getFirstThrowableOfType(CreationException.class.cast(cause), clazz); return getFirstThrowableOfType(CreationException.class.cast(cause), clazz);
return cause; return cause;
@ -99,9 +130,10 @@ public class Throwables2 {
return (Exception) throwable; return (Exception) throwable;
} }
} }
for (Class<Exception> propagatableExceptionType : new Class[] { IllegalStateException.class, AssertionError.class, for (Class<Exception> propagatableExceptionType : new Class[] { IllegalStateException.class,
UnsupportedOperationException.class, IllegalArgumentException.class, AuthorizationException.class, AssertionError.class, UnsupportedOperationException.class, IllegalArgumentException.class,
ResourceNotFoundException.class, InsufficientResourcesException.class, HttpResponseException.class }) { AuthorizationException.class, ResourceNotFoundException.class, InsufficientResourcesException.class,
HttpResponseException.class }) {
Throwable throwable = getFirstThrowableOfType(exception, propagatableExceptionType); Throwable throwable = getFirstThrowableOfType(exception, propagatableExceptionType);
if (throwable != null) { if (throwable != null) {
if (throwable instanceof AssertionError) if (throwable instanceof AssertionError)

View File

@ -0,0 +1,249 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.concurrent;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Maps.newHashMap;
import static java.util.concurrent.Executors.newCachedThreadPool;
import static org.jclouds.concurrent.FutureIterables.awaitCompletion;
import static org.testng.Assert.assertEquals;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.jclouds.logging.Logger;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* Tests behavior of FutureIterables
*
* @author Adrian Cole
*/
@Test(groups = "performance", enabled = false, sequential = true, testName = "FutureIterablesPerformanceTest")
public class FutureIterablesPerformanceTest {
ExecutorService ioFunctionExecutor = newCachedThreadPool();
@Test(enabled = false)
public void testMakeListenableDoesntSerializeFutures() throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION;
long expectedMin = IO_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
long start = System.currentTimeMillis();
Map<String, Future<Long>> responses = runCallables(chainExecutor);
checkTimeThresholds(expectedMin, expectedMax, expectedOverhead, start, responses);
}
@Test(enabled = false)
public void testAwaitCompletionUsingSameThreadExecutorDoesntSerializeFutures() throws InterruptedException,
ExecutionException {
long expectedMax = IO_DURATION;
long expectedMin = IO_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
long start = System.currentTimeMillis();
Map<String, Future<Long>> responses = runCallables(chainExecutor);
Map<String, Exception> exceptions = awaitCompletion(responses, MoreExecutors.sameThreadExecutor(), null,
Logger.CONSOLE, "test same thread");
assertEquals(exceptions.size(), 0);
checkTimeThresholds(expectedMin, expectedMax, expectedOverhead, start, responses);
}
@Test(enabled = false)
public void whenCachedThreadPoolIsUsedForChainAndListenerMaxDurationIsSumOfCallableAndListener()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + LISTENER_DURATION;
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT * 4 + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = userthreads;
ExecutorService listenerExecutor = userthreads;
checkThresholdsUsingCompose(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
@Test(enabled = false)
public void whenCachedThreadPoolIsUsedForChainButSameThreadForListenerMaxDurationIsSumOfCallableAndListener()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + LISTENER_DURATION;
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = userthreads;
ExecutorService listenerExecutor = MoreExecutors.sameThreadExecutor();
checkThresholdsUsingCompose(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
@Test(enabled = false)
public void whenSameThreadIsUsedForChainButCachedThreadPoolForListenerMaxDurationIsIOAndSumOfAllListeners()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + (LISTENER_DURATION * COUNT);
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
ExecutorService listenerExecutor = userthreads;
checkThresholdsUsingCompose(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
@Test(enabled = false)
public void whenSameThreadIsUsedForChainAndListenerMaxDurationIsIOAndSumOfAllListeners()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + (LISTENER_DURATION * COUNT);
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
ExecutorService listenerExecutor = MoreExecutors.sameThreadExecutor();
checkThresholdsUsingCompose(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
public static final int FUDGE = 5;
public static final int COUNT = 100;
public static final int IO_DURATION = 50;
public static final int LISTENER_DURATION = 100;
private void checkThresholdsUsingCompose(long expectedMin, long expectedMax, long expectedOverhead,
ExecutorService chainExecutor, final ExecutorService listenerExecutor) {
long start = System.currentTimeMillis();
Map<String, Future<Long>> responses = newHashMap();
for (int i = 0; i < COUNT; i++)
responses.put(i + "", org.jclouds.concurrent.Futures.compose(org.jclouds.concurrent.Futures.makeListenable(
simultateIO(), chainExecutor), new Function<Long, Long>() {
@Override
public Long apply(Long from) {
try {
Thread.sleep(LISTENER_DURATION);
} catch (InterruptedException e) {
propagate(e);
}
return System.currentTimeMillis();
}
}, listenerExecutor));
checkTimeThresholds(expectedMin, expectedMax, expectedOverhead, start, responses);
}
private Map<String, Future<Long>> runCallables(ExecutorService chainExecutor) {
Map<String, Future<Long>> responses = newHashMap();
for (int i = 0; i < COUNT; i++)
responses.put(i + "", org.jclouds.concurrent.Futures.makeListenable(simultateIO(), chainExecutor));
return responses;
}
private Future<Long> simultateIO() {
return ioFunctionExecutor.submit(new Callable<Long>() {
@Override
public Long call() throws Exception {
Thread.sleep(IO_DURATION);
return System.currentTimeMillis();
}
});
}
public static long getMaxIn(Map<String, Future<Long>> responses) {
Iterable<Long> collection = Iterables.transform(responses.values(), new Function<Future<Long>, Long>() {
@Override
public Long apply(Future<Long> from) {
try {
return from.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return null;
}
});
long time = Collections.max(Sets.newHashSet(collection));
return time;
}
public static long getMinIn(Map<String, Future<Long>> responses) {
Iterable<Long> collection = Iterables.transform(responses.values(), new Function<Future<Long>, Long>() {
@Override
public Long apply(Future<Long> from) {
try {
return from.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return null;
}
});
long time = Collections.min(Sets.newHashSet(collection));
return time;
}
private static void checkTimeThresholds(long expectedMin, long expectedMax, long expectedOverhead, long start,
Map<String, Future<Long>> responses) {
long time = getMaxIn(responses) - start;
assert time >= expectedMax && time < expectedMax + expectedOverhead : String.format("expectedMax %d, max %d",
expectedMax, time);
time = getMinIn(responses) - start;
assert time >= expectedMin && time < expectedMin + expectedOverhead : String.format("expectedMin %d, min %d",
expectedMin, time);
time = getMaxIn(responses) - start;
assert time >= expectedMax && time < expectedMax + expectedOverhead : String.format("expectedMax %d, max %d",
expectedMax, time);
}
}

View File

@ -18,232 +18,66 @@
*/ */
package org.jclouds.concurrent; package org.jclouds.concurrent;
import static com.google.common.base.Throwables.propagate; import static org.jclouds.concurrent.FutureIterables.transformParallel;
import static com.google.common.collect.Maps.newHashMap;
import static java.util.concurrent.Executors.newCachedThreadPool;
import static org.jclouds.concurrent.FutureIterables.awaitCompletion;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Iterables; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
/** /**
* Tests behavior of FutureIterables * Tests behavior of FutureIterables
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "performance", enabled = false, sequential = true, testName = "FutureIterablesTest") @Test(groups = "unit", singleThreaded = true, testName = "FutureIterablesTest")
public class FutureIterablesTest { public class FutureIterablesTest {
ExecutorService ioFunctionExecutor = newCachedThreadPool();
@Test(enabled = false) public void testAuthorizationExceptionPropagatesAndOnlyTriesOncePerElement() {
public void testMakeListenableDoesntSerializeFutures() throws InterruptedException, ExecutionException { final AtomicInteger counter = new AtomicInteger();
long expectedMax = IO_DURATION;
long expectedMin = IO_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
long start = System.currentTimeMillis();
Map<String, Future<Long>> responses = runCallables(chainExecutor);
checkTimeThresholds(expectedMin, expectedMax, expectedOverhead, start, responses);
}
@Test(enabled = false)
public void testAwaitCompletionUsingSameThreadExecutorDoesntSerializeFutures() throws InterruptedException,
ExecutionException {
long expectedMax = IO_DURATION;
long expectedMin = IO_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
long start = System.currentTimeMillis();
Map<String, Future<Long>> responses = runCallables(chainExecutor);
Map<String, Exception> exceptions = awaitCompletion(responses, MoreExecutors.sameThreadExecutor(), null,
Logger.CONSOLE, "test same thread");
assertEquals(exceptions.size(), 0);
checkTimeThresholds(expectedMin, expectedMax, expectedOverhead, start, responses);
}
@Test(enabled = false)
public void whenCachedThreadPoolIsUsedForChainAndListenerMaxDurationIsSumOfCallableAndListener()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + LISTENER_DURATION;
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT * 4 + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try { try {
ExecutorService chainExecutor = userthreads; transformParallel(ImmutableSet.of("hello", "goodbye"), new Function<String, Future<String>>() {
ExecutorService listenerExecutor = userthreads;
checkThresholdsUsingCompose(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
@Test(enabled = false)
public void whenCachedThreadPoolIsUsedForChainButSameThreadForListenerMaxDurationIsSumOfCallableAndListener()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + LISTENER_DURATION;
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = userthreads;
ExecutorService listenerExecutor = MoreExecutors.sameThreadExecutor();
checkThresholdsUsingCompose(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
@Test(enabled = false)
public void whenSameThreadIsUsedForChainButCachedThreadPoolForListenerMaxDurationIsIOAndSumOfAllListeners()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + (LISTENER_DURATION * COUNT);
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
ExecutorService listenerExecutor = userthreads;
checkThresholdsUsingCompose(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
@Test(enabled = false)
public void whenSameThreadIsUsedForChainAndListenerMaxDurationIsIOAndSumOfAllListeners()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + (LISTENER_DURATION * COUNT);
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
ExecutorService listenerExecutor = MoreExecutors.sameThreadExecutor();
checkThresholdsUsingCompose(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
public static final int FUDGE = 5;
public static final int COUNT = 100;
public static final int IO_DURATION = 50;
public static final int LISTENER_DURATION = 100;
private void checkThresholdsUsingCompose(long expectedMin, long expectedMax, long expectedOverhead,
ExecutorService chainExecutor, final ExecutorService listenerExecutor) {
long start = System.currentTimeMillis();
Map<String, Future<Long>> responses = newHashMap();
for (int i = 0; i < COUNT; i++)
responses.put(i + "", org.jclouds.concurrent.Futures.compose(org.jclouds.concurrent.Futures.makeListenable(
simultateIO(), chainExecutor), new Function<Long, Long>() {
@Override @Override
public Long apply(Long from) { public Future<String> apply(String input) {
counter.incrementAndGet();
return com.google.common.util.concurrent.Futures.immediateFailedFuture(new AuthorizationException());
}
}, MoreExecutors.sameThreadExecutor(), null, Logger.CONSOLE, "");
assert false;
} catch (AuthorizationException e) {
assertEquals(counter.get(), 2);
}
}
public void testNormalExceptionPropagatesAsTransformParallelExceptionAndTries5XPerElement() {
final AtomicInteger counter = new AtomicInteger();
try { try {
Thread.sleep(LISTENER_DURATION); transformParallel(ImmutableSet.of("hello", "goodbye"), new Function<String, Future<String>>() {
} catch (InterruptedException e) {
propagate(e);
}
return System.currentTimeMillis();
}
}, listenerExecutor));
checkTimeThresholds(expectedMin, expectedMax, expectedOverhead, start, responses);
}
private Map<String, Future<Long>> runCallables(ExecutorService chainExecutor) {
Map<String, Future<Long>> responses = newHashMap();
for (int i = 0; i < COUNT; i++)
responses.put(i + "", org.jclouds.concurrent.Futures.makeListenable(simultateIO(), chainExecutor));
return responses;
}
private Future<Long> simultateIO() {
return ioFunctionExecutor.submit(new Callable<Long>() {
@Override @Override
public Long call() throws Exception { public Future<String> apply(String input) {
Thread.sleep(IO_DURATION); counter.incrementAndGet();
return System.currentTimeMillis(); return com.google.common.util.concurrent.Futures.immediateFailedFuture(new RuntimeException());
} }
}); }, MoreExecutors.sameThreadExecutor(), null, Logger.CONSOLE, "");
assert false;
} catch (TransformParallelException e) {
assertEquals(e.getFromToException().size(), 2);
assertEquals(counter.get(), 10);
} }
public static long getMaxIn(Map<String, Future<Long>> responses) {
Iterable<Long> collection = Iterables.transform(responses.values(), new Function<Future<Long>, Long>() {
@Override
public Long apply(Future<Long> from) {
try {
return from.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return null;
} }
});
long time = Collections.max(Sets.newHashSet(collection));
return time;
}
public static long getMinIn(Map<String, Future<Long>> responses) {
Iterable<Long> collection = Iterables.transform(responses.values(), new Function<Future<Long>, Long>() {
@Override
public Long apply(Future<Long> from) {
try {
return from.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return null;
}
});
long time = Collections.min(Sets.newHashSet(collection));
return time;
}
private static void checkTimeThresholds(long expectedMin, long expectedMax, long expectedOverhead, long start,
Map<String, Future<Long>> responses) {
long time = getMaxIn(responses) - start;
assert time >= expectedMax && time < expectedMax + expectedOverhead : String.format("expectedMax %d, max %d",
expectedMax, time);
time = getMinIn(responses) - start;
assert time >= expectedMin && time < expectedMin + expectedOverhead : String.format("expectedMin %d, min %d",
expectedMin, time);
time = getMaxIn(responses) - start;
assert time >= expectedMax && time < expectedMax + expectedOverhead : String.format("expectedMax %d, max %d",
expectedMax, time);
}
} }

View File

@ -23,10 +23,13 @@ import static org.testng.Assert.assertEquals;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.jclouds.location.suppliers.LocationIdToIso3166CodesSupplier;
import org.jclouds.util.Suppliers2;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -42,14 +45,14 @@ import com.google.inject.Provides;
public class ProvideIso3166CodesByLocationIdViaPropertiesTest { public class ProvideIso3166CodesByLocationIdViaPropertiesTest {
public void testEmptyWhenNoLocationsBound() { public void testEmptyWhenNoLocationsBound() {
ProvideIso3166CodesByLocationIdViaProperties fn = createWithValue(ImmutableMap.<String, String> of()); LocationIdToIso3166CodesSupplier fn = createWithValue(ImmutableMap.<String, String> of());
assertEquals(fn.get(), ImmutableMap.<String, Set<String>> of()); assertEquals(fn.get(), ImmutableMap.<String, Set<String>> of());
} }
public void testEmptyWhenRegionsAndZonesBoundButNoIsoCodes() { public void testEmptyWhenRegionsAndZonesBoundButNoIsoCodes() {
ProvideIso3166CodesByLocationIdViaProperties fn = createWithValue(ImmutableMap.<String, String> of( LocationIdToIso3166CodesSupplier fn = createWithValue(ImmutableMap.<String, String> of(
"jclouds.regions", "us-east", "jclouds.zones", "us-easta")); "jclouds.regions", "us-east", "jclouds.zones", "us-easta"));
assertEquals(fn.get(), ImmutableMap.<String, Set<String>> of()); assertEquals(fn.get(), ImmutableMap.<String, Set<String>> of());
@ -57,20 +60,18 @@ public class ProvideIso3166CodesByLocationIdViaPropertiesTest {
public void testIsoCodesWhenRegionsAndZonesBoundWithIsoCodes() { public void testIsoCodesWhenRegionsAndZonesBoundWithIsoCodes() {
ProvideIso3166CodesByLocationIdViaProperties fn = createWithValue(ImmutableMap.<String, String> of( LocationIdToIso3166CodesSupplier fn = createWithValue(ImmutableMap.<String, String> of(
"jclouds.regions", "us-east", "jclouds.region.us-east.iso3166-codes", "US", "jclouds.zones", "us-easta", "jclouds.regions", "us-east", "jclouds.region.us-east.iso3166-codes", "US", "jclouds.zones", "us-easta",
"jclouds.zone.us-easta.iso3166-codes", "US-CA")); "jclouds.zone.us-easta.iso3166-codes", "US-CA"));
assertEquals( assertEquals(Maps.transformValues(fn.get(), Suppliers.<Set<String>> supplierFunction()), ImmutableMap
fn.get(), .<String, Set<String>> of("us-east", ImmutableSet.of("US"), "us-easta", ImmutableSet.of("US-CA")));
ImmutableMap.<String, Set<String>> of("us-east", ImmutableSet.of("US"), "us-easta",
ImmutableSet.of("US-CA")));
} }
// //
private ProvideIso3166CodesByLocationIdViaProperties createWithValue(final ImmutableMap<String, String> value) { private LocationIdToIso3166CodesSupplier createWithValue(final ImmutableMap<String, String> value) {
ProvideIso3166CodesByLocationIdViaProperties fn = Guice.createInjector(new AbstractModule() { LocationIdToIso3166CodesSupplier fn = Guice.createInjector(new AbstractModule() {
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Provides @Provides
Function<Predicate<String>, Map<String, String>> provide() { Function<Predicate<String>, Map<String, String>> provide() {
@ -87,7 +88,7 @@ public class ProvideIso3166CodesByLocationIdViaPropertiesTest {
protected void configure() { protected void configure() {
} }
}).getInstance(ProvideIso3166CodesByLocationIdViaProperties.class); }).getInstance(LocationIdToIso3166CodesSupplier.class);
return fn; return fn;
} }

View File

@ -22,9 +22,12 @@ import static org.testng.Assert.assertEquals;
import java.io.File; import java.io.File;
import java.net.URI; import java.net.URI;
import java.util.Map;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
/** /**
@ -37,33 +40,34 @@ public class RegionToEndpointOrProviderIfNullTest {
@Test @Test
public void testWhenFindsRegion() throws SecurityException, NoSuchMethodException { public void testWhenFindsRegion() throws SecurityException, NoSuchMethodException {
RegionToEndpointOrProviderIfNull fn = new RegionToEndpointOrProviderIfNull("leader", URI.create("http://leader"), RegionToEndpointOrProviderIfNull fn = new RegionToEndpointOrProviderIfNull("leader", Suppliers.ofInstance(URI
ImmutableMap.of("1", URI.create("http://1"))); .create("http://leader")), Suppliers.<Map<String, Supplier<URI>>>ofInstance(ImmutableMap.of("1", Suppliers.ofInstance(URI.create("http://1")))));
assertEquals(fn.apply("1"), URI.create("http://1")); assertEquals(fn.apply("1"), URI.create("http://1"));
} }
public void testNullReturnsProvider() { public void testNullReturnsProvider() {
RegionToEndpointOrProviderIfNull fn = new RegionToEndpointOrProviderIfNull("leader", URI.create("http://leader"), RegionToEndpointOrProviderIfNull fn = new RegionToEndpointOrProviderIfNull("leader", Suppliers.ofInstance(URI
ImmutableMap.of("1", URI.create("http://1"))); .create("http://leader")), Suppliers.<Map<String, Supplier<URI>>>ofInstance(ImmutableMap.of("1", Suppliers.ofInstance(URI.create("http://1")))));
assertEquals(fn.apply("leader"), URI.create("http://leader")); assertEquals(fn.apply("leader"), URI.create("http://leader"));
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testMustBeString() { public void testMustBeString() {
RegionToEndpointOrProviderIfNull fn = new RegionToEndpointOrProviderIfNull("leader", URI.create("http://leader"), RegionToEndpointOrProviderIfNull fn = new RegionToEndpointOrProviderIfNull("leader", Suppliers.ofInstance(URI
ImmutableMap.of("1", URI.create("http://1"))); .create("http://leader")), Suppliers.<Map<String, Supplier<URI>>>ofInstance(ImmutableMap.of("1", Suppliers.ofInstance(URI.create("http://1")))));
fn.apply(new File("foo")); fn.apply(new File("foo"));
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testMustBeInRegionMapIfSpecified() { public void testMustBeInRegionMapIfSpecified() {
RegionToEndpointOrProviderIfNull fn = new RegionToEndpointOrProviderIfNull("leader", URI.create("http://leader"), RegionToEndpointOrProviderIfNull fn = new RegionToEndpointOrProviderIfNull("leader", Suppliers.ofInstance(URI
ImmutableMap.of("1", URI.create("http://1"))); .create("http://leader")), Suppliers.<Map<String, Supplier<URI>>>ofInstance(ImmutableMap.of("1", Suppliers.ofInstance(URI.create("http://1")))));
fn.apply("2"); fn.apply("2");
} }
public void testOkIfNoRegionMappings() { public void testOkIfNoRegionMappings() {
new RegionToEndpointOrProviderIfNull("leader", URI.create("http://leader"), ImmutableMap.<String, URI> of()); new RegionToEndpointOrProviderIfNull("leader", Suppliers.ofInstance(URI.create("http://leader")), Suppliers
.<Map<String, Supplier<URI>>> ofInstance(ImmutableMap.<String, Supplier<URI>> of()));
} }
} }

View File

@ -22,9 +22,12 @@ import static org.testng.Assert.assertEquals;
import java.io.File; import java.io.File;
import java.net.URI; import java.net.URI;
import java.util.Map;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
/** /**
@ -36,25 +39,30 @@ import com.google.common.collect.ImmutableMap;
public class ZoneToEndpointTest { public class ZoneToEndpointTest {
@Test @Test
public void testCorrect() throws SecurityException, NoSuchMethodException { public void testCorrect() {
ZoneToEndpoint fn = new ZoneToEndpoint(ImmutableMap.of("1", URI.create("http://1"))); ZoneToEndpoint fn = new ZoneToEndpoint(Suppliers.<Map<String, Supplier<URI>>> ofInstance(ImmutableMap.of("1",
Suppliers.ofInstance(URI.create("http://1")))));
assertEquals(fn.apply("1"), URI.create("http://1")); assertEquals(fn.apply("1"), URI.create("http://1"));
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testMustBeString() { public void testMustBeString() {
ZoneToEndpoint fn = new ZoneToEndpoint(ImmutableMap.of("1", URI.create("http://1"))); ZoneToEndpoint fn = new ZoneToEndpoint(Suppliers.<Map<String, Supplier<URI>>> ofInstance(ImmutableMap.of("1",
Suppliers.ofInstance(URI.create("http://1")))));
fn.apply(new File("foo")); fn.apply(new File("foo"));
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalStateException.class)
public void testMustHaveEndpoints() { public void testMustHaveEndpoints() {
new ZoneToEndpoint(ImmutableMap.<String, URI> of()); ZoneToEndpoint fn = new ZoneToEndpoint(Suppliers.<Map<String, Supplier<URI>>> ofInstance(ImmutableMap
.<String, Supplier<URI>> of()));
fn.apply("1");
} }
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testNullIsIllegal() { public void testNullIsIllegal() {
ZoneToEndpoint fn = new ZoneToEndpoint(ImmutableMap.of("1", URI.create("http://1"))); ZoneToEndpoint fn = new ZoneToEndpoint(Suppliers.<Map<String, Supplier<URI>>> ofInstance(ImmutableMap.of("1",
Suppliers.ofInstance(URI.create("http://1")))));
fn.apply(null); fn.apply(null);
} }
} }

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.jclouds.location.suppliers; package org.jclouds.location.suppliers.all;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -24,6 +24,7 @@ import java.net.URI;
import org.jclouds.domain.LocationBuilder; import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.location.suppliers.all.JustProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.jclouds.location.suppliers; package org.jclouds.location.suppliers.implicit;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -53,7 +53,7 @@ public class OnlyLocationOrFirstRegionOptionallyMatchingRegionIdTest {
Supplier<Set<? extends Location>> supplier = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet Supplier<Set<? extends Location>> supplier = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(provider, region, region2, zone)); .<Location> of(provider, region, region2, zone));
OnlyLocationOrFirstRegionOptionallyMatchingRegionId fn = new OnlyLocationOrFirstRegionOptionallyMatchingRegionId( OnlyLocationOrFirstRegionOptionallyMatchingRegionId fn = new OnlyLocationOrFirstRegionOptionallyMatchingRegionId(
"foo", supplier); Suppliers.ofInstance("foo"), supplier);
try { try {
fn.get(); fn.get();
@ -70,7 +70,7 @@ public class OnlyLocationOrFirstRegionOptionallyMatchingRegionIdTest {
Supplier<Set<? extends Location>> supplier = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet Supplier<Set<? extends Location>> supplier = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(provider)); .<Location> of(provider));
OnlyLocationOrFirstRegionOptionallyMatchingRegionId fn = new OnlyLocationOrFirstRegionOptionallyMatchingRegionId( OnlyLocationOrFirstRegionOptionallyMatchingRegionId fn = new OnlyLocationOrFirstRegionOptionallyMatchingRegionId(
null, supplier); Suppliers.<String>ofInstance(null), supplier);
assertEquals(fn.get(), provider); assertEquals(fn.get(), provider);
} }
@ -79,7 +79,7 @@ public class OnlyLocationOrFirstRegionOptionallyMatchingRegionIdTest {
Supplier<Set<? extends Location>> supplier = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet Supplier<Set<? extends Location>> supplier = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(provider, region, region2, zone)); .<Location> of(provider, region, region2, zone));
OnlyLocationOrFirstRegionOptionallyMatchingRegionId fn = new OnlyLocationOrFirstRegionOptionallyMatchingRegionId( OnlyLocationOrFirstRegionOptionallyMatchingRegionId fn = new OnlyLocationOrFirstRegionOptionallyMatchingRegionId(
null, supplier); Suppliers.<String>ofInstance(null), supplier);
assertEquals(fn.get(), region); assertEquals(fn.get(), region);
} }
@ -88,7 +88,7 @@ public class OnlyLocationOrFirstRegionOptionallyMatchingRegionIdTest {
Supplier<Set<? extends Location>> supplier = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet Supplier<Set<? extends Location>> supplier = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(provider, region, region2, zone)); .<Location> of(provider, region, region2, zone));
OnlyLocationOrFirstRegionOptionallyMatchingRegionId fn = new OnlyLocationOrFirstRegionOptionallyMatchingRegionId( OnlyLocationOrFirstRegionOptionallyMatchingRegionId fn = new OnlyLocationOrFirstRegionOptionallyMatchingRegionId(
region2.getId(), supplier); Suppliers.ofInstance(region2.getId()), supplier);
assertEquals(fn.get(), region2); assertEquals(fn.get(), region2);
} }
} }

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.jclouds.location.suppliers; package org.jclouds.location.suppliers.implicit;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -26,6 +26,7 @@ import java.util.Set;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder; import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.location.suppliers.implicit.OnlyLocationOrFirstZone;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;

View File

@ -144,6 +144,8 @@ import org.testng.annotations.Test;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -181,7 +183,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
bind(URI.class).annotatedWith(Localhost2.class).toInstance(URI.create("http://localhost:1111")); bind(new TypeLiteral<Supplier<URI>>() {
}).annotatedWith(Localhost2.class).toInstance(
Suppliers.ofInstance(URI.create("http://localhost:1111")));
bind(IOExceptionRetryHandler.class).toInstance(IOExceptionRetryHandler.NEVER_RETRY); bind(IOExceptionRetryHandler.class).toInstance(IOExceptionRetryHandler.NEVER_RETRY);
} }
@ -2436,7 +2440,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
}).toInstance(ImmutableSet.of("foo")); }).toInstance(ImmutableSet.of("foo"));
bind(new TypeLiteral<Set<String>>() { bind(new TypeLiteral<Set<String>>() {
}).annotatedWith(Names.named("bar")).toInstance(ImmutableSet.of("bar")); }).annotatedWith(Names.named("bar")).toInstance(ImmutableSet.of("bar"));
bind(URI.class).annotatedWith(Localhost2.class).toInstance(URI.create("http://localhost:1111")); bind(new TypeLiteral<Supplier<URI>>() {
}).annotatedWith(Localhost2.class).toInstance(
Suppliers.ofInstance(URI.create("http://localhost:1111")));
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")

View File

@ -26,8 +26,11 @@ import static org.testng.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
import java.net.SocketException; import java.net.SocketException;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.jclouds.concurrent.TransformParallelException;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
@ -36,6 +39,7 @@ import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.inject.CreationException; import com.google.inject.CreationException;
import com.google.inject.ProvisionException; import com.google.inject.ProvisionException;
@ -113,6 +117,38 @@ public class Throwables2Test {
assertEquals(getFirstThrowableOfType(pex, AuthorizationException.class), null); assertEquals(getFirstThrowableOfType(pex, AuthorizationException.class), null);
} }
@SuppressWarnings("unchecked")
public void testGetCauseTransformParallel() {
Exception aex = createMock(AuthorizationException.class);
TransformParallelException pex = new TransformParallelException((Map) ImmutableMap.of(), ImmutableMap.of("bad",
aex), "test");
assertEquals(getFirstThrowableOfType(pex, AuthorizationException.class), aex);
}
@SuppressWarnings("unchecked")
public void testGetFirstThrowableOfTypeInnerTransformParallel() {
Exception aex = createMock(AuthorizationException.class);
TransformParallelException pex = new TransformParallelException((Map) ImmutableMap.of(), ImmutableMap.of("bad",
(Exception) new ExecutionException(aex)), "test");
assertEquals(getFirstThrowableOfType(pex, AuthorizationException.class), aex);
}
@SuppressWarnings("unchecked")
public void testGetFirstThrowableOfTypeOuterTransformParallel() {
Exception aex = createMock(AuthorizationException.class);
TransformParallelException pex = new TransformParallelException((Map) ImmutableMap.of(), ImmutableMap.of("bad",
(Exception) aex), "test");
assertEquals(getFirstThrowableOfType(new ExecutionException(pex), AuthorizationException.class), aex);
}
@SuppressWarnings("unchecked")
public void testGetFirstThrowableOfTypeFailTransformParallel() {
Exception aex = createMock(TimeoutException.class);
TransformParallelException pex = new TransformParallelException((Map) ImmutableMap.of(), ImmutableMap.of("bad",
aex), "test");
assertEquals(getFirstThrowableOfType(pex, AuthorizationException.class), null);
}
@Test @Test
public void testReturnExceptionThatsInList() throws Exception { public void testReturnExceptionThatsInList() throws Exception {
Exception e = new TestException(); Exception e = new TestException();

View File

@ -18,22 +18,7 @@
*/ */
package org.jclouds.loadbalancer.config; package org.jclouds.loadbalancer.config;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
import com.google.common.base.Supplier;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/** /**
* *
@ -41,25 +26,8 @@ import com.google.inject.Provides;
*/ */
public abstract class BaseLoadBalancerServiceContextModule extends AbstractModule { public abstract class BaseLoadBalancerServiceContextModule extends AbstractModule {
protected AtomicReference<AuthorizationException> authException = new AtomicReference<AuthorizationException>();
@Override @Override
protected void configure() { protected void configure() {
} }
@Provides
@Singleton
@Memoized
protected Supplier<Set<? extends Location>> supplyLocationCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
final Supplier<Set<? extends Location>> locationSupplier) {
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Set<? extends Location>>(authException, seconds,
new Supplier<Set<? extends Location>>() {
@Override
public Set<? extends Location> get() {
return locationSupplier.get();
}
});
}
} }

View File

@ -1,92 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.loadbalancer.config;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.OnlyLocationOrFirstRegionOptionallyMatchingRegionId;
import com.google.common.base.Supplier;
import com.google.inject.AbstractModule;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
/**
* @author Adrian Cole
*/
public abstract class BindLoadBalancerSuppliersByClass extends AbstractModule {
@Override
protected void configure() {
bindLocationSupplier(defineLocationSupplier());
bindDefaultLocationSupplier(defineDefaultLocationSupplier());
}
protected Class<? extends Supplier<Set<? extends Location>>> defineLocationSupplier() {
return SupplierOfLocationSet.class;
}
@Singleton
static class SupplierOfLocationSet implements Supplier<Set<? extends Location>> {
private final Set<? extends Location> locations;
@Inject
SupplierOfLocationSet(Set<? extends Location> locations) {
this.locations = locations;
}
@Override
public Set<? extends Location> get() {
return locations;
}
}
protected Class<? extends Supplier<Location>> defineDefaultLocationSupplier() {
return OnlyLocationOrFirstRegionOptionallyMatchingRegionId.class;
}
protected void bindImageSupplier(Class<? extends Supplier<Set<? extends Image>>> clazz) {
bind(new TypeLiteral<Supplier<Set<? extends Image>>>() {
}).to(clazz).in(Scopes.SINGLETON);
}
protected void bindLocationSupplier(Class<? extends Supplier<Set<? extends Location>>> clazz) {
bind(new TypeLiteral<Supplier<Set<? extends Location>>>() {
}).to(clazz).in(Scopes.SINGLETON);
}
protected void bindDefaultLocationSupplier(Class<? extends Supplier<Location>> clazz) {
bind(new TypeLiteral<Supplier<Location>>() {
}).to(clazz).in(Scopes.SINGLETON);
}
protected void bindHardwareSupplier(Class<? extends Supplier<Set<? extends Hardware>>> clazz) {
bind(new TypeLiteral<Supplier<Set<? extends Hardware>>>() {
}).to(clazz).in(Scopes.SINGLETON);
}
}

View File

@ -22,7 +22,6 @@ import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule; import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import org.jclouds.servermanager.Datacenter; import org.jclouds.servermanager.Datacenter;
import org.jclouds.servermanager.Hardware; import org.jclouds.servermanager.Hardware;
import org.jclouds.servermanager.Image; import org.jclouds.servermanager.Image;
@ -35,7 +34,6 @@ import org.jclouds.servermanager.compute.functions.ServerToNodeMetadata;
import org.jclouds.servermanager.compute.strategy.ServerManagerComputeServiceAdapter; import org.jclouds.servermanager.compute.strategy.ServerManagerComputeServiceAdapter;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
/** /**
@ -62,7 +60,7 @@ public class ServerManagerComputeServiceContextModule extends
}).to(ServerManagerHardwareToHardware.class); }).to(ServerManagerHardwareToHardware.class);
bind(new TypeLiteral<Function<Datacenter, Location>>() { bind(new TypeLiteral<Function<Datacenter, Location>>() {
}).to(DatacenterToLocation.class); }).to(DatacenterToLocation.class);
bind(new TypeLiteral<Supplier<Location>>() { // to have the compute service adapter override default locations
}).to(OnlyLocationOrFirstZone.class); install(new LocationsFromComputeServiceAdapterModule<Server, Hardware, Image, Datacenter>(){});
} }
} }