EMMA Coverage Report (generated Wed Oct 26 13:47:17 EDT 2011)
[all classes][org.jclouds.rest]

COVERAGE SUMMARY FOR SOURCE FILE [RestContextBuilder.java]

nameclass, %method, %block, %line, %
RestContextBuilder.java92%  (11/12)88%  (36/41)87%  (546/626)88%  (83.8/95)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class RestContextBuilder$20%   (0/1)0%   (0/2)0%   (0/11)0%   (0/2)
RestContextBuilder$2 (RestContextBuilder): void 0%   (0/1)0%   (0/6)0%   (0/1)
apply (Module): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
     
class RestContextBuilder$3100% (1/1)67%  (2/3)71%  (46/65)75%  (3/4)
toString (): String 0%   (0/1)0%   (0/19)0%   (0/1)
RestContextBuilder$3 (RestContextBuilder): void 100% (1/1)100% (6/6)100% (1/1)
configure (): void 100% (1/1)100% (40/40)100% (2/2)
     
class RestContextBuilder$BindPropertiesAndPrincipalContext100% (1/1)100% (4/4)87%  (188/215)88%  (29.8/34)
timeouts (): Map 100% (1/1)59%  (26/44)64%  (5.8/9)
configure (): void 100% (1/1)93%  (122/131)94%  (16/17)
RestContextBuilder$BindPropertiesAndPrincipalContext (Properties): void 100% (1/1)100% (9/9)100% (3/3)
constants (): Multimap 100% (1/1)100% (31/31)100% (5/5)
     
class RestContextBuilder100% (1/1)89%  (16/18)91%  (234/257)90%  (46/51)
addContextModuleIfNotPresent (List): void 0%   (0/1)0%   (0/11)0%   (0/3)
getProperties (): Properties 0%   (0/1)0%   (0/3)0%   (0/1)
addExecutorServiceIfNotPresent (List): void 100% (1/1)70%  (21/30)80%  (4/5)
RestContextBuilder (Class, Class, Properties): void 100% (1/1)100% (27/27)100% (6/6)
addClientModule (List): void 100% (1/1)100% (11/11)100% (2/2)
addClientModuleIfNotPresent (List): void 100% (1/1)100% (8/8)100% (3/3)
addContextModule (List): void 100% (1/1)100% (8/8)100% (2/2)
addCredentialStoreIfNotPresent (List): void 100% (1/1)100% (14/14)100% (3/3)
addHttpModuleIfNeededAndNotPresent (List): void 100% (1/1)100% (15/15)100% (3/3)
addLoggingModuleIfNotPresent (List): void 100% (1/1)100% (12/12)100% (3/3)
atLeastOneModuleRequiresHttp (List): boolean 100% (1/1)100% (7/7)100% (1/1)
buildContext (): RestContext 100% (1/1)100% (22/22)100% (2/2)
buildInjector (): Injector 100% (1/1)100% (41/41)100% (9/9)
defaultOrAtLeastOneModuleRequiresHttp (List): boolean 100% (1/1)100% (12/12)100% (1/1)
ifHttpConfigureRestOtherwiseGuiceClientFactory (List): void 100% (1/1)100% (11/11)100% (3/3)
nothingConfiguresAnHttpService (List): boolean 100% (1/1)100% (11/11)100% (1/1)
restClientModulePresent (List): boolean 100% (1/1)100% (7/7)100% (1/1)
withModules (Iterable): RestContextBuilder 100% (1/1)100% (7/7)100% (2/2)
     
class RestContextBuilder$1100% (1/1)100% (2/2)100% (11/11)100% (2/2)
RestContextBuilder$1 (RestContextBuilder): void 100% (1/1)100% (6/6)100% (1/1)
apply (Module): boolean 100% (1/1)100% (5/5)100% (1/1)
     
class RestContextBuilder$4100% (1/1)100% (2/2)100% (11/11)100% (2/2)
RestContextBuilder$4 (RestContextBuilder): void 100% (1/1)100% (6/6)100% (1/1)
apply (Module): boolean 100% (1/1)100% (5/5)100% (1/1)
     
class RestContextBuilder$5100% (1/1)100% (2/2)100% (11/11)100% (2/2)
RestContextBuilder$5 (RestContextBuilder): void 100% (1/1)100% (6/6)100% (1/1)
apply (Module): boolean 100% (1/1)100% (5/5)100% (1/1)
     
class RestContextBuilder$6100% (1/1)100% (2/2)100% (11/11)100% (2/2)
RestContextBuilder$6 (RestContextBuilder): void 100% (1/1)100% (6/6)100% (1/1)
apply (Module): boolean 100% (1/1)100% (5/5)100% (1/1)
     
