1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.jclouds.rest.config;
20
21 import javax.inject.Named;
22 import javax.inject.Singleton;
23 import javax.ws.rs.core.UriBuilder;
24
25 import org.jclouds.functions.IdentityFunction;
26 import org.jclouds.http.HttpRequest;
27 import org.jclouds.http.HttpResponse;
28 import org.jclouds.http.TransformingHttpCommand;
29 import org.jclouds.http.TransformingHttpCommandExecutorService;
30 import org.jclouds.http.TransformingHttpCommandImpl;
31 import org.jclouds.http.functions.config.SaxParserModule;
32 import org.jclouds.internal.ClassMethodArgs;
33 import org.jclouds.json.config.GsonModule;
34 import org.jclouds.rest.AsyncClientFactory;
35 import org.jclouds.rest.HttpAsyncClient;
36 import org.jclouds.rest.HttpClient;
37 import org.jclouds.rest.binders.BindToJsonPayloadWrappedWith;
38 import org.jclouds.rest.internal.AsyncRestClientProxy;
39 import org.jclouds.rest.internal.RestAnnotationProcessor;
40 import org.jclouds.rest.internal.SeedAnnotationCache;
41
42 import com.google.common.base.Function;
43 import com.google.common.cache.Cache;
44 import com.google.common.cache.CacheBuilder;
45 import com.google.common.cache.CacheLoader;
46 import com.google.common.collect.ImmutableMap;
47 import com.google.inject.AbstractModule;
48 import com.google.inject.Inject;
49 import com.google.inject.Injector;
50 import com.google.inject.Key;
51 import com.google.inject.Provides;
52 import com.google.inject.Scopes;
53 import com.google.inject.TypeLiteral;
54 import com.google.inject.assistedinject.FactoryModuleBuilder;
55 import com.google.inject.name.Names;
56 import com.google.inject.util.Types;
57 import com.sun.jersey.api.uri.UriBuilderImpl;
58
59
60
61
62
63 public class RestModule extends AbstractModule {
64
65 @Override
66 protected void configure() {
67 install(new SaxParserModule());
68 install(new GsonModule());
69 install(new FactoryModuleBuilder().build(BindToJsonPayloadWrappedWith.Factory.class));
70 bind(IdentityFunction.class).toInstance(IdentityFunction.INSTANCE);
71 bind(UriBuilder.class).to(UriBuilderImpl.class);
72 bind(AsyncRestClientProxy.Factory.class).to(Factory.class).in(Scopes.SINGLETON);
73 BinderUtils.bindAsyncClient(binder(), HttpAsyncClient.class);
74 BinderUtils.bindClient(binder(), HttpClient.class, HttpAsyncClient.class, ImmutableMap.<Class<?>, Class<?>> of(
75 HttpClient.class, HttpAsyncClient.class));
76 }
77
78 @Provides
79 @Singleton
80 protected Cache<Class<?>, Boolean> seedAnnotationCache(SeedAnnotationCache seedAnnotationCache) {
81 return CacheBuilder.newBuilder().build(seedAnnotationCache);
82 }
83
84 @Provides
85 @Singleton
86 @Named("async")
87 Cache<ClassMethodArgs, Object> provideAsyncDelegateMap(CreateAsyncClientForCaller createAsyncClientForCaller) {
88 return CacheBuilder.newBuilder().build(createAsyncClientForCaller);
89 }
90
91 static class CreateAsyncClientForCaller extends CacheLoader<ClassMethodArgs, Object> {
92 private final Injector injector;
93 private final AsyncRestClientProxy.Factory factory;
94
95 @Inject
96 CreateAsyncClientForCaller(Injector injector, AsyncRestClientProxy.Factory factory) {
97 this.injector = injector;
98 this.factory = factory;
99 }
100
101 @SuppressWarnings( { "unchecked", "rawtypes" })
102 @Override
103 public Object load(final ClassMethodArgs from) {
104 Class clazz = from.getAsyncClass();
105 TypeLiteral typeLiteral = TypeLiteral.get(clazz);
106 RestAnnotationProcessor util = (RestAnnotationProcessor) injector.getInstance(Key.get(TypeLiteral.get(Types
107 .newParameterizedType(RestAnnotationProcessor.class, clazz))));
108
109
110 util.setCaller(from);
111 Cache<ClassMethodArgs, Object> delegateMap = injector.getInstance(Key.get(
112 new TypeLiteral<Cache<ClassMethodArgs, Object>>() {
113 }, Names.named("async")));
114 AsyncRestClientProxy proxy = new AsyncRestClientProxy(injector, factory, util, typeLiteral, delegateMap);
115 injector.injectMembers(proxy);
116 return AsyncClientFactory.create(clazz, proxy);
117 }
118 }
119
120 private static class Factory implements AsyncRestClientProxy.Factory {
121 @Inject
122 private TransformingHttpCommandExecutorService executorService;
123
124 @SuppressWarnings( { "unchecked", "rawtypes" })
125 @Override
126 public TransformingHttpCommand<?> create(HttpRequest request, Function<HttpResponse, ?> transformer) {
127 return new TransformingHttpCommandImpl(executorService, request, transformer);
128 }
129
130 }
131
132 }