fix covariance/assignability in RestContext<? extends Client> subclasses

This commit is contained in:
Adrian Cole 2012-04-17 14:47:32 -07:00
parent 98a205b603
commit dab1dd69fc
55 changed files with 259 additions and 194 deletions

View File

@ -50,9 +50,6 @@ import com.google.inject.Provides;
*/
@ConfiguresRestClient
public class AtmosRestClientModule extends RestClientModule<AtmosClient, AtmosAsyncClient> {
public AtmosRestClientModule() {
super(AtmosClient.class, AtmosAsyncClient.class);
}
@Override
protected void configure() {

View File

@ -54,10 +54,6 @@ import com.google.inject.Provides;
@ConfiguresRestClient
public class CloudFilesRestClientModule extends RestClientModule<CloudFilesClient, CloudFilesAsyncClient> {
public CloudFilesRestClientModule() {
super(CloudFilesClient.class, CloudFilesAsyncClient.class);
}
@Provides
@Singleton
CommonSwiftClient provideCommonSwiftClient(CloudFilesClient in) {

View File

@ -73,7 +73,7 @@ public class CloudLoadBalancersRestClientModule extends
.build();
public CloudLoadBalancersRestClientModule() {
super(CloudLoadBalancersClient.class, CloudLoadBalancersAsyncClient.class, DELEGATE_MAP);
super(DELEGATE_MAP);
}
protected void installLocations() {

View File

@ -54,10 +54,6 @@ import com.google.inject.Provides;
@ConfiguresRestClient
public class CloudServersRestClientModule extends RestClientModule<CloudServersClient, CloudServersAsyncClient> {
public CloudServersRestClientModule() {
super(CloudServersClient.class, CloudServersAsyncClient.class);
}
@Override
protected void configure() {
bind(DateAdapter.class).to(Iso8601DateAdapter.class);

View File

@ -57,10 +57,6 @@ import com.google.inject.TypeLiteral;
@ConfiguresRestClient
public class CloudSigmaRestClientModule extends RestClientModule<CloudSigmaClient, CloudSigmaAsyncClient> {
public CloudSigmaRestClientModule() {
super(CloudSigmaClient.class, CloudSigmaAsyncClient.class);
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(CloudSigmaErrorHandler.class);

View File

@ -221,7 +221,7 @@ public class CloudStackRestClientModule extends RestClientModule<CloudStackClien
}
public CloudStackRestClientModule() {
super(CloudStackClient.class, CloudStackAsyncClient.class, DELEGATE_MAP);
super(DELEGATE_MAP);
}
@Override

View File

@ -30,8 +30,5 @@ import org.jclouds.rest.ConfiguresRestClient;
*/
@ConfiguresRestClient
public class CloudWatchRestClientModule extends FormSigningRestClientModule<CloudWatchClient, CloudWatchAsyncClient> {
public CloudWatchRestClientModule() {
super(CloudWatchClient.class, CloudWatchAsyncClient.class);
}
}

View File

@ -63,10 +63,6 @@ import com.google.inject.Provides;
@ConfiguresRestClient
public class DeltacloudRestClientModule extends RestClientModule<DeltacloudClient, DeltacloudAsyncClient> {
public DeltacloudRestClientModule() {
super(DeltacloudClient.class, DeltacloudAsyncClient.class);
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(DeltacloudErrorHandler.class);

View File

@ -62,7 +62,7 @@ public class EC2ApiMetadata extends BaseRestApiMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = 4424763314988423886L;
public static final TypeToken<RestContext<EC2Client, EC2AsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<EC2Client, EC2AsyncClient>>() {
public static final TypeToken<RestContext<? extends EC2Client, ? extends EC2AsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<? extends EC2Client, ? extends EC2AsyncClient>>() {
private static final long serialVersionUID = -5070937833892503232L;
};
@ -103,6 +103,7 @@ public class EC2ApiMetadata extends BaseRestApiMetadata {
.documentation(URI.create("http://docs.amazonwebservices.com/AWSEC2/latest/APIReference"))
.version(EC2AsyncClient.VERSION)
.defaultProperties(EC2ApiMetadata.defaultProperties())
.context(CONTEXT_TOKEN)
.wrapper(EC2ComputeServiceContext.class)
.defaultModules(ImmutableSet.<Class<? extends Module>>of(EC2RestClientModule.class, EC2ResolveImagesModule.class, EC2ComputeServiceContextModule.class));
}

View File

@ -49,6 +49,7 @@ import org.jclouds.location.suppliers.derived.ZoneIdsFromRegionIdToZoneIdsValues
import org.jclouds.rest.ConfiguresRestClient;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
import com.google.inject.Scopes;
/**
@ -59,27 +60,29 @@ import com.google.inject.Scopes;
@ConfiguresRestClient
public class EC2RestClientModule<S extends EC2Client, A extends EC2AsyncClient> extends
WithZonesFormSigningRestClientModule<S, A> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
.put(AMIClient.class, AMIAsyncClient.class)//
.put(ElasticIPAddressClient.class, ElasticIPAddressAsyncClient.class)//
.put(InstanceClient.class, InstanceAsyncClient.class)//
.put(KeyPairClient.class, KeyPairAsyncClient.class)//
.put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)//
.put(WindowsClient.class, WindowsAsyncClient.class)//
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
.build();
.put(AMIClient.class, AMIAsyncClient.class)//
.put(ElasticIPAddressClient.class, ElasticIPAddressAsyncClient.class)//
.put(InstanceClient.class, InstanceAsyncClient.class)//
.put(KeyPairClient.class, KeyPairAsyncClient.class)//
.put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)//
.put(WindowsClient.class, WindowsAsyncClient.class)//
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
.build();
@SuppressWarnings("unchecked")
public EC2RestClientModule() {
this((Class) EC2Client.class, (Class) EC2AsyncClient.class, DELEGATE_MAP);
super((TypeToken) TypeToken.of(EC2Client.class), (TypeToken) TypeToken.of(EC2AsyncClient.class), DELEGATE_MAP);
}
public EC2RestClientModule(Class<S> sync, Class<A> async, Map<Class<?>, Class<?>> delegateMap) {
super(sync, async, delegateMap);
protected EC2RestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType,
Map<Class<?>, Class<?>> sync2Async) {
super(syncClientType, asyncClientType, sync2Async);
}
@Override
protected void installLocations() {
install(new LocationModule());

View File

@ -62,13 +62,9 @@ import com.google.inject.Provides;
*/
@Test(groups = "unit")
public abstract class BaseEC2AsyncClientTest<T> extends BaseAsyncClientTest<T> {
@ConfiguresRestClient
@ConfiguresRestClient
protected static class StubEC2RestClientModule extends EC2RestClientModule<EC2Client, EC2AsyncClient> {
public StubEC2RestClientModule() {
super(EC2Client.class, EC2AsyncClient.class, DELEGATE_MAP);
}
@Provides
@Singleton
LoadingCache<RegionAndName, Image> provide(){

View File

@ -57,10 +57,6 @@ import com.google.inject.TypeLiteral;
@ConfiguresRestClient
public class ElasticStackRestClientModule extends RestClientModule<ElasticStackClient, ElasticStackAsyncClient> {
public ElasticStackRestClientModule() {
super(ElasticStackClient.class, ElasticStackAsyncClient.class);
}
@Override
protected void configure() {
super.configure();

View File

@ -51,7 +51,6 @@ public class NovaRestClientModule extends RestClientModule<NovaClient, NovaAsync
private final OpenStackAuthenticationModule module;
public NovaRestClientModule(OpenStackAuthenticationModule module) {
super(NovaClient.class, NovaAsyncClient.class);
this.module = module;
}

View File

@ -41,10 +41,6 @@ import com.google.inject.Scopes;
@ConfiguresRestClient
public class NovaEC2RestClientModule extends EC2RestClientModule<EC2Client, EC2AsyncClient> {
public NovaEC2RestClientModule() {
super(EC2Client.class, EC2AsyncClient.class, DELEGATE_MAP);
}
@Override
protected void configure() {
super.configure();

View File

@ -78,7 +78,7 @@ public class NovaRestClientModule extends RestClientModule<NovaClient, NovaAsync
.put(KeyPairClient.class, KeyPairAsyncClient.class).build();
public NovaRestClientModule() {
super(NovaClient.class, NovaAsyncClient.class, DELEGATE_MAP);
super(DELEGATE_MAP);
}
@Override

View File

@ -65,7 +65,7 @@ public class S3ApiMetadata extends BaseRestApiMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = 820062881469203616L;
public static final TypeToken<RestContext<S3Client, S3AsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<S3Client, S3AsyncClient>>() {
public static final TypeToken<RestContext<? extends S3Client,? extends S3AsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<? extends S3Client,? extends S3AsyncClient>>() {
private static final long serialVersionUID = -5070937833892503232L;
};
@ -107,6 +107,7 @@ public class S3ApiMetadata extends BaseRestApiMetadata {
.documentation(URI.create("http://docs.amazonwebservices.com/AmazonS3/latest/API"))
.version(S3AsyncClient.VERSION)
.defaultProperties(S3ApiMetadata.defaultProperties())
.context(CONTEXT_TOKEN)
.wrapper(TypeToken.of(S3BlobStoreContext.class))
.defaultModules(ImmutableSet.<Class<? extends Module>>of(S3RestClientModule.class, S3BlobStoreContextModule.class));
}

View File

@ -46,6 +46,7 @@ import org.jclouds.s3.handlers.S3RedirectionRetryHandler;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Maps;
import com.google.common.reflect.TypeToken;
import com.google.inject.Provides;
import com.google.inject.Scopes;
@ -59,11 +60,11 @@ public class S3RestClientModule<S extends S3Client, A extends S3AsyncClient> ext
@SuppressWarnings("unchecked")
public S3RestClientModule() {
this((Class) S3Client.class, (Class) S3AsyncClient.class);
this((TypeToken) TypeToken.of(S3Client.class), (TypeToken) TypeToken.of(S3AsyncClient.class));
}
public S3RestClientModule(Class<S> sync, Class<A> async) {
super(sync, async);
protected S3RestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType) {
super(syncClientType, asyncClientType);
}
@Provides
@ -82,10 +83,10 @@ public class S3RestClientModule<S extends S3Client, A extends S3AsyncClient> ext
@Override
protected void configure() {
super.configure();
install(new S3ObjectModule());
install(new S3ParserModule());
bind(RequestAuthorizeSignature.class).in(Scopes.SINGLETON);
super.configure();
}
@Override

View File

@ -478,13 +478,9 @@ public abstract class S3AsyncClientTest<T extends S3AsyncClient> extends BaseS3A
checkFilters(request);
}
@ConfiguresRestClient
@ConfiguresRestClient
private static final class TestS3RestClientModule extends S3RestClientModule<S3Client, S3AsyncClient> {
public TestS3RestClientModule() {
super(S3Client.class, S3AsyncClient.class);
}
@Override
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return "2009-11-08T15:54:08.897Z";

View File

@ -118,10 +118,6 @@ public class S3BlobRequestSignerTest extends BaseS3AsyncClientTest<S3AsyncClient
@ConfiguresRestClient
private static final class TestS3RestClientModule extends S3RestClientModule<S3Client, S3AsyncClient> {
public TestS3RestClientModule() {
super(S3Client.class, S3AsyncClient.class);
}
@Override
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return "Thu, 05 Jun 2008 16:38:19 GMT";

View File

@ -40,10 +40,6 @@ public abstract class BaseS3ClientExpectTest extends BaseRestClientExpectTest<S3
@ConfiguresRestClient
private static final class TestS3RestClientModule extends S3RestClientModule<S3Client, S3AsyncClient> {
public TestS3RestClientModule() {
super(S3Client.class, S3AsyncClient.class);
}
@Override
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return CONSTANT_DATE;

View File

@ -50,13 +50,11 @@ public class BaseSwiftRestClientModule<S extends CommonSwiftClient, A extends Co
RestClientModule<S, A> {
private final OpenStackAuthenticationModule module;
public BaseSwiftRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
this(new OpenStackAuthenticationModule(), syncClientType, asyncClientType);
public BaseSwiftRestClientModule() {
this(new OpenStackAuthenticationModule());
}
public BaseSwiftRestClientModule(OpenStackAuthenticationModule module, Class<S> syncClientType,
Class<A> asyncClientType) {
super(syncClientType, asyncClientType);
public BaseSwiftRestClientModule(OpenStackAuthenticationModule module) {
this.module = module;
}

View File

@ -35,10 +35,6 @@ import com.google.inject.Provides;
@ConfiguresRestClient
public class SwiftRestClientModule extends BaseSwiftRestClientModule<SwiftClient, SwiftAsyncClient> {
public SwiftRestClientModule() {
super(SwiftClient.class, SwiftAsyncClient.class);
}
@Provides
@Singleton
CommonSwiftClient provideCommonSwiftClient(SwiftClient in) {

View File

@ -67,7 +67,7 @@ public abstract class CommonSwiftClientTest extends BaseAsyncClientTest<SwiftAsy
protected static class TestSwiftRestClientModule extends
BaseSwiftRestClientModule<SwiftClient, SwiftAsyncClient> {
private TestSwiftRestClientModule() {
super(new TestOpenStackAuthenticationModule(), SwiftClient.class, SwiftAsyncClient.class);
super(new TestOpenStackAuthenticationModule());
}
@Provides
@Singleton

View File

@ -144,7 +144,7 @@ public class VCloudRestClientModule extends RestClientModule<VCloudClient, VClou
.build();
public VCloudRestClientModule() {
super(VCloudClient.class, VCloudAsyncClient.class, DELEGATE_MAP);
super(DELEGATE_MAP);
}
@Provides

View File

@ -26,6 +26,7 @@ import org.jclouds.s3.S3Client;
import org.jclouds.s3.config.S3RestClientModule;
import org.jclouds.walrus.WalrusAsyncClient;
import com.google.common.reflect.TypeToken;
import com.google.inject.Provides;
/**
@ -34,9 +35,8 @@ import com.google.inject.Provides;
*/
@ConfiguresRestClient
public class WalrusRestClientModule extends S3RestClientModule<S3Client, WalrusAsyncClient> {
public WalrusRestClientModule() {
super(S3Client.class, WalrusAsyncClient.class);
super(TypeToken.of(S3Client.class), TypeToken.of(WalrusAsyncClient.class));
}
@Provides

View File

@ -31,22 +31,32 @@ import org.jclouds.http.annotation.ServerError;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.reflect.TypeToken;
/**
*
* @author Adrian Cole
*/
@ConfiguresRestClient
public class AWSRestClientModule<S, A> extends RestClientModule<S, A> {
public abstract class AWSRestClientModule<S, A> extends RestClientModule<S, A> {
public AWSRestClientModule(Class<S> syncClientType, Class<A> asyncClientType, Map<Class<?>, Class<?>> delegates) {
super(syncClientType, asyncClientType, delegates);
protected AWSRestClientModule(Map<Class<?>, Class<?>> delegates) {
super(delegates);
}
public AWSRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
protected AWSRestClientModule() {
}
protected AWSRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType) {
super(syncClientType, asyncClientType);
}
protected AWSRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType,
Map<Class<?>, Class<?>> sync2Async) {
super(syncClientType, asyncClientType, sync2Async);
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAWSErrorFromXmlContent.class);

View File

@ -31,6 +31,7 @@ import org.jclouds.date.TimeStamp;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RequestSigner;
import com.google.common.reflect.TypeToken;
import com.google.inject.Provides;
/**
@ -38,17 +39,24 @@ import com.google.inject.Provides;
* @author Adrian Cole
*/
@ConfiguresRestClient
public class FormSigningRestClientModule<S, A> extends AWSRestClientModule<S, A> {
public abstract class FormSigningRestClientModule<S, A> extends AWSRestClientModule<S, A> {
public FormSigningRestClientModule(Class<S> syncClientType, Class<A> asyncClientType,
Map<Class<?>, Class<?>> delegates) {
super(syncClientType, asyncClientType, delegates);
protected FormSigningRestClientModule(Map<Class<?>, Class<?>> delegates) {
super(delegates);
}
public FormSigningRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
protected FormSigningRestClientModule() {
}
protected FormSigningRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType) {
super(syncClientType, asyncClientType);
}
protected FormSigningRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType,
Map<Class<?>, Class<?>> sync2Async) {
super(syncClientType, asyncClientType, sync2Async);
}
@Provides
@TimeStamp
protected String provideTimeStamp(final DateService dateService,

View File

@ -23,21 +23,29 @@ import java.util.Map;
import org.jclouds.rest.ConfiguresRestClient;
import com.google.common.reflect.TypeToken;
/**
*
* @author Adrian Cole
*/
@ConfiguresRestClient
public class WithZonesFormSigningRestClientModule<S, A> extends FormSigningRestClientModule<S, A> {
public WithZonesFormSigningRestClientModule(Class<S> syncClientType, Class<A> asyncClientType,
Map<Class<?>, Class<?>> delegates) {
super(syncClientType, asyncClientType, delegates);
public abstract class WithZonesFormSigningRestClientModule<S, A> extends FormSigningRestClientModule<S, A> {
protected WithZonesFormSigningRestClientModule(Map<Class<?>, Class<?>> delegates) {
super(delegates);
}
public WithZonesFormSigningRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
protected WithZonesFormSigningRestClientModule() {
}
protected WithZonesFormSigningRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType) {
super(syncClientType, asyncClientType);
}
protected WithZonesFormSigningRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType,
Map<Class<?>, Class<?>> sync2Async) {
super(syncClientType, asyncClientType, sync2Async);
}
}

View File

@ -38,6 +38,7 @@ import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.reflect.TypeToken;
import com.google.inject.Provides;
/**
@ -47,8 +48,11 @@ import com.google.inject.Provides;
*/
@ConfiguresRestClient
public class AzureStorageRestClientModule<S, A> extends RestClientModule<S, A> {
protected AzureStorageRestClientModule() {
public AzureStorageRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
}
public AzureStorageRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType) {
super(syncClientType, asyncClientType);
}

View File

@ -39,6 +39,7 @@ import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Injector;
import com.google.inject.Module;
@ -140,8 +141,9 @@ public class SharedKeyLiteAuthenticationTest {
.credentials(ACCOUNT, "credential")
.modules(
ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(),
new AzureStorageRestClientModule<IntegrationTestClient, IntegrationTestAsyncClient>(
IntegrationTestClient.class, IntegrationTestAsyncClient.class))).buildInjector();
new AzureStorageRestClientModule<IntegrationTestClient, IntegrationTestAsyncClient>(TypeToken
.of(IntegrationTestClient.class), TypeToken.of(IntegrationTestAsyncClient.class))))
.buildInjector();
filter = injector.getInstance(SharedKeyLiteAuthentication.class);
}
}

View File

@ -96,13 +96,11 @@ import com.google.inject.TypeLiteral;
public class TerremarkVCloudRestClientModule<S, A> extends RestClientModule<S, A> {
public TerremarkVCloudRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
super(syncClientType, asyncClientType);
public TerremarkVCloudRestClientModule() {
}
public TerremarkVCloudRestClientModule(Class<S> syncClientType, Class<A> asyncClientType,
Map<Class<?>, Class<?>> delegateMap) {
super(syncClientType, asyncClientType, delegateMap);
public TerremarkVCloudRestClientModule(Map<Class<?>, Class<?>> delegateMap) {
super(delegateMap);
}
@Override

View File

@ -68,6 +68,8 @@ import org.jclouds.rest.config.BindPropertiesToAnnotations;
import org.jclouds.rest.config.CredentialStoreModule;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.internal.BaseRestApiMetadata;
import org.jclouds.rest.internal.RestContextImpl;
import org.nnsoft.guice.rocoto.Rocoto;
import org.nnsoft.guice.rocoto.configuration.ConfigurationModule;
@ -93,6 +95,7 @@ import com.google.inject.Module;
import com.google.inject.Provides;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Types;
/**
* Creates {@link RestContext} or {@link Injector} instances based on the most commonly requested
@ -109,6 +112,37 @@ import com.google.inject.TypeLiteral;
*/
public final class ContextBuilder {
static class ResolveRestContextModule extends AbstractModule {
private final RestApiMetadata restApiMetadata;
ResolveRestContextModule(RestApiMetadata restApiMetadata) {
this.restApiMetadata = restApiMetadata;
}
@SuppressWarnings("unchecked")
@Override
protected void configure() {
if (restApiMetadata.getContext().getRawType().equals(RestContext.class)) {
TypeToken concreteType = BaseRestApiMetadata.contextToken(TypeToken.of(restApiMetadata.getApi()), TypeToken
.of(restApiMetadata.getAsyncApi()));
// bind explicit type
bind(TypeLiteral.get(concreteType.getType())).to(
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(RestContextImpl.class, restApiMetadata
.getApi(), restApiMetadata.getAsyncApi())));
// bind potentially wildcard type
if (!concreteType.equals(restApiMetadata.getContext())) {
bind(TypeLiteral.get(restApiMetadata.getContext().getType())).to(
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(RestContextImpl.class, restApiMetadata
.getApi(), restApiMetadata.getAsyncApi())));
}
// bind w/o types
bind(TypeLiteral.get(RestContext.class)).to(
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(RestContextImpl.class, restApiMetadata
.getApi(), restApiMetadata.getAsyncApi())));
}
}
}
private final class BindDefaultContextQualifiedToProvider extends AbstractModule {
@Override
protected void configure() {
@ -301,6 +335,7 @@ public final class ContextBuilder {
Iterable<Module> defaultModules = ifSpecifiedByUserDontIncludeDefaultRestModule(restModuleSpecifiedByUser);
Iterables.addAll(modules, defaultModules);
addClientModuleIfNotPresent(modules);
addRestContextBinding();
addLoggingModuleIfNotPresent(modules);
addHttpModuleIfNeededAndNotPresent(modules);
addExecutorServiceIfNotPresent(modules);
@ -314,6 +349,12 @@ public final class ContextBuilder {
return returnVal;
}
void addRestContextBinding() {
if (apiMetadata instanceof RestApiMetadata) {
modules.add(new ResolveRestContextModule(RestApiMetadata.class.cast(apiMetadata)));
}
}
private Iterable<Module> ifSpecifiedByUserDontIncludeDefaultRestModule(boolean restModuleSpecifiedByUser) {
Iterable<Module> defaultModules = Iterables.transform(apiMetadata.getDefaultModules(),
new Function<Class<? extends Module>, Module>() {
@ -384,8 +425,8 @@ public final class ContextBuilder {
protected void addClientModule(List<Module> modules) {
// TODO: move this up
if (apiMetadata instanceof RestApiMetadata) {
final RestApiMetadata rest = RestApiMetadata.class.cast(apiMetadata);
modules.add(new RestClientModule(rest.getApi(), rest.getAsyncApi()));
RestApiMetadata rest = RestApiMetadata.class.cast(apiMetadata);
modules.add(new RestClientModule(TypeToken.of(rest.getApi()), TypeToken.of(rest.getAsyncApi())));
} else {
modules.add(new RestModule());
}

View File

@ -21,13 +21,10 @@ package org.jclouds.rest.config;
import java.util.Map;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl;
import org.jclouds.util.TypeTokens2;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Types;
import com.google.common.reflect.TypeToken;
/**
*
@ -35,50 +32,65 @@ import com.google.inject.util.Types;
*/
@ConfiguresRestClient
public class RestClientModule<S, A> extends RestModule {
protected final Class<A> asyncClientType;
protected final Class<S> syncClientType;
protected final TypeToken<S> syncClientType;
protected final TypeToken<A> asyncClientType;
public RestClientModule(Class<S> syncClientType, Class<A> asyncClientType,
Map<Class<?>, Class<?>> sync2Async) {
/**
* Note that this ctor requires that you instantiate w/resolved generic params. For example, via
* a subclass of a bound type, or natural instantiation w/resolved type params.
*/
protected RestClientModule(Map<Class<?>, Class<?>> sync2Async) {
super(sync2Async);
this.asyncClientType = asyncClientType;
this.syncClientType = syncClientType;
this.syncClientType = TypeTokens2.checkBound(new TypeToken<S>(getClass()) {
private static final long serialVersionUID = 7519656925453755752L;
});
this.asyncClientType = TypeTokens2.checkBound(new TypeToken<A>(getClass()) {
private static final long serialVersionUID = -4420015967358511548L;
});
}
public RestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
this(syncClientType, asyncClientType, ImmutableMap
.<Class<?>, Class<?>> of(syncClientType, asyncClientType));
/**
* @see #RestClientModule(Map)
*/
protected RestClientModule() {
this(ImmutableMap.<Class<?>, Class<?>> of());
}
/**
* @see #RestClientModule(TypeToken, TypeToken, Map)
*/
public RestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType) {
this(syncClientType, asyncClientType, ImmutableMap.<Class<?>, Class<?>> of());
}
/**
* only necessary when type params are not resolvable at runtime.
*/
public RestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType, Map<Class<?>, Class<?>> sync2Async) {
super(sync2Async);
this.syncClientType = TypeTokens2.checkBound(syncClientType);
this.asyncClientType = TypeTokens2.checkBound(asyncClientType);
}
@SuppressWarnings( { "unchecked", "rawtypes" })
@Override
protected void configure() {
super.configure();
// Ensures the restcontext can be looked up without generic types.
bind(new TypeLiteral<RestContext>() {
}).to(
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(
RestContextImpl.class, syncClientType, asyncClientType))).in(
Scopes.SINGLETON);
bind(TypeLiteral.get(Types.newParameterizedType(RestContext.class, syncClientType, asyncClientType))).to(
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(RestContextImpl.class, syncClientType,
asyncClientType))).in(Scopes.SINGLETON);
bindAsyncClient();
bindClient();
bindErrorHandlers();
bindRetryHandlers();
}
/**
* overrides this to change the default retry handlers for the http engine
*
* ex.
*
* <pre>
* bind(HttpRetryHandler.class).annotatedWith(Redirection.class).to(
* AWSRedirectionRetryHandler.class);
* bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(
* AWSClientErrorRetryHandler.class);
* bind(HttpRetryHandler.class).annotatedWith(Redirection.class).to(AWSRedirectionRetryHandler.class);
* bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(AWSClientErrorRetryHandler.class);
* </pre>
*
*/
@ -91,12 +103,9 @@ public class RestClientModule<S, A> extends RestModule {
* ex.
*
* <pre>
* bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
* ParseAWSErrorFromXmlContent.class);
* bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
* ParseAWSErrorFromXmlContent.class);
* bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
* ParseAWSErrorFromXmlContent.class);
* bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAWSErrorFromXmlContent.class);
* bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseAWSErrorFromXmlContent.class);
* bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseAWSErrorFromXmlContent.class);
* </pre>
*
*
@ -105,12 +114,11 @@ public class RestClientModule<S, A> extends RestModule {
}
protected void bindAsyncClient() {
BinderUtils.bindAsyncClient(binder(), asyncClientType);
BinderUtils.bindAsyncClient(binder(), asyncClientType.getRawType());
}
protected void bindClient() {
BinderUtils.bindClient(binder(), syncClientType, asyncClientType,
sync2Async);
BinderUtils.bindClient(binder(), syncClientType.getRawType(), asyncClientType.getRawType(), sync2Async);
}
}

View File

@ -67,6 +67,14 @@ public class BaseRestApiMetadata extends BaseApiMetadata implements RestApiMetad
return props;
}
public static <S, A> TypeToken<RestContext<S, A>> contextToken(TypeToken<S> apiToken, TypeToken<A> asyncApiToken) {
return new TypeToken<RestContext<S, A>>() {
private static final long serialVersionUID = 1L;
}.where(new TypeParameter<S>() {
}, apiToken).where(new TypeParameter<A>() {
}, asyncApiToken);
}
public static class Builder extends BaseApiMetadata.Builder implements RestApiMetadata.Builder {
protected Class<?> api;
protected Class<?> asyncApi;
@ -81,14 +89,6 @@ public class BaseRestApiMetadata extends BaseApiMetadata implements RestApiMetad
.defaultProperties(BaseRestApiMetadata.defaultProperties());
}
protected <S, A> TypeToken<RestContext<S, A>> contextToken(TypeToken<S> apiToken, TypeToken<A> asyncApiToken) {
return new TypeToken<RestContext<S, A>>() {
private static final long serialVersionUID = 1L;
}.where(new TypeParameter<S>() {
}, apiToken).where(new TypeParameter<A>() {
}, asyncApiToken);
}
/**
* {@inheritDoc}
*/

View File

@ -0,0 +1,40 @@
/**
* 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.util;
import static com.google.common.base.Preconditions.checkState;
import java.lang.reflect.TypeVariable;
import com.google.common.reflect.TypeToken;
/**
*
* @author Adrian Cole
*/
public class TypeTokens2 {
/**
* @throws IllegalStateException if the type is an instanceof {@link TypeVariable}
*/
public static <T> TypeToken<T> checkBound(TypeToken<T> type) throws IllegalStateException {
checkState(!(type.getType() instanceof TypeVariable<?>),
"unbound type variable: %s, use ctor that explicitly assigns this", type);
return type;
}
}

View File

@ -54,7 +54,7 @@ import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.sun.jersey.api.uri.UriBuilderImpl;
@Test(groups = "unit")
@Test(groups = "unit", testName = "BackoffLimitedRetryHandlerTest")
public class BackoffLimitedRetryHandlerTest {
BackoffLimitedRetryHandler handler = new BackoffLimitedRetryHandler();

View File

@ -176,7 +176,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
@ConfiguresRestClient
protected static class CallerModule extends RestClientModule<Caller, AsyncCaller> {
CallerModule() {
super(Caller.class, AsyncCaller.class, ImmutableMap.<Class<?>, Class<?>> of(Callee.class, AsyncCallee.class, Callee2.class, AsyncCallee2.class));
super(ImmutableMap.<Class<?>, Class<?>> of(Callee.class, AsyncCallee.class, Callee2.class, AsyncCallee2.class));
}
@Override

View File

@ -30,8 +30,5 @@ import org.jclouds.rest.ConfiguresRestClient;
*/
@ConfiguresRestClient
public class ELBRestClientModule extends FormSigningRestClientModule<ELBClient, ELBAsyncClient> {
public ELBRestClientModule() {
super(ELBClient.class, ELBAsyncClient.class);
}
}

View File

@ -64,7 +64,7 @@ public class GleSYSRestClientModule extends RestClientModule<GleSYSClient, GleSY
.build();
public GleSYSRestClientModule() {
super(GleSYSClient.class, GleSYSAsyncClient.class, DELEGATE_MAP);
super(DELEGATE_MAP);
}
@Override

View File

@ -56,7 +56,7 @@ public class OpSourceServersRestClientModule extends
.build();
public OpSourceServersRestClientModule() {
super(OpSourceServersClient.class, OpSourceServersAsyncClient.class, DELEGATE_MAP);
super(DELEGATE_MAP);
}
@Override

View File

@ -147,7 +147,7 @@ public class VPDCRestClientModule extends RestClientModule<VPDCClient, VPDCAsync
.build();
public VPDCRestClientModule() {
super(VPDCClient.class, VPDCAsyncClient.class, DELEGATE_MAP);
super(DELEGATE_MAP);
}
@Singleton

View File

@ -152,7 +152,7 @@ public class VCloudDirectorRestClientModule extends RestClientModule<VCloudDirec
}
public VCloudDirectorRestClientModule() {
super(VCloudDirectorClient.class, VCloudDirectorAsyncClient.class, ADMIN_DELEGATE_MAP);
super(ADMIN_DELEGATE_MAP);
}
@Override

View File

@ -82,6 +82,7 @@ public class AWSEC2ApiMetadata extends EC2ApiMetadata {
.version(AWSEC2AsyncClient.VERSION)
.name("Amazon-specific EC2 API")
.wrapper(AWSEC2ComputeServiceContext.class)
.context(CONTEXT_TOKEN)
.defaultProperties(AWSEC2ApiMetadata.defaultProperties())
.defaultModules(ImmutableSet.<Class<? extends Module>>of(AWSEC2RestClientModule.class, EC2ResolveImagesModule.class, AWSEC2ComputeServiceContextModule.class));
}

View File

@ -64,6 +64,7 @@ import org.jclouds.ec2.services.WindowsClient;
import org.jclouds.rest.ConfiguresRestClient;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
import com.google.inject.Provides;
/**
@ -90,7 +91,7 @@ public class AWSEC2RestClientModule extends EC2RestClientModule<AWSEC2Client, AW
.build();
public AWSEC2RestClientModule() {
super(AWSEC2Client.class, AWSEC2AsyncClient.class, DELEGATE_MAP);
super(TypeToken.of(AWSEC2Client.class), TypeToken.of(AWSEC2AsyncClient.class), DELEGATE_MAP);
}
@Singleton

View File

@ -28,11 +28,13 @@ import java.util.Properties;
import java.util.Set;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
import org.jclouds.aws.ec2.reference.AWSEC2Constants;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.Template;
import org.jclouds.ec2.EC2ApiMetadata;
import org.jclouds.ec2.compute.EC2TemplateBuilderLiveTest;
import org.jclouds.ec2.compute.predicates.EC2ImagePredicates;
import org.jclouds.ec2.domain.InstanceType;
@ -366,6 +368,12 @@ public class AWSEC2TemplateBuilderLiveTest extends EC2TemplateBuilderLiveTest {
assertEquals(defaultTemplate.getImage().getId(), imageId);
}
@Test
public void testAssignability() {
context.unwrap(EC2ApiMetadata.CONTEXT_TOKEN);
context.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN);
}
@Override
protected Set<String> getIso3166Codes() {
return ImmutableSet.<String> of("US-VA", "US-CA", "US-OR", "BR-SP", "IE", "SG", "JP-13");

View File

@ -73,6 +73,7 @@ public class AWSS3ApiMetadata extends S3ApiMetadata {
id("aws-s3")
.name("Amazon-specific S3 API")
.defaultProperties(AWSS3ApiMetadata.defaultProperties())
.context(CONTEXT_TOKEN)
.wrapper(TypeToken.of(AWSS3BlobStoreContext.class))
.defaultModules(ImmutableSet.<Class<? extends Module>>of(AWSS3RestClientModule.class, AWSS3BlobStoreContextModule.class));
}

View File

@ -41,6 +41,7 @@ import org.jclouds.s3.config.S3RestClientModule;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.reflect.TypeToken;
import com.google.inject.Provides;
/**
@ -51,6 +52,10 @@ import com.google.inject.Provides;
@ConfiguresRestClient
public class AWSS3RestClientModule extends S3RestClientModule<AWSS3Client, AWSS3AsyncClient> {
public AWSS3RestClientModule() {
super(TypeToken.of(AWSS3Client.class), TypeToken.of(AWSS3AsyncClient.class));
}
@Override
protected Supplier<String> defaultRegionForBucket(@Region Supplier<String> defaultRegion) {
return Suppliers.ofInstance(US_STANDARD);
@ -69,10 +74,6 @@ public class AWSS3RestClientModule extends S3RestClientModule<AWSS3Client, AWSS3
return Suppliers.ofInstance(URI.create(endpoint));
}
public AWSS3RestClientModule() {
super(AWSS3Client.class, AWSS3AsyncClient.class);
}
@Singleton
@Provides
S3Client provide(AWSS3Client in) {

View File

@ -36,10 +36,6 @@ import org.jclouds.rest.ConfiguresRestClient;
@ConfiguresRestClient
public class AzureBlobRestClientModule extends AzureStorageRestClientModule<AzureBlobClient, AzureBlobAsyncClient> {
public AzureBlobRestClientModule() {
super(AzureBlobClient.class, AzureBlobAsyncClient.class);
}
@Override
protected void configure() {
install(new AzureBlobModule());

View File

@ -71,7 +71,7 @@ public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGri
.build();
public GoGridRestClientModule() {
super(GoGridClient.class, GoGridAsyncClient.class, DELEGATE_MAP);
super(DELEGATE_MAP);
}
@Provides

View File

@ -67,7 +67,7 @@ public class HPCloudObjectStorageRestClientModule extends
HPCloudCDNClient.class, HPCloudCDNAsyncClient.class).build();
public HPCloudObjectStorageRestClientModule() {
super(HPCloudObjectStorageClient.class, HPCloudObjectStorageAsyncClient.class, DELEGATE_MAP);
super(DELEGATE_MAP);
}
protected void configure() {

View File

@ -48,10 +48,6 @@ import com.google.inject.Scopes;
@ConfiguresRestClient
public class RimuHostingRestClientModule extends RestClientModule<RimuHostingClient, RimuHostingAsyncClient> {
public RimuHostingRestClientModule() {
super(RimuHostingClient.class, RimuHostingAsyncClient.class);
}
@Override
protected void configure() {
bind(DateAdapter.class).to(RimuIso8601DateAdapter.class);

View File

@ -35,10 +35,6 @@ import org.jclouds.slicehost.handlers.ParseSlicehostErrorFromHttpResponse;
@ConfiguresRestClient
public class SlicehostRestClientModule extends RestClientModule<SlicehostClient, SlicehostAsyncClient> {
public SlicehostRestClientModule() {
super(SlicehostClient.class, SlicehostAsyncClient.class);
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseSlicehostErrorFromHttpResponse.class);

View File

@ -62,7 +62,7 @@ public class SoftLayerRestClientModule extends RestClientModule<SoftLayerClient,
.build();
public SoftLayerRestClientModule() {
super(SoftLayerClient.class, SoftLayerAsyncClient.class, DELEGATE_MAP);
super(DELEGATE_MAP);
}
@Override

View File

@ -61,7 +61,7 @@ public class TerremarkECloudRestClientModule extends
.build();
public TerremarkECloudRestClientModule() {
super(TerremarkECloudClient.class, TerremarkECloudAsyncClient.class, DELEGATE_MAP);
super(DELEGATE_MAP);
}
@Provides

View File

@ -39,10 +39,6 @@ import com.google.inject.Provides;
public class TerremarkVCloudExpressRestClientModule extends
TerremarkVCloudRestClientModule<TerremarkVCloudExpressClient, TerremarkVCloudExpressAsyncClient> {
public TerremarkVCloudExpressRestClientModule() {
super(TerremarkVCloudExpressClient.class, TerremarkVCloudExpressAsyncClient.class);
}
@Provides
@Singleton
protected TerremarkVCloudAsyncClient provideVCloudAsyncClient(TerremarkVCloudExpressAsyncClient in) {