class RestContextBuilder$7100% (1/1)100% (2/2)100% (11/11)100% (2/2)
RestContextBuilder$7 (RestContextBuilder): void 100% (1/1)100% (6/6)100% (1/1)
apply (Module): boolean 100% (1/1)100% (5/5)100% (1/1)
     
class RestContextBuilder$8100% (1/1)100% (2/2)100% (11/11)100% (2/2)
RestContextBuilder$8 (RestContextBuilder): void 100% (1/1)100% (6/6)100% (1/1)
apply (Module): boolean 100% (1/1)100% (5/5)100% (1/1)
     
class RestContextBuilder$BindPropertiesAndPrincipalContext$1100% (1/1)100% (1/1)100% (6/6)100% (1/1)
RestContextBuilder$BindPropertiesAndPrincipalContext$1 (RestContextBuilder$Bi... 100% (1/1)100% (6/6)100% (1/1)
     
class RestContextBuilder$BindPropertiesAndPrincipalContext$2100% (1/1)100% (1/1)100% (6/6)100% (1/1)
RestContextBuilder$BindPropertiesAndPrincipalContext$2 (RestContextBuilder$Bi... 100% (1/1)100% (6/6)100% (1/1)

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 */
19package org.jclouds.rest;
20 
21import static com.google.common.base.Preconditions.checkNotNull;
22import static com.google.common.base.Predicates.equalTo;
23import static com.google.common.base.Predicates.instanceOf;
24import static com.google.common.base.Predicates.not;
25import static com.google.common.base.Splitter.on;
26import static com.google.common.collect.Iterables.addAll;
27import static com.google.common.collect.Iterables.any;
28import static com.google.common.collect.Iterables.filter;
29import static com.google.inject.Scopes.SINGLETON;
30import static com.google.inject.name.Names.bindProperties;
31import static com.google.inject.util.Types.newParameterizedType;
32import static org.jclouds.Constants.PROPERTY_API;
33import static org.jclouds.Constants.PROPERTY_API_VERSION;
34import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
35import static org.jclouds.Constants.PROPERTY_ENDPOINT;
36import static org.jclouds.Constants.PROPERTY_IDENTITY;
37import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
38import static org.jclouds.Constants.PROPERTY_PROVIDER;
39import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
40 
41import java.net.URI;
42import java.util.*;
43import java.util.Map.Entry;
44 
45import javax.inject.Inject;
46import javax.inject.Named;
47import javax.inject.Singleton;
48 
49import com.google.common.collect.*;
50import org.jclouds.concurrent.MoreExecutors;
51import org.jclouds.concurrent.SingleThreaded;
52import org.jclouds.concurrent.config.ConfiguresExecutorService;
53import org.jclouds.concurrent.config.ExecutorServiceModule;
54import org.jclouds.http.RequiresHttp;
55import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
56import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
57import org.jclouds.location.Iso3166;
58import org.jclouds.location.Provider;
59import org.jclouds.location.config.ProvideIso3166CodesByLocationIdViaProperties;
60import org.jclouds.logging.config.LoggingModule;
61import org.jclouds.logging.jdk.config.JDKLoggingModule;
62import org.jclouds.rest.annotations.Api;
63import org.jclouds.rest.annotations.ApiVersion;
64import org.jclouds.rest.annotations.Credential;
65import org.jclouds.rest.annotations.Identity;
66import org.jclouds.rest.config.CredentialStoreModule;
67import org.jclouds.rest.config.RestClientModule;
68import org.jclouds.rest.config.RestModule;
69import org.jclouds.rest.internal.RestContextImpl;
70 
71import com.google.common.annotations.VisibleForTesting;
72import com.google.common.base.Predicate;
73import com.google.inject.AbstractModule;
74import com.google.inject.Guice;
75import com.google.inject.Injector;
76import com.google.inject.Key;
77import com.google.inject.Module;
78import com.google.inject.Provides;
79import com.google.inject.TypeLiteral;
80 
81/**
82 * Creates {@link RestContext} or {@link Injector} instances based on the most commonly requested
83 * arguments.
84 * <p/>
85 * Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
86 * <p/>
87 * <p/>
88 * If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
89 * {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
90 * 
91 * @author Adrian Cole, Andrew Newdigate
92 * @see RestContext
93 */
94public class RestContextBuilder<S, A> {
95 
96   static class BindPropertiesAndPrincipalContext extends AbstractModule {
97      protected Properties properties;
98 
99      protected BindPropertiesAndPrincipalContext(Properties properties) {
100         this.properties = checkNotNull(properties, "properties");
101      }
102 
103      @Provides
104      @Singleton
105      @Named("CONSTANTS")
106      protected Multimap<String, String> constants() {
107         ImmutableMultimap.Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
108         for (Entry<Object, Object> entry : properties.entrySet())
109            if (entry.getValue() != null)
110               builder.put(entry.getKey().toString(), entry.getValue().toString());
111         return LinkedHashMultimap.create(builder.build());
112      }
113 
114      @Provides
115      @Singleton
116      @Named("TIMEOUTS")
117      protected Map<String, Long> timeouts() {
118         final ImmutableMap.Builder<String, Long> builder = ImmutableMap.<String, Long> builder();
119         for (final Entry<Object, Object> entry : properties.entrySet()) {
120            final String key = String.valueOf(entry.getKey());
121            if (key.startsWith(PROPERTY_TIMEOUTS_PREFIX) && entry.getValue() != null) {
122               try {
123                  final Long val = Long.valueOf(String.valueOf(entry.getValue()));
124                  builder.put(key.replaceFirst(PROPERTY_TIMEOUTS_PREFIX, ""), val);
125               } catch (final Throwable t) {}
126            }
127         }
128         return builder.build();
129      }
130 
131      @Override
132      protected void configure() {
133         Properties toBind = new Properties();
134         toBind.putAll(checkNotNull(properties, "properties"));
135         toBind.putAll(System.getProperties());
136         bindProperties(binder(), toBind);
137         bind(String.class).annotatedWith(Provider.class).toInstance(
138                  checkNotNull(toBind.getProperty(PROPERTY_PROVIDER), PROPERTY_PROVIDER));
139         bind(URI.class).annotatedWith(Provider.class).toInstance(
140                  URI.create(checkNotNull(toBind.getProperty(PROPERTY_ENDPOINT), PROPERTY_ENDPOINT)));
141         bind(new TypeLiteral<Set<String>>() {
142         }).annotatedWith(Iso3166.class).toInstance(
143                  ImmutableSet.copyOf(filter(on(',').split(
144                           checkNotNull(toBind.getProperty(PROPERTY_ISO3166_CODES), PROPERTY_ISO3166_CODES)),
145                           not(equalTo("")))));
146         bind(new TypeLiteral<Map<String, Set<String>>>() {
147         }).annotatedWith(Iso3166.class).toProvider(ProvideIso3166CodesByLocationIdViaProperties.class);
148         if (toBind.containsKey(PROPERTY_API))
149            bind(String.class).annotatedWith(Api.class).toInstance(toBind.getProperty(PROPERTY_API));
150         if (toBind.containsKey(PROPERTY_API_VERSION))
151            bind(String.class).annotatedWith(ApiVersion.class).toInstance(toBind.getProperty(PROPERTY_API_VERSION));
152         if (toBind.containsKey(PROPERTY_IDENTITY))
153            bind(String.class).annotatedWith(Identity.class).toInstance(
154                     checkNotNull(toBind.getProperty(PROPERTY_IDENTITY), PROPERTY_IDENTITY));
155         if (toBind.containsKey(PROPERTY_CREDENTIAL))
156            bind(String.class).annotatedWith(Credential.class).toInstance(toBind.getProperty(PROPERTY_CREDENTIAL));
157      }
158   }
159 
160   protected Properties properties;
161   protected List<Module> modules = new ArrayList<Module>(3);
162   protected Class<A> asyncClientType;
163   protected Class<S> syncClientType;
164 
165   @Inject
166   public RestContextBuilder(Class<S> syncClientClass, Class<A> asyncClientClass, Properties properties) {
167      this.asyncClientType = checkNotNull(asyncClientClass, "asyncClientType");
168      this.syncClientType = checkNotNull(syncClientClass, "syncClientType");
169      this.properties = checkNotNull(properties, "properties");
170   }
171 
172   public RestContextBuilder<S, A> withModules(Iterable<Module> modules) {
173      addAll(this.modules, modules);
174      return this;
175   }
176 
177   public Injector buildInjector() {
178      addContextModule(modules);
179      addClientModuleIfNotPresent(modules);
180      addLoggingModuleIfNotPresent(modules);
181      addHttpModuleIfNeededAndNotPresent(modules);
182      ifHttpConfigureRestOtherwiseGuiceClientFactory(modules);
183      addExecutorServiceIfNotPresent(modules);
184      addCredentialStoreIfNotPresent(modules);
185      modules.add(new BindPropertiesAndPrincipalContext(properties));
186      return Guice.createInjector(modules);
187   }
188 
189   @VisibleForTesting
190   protected void addLoggingModuleIfNotPresent(List<Module> modules) {
191      if (!any(modules, instanceOf(LoggingModule.class)))
192         modules.add(new JDKLoggingModule());
193   }
194 
195   @VisibleForTesting
196   protected void addHttpModuleIfNeededAndNotPresent(List<Module> modules) {
197      if (defaultOrAtLeastOneModuleRequiresHttp(modules) && nothingConfiguresAnHttpService(modules))
198         modules.add(new JavaUrlHttpCommandExecutorServiceModule());
199   }
200 
201   private boolean nothingConfiguresAnHttpService(List<Module> modules) {
202      return (!any(modules, new Predicate<Module>() {
203         public boolean apply(Module input) {
204            return input.getClass().isAnnotationPresent(ConfiguresHttpCommandExecutorService.class);
205         }
206 
207      }));
208   }
209 
210   @VisibleForTesting
211   protected void addContextModuleIfNotPresent(List<Module> modules) {
212      if (!any(modules, new Predicate<Module>() {
213         public boolean apply(Module input) {
214            return input.getClass().isAnnotationPresent(ConfiguresRestContext.class);
215         }
216 
217      })) {
218         addContextModule(modules);
219      }
220   }
221 
222   @VisibleForTesting
223   protected void addContextModule(List<Module> modules) {
224      modules.add(new AbstractModule() {
225 
226         @SuppressWarnings( { "unchecked", "rawtypes" })
227         @Override
228         protected void configure() {
229            bind(
230                     (TypeLiteral) TypeLiteral.get(newParameterizedType(RestContext.class, syncClientType,
231                              asyncClientType))).to(
232                     TypeLiteral.get(newParameterizedType(RestContextImpl.class, syncClientType, asyncClientType))).in(
233                     SINGLETON);
234 
235         }
236 
237         public String toString() {
238            return String.format("configure rest context %s->%s", syncClientType.getSimpleName(), asyncClientType
239                     .getSimpleName());
240         }
241 
242      });
243   }
244 
245   @VisibleForTesting
246   protected void ifHttpConfigureRestOtherwiseGuiceClientFactory(List<Module> modules) {
247      if (defaultOrAtLeastOneModuleRequiresHttp(modules)) {
248         modules.add(new RestModule());
249      }
250   }
251 
252   private boolean defaultOrAtLeastOneModuleRequiresHttp(List<Module> modules) {
253      return atLeastOneModuleRequiresHttp(modules) || !restClientModulePresent(modules);
254   }
255 
256   private boolean atLeastOneModuleRequiresHttp(List<Module> modules) {
257      return any(modules, new Predicate<Module>() {
258         public boolean apply(Module input) {
259            return input.getClass().isAnnotationPresent(RequiresHttp.class);
260         }
261      });
262   }
263 
264   @VisibleForTesting
265   protected void addClientModuleIfNotPresent(List<Module> modules) {
266      if (!restClientModulePresent(modules)) {
267         addClientModule(modules);
268      }
269   }
270 
271   private boolean restClientModulePresent(List<Module> modules) {
272      return any(modules, new Predicate<Module>() {
273         public boolean apply(Module input) {
274            return input.getClass().isAnnotationPresent(ConfiguresRestClient.class);
275         }
276 
277      });
278   }
279 
280   protected void addClientModule(List<Module> modules) {
281      modules.add(new RestClientModule<S, A>(syncClientType, asyncClientType));
282   }
283 
284   @VisibleForTesting
285   protected void addExecutorServiceIfNotPresent(List<Module> modules) {
286      if (!any(modules, new Predicate<Module>() {
287         public boolean apply(Module input) {
288            return input.getClass().isAnnotationPresent(ConfiguresExecutorService.class);
289         }
290      }
291 
292      )) {
293         if (any(modules, new Predicate<Module>() {
294            public boolean apply(Module input) {
295               return input.getClass().isAnnotationPresent(SingleThreaded.class);
296            }
297         })) {
298            modules.add(new ExecutorServiceModule(MoreExecutors.sameThreadExecutor(), MoreExecutors
299                     .sameThreadExecutor()));
300         } else {
301            modules.add(new ExecutorServiceModule());
302         }
303      }
304   }
305 
306   @VisibleForTesting
307   protected void addCredentialStoreIfNotPresent(List<Module> modules) {
308      if (!any(modules, new Predicate<Module>() {
309         public boolean apply(Module input) {
310            return input.getClass().isAnnotationPresent(ConfiguresCredentialStore.class);
311         }
312      }
313 
314      )) {
315         modules.add(new CredentialStoreModule());
316      }
317   }
318 
319   @VisibleForTesting
320   public Properties getProperties() {
321      return properties;
322   }
323 
324   @SuppressWarnings("unchecked")
325   public <T extends RestContext<S, A>> T buildContext() {
326      Injector injector = buildInjector();
327      return (T) injector
328               .getInstance(Key.get(newParameterizedType(RestContext.class, syncClientType, asyncClientType)));
329   }
330}

[all classes][org.jclouds.rest]
EMMA 2.0.5312 (C) Vladimir Roubtsov