package io.robe.guice; import com.google.common.base.Preconditions; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.Stage; import io.dropwizard.Configuration; import io.dropwizard.ConfiguredBundle; import io.dropwizard.setup.Bootstrap; import io.dropwizard.setup.Environment; import io.robe.guice.scanner.Scanner; import org.reflections.Reflections; import org.reflections.scanners.SubTypesScanner; import org.reflections.scanners.TypeAnnotationsScanner; import org.reflections.util.ClasspathHelper; import org.reflections.util.ConfigurationBuilder; import org.reflections.util.FilterBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.LinkedList; import java.util.List; import java.util.Set; public class GuiceBundle<T extends Configuration & HasGuiceConfiguration> implements ConfiguredBundle<T> { private static final Logger LOGGER = LoggerFactory.getLogger(GuiceBundle.class); private static Injector injector = null; private static GuiceConfiguration configuration; private Reflections reflections; private List<Module> modules = new LinkedList<>(); private DropwizardEnvironmentModule deModule; private Class<T> type; public GuiceBundle(List<Module> modules, Class<T> type) { Preconditions.checkNotNull(modules); Preconditions.checkArgument(!modules.isEmpty()); this.modules = modules; this.type = type; } public static GuiceConfiguration getConfiguration() { return configuration; } public static Injector getInjector() { return injector; } @Override public void initialize(Bootstrap<?> bootstrap) { deModule = new DropwizardEnvironmentModule<>(type); modules.add(new JerseyModule()); modules.add(deModule); injector = Guice.createInjector(Stage.PRODUCTION, modules); } /** * Initializes the environment. * * @param configuration the configuration object * @param environment the io.robe.admin's {@link io.dropwizard.setup.Environment} */ @Override public void run(T configuration, Environment environment) { try { if (configuration.getGuice() == null) { LOGGER.error("GuiceBundle can not work without and configuration!"); } GuiceBundle.configuration = configuration.getGuice(); createReflections(configuration.getGuice().getScanPackages()); JerseyUtil.registerGuiceBound(injector, environment.jersey()); JerseyUtil.registerGuiceFilter(environment); deModule.setEnvironmentData(configuration, environment); findAndRunScanners(environment, injector); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } } /** * Creates a {@link org.reflections.Reflections} with the given packages (configuration) * * @param scanPackages */ private void createReflections(String[] scanPackages) { if (scanPackages.length < 1) { LOGGER.warn("No package defined in configuration (scanPackages)!"); return; } ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); FilterBuilder filterBuilder = new FilterBuilder(); for (String packageName : scanPackages) { configurationBuilder.addUrls(ClasspathHelper.forPackage(packageName)); filterBuilder.include(FilterBuilder.prefix(packageName)); } configurationBuilder.filterInputsBy(filterBuilder).setScanners(new SubTypesScanner(), new TypeAnnotationsScanner()); this.reflections = new Reflections(configurationBuilder); } /** * Collects all classes extended {@link io.robe.guice.scanner.Scanner} and adds them to environment * * @param environment target environment * @param injector guice injector to create instances. */ private void findAndRunScanners(Environment environment, Injector injector) { Set<Class<? extends Scanner>> scanners = reflections.getSubTypesOf(Scanner.class); for (Class<? extends Scanner> scanner : scanners) { try { LOGGER.info(scanner.getName() + ": "); Scanner instance = scanner.newInstance(); instance.scanAndAdd(environment, injector, reflections); } catch (Exception e) { LOGGER.error("Added scanner: " + scanner, e); } } } }