package io.graceland.inject; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.codahale.metrics.health.HealthCheck; import com.google.common.base.Preconditions; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.inject.ConfigurationException; import com.google.inject.Injector; import com.google.inject.Key; import io.dropwizard.Bundle; import io.dropwizard.cli.Command; import io.dropwizard.lifecycle.Managed; import io.dropwizard.servlets.tasks.Task; import io.graceland.dropwizard.Configurator; import io.graceland.dropwizard.Initializer; import io.graceland.filter.FilterSpec; /** * Wraps a Guice {@link com.google.inject.Injector} and provides helper functions to help deal with bindings coming * from a {@link com.google.inject.multibindings.Multibinder}. */ public class InjectorWrapper { private static final Logger LOGGER = LoggerFactory.getLogger(InjectorWrapper.class); private final Injector injector; InjectorWrapper(Injector injector) { this.injector = Preconditions.checkNotNull(injector, "Injector cannot be null."); } /** * Returns a wrapper around the {@link com.google.inject.Injector}. * * @param injector The injector to wrap. * @return A wrapper. */ public static InjectorWrapper wrap(Injector injector) { Preconditions.checkNotNull(injector, "Injector cannot be null."); return new InjectorWrapper(injector); } // ===================== // KISS Helper Functions // ===================== private <T> Set<T> getSetSafely(Key<Set<T>> key) { try { return injector.getInstance(key); } catch (ConfigurationException e) { LOGGER.debug("No bindings found for key: {}", key, e); return ImmutableSet.of(); } } private <T> ImmutableSet<T> getAndBuildInstances(Key<Set<T>> concreteKey, Key<Set<Class<? extends T>>> classKey) { Set<T> instances = getSetSafely(concreteKey); Set<Class<? extends T>> classes = getSetSafely(classKey); ImmutableSet.Builder<T> allInstances = ImmutableSet.builder(); allInstances.addAll(instances); for (Class<? extends T> klass : classes) { T instance = injector.getInstance(klass); allInstances.add(instance); } return allInstances.build(); } // ============================= // Injector Multibinder Wrappers // ============================= /** * Returns a Set of Jersey components, including Providers and Resources. These objects are usually fed into the * {@link io.dropwizard.jersey.setup.JerseyEnvironment#register(Class)} method. * * @return An immutable set of Jersey components. */ @SuppressWarnings("unchecked") public ImmutableSet<Object> getJerseyComponents() { Set<Object> components = getSetSafely(Keys.JerseyComponents); ImmutableSet.Builder<Object> builder = ImmutableSet.builder(); for (Object classOrInstance : components) { if (classOrInstance instanceof Class) { Object instance = injector.getInstance((Class<Object>) classOrInstance); builder.add(instance); } else { builder.add(classOrInstance); } } return builder.build(); } public ImmutableSet<HealthCheck> getHealthChecks() { return getAndBuildInstances(Keys.HealthChecks, Keys.HealthCheckClasses); } public ImmutableSet<Task> getTasks() { return getAndBuildInstances(Keys.Tasks, Keys.TaskClasses); } public ImmutableSet<Managed> getManaged() { return getAndBuildInstances(Keys.ManagedObjects, Keys.ManagedObjectClasses); } public ImmutableSet<Bundle> getBundles() { return getAndBuildInstances(Keys.Bundles, Keys.BundleClasses); } public ImmutableSet<Command> getCommands() { return getAndBuildInstances(Keys.Commands, Keys.CommandClasses); } public ImmutableSet<Initializer> getInitializers() { return getAndBuildInstances(Keys.Initializers, Keys.InitializerClasses); } public ImmutableSet<Configurator> getConfigurators() { return getAndBuildInstances(Keys.Configurators, Keys.ConfiguratorClasses); } public ImmutableList<FilterSpec> getFilterSpecs() { return FluentIterable .from(getSetSafely(Keys.FilterSpecs)) .toSortedList(FilterSpec.PRIORITY_COMPARATOR); } }