cucumber.runtime.io.ClasspathResourceLoader Maven / Gradle / Ivy
package cucumber.runtime.io;
import cucumber.runtime.CucumberException;
import cucumber.runtime.Utils;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashSet;
public class ClasspathResourceLoader implements ResourceLoader {
private final ClassLoader classLoader;
public ClasspathResourceLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public Iterable resources(String path, String suffix) {
return new ClasspathIterable(classLoader, path, suffix);
}
public Collection> getAnnotations(String packageName) {
return getDescendants(Annotation.class, packageName);
}
public Collection> getDescendants(Class parentType, String packageName) {
String packagePath = packageName.replace('.', '/').replace(File.separatorChar, '/');
Collection> result = new HashSet>();
for (Resource classResource : resources(packagePath, ".class")) {
String className = classResource.getClassName();
Class> clazz = loadClass(className, classLoader);
if (clazz != null && !parentType.equals(clazz) && parentType.isAssignableFrom(clazz)) {
result.add(clazz.asSubclass(parentType));
}
}
return result;
}
public T instantiateExactlyOneSubclass(Class parentType, String packageName, Class[] constructorParams, Object[] constructorArgs) {
Collection extends T> instances = instantiateSubclasses(parentType, packageName, constructorParams, constructorArgs);
if (instances.size() == 1) {
return instances.iterator().next();
} else if (instances.size() == 0) {
throw new CucumberException("Couldn't find a single implementation of " + parentType);
} else {
throw new CucumberException("Expected only one instance, but found too many: " + instances);
}
}
public Collection extends T> instantiateSubclasses(Class parentType, String packageName, Class[] constructorParams, Object[] constructorArgs) {
Collection result = new HashSet();
for (Class extends T> clazz : getDescendants(parentType, packageName)) {
if (Utils.isInstantiable(clazz) && Utils.hasConstructor(clazz, constructorParams)) {
result.add(newInstance(constructorParams, constructorArgs, clazz));
}
}
return result;
}
private Class> loadClass(String className, ClassLoader classLoader) {
try {
return classLoader.loadClass(className);
} catch (ClassNotFoundException ignore) {
return null;
} catch (NoClassDefFoundError ignore) {
return null;
}
}
private T newInstance(Class[] constructorParams, Object[] constructorArgs, Class extends T> clazz) {
try {
return clazz.getConstructor(constructorParams).newInstance(constructorArgs);
} catch (InstantiationException e) {
throw new CucumberException(e);
} catch (IllegalAccessException e) {
throw new CucumberException(e);
} catch (InvocationTargetException e) {
throw new CucumberException(e);
} catch (NoSuchMethodException e) {
throw new CucumberException(e);
}
}
}