Package org.jclouds

Source Code of org.jclouds.ContextBuilder

/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds;

import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.containsPattern;
import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.base.Predicates.not;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.base.Predicates.or;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.addAll;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.newArrayListWithCapacity;
import static com.google.common.collect.Maps.filterKeys;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.Constants.PROPERTY_API;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_BUILD_VERSION;
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_IDENTITY;
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
import static org.jclouds.Constants.PROPERTY_PROVIDER;
import static org.jclouds.reflect.Reflection2.typeToken;
import static org.jclouds.util.Throwables2.propagateAuthorizationOrOriginalException;

import java.io.Closeable;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;

import org.jclouds.apis.ApiMetadata;
import org.jclouds.apis.Apis;
import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.config.BindApiContextWithWildcardExtendsExplicitAndRawType;
import org.jclouds.config.BindNameToContext;
import org.jclouds.config.BindPropertiesToExpandedValues;
import org.jclouds.config.BindRestContextWithWildcardExtendsExplicitAndRawType;
import org.jclouds.domain.Credentials;
import org.jclouds.events.config.ConfiguresEventBus;
import org.jclouds.events.config.EventBusModule;
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.lifecycle.Closer;
import org.jclouds.lifecycle.config.LifeCycleModule;
import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.Providers;
import org.jclouds.providers.config.BindProviderMetadataContextAndCredentials;
import org.jclouds.providers.internal.UpdateProviderMetadataFromProperties;
import org.jclouds.rest.ConfiguresCredentialStore;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.HttpApiMetadata;
import org.jclouds.rest.RestApiMetadata;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.config.CredentialStoreModule;
import org.jclouds.rest.config.HttpApiModule;
import org.jclouds.rest.config.SyncToAsyncHttpInvocationModule;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rest.config.RestModule;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.common.util.concurrent.ExecutionList;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;

/**
* Creates {@link Context} or {@link Injector} configured to an api and
* endpoint. Alternatively, this can be used to make a portable {@link View} of
* that api.
*
* <br/>
* ex. to build a {@code Api} on a particular endpoint using the typed
* interface
*
* <pre>
* api = ContextBuilder.newBuilder(new NovaApiMetadata())
*                     .endpoint("http://10.10.10.10:5000/v2.0")
*                     .credentials(user, pass)
*                     .buildApi(NovaApi.class);
* </pre>
*
* <br/>
* ex. to build a {@link View} of a particular backend context, looked up by
* key.
*
* <pre>
* context = ContextBuilder.newBuilder("aws-s3")
*                         .credentials(apikey, secret)
*                         .buildView(BlobStoreContext.class);
* </pre>
*
* <h4>Assumptions</h4>
*
* Threadsafe objects will be bound as singletons to the Injector or Context
* provided.
* <p/>
* If no <code>Module</code>s are specified, the default
* {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be
* installed.
*
* @author Adrian Cole, Andrew Newdigate
* @see Context
* @see View
* @see ApiMetadata
* @see ProviderMetadata
*/
public class ContextBuilder {

   /**
    * looks up a provider or api with the given id
    *
    * @param providerOrApi
    *           id of the provider or api
    * @return means to build a context to that provider
    * @throws NoSuchElementException
    *            if the id was not configured.
    */
   public static ContextBuilder newBuilder(String providerOrApi) throws NoSuchElementException {
      try {
         try {
            return ContextBuilder.newBuilder(Providers.withId(providerOrApi));
         } catch (NoSuchElementException e) {
            return ContextBuilder.newBuilder(Apis.withId(providerOrApi));
         }
      } catch (NoSuchElementException e) {
         Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
         builder.putAll("providers", transform(Providers.all(), Providers.idFunction()));
         builder.putAll("apis", transform(Apis.all(), Apis.idFunction()));
         throw new NoSuchElementException(String.format("key [%s] not in the list of providers or apis: %s",
                  providerOrApi, builder.build()));
      }
   }

   public static ContextBuilder newBuilder(ApiMetadata apiMetadata) {
      try {
         return new ContextBuilder(apiMetadata);
      } catch (Exception e) {
         return propagateAuthorizationOrOriginalException(e);
      }
   }

   public static ContextBuilder newBuilder(ProviderMetadata providerMetadata) {
      try {
         return new ContextBuilder(providerMetadata);
      } catch (Exception e) {
         return propagateAuthorizationOrOriginalException(e);
      }
   }

