View Javadoc

1   /**
2    * Licensed to jclouds, Inc. (jclouds) under one or more
3    * contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  jclouds licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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   * @author Adrian Cole
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          // cannot use child injectors due to the super coarse guice lock on
109          // Singleton
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 }