// Copyright © 2011-2014, Esko Luontola <www.orfjackal.net>
// This software is released under the Apache License 2.0.
// The license text is at http://www.apache.org/licenses/LICENSE-2.0
package fi.jumi.core.drivers;
import fi.jumi.api.drivers.Driver;
import fi.jumi.core.util.*;
import javax.annotation.concurrent.NotThreadSafe;
import java.io.PrintStream;
import java.util.*;
@NotThreadSafe
public class DriverFinderFactory {
public static CompositeDriverFinder createDriverFinder(ClassLoader testClassLoader, PrintStream logOutput) {
List<DriverFinder> driverFinders = new ArrayList<>();
driverFinders.add(new AbstractClassIgnoringDriverFinder());
driverFinders.add(new RunViaAnnotationDriverFinder());
if (isOnClasspath("org.junit.Test", testClassLoader)) {
driverFinders.add(createJUnitCompatibilityDriverFinder(testClassLoader));
} else {
logOutput.println("JUnit not found on classpath; disabling JUnit compatibility");
}
driverFinders.add(new NonTestClassesIgnoringDriverFinder(logOutput));
return new CompositeDriverFinder(driverFinders);
}
private static DriverFinder createJUnitCompatibilityDriverFinder(ClassLoader classLoader) {
try {
// XXX: JUnitCompatibilityDriverFinder must be loaded from a class loader that has JUnit on its classpath,
// but our current class loader is the Jumi daemon's class loader, and only the test class loader has JUnit.
return (DriverFinder)
new LocallyDefiningClassLoader("fi.jumi.core.junit.", classLoader)
.loadClass("fi.jumi.core.junit.JUnitCompatibilityDriverFinder")
.newInstance();
} catch (Exception e) {
throw Boilerplate.rethrow(e);
}
}
private static boolean isOnClasspath(String className, ClassLoader classLoader) {
try {
classLoader.loadClass(className);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
@NotThreadSafe
private static class NonTestClassesIgnoringDriverFinder implements DriverFinder {
private final PrintStream logOutput;
public NonTestClassesIgnoringDriverFinder(PrintStream logOutput) {
this.logOutput = logOutput;
}
@Override
public Driver findTestClassDriver(Class<?> testClass) {
logOutput.println("Not recognized as a test class: " + testClass.getName());
return new IgnoreSilentlyDriver();
}
}
}