   protected Optional<String> name = Optional.absent();
   protected Optional<ProviderMetadata> providerMetadata = Optional.absent();
   protected final String providerId;
   protected Optional<String> endpoint = Optional.absent();
   protected Optional<String> identity = Optional.absent();
   protected Optional<Supplier<Credentials>> credentialsSupplierOption = Optional.absent();
   @Nullable
   protected String credential;
   protected ApiMetadata apiMetadata;
   protected String apiVersion;
   protected String buildVersion;
   protected Optional<Properties> overrides = Optional.absent();
   protected List<Module> modules = newArrayListWithCapacity(3);

   @Override
   public String toString() {
      return toStringHelper("").add("providerMetadata", providerMetadata).add("apiMetadata", apiMetadata).toString();
   }

   protected ContextBuilder(ProviderMetadata providerMetadata) {
      this(providerMetadata, checkNotNull(providerMetadata, "providerMetadata").getApiMetadata());
   }

   protected ContextBuilder(@Nullable ProviderMetadata providerMetadata, ApiMetadata apiMetadata) {
      this.apiMetadata = checkNotNull(apiMetadata, "apiMetadata");
      if (providerMetadata != null) {
         this.providerMetadata = Optional.of(providerMetadata);
         this.endpoint = Optional.of(providerMetadata.getEndpoint());
         this.providerId = providerMetadata.getId();
      } else {
         this.endpoint = apiMetadata.getDefaultEndpoint();
         this.providerId = apiMetadata.getId();
      }
      this.identity = apiMetadata.getDefaultIdentity();
      this.credential = apiMetadata.getDefaultCredential().orNull();
      this.apiVersion = apiMetadata.getVersion();
      this.buildVersion = apiMetadata.getBuildVersion().or("");
   }

   public ContextBuilder(ApiMetadata apiMetadata) {
      this(null, apiMetadata);
   }

   public ContextBuilder name(String name) {
     this.name = Optional.of(checkNotNull(name, "name"));
     return this;
   }

   /**
    * returns the current login credentials. jclouds will not cache this value. Use this when you need to change
    * credentials at runtime.
    */
   public ContextBuilder credentialsSupplier(Supplier<Credentials> credentialsSupplier) {
      this.credentialsSupplierOption = Optional.of(checkNotNull(credentialsSupplier, "credentialsSupplier"));
      return this;
   }
  
   /**
    * constant value of the cloud identity and credential.
    *
    * @param credential (optional depending on {@link ApiMetadata#getCredentialName()}
    */
   public ContextBuilder credentials(String identity, @Nullable String credential) {
      this.identity = Optional.of(checkNotNull(identity, "identity"));
      this.credential = credential;
      return this;
   }

   public ContextBuilder endpoint(String endpoint) {
      this.endpoint = Optional.of(checkNotNull(endpoint, "endpoint"));
      return this;
   }

   public ContextBuilder apiVersion(String apiVersion) {
      this.apiVersion = checkNotNull(apiVersion, "apiVersion");
      return this;
   }

   public ContextBuilder buildVersion(String buildVersion) {
      this.buildVersion = checkNotNull(buildVersion, "buildVersion");
      return this;
   }

   public ContextBuilder modules(Iterable<? extends Module> modules) {
      addAll(this.modules, checkNotNull(modules, "modules"));
      return this;
   }

   public ContextBuilder overrides(Properties overrides) {
      this.overrides = Optional.of(checkNotNull(overrides, "overrides"));
      return this;
   }

   public static String searchPropertiesForProviderScopedProperty(Properties mutable, String prov, String key) throws NoSuchElementException {
      try {
         return find(newArrayList(mutable.getProperty(prov + "." + key), mutable.getProperty("jclouds." + key)),
                  notNull());
      } catch (NoSuchElementException e) {
         throw new NoSuchElementException(String.format("property %s.%s not present in properties: %s", prov, key, mutable.keySet()));
      } finally {
         mutable.remove(prov + "." + key);
         mutable.remove("jclouds." + key);
      }
   }

