EMMA Coverage Report (generated Wed Aug 10 12:30:04 EDT 2011)
[all classes][org.jclouds.rest]

COVERAGE SUMMARY FOR SOURCE FILE [RestContextBuilder.java]

nameclass, %method, %block, %line, %
RestContextBuilder.java92%  (11/12)88%  (35/40)89%  (520/582)91%  (78/86)

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

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