Issue 919: added RegionIdFilter and ZoneIdFilter

This commit is contained in:
Adrian Cole 2012-05-09 18:21:56 -07:00
parent acf1bc2d22
commit 9701d80bbb
8 changed files with 432 additions and 12 deletions

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.location.config;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import java.net.URI;
@ -35,6 +36,8 @@ import org.jclouds.location.Iso3166;
import org.jclouds.location.Provider;
import org.jclouds.location.Region;
import org.jclouds.location.Zone;
import org.jclouds.location.predicates.RegionIdFilter;
import org.jclouds.location.predicates.ZoneIdFilter;
import org.jclouds.location.suppliers.ImplicitLocationSupplier;
import org.jclouds.location.suppliers.ImplicitRegionIdSupplier;
import org.jclouds.location.suppliers.LocationIdToIso3166CodesSupplier;
@ -51,7 +54,10 @@ import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExc
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Sets;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
@ -107,10 +113,36 @@ public class LocationModule extends AbstractModule {
@Singleton
@Region
protected Supplier<Set<String>> regionIdsSupplier(AtomicReference<AuthorizationException> authException,
@Named(PROPERTY_SESSION_INTERVAL) long seconds, RegionIdsSupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds, uncached);
@Named(PROPERTY_SESSION_INTERVAL) long seconds, RegionIdFilter filter, RegionIdsSupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds,
Suppliers.compose(new FilterStrings(filter), uncached));
}
@Provides
@Singleton
@Zone
protected Supplier<Set<String>> zoneIdsSupplier(
AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds,
ZoneIdFilter filter, ZoneIdsSupplier uncached) {
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, seconds,
Suppliers.compose(new FilterStrings(filter), uncached));
}
static class FilterStrings implements Function<Set<String>, Set<String>>{
public final Predicate<String> filter;
public FilterStrings(Predicate<String> filter) {
this.filter = checkNotNull(filter, "filter");
}
@Override
public Set<String> apply(Set<String> input) {
return Sets.filter(input, filter);
}
}
@Provides
@Singleton
@Region
@ -128,15 +160,7 @@ public class LocationModule extends AbstractModule {
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

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.predicates;
import org.jclouds.location.predicates.fromconfig.AnyOrConfiguredRegionId;
import com.google.common.base.Predicate;
import com.google.inject.ImplementedBy;
/**
* Means to constrain regions returned to abstraction calls. Particularly useful
* to whitelist certain regions.
*
* @author Adrian Cole
*/
@ImplementedBy(AnyOrConfiguredRegionId.class)
public interface RegionIdFilter extends Predicate<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.predicates;
import org.jclouds.location.predicates.fromconfig.AnyOrConfiguredZoneId;
import com.google.common.base.Predicate;
import com.google.inject.ImplementedBy;
/**
* Means to constrain zones returned to abstraction calls. Particularly useful
* to whitelist certain zones.
*
* @author Adrian Cole
*/
@ImplementedBy(AnyOrConfiguredZoneId.class)
public interface ZoneIdFilter extends Predicate<String> {
}

View File

@ -0,0 +1,56 @@
/**
* 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.predicates.fromconfig;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.location.predicates.RegionIdFilter;
import org.jclouds.location.suppliers.fromconfig.RegionIdsFromConfiguration;
/**
*
* If there are regions configured in {@link RegionIdsFromConfiguration}, return
* true if that set contains the input param. If there aren't, return true.
*
* @author Adrian Cole
*/
@Singleton
public class AnyOrConfiguredRegionId implements RegionIdFilter {
private RegionIdsFromConfiguration idsInConfigSupplier;
@Inject
protected AnyOrConfiguredRegionId(RegionIdsFromConfiguration idsInConfigSupplier) {
this.idsInConfigSupplier = checkNotNull(idsInConfigSupplier, "idsInConfigSupplier");
}
@Override
public boolean apply(String input) {
Set<String> idsInConfig = idsInConfigSupplier.get();
if (idsInConfig.size() == 0)
return true;
return idsInConfig.contains(input);
}
}

View File

@ -0,0 +1,56 @@
/**
* 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.predicates.fromconfig;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.location.predicates.ZoneIdFilter;
import org.jclouds.location.suppliers.fromconfig.ZoneIdsFromConfiguration;
/**
*
* If there are zones configured in {@link ZoneIdsFromConfiguration}, return
* true if that set contains the input param. If there aren't, return true.
*
* @author Adrian Cole
*/
@Singleton
public class AnyOrConfiguredZoneId implements ZoneIdFilter {
private ZoneIdsFromConfiguration idsInConfigSupplier;
@Inject
protected AnyOrConfiguredZoneId(ZoneIdsFromConfiguration idsInConfigSupplier) {
this.idsInConfigSupplier = checkNotNull(idsInConfigSupplier, "idsInConfigSupplier");
}
@Override
public boolean apply(String input) {
Set<String> idsInConfig = idsInConfigSupplier.get();
if (idsInConfig.size() == 0)
return true;
return idsInConfig.contains(input);
}
}

View File

@ -18,10 +18,12 @@
*/
package org.jclouds.json;
import static com.google.common.base.Objects.equal;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
@ -31,11 +33,17 @@ import java.util.concurrent.atomic.AtomicReference;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.base.Optional;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonParser;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import com.google.inject.TypeLiteral;
/**
@ -75,6 +83,64 @@ public class GsonExperimentsTest {
assertEquals(json2, "[\"hello\",5,{\"name\":\"GREETINGS\",\"source\":\"guest\"}]");
}
public class OptionalTypeAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
Type type = typeToken.getType();
if (typeToken.getRawType() != Optional.class || !(type instanceof ParameterizedType)) {
return null;
}
Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
TypeAdapter<?> elementAdapter = gson.getAdapter(TypeToken.get(elementType));
return (TypeAdapter<T>) newOptionalAdapter(elementAdapter);
}
private <E> TypeAdapter<Optional<E>> newOptionalAdapter(final TypeAdapter<E> elementAdapter) {
return new TypeAdapter<Optional<E>>() {
public void write(JsonWriter out, Optional<E> value) throws IOException {
if (value == null || !value.isPresent()) {
out.nullValue();
return;
}
elementAdapter.write(out, value.get());
}
public Optional<E> read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return Optional.absent();
}
return Optional.of(elementAdapter.read(in));
}
};
}
}
static class OptionalType {
Optional<String> present = Optional.of("hello");
Optional<String> notPresent = Optional.absent();
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof OptionalType) {
final OptionalType other = OptionalType.class.cast(object);
return equal(present, other.present) && equal(notPresent, other.notPresent);
} else {
return false;
}
}
}
public void testPersistOptional() {
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new OptionalTypeAdapterFactory()).create();
String json = gson.toJson(new OptionalType());
assertEquals(json, "{\"present\":\"hello\"}");
assertEquals(gson.fromJson(json, OptionalType.class), new OptionalType());
}
// inspired by
// http://code.google.com/p/google-gson/source/browse/trunk/extras/src/main/java/com/google/gson/extras/examples/rawcollections/RawCollectionsExample.java
public void testRawCollectionsWithParser() {
@ -111,7 +177,7 @@ public class GsonExperimentsTest {
JsonToken token = reader.peek();
for (; token != JsonToken.END_DOCUMENT && nnn(toFind, reader, token, name); token = skipAndPeek(token, reader))
;
T val = gson.<T>fromJson(reader, type);
T val = gson.<T> fromJson(reader, type);
reader.close();
return val;
}

View File

@ -0,0 +1,74 @@
/**
* 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.predicates.fromconfig;
import static org.testng.Assert.assertEquals;
import java.util.Set;
import org.jclouds.location.Provider;
import org.jclouds.location.predicates.RegionIdFilter;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.name.Names;
/**
* Tests behavior of {@code AnyOrConfiguredRegionId}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "AnyOrConfiguredRegionIdTest")
public class AnyOrConfiguredRegionIdTest {
@Test
public void testWithoutConfigAllIdsMatch() {
Set<String> regionIds = ImmutableSet.of("us-east-1", "eu-west-1");
RegionIdFilter filter = Guice.createInjector(new AbstractModule(){
@Override
protected void configure() {
bindConstant().annotatedWith(Provider.class).to("aws-ec2");
}
}).getInstance(AnyOrConfiguredRegionId.class);
assertEquals(Sets.filter(regionIds, filter), ImmutableSet.of("us-east-1", "eu-west-1"));
}
@Test
public void testWithConfigOnlyMatchingIds() {
Set<String> regionIds = ImmutableSet.of("us-east-1", "eu-west-1");
RegionIdFilter filter = Guice.createInjector(new AbstractModule(){
@Override
protected void configure() {
bindConstant().annotatedWith(Provider.class).to("aws-ec2");
bindConstant().annotatedWith(Names.named("jclouds.regions")).to("us-east-1,unknown-1");
}
}).getInstance(AnyOrConfiguredRegionId.class);
assertEquals(Sets.filter(regionIds, filter), ImmutableSet.of("us-east-1"));
}
}

View File

@ -0,0 +1,74 @@
/**
* 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.predicates.fromconfig;
import static org.testng.Assert.assertEquals;
import java.util.Set;
import org.jclouds.location.Provider;
import org.jclouds.location.predicates.ZoneIdFilter;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.name.Names;
/**
* Tests behavior of {@code AnyOrConfiguredZoneId}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "AnyOrConfiguredZoneIdTest")
public class AnyOrConfiguredZoneIdTest {
@Test
public void testWithoutConfigAllIdsMatch() {
Set<String> zoneIds = ImmutableSet.of("us-east-1a", "us-east-1b");
ZoneIdFilter filter = Guice.createInjector(new AbstractModule(){
@Override
protected void configure() {
bindConstant().annotatedWith(Provider.class).to("aws-ec2");
}
}).getInstance(AnyOrConfiguredZoneId.class);
assertEquals(Sets.filter(zoneIds, filter), ImmutableSet.of("us-east-1a", "us-east-1b"));
}
@Test
public void testWithConfigOnlyMatchingIds() {
Set<String> zoneIds = ImmutableSet.of("us-east-1a", "us-east-1b");
ZoneIdFilter filter = Guice.createInjector(new AbstractModule(){
@Override
protected void configure() {
bindConstant().annotatedWith(Provider.class).to("aws-ec2");
bindConstant().annotatedWith(Names.named("jclouds.zones")).to("us-east-1a,us-east-1d");
}
}).getInstance(AnyOrConfiguredZoneId.class);
assertEquals(Sets.filter(zoneIds, filter), ImmutableSet.of("us-east-1a"));
}
}