ExcludeClassesClassLoader.java
package top.infra.test.classloader.exclude;
import com.google.common.collect.ImmutableList;
import lombok.extern.slf4j.Slf4j;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
/**
* see: https://medium.com/@davehagler/junit-testrunner-with-a-custom-classloader-337d447dba4f
*/
@Slf4j
public class ExcludeClassesClassLoader extends URLClassLoader {
private final ClassLoader parentClassLoader;
private Collection<String> excludes;
public ExcludeClassesClassLoader(
final ClassLoader parentClassLoader, final URL[] urls, final Collection<String> excludes) {
super(urls, null);
log.info("ExcludeClassesClassLoader parentClassLoader " + parentClassLoader);
this.setExcludes(excludes);
this.parentClassLoader = parentClassLoader;
}
@Override
public synchronized Class<?> loadClass(final String name) throws ClassNotFoundException {
//log.info("loadClass " + name);
if (!this.excludes.contains(name)) {
// User's test class is already loaded by parentClassLoader
// Must use parentClassLoader to load top.infra.test.classloader.exclude.ExcludeClasses.
if (!name.startsWith("java.")
&& !name.startsWith("javax.")
&& !name.startsWith("org.junit.")
&& !name.startsWith("org.xml.")
&& !name.startsWith("org.w3c.")
&& !name.startsWith("sun.")
&& !"top.infra.test.classloader.exclude.ExcludeClasses".equals(name)
) {
final Class<?> result;
final Class<?> loadedClass = this.findLoadedClass(name);
if (loadedClass == null) {
result = this.findClass(name);
} else {
result = loadedClass;
}
return result;
}
return this.parentClassLoader.loadClass(name);
} else {
throw new ClassNotFoundException("class " + name + " is excluded from classpath");
}
}
public void setExcludes(final Collection<String> excludes) {
this.excludes = excludes != null ? excludes : ImmutableList.of();
}
}