   public Injector buildInjector() {

      Properties unexpanded = currentStateToUnexpandedProperties();

      Set<String> keysToResolve = ImmutableSet.of(PROPERTY_IDENTITY, PROPERTY_CREDENTIAL, PROPERTY_ENDPOINT,
            PROPERTY_API, PROPERTY_API_VERSION, PROPERTY_BUILD_VERSION);

      Set<String> optionalKeys;
      if (credentialsSupplierOption.isPresent()) {
         optionalKeys = ImmutableSet.of(PROPERTY_IDENTITY, PROPERTY_CREDENTIAL);
      } else if (!apiMetadata.getCredentialName().isPresent()) {
         optionalKeys = ImmutableSet.of(PROPERTY_CREDENTIAL);
      } else {
         optionalKeys = ImmutableSet.of();
      }

      Properties resolved = resolveProperties(unexpanded, providerId, keysToResolve, optionalKeys);

      Properties expanded = expandProperties(resolved);

      Supplier<Credentials> credentialsSupplier = buildCredentialsSupplier(expanded);

      ProviderMetadata providerMetadata = new UpdateProviderMetadataFromProperties(apiMetadata, this.providerMetadata)
            .apply(expanded);

      // We use either the specified name (optional) or a hash of provider/api, endpoint, api version & identity. Hash
      // is used to be something readable.
      return buildInjector(name.or(String.valueOf(Objects.hashCode(providerMetadata.getId(),
            providerMetadata.getEndpoint(), providerMetadata.getApiMetadata().getVersion(), credentialsSupplier))),
            providerMetadata, credentialsSupplier, modules);
   }

   protected Supplier<Credentials> buildCredentialsSupplier(Properties expanded) {
      Credentials creds = new Credentials(getAndRemove(expanded, PROPERTY_IDENTITY), getAndRemove(expanded,
            PROPERTY_CREDENTIAL));

      Supplier<Credentials> credentialsSupplier;
      if (credentialsSupplierOption.isPresent()) {
         credentialsSupplier = credentialsSupplierOption.get();
      } else {
         credentialsSupplier = Suppliers.ofInstance(creds);
      }
      return credentialsSupplier;
   }

   private static String getAndRemove(Properties expanded, String key) {
      try {
         return expanded.getProperty(key);
      } finally {
         expanded.remove(key);
      }
   }
  
   private Properties currentStateToUnexpandedProperties() {
      Properties defaults = new Properties();
      defaults.putAll(apiMetadata.getDefaultProperties());
      defaults.setProperty(PROPERTY_PROVIDER,providerId);
      if (providerMetadata.isPresent()) {
         defaults.putAll(providerMetadata.get().getDefaultProperties());
         defaults.setProperty(PROPERTY_ISO3166_CODES, Joiner.on(',').join(providerMetadata.get().getIso3166Codes()));
      }
      if (endpoint.isPresent())
         defaults.setProperty(PROPERTY_ENDPOINT, endpoint.get());
      defaults.setProperty(PROPERTY_API, apiMetadata.getName());
      defaults.setProperty(PROPERTY_API_VERSION, apiVersion);
      defaults.setProperty(PROPERTY_BUILD_VERSION, buildVersion);
      if (identity.isPresent())
         defaults.setProperty(PROPERTY_IDENTITY, identity.get());
      if (credential != null)
         defaults.setProperty(PROPERTY_CREDENTIAL, credential);
      if (overrides.isPresent())
         defaults.putAll(checkNotNull(overrides.get(), "overrides"));
      defaults.putAll(propertiesPrefixedWithJcloudsApiOrProviderId(getSystemProperties(), apiMetadata.getId(), providerId));
      return defaults;
   }

   @VisibleForTesting
   protected Properties getSystemProperties() {
      return System.getProperties();
   }


   private Properties expandProperties(final Properties resolved) {
      return Guice.createInjector(new BindPropertiesToExpandedValues(resolved)).getInstance(Properties.class);
   }

   public static Injector buildInjector(String name, ProviderMetadata providerMetadata, Supplier<Credentials> creds, List<Module> inputModules) {
      List<Module> modules = newArrayList();
      modules.addAll(inputModules);
      boolean apiModuleSpecifiedByUser = apiModulePresent(inputModules);
      Iterable<Module> defaultModules = ifSpecifiedByUserDontIncludeDefaultApiModule(
               providerMetadata.getApiMetadata(), apiModuleSpecifiedByUser);
      addAll(modules, defaultModules);
      addClientModuleIfNotPresent(providerMetadata.getApiMetadata(), modules);
      addRestContextBinding(providerMetadata.getApiMetadata(), modules);
      addLoggingModuleIfNotPresent(modules);
      addHttpModuleIfNeededAndNotPresent(modules);
      addExecutorServiceIfNotPresent(modules);
      addEventBusIfNotPresent(modules);
      addCredentialStoreIfNotPresent(modules);
      modules.add(new LifeCycleModule());
      modules.add(new BindProviderMetadataContextAndCredentials(providerMetadata, creds));
      modules.add(new BindNameToContext(name));
      Injector returnVal = Guice.createInjector(Stage.PRODUCTION, modules);
      returnVal.getInstance(ExecutionList.class).execute();
      return returnVal;
   }

