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 java.util.concurrent.ConcurrentMap;
22
23 import javax.inject.Named;
24 import javax.inject.Singleton;
25 import javax.ws.rs.core.UriBuilder;
26
27 import org.jclouds.functions.IdentityFunction;
28 import org.jclouds.http.HttpRequest;
29 import org.jclouds.http.HttpResponse;
30 import org.jclouds.http.TransformingHttpCommand;
31 import org.jclouds.http.TransformingHttpCommandExecutorService;
32 import org.jclouds.http.TransformingHttpCommandImpl;
33 import org.jclouds.http.functions.config.SaxParserModule;
34 import org.jclouds.internal.ClassMethodArgs;
35 import org.jclouds.json.config.GsonModule;
36 import org.jclouds.rest.AsyncClientFactory;
37 import org.jclouds.rest.HttpAsyncClient;
38 import org.jclouds.rest.HttpClient;
39 import org.jclouds.rest.binders.BindToJsonPayloadWrappedWith;
40 import org.jclouds.rest.internal.AsyncRestClientProxy;
41 import org.jclouds.rest.internal.RestAnnotationProcessor;
42 import org.jclouds.rest.internal.SeedAnnotationCache;
43
44 import com.google.common.base.Function;
45 import com.google.common.collect.ImmutableMap;
46 import com.google.common.collect.MapMaker;
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 ConcurrentMap<Class<?>, Boolean> seedAnnotationCache(SeedAnnotationCache seedAnnotationCache) {
81 return new MapMaker().makeComputingMap(seedAnnotationCache);
82 }
83
84 @Provides
85 @Singleton
86 @Named("async")
87 ConcurrentMap<ClassMethodArgs, Object> provideAsyncDelegateMap(CreateAsyncClientForCaller createAsyncClientForCaller) {
88 return new MapMaker().makeComputingMap(createAsyncClientForCaller);
89 }
90
91 static class CreateAsyncClientForCaller implements Function<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 apply(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 ConcurrentMap<ClassMethodArgs, Object> delegateMap = injector.getInstance(Key.get(
112 new TypeLiteral<ConcurrentMap<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 }