code: package io.paradoxical.cassieq.bundles;
  
  import com.google.inject.Injector;
  import com.google.inject.Module;
  import com.hubspot.dropwizard.guice.GuiceBundle;
  import com.hubspot.dropwizard.guice.InjectorFactory;
  import com.netflix.governator.Governator;
  import io.paradoxical.cassieq.ServiceConfiguration;
  import io.paradoxical.cassieq.discoverable.ApiDiscoverableRoot;
  import io.paradoxical.cassieq.modules.DefaultApplicationModules;
  
  import java.util.List;
  
  public class GuiceBundleProvider {
  
      public static final InjectorFactory DefaultInjectorFactory = (stage, modules) -> Governator.createInjector(modules);
      private final InjectorFactory injectorFactory;
  
      private GuiceBundle<ServiceConfiguration> bundle;
  
      public Injector getInjector() {
          return getBundle().getInjector();
      }
  
      public GuiceBundleProvider() {
          this(DefaultInjectorFactory);
      }
  
      public GuiceBundleProvider(InjectorFactory injectorFactory) {
          this.injectorFactory = injectorFactory;
      }
  
      public synchronized GuiceBundle<ServiceConfiguration> getBundle() {
          if (bundle == null) {
              bundle = buildGuiceBundle();
          }
  
          return bundle;
      }
  
      protected List<Module> getModules() {
          return DefaultApplicationModules.getModules();
      }
  
      private GuiceBundle<ServiceConfiguration> buildGuiceBundle() {
          final GuiceBundle.Builder<ServiceConfiguration> builder = GuiceBundle.<ServiceConfiguration>newBuilder();
  
          builder.enableAutoConfig(ApiDiscoverableRoot.class.getPackage().getName())
                 .setConfigClass(ServiceConfiguration.class)
                 .setInjectorFactory(injectorFactory);
  
          getModules().stream().forEach(builder::addModule);
  
          return builder.build();
      }
  }
  
  