   static Properties resolveProperties(Properties mutable, String providerId, Set<String> keys, Set<String> optionalKeys) throws NoSuchElementException {
      for (String key : keys){
         try {
            String scopedProperty = ImmutableList.copyOf(Splitter.on('.').split(key)).get(1);
            mutable.setProperty(key, searchPropertiesForProviderScopedProperty(mutable, providerId,scopedProperty));
         } catch (NoSuchElementException e){
            if (!optionalKeys.contains(key))
               throw e;
         }
      }
      return mutable;
   }

   static void addRestContextBinding(ApiMetadata apiMetadata, List<Module> modules) {
      if (apiMetadata instanceof HttpApiMetadata) {
         try {
            modules
                  .add(new BindApiContextWithWildcardExtendsExplicitAndRawType(HttpApiMetadata.class.cast(apiMetadata)));
         } catch (IllegalArgumentException ignored) {

         }
      } else if (apiMetadata instanceof RestApiMetadata) {
         try {
            modules.add(new BindRestContextWithWildcardExtendsExplicitAndRawType(RestApiMetadata.class
                  .cast(apiMetadata)));
         } catch (IllegalArgumentException ignored) {

         }
      }
   }

   static Iterable<Module> ifSpecifiedByUserDontIncludeDefaultApiModule(ApiMetadata apiMetadata,
            boolean restModuleSpecifiedByUser) {
      Iterable<Module> defaultModules = transform(apiMetadata.getDefaultModules(),
               new Function<Class<? extends Module>, Module>() {

                  @Override
                  public Module apply(Class<? extends Module> arg0) {
                     try {
                        return arg0.newInstance();
                     } catch (InstantiationException e) {
                        throw propagate(e);
                     } catch (IllegalAccessException e) {
                        throw propagate(e);
                     }
                  }

               });
      if (restModuleSpecifiedByUser)
         defaultModules = filter(defaultModules, and(not(configuresApi), not(configuresRest)));
      return defaultModules;
   }

   @SuppressWarnings( { "unchecked" })
   static Map<String, Object> propertiesPrefixedWithJcloudsApiOrProviderId(Properties properties, String apiId,
            String providerId) {
      return filterKeys(Map.class.cast(properties), containsPattern("^(jclouds|" + providerId + "|" + apiId + ").*"));
   }

   @VisibleForTesting
   static void addLoggingModuleIfNotPresent(List<Module> modules) {
      if (!any(modules, instanceOf(LoggingModule.class)))
         modules.add(new JDKLoggingModule());
   }

   @VisibleForTesting
   static void addHttpModuleIfNeededAndNotPresent(List<Module> modules) {
      if (nothingConfiguresAnHttpService(modules))
         modules.add(new JavaUrlHttpCommandExecutorServiceModule());
   }

   static boolean nothingConfiguresAnHttpService(List<Module> modules) {
      return !any(modules, new Predicate<Module>() {
         public boolean apply(Module input) {
            return input.getClass().isAnnotationPresent(ConfiguresHttpCommandExecutorService.class);
         }

      });
   }

   @VisibleForTesting
   static void addClientModuleIfNotPresent(ApiMetadata apiMetadata, List<Module> modules) {
      if (!apiModulePresent(modules)) {
         addClientModule(apiMetadata, modules);
      }
   }
   private static boolean apiModulePresent(List<Module> modules) {
      return any(modules, or(configuresApi, configuresRest));
   }

   private static Predicate<Module> configuresApi = new Predicate<Module>() {
      public boolean apply(Module input) {
         return input.getClass().isAnnotationPresent(ConfiguresHttpApi.class);
      }

   };

   private static Predicate<Module> configuresRest = new Predicate<Module>() {
      public boolean apply(Module input) {
         return input.getClass().isAnnotationPresent(ConfiguresRestClient.class);
      }

   };

   @SuppressWarnings({ "unchecked", "rawtypes" })
   static void addClientModule(ApiMetadata apiMetadata, List<Module> modules) {
      // TODO: move this up
      if (apiMetadata instanceof HttpApiMetadata) {
         HttpApiMetadata api = HttpApiMetadata.class.cast(apiMetadata);
         modules.add(new HttpApiModule(api.getApi()));
      } else if (apiMetadata instanceof RestApiMetadata) {
         RestApiMetadata rest = RestApiMetadata.class.cast(apiMetadata);
         modules.add(new RestClientModule(typeToken(rest.getApi()), typeToken(rest.getAsyncApi())));
      } else {
         modules.add(new RestModule());
         modules.add(new SyncToAsyncHttpInvocationModule());
      }
   }

