<artifactId>log4j-slf4j-impl</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.infrautils</groupId>
+ <artifactId>inject.guice</artifactId>
+ </dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-multibindings</artifactId>
<artifactId>mycila-guice-jsr250</artifactId>
<scope>compile</scope>
</dependency>
-
- <!-- TODO remove when infrautils' ClasspathHellDuplicatesCheckRule pulls in classgraph, see https://git.opendaylight.org/gerrit/#/c/76625/ -->
- <dependency>
- <groupId>io.github.classgraph</groupId>
- <artifactId>classgraph</artifactId>
- <version>4.6.10</version>
- </dependency>
</dependencies>
<build>
+++ /dev/null
-/*
- * Copyright © 2018 Red Hat, Inc. and others.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.infrautils.inject;
-
-import io.github.classgraph.ClassGraph;
-import io.github.classgraph.ClassInfo;
-import io.github.classgraph.ClassInfoList;
-import io.github.classgraph.ScanResult;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import javax.inject.Singleton;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Class path scanner designed to be used with Guice. This provides a way for modules to request the bindings they
- * need by scanning the class path.
- */
-@SuppressWarnings("rawtypes")
-public class ClassPathScanner {
- private static final Logger LOG = LoggerFactory.getLogger(ClassPathScanner.class);
-
- private final Map<String, Class> implementations = new HashMap<>();
- private final Set<Class<?>> singletons = new HashSet<>();
-
- /**
- * Create a class path scanner, scanning packages with the given prefix for {@literal @}Singleton annotated classes.
- *
- * @param prefix The package prefix.
- */
- public ClassPathScanner(String prefix) {
- try (ScanResult scanResult =
- new ClassGraph()
- .enableClassInfo()
- .enableAnnotationInfo()
- .whitelistPackages(prefix)
- .scan()) {
- Set<String> duplicateInterfaces = new HashSet<>();
- for (ClassInfo singletonInfo : scanResult.getClassesWithAnnotation(Singleton.class.getName())) {
- ClassInfoList interfaces = singletonInfo.getInterfaces();
- if (interfaces.isEmpty()) {
- singletons.add(singletonInfo.loadClass());
- } else {
- for (ClassInfo interfaceInfo : interfaces) {
- String interfaceName = interfaceInfo.getName();
- if (!duplicateInterfaces.contains(interfaceName)) {
- if (implementations.put(interfaceName, singletonInfo.loadClass()) != null) {
- LOG.debug("{} is declared multiple times, ignoring it", interfaceName);
- implementations.remove(interfaceName);
- duplicateInterfaces.add(interfaceName);
- }
- }
- }
- }
- }
- }
- }
-
- /**
- * Binds all {@link Singleton} annotated classes discovered by scanning the class path to all their interfaces.
- *
- * @param prefix the package prefix of Singleton implementations to consider
- * @param binder The binder (modeled as a generic consumer)
- */
- public void bindAllSingletons(String prefix, BiConsumer<Class, Class> binder, Consumer<Class> singletonConsumer) {
- implementations.forEach((interfaceName, singletonClass) -> {
- if (singletonClass.getName().startsWith(prefix)) {
- try {
- Class interfaceClass = Class.forName(interfaceName);
- binder.accept(interfaceClass, singletonClass);
- // TODO later probably lower this info to debug, but for now it's very useful..
- LOG.info("Bound {} to {}", interfaceClass, singletonClass);
- } catch (ClassNotFoundException e) {
- LOG.warn("ClassNotFoundException on Class.forName: {}", interfaceName, e);
- }
- }
- });
- singletons.stream().filter(singletonClass -> singletonClass.getName().startsWith(prefix))
- .forEach(singletonClass -> singletonConsumer.accept(singletonClass));
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2018 Red Hat, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.infrautils.inject.guice;
-
-import java.util.Optional;
-import org.opendaylight.infrautils.inject.guice.testutils.AbstractCheckedModule;
-
-/**
- * Guice Module with classpath scanning based autowiring.
- *
- * @author Michael Vorburger.ch
- */
-public class AutoWiringModule extends AbstractCheckedModule {
-
- protected final GuiceClassPathBinder classPathBinder;
- private final Optional<String> packagePrefix;
-
- public AutoWiringModule(GuiceClassPathBinder classPathBinder, String packagePrefix) {
- this.classPathBinder = classPathBinder;
- this.packagePrefix = Optional.of(packagePrefix);
- }
-
- @Override
- protected final void checkedConfigure() throws Exception {
- packagePrefix.ifPresent(prefix -> classPathBinder.bindAllSingletons(prefix, binder()));
- configureMore();
- }
-
- protected void configureMore() throws Exception {
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2018 Red Hat, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.infrautils.inject.guice;
-
-import com.google.inject.Binder;
-import javax.inject.Singleton;
-import org.opendaylight.infrautils.inject.ClassPathScanner;
-
-/**
- * Binds interfaces to implementations in Guice by scanning the classpath.
- */
-public class GuiceClassPathBinder {
- private final ClassPathScanner scanner;
-
- public GuiceClassPathBinder(String prefix) {
- this.scanner = new ClassPathScanner(prefix);
- }
-
- /**
- * Binds all {@link Singleton} annotated classes discovered by scanning the class path to all their interfaces.
- *
- * @param prefix the package prefix of Singleton implementations to consider
- * @param binder The binder to set up.
- */
- @SuppressWarnings("unchecked")
- public void bindAllSingletons(String prefix, Binder binder) {
- scanner.bindAllSingletons(prefix,
- (contract, implementation) -> binder.bind(contract).to(implementation),
- singleton -> binder.bind(singleton));
- }
-}
+++ /dev/null
-/*
- * Copyright © 2018 Red Hat, Inc. and others.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.infrautils.inject.tests;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import org.junit.Test;
-import org.opendaylight.infrautils.inject.ClassPathScanner;
-
-public class ClassPathScannerTest {
-
- private static final String PREFIX = "org.opendaylight.infrautils.inject.tests";
-
- @Test
- public void testClasspathScanning() {
- Set<Class<?>> singletons = new HashSet<>();
- Map<Class<?>, Class<?>> bindings = new HashMap<>();
- new ClassPathScanner(PREFIX).bindAllSingletons(PREFIX, bindings::put, singletons::add);
- assertThat(bindings).containsExactly(
- ClassPathScannerTestTopInterface.class, ClassPathScannerTestImplementation.class,
- ClassPathScannerTestAnotherInterface.class, ClassPathScannerTestImplementation.class);
- assertThat(singletons).containsExactly(ClassPathScannerTestNoInterfacesImplementation.class);
- }
-
- @Test
- public void testClasspathExclusion() {
- Set<Class<?>> singletons = new HashSet<>();
- Map<Class<?>, Class<?>> bindings = new HashMap<>();
- new ClassPathScanner(PREFIX).bindAllSingletons("nope", bindings::put, singletons::add);
- assertThat(bindings).isEmpty();
- assertThat(singletons).isEmpty();
- }
-}
+++ /dev/null
-/*
- * Copyright © 2018 Red Hat, Inc. and others.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.infrautils.inject.tests;
-
-public interface ClassPathScannerTestAnotherInterface {
-}
+++ /dev/null
-/*
- * Copyright © 2018 Red Hat, Inc. and others.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.infrautils.inject.tests;
-
-import javax.inject.Singleton;
-
-@Singleton
-public class ClassPathScannerTestImplementation
- implements ClassPathScannerTestTopInterface, ClassPathScannerTestAnotherInterface {
-}
+++ /dev/null
-/*
- * Copyright © 2018 Red Hat, Inc. and others.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.infrautils.inject.tests;
-
-import javax.inject.Singleton;
-
-@Singleton
-public class ClassPathScannerTestNoInterfacesImplementation {
-}
+++ /dev/null
-/*
- * Copyright © 2018 Red Hat, Inc. and others.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.infrautils.inject.tests;
-
-public interface ClassPathScannerTestTopInterface {
-}