   @VisibleForTesting
   static void addEventBusIfNotPresent(List<Module> modules) {
      if (!any(modules, new Predicate<Module>() {
         public boolean apply(Module input) {
            return input.getClass().isAnnotationPresent(ConfiguresEventBus.class);
         }
      }

      )) {
         modules.add(new EventBusModule());
      }
   }

   @VisibleForTesting
   static void addExecutorServiceIfNotPresent(List<Module> modules) {
      if (!any(modules, new Predicate<Module>() {
         public boolean apply(Module input) {
            return input.getClass().isAnnotationPresent(ConfiguresExecutorService.class);
         }
      }

      )) {
         if (any(modules, new Predicate<Module>() {
            public boolean apply(Module input) {
               return input.getClass().isAnnotationPresent(SingleThreaded.class);
            }
         })) {
            modules.add(new ExecutorServiceModule(sameThreadExecutor(), sameThreadExecutor()));
         } else {
            modules.add(new ExecutorServiceModule());
         }
      }
   }

   @VisibleForTesting
   static void addCredentialStoreIfNotPresent(List<Module> modules) {
      if (!any(modules, new Predicate<Module>() {
         public boolean apply(Module input) {
            return input.getClass().isAnnotationPresent(ConfiguresCredentialStore.class);
         }
      }

      )) {
         modules.add(new CredentialStoreModule());
      }
   }

   /**
    * Builds the base context for this api. Note that this may be of type {@link Closer}, if nothing
    * else was configured via {@link ApiMetadata#getContext()}. Typically, the type returned is
    * {@link RestContext}
    *
    * @see ApiMetadata#getContext()
    * @see #build(TypeToken)
    */
   @SuppressWarnings("unchecked")
   public <C extends Context> C build() {
      return (C) build(apiMetadata.getContext());
   }

   /**
    * @see #buildView(Class)
    */
   public <V extends View> V build(Class<V> viewType) {
     return buildView(checkNotNull(viewType, "viewType"));
   }

   /**
    * @see #buildView(TypeToken)
    */
   public <V extends View> V buildView(Class<V> viewType) {
     return buildView(typeToken(viewType));
   }
  
   /**
    * this will build any {@link ApiMetadata#getViews() view} supported by the ApiMetadata.
    *
    * ex. {@code builder.build(BlobStoreContext.class) } will work, if {@code TypeToken<BlobStore>}
    * is a configured {@link ApiMetadata#getViews() view} of this api.
    *
    */
   @SuppressWarnings("unchecked")
   public <V extends View> V buildView(TypeToken<V> viewType) {
      TypeToken<V> returnType;
      try {
         returnType = (TypeToken<V>) Apis.findView(apiMetadata, checkNotNull(viewType, "viewType"));
      } catch (NoSuchElementException e) {
         throw new IllegalArgumentException(String.format(
                  "api %s not wrappable as %s; context: %s, views: %s", apiMetadata,
                  viewType, apiMetadata.getContext(), apiMetadata.getViews()));
      }
      return (V) buildInjector().getInstance(Key.get(TypeLiteral.get(returnType.getType())));
   }

   /**
    * this will build the {@link ApiMetadata#getContext() context} supported by the current ApiMetadata.
    */
   @SuppressWarnings("unchecked")
   public <C extends Context> C build(TypeToken<C> contextType) {
      TypeToken<C> returnType = null;
      if (contextType.isAssignableFrom(apiMetadata.getContext()))
         returnType = (TypeToken<C>) apiMetadata.getContext();
      else
         throw new IllegalArgumentException(String.format("api %s not assignable from %s; context: %s", apiMetadata,
                  contextType, apiMetadata.getContext()));
      return (C) buildInjector().getInstance(Key.get(TypeLiteral.get(returnType.getType())));
   }

   /**
    * This will return the top-level interface for the api or provider.
    *
    * Ex.
    * <pre>
    * api = ContextBuilder.newBuilder("openstack-nova")
    *                     ...
    *                     .buildApi(NovaApi.class);
    *</pre>
    */
   public <A extends Closeable> A buildApi(Class<A> api) {
      return buildApi(typeToken(api));
   }

   /**
    * like {@link #buildApi(Class)} but permits a type-token for convenience.
    */
   @SuppressWarnings("unchecked")
   public <A extends Closeable> A buildApi(TypeToken<A> apiType) {
      return (A) buildInjector().getInstance(Key.get(TypeLiteral.get(apiType.getType())));
   }

   public ApiMetadata getApiMetadata() {
      return apiMetadata;
   }
}
TOP

Related Classes of org.jclouds.ContextBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.