Skip to content

Commit

Permalink
Revert "Hackily force use of FacadeLoader as TCCL in multimodule tests"
Browse files Browse the repository at this point in the history
This reverts commit 73c1dd4.
  • Loading branch information
holly-cummins committed Jan 15, 2025
1 parent 73c1dd4 commit e76475a
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,10 @@ public class QuarkusClassLoader extends ClassLoader implements Closeable {
registerAsParallelCapable();
}

private ClassLoader facade;

private static RuntimeException nonQuarkusClassLoaderError() {
return new IllegalStateException("The current classloader is not an instance of "
+ QuarkusClassLoader.class.getName() + " but "
+ Thread.currentThread()
.getContextClassLoader()
.getClass()
.getName());
+ Thread.currentThread().getContextClassLoader().getClass().getName());
}

/**
Expand All @@ -77,8 +72,7 @@ private static RuntimeException nonQuarkusClassLoaderError() {
* @param visitor runtime resource visitor
*/
public static void visitRuntimeResources(String resourceName, Consumer<PathVisit> visitor) {
if (Thread.currentThread()
.getContextClassLoader() instanceof QuarkusClassLoader classLoader) {
if (Thread.currentThread().getContextClassLoader() instanceof QuarkusClassLoader classLoader) {
for (var element : classLoader.getElementsWithResource(resourceName)) {
if (element.isRuntime()) {
element.apply(tree -> {
Expand All @@ -93,8 +87,7 @@ public static void visitRuntimeResources(String resourceName, Consumer<PathVisit
}

public static List<ClassPathElement> getElements(String resourceName, boolean onlyFromCurrentClassLoader) {
if (Thread.currentThread()
.getContextClassLoader() instanceof QuarkusClassLoader classLoader) {
if (Thread.currentThread().getContextClassLoader() instanceof QuarkusClassLoader classLoader) {
return classLoader.getElementsWithResource(resourceName, onlyFromCurrentClassLoader);
}
throw nonQuarkusClassLoaderError();
Expand All @@ -114,8 +107,7 @@ public static boolean isClassPresentAtRuntime(String className) {
* Indicates if a given class is considered an application class.
*/
public static boolean isApplicationClass(String className) {
if (Thread.currentThread()
.getContextClassLoader() instanceof QuarkusClassLoader classLoader) {
if (Thread.currentThread().getContextClassLoader() instanceof QuarkusClassLoader classLoader) {
String resourceName = fromClassNameToResourceName(className);
ClassPathResourceIndex classPathResourceIndex = classLoader.getClassPathResourceIndex();

Expand All @@ -134,8 +126,7 @@ public static boolean isApplicationClass(String className) {
public static boolean isResourcePresentAtRuntime(String resourcePath) {
List<ClassPathElement> classPathElements = QuarkusClassLoader.getElements(resourcePath, false);
for (int i = 0; i < classPathElements.size(); i++) {
if (classPathElements.get(i)
.isRuntime()) {
if (classPathElements.get(i).isRuntime()) {
return true;
}
}
Expand Down Expand Up @@ -181,8 +172,7 @@ public static boolean isResourcePresentAtRuntime(String resourcePath) {
static {
ClassLoader cl = null;
try {
cl = (ClassLoader) ClassLoader.class.getDeclaredMethod("getPlatformClassLoader")
.invoke(null);
cl = (ClassLoader) ClassLoader.class.getDeclaredMethod("getPlatformClassLoader").invoke(null);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {

}
Expand All @@ -196,9 +186,6 @@ private QuarkusClassLoader(Builder builder) {
// Not passing the name to the parent constructor on purpose:
// stacktraces become very ugly if we do that.
super(builder.parent);

this.facade = Thread.currentThread().getContextClassLoader();

this.name = builder.name;
this.status = STATUS_OPEN;
this.normalPriorityElements = builder.normalPriorityElements;
Expand Down Expand Up @@ -262,8 +249,7 @@ public Enumeration<URL> getResources(String unsanitisedName, boolean parentAlrea
ensureOpen(unsanitisedName);

for (int i = 0; i < classLoaderEventListeners.size(); i++) {
classLoaderEventListeners.get(i)
.enumeratingResourceURLs(unsanitisedName, this.name);
classLoaderEventListeners.get(i).enumeratingResourceURLs(unsanitisedName, this.name);
}
ClassPathResourceIndex classPathResourceIndex = getClassPathResourceIndex();
String name = sanitizeName(unsanitisedName);
Expand Down Expand Up @@ -298,8 +284,7 @@ public Enumeration<URL> getResources(String unsanitisedName, boolean parentAlrea
if (!classPathElements.isEmpty()) {
boolean endsWithTrailingSlash = unsanitisedName.endsWith("/");
for (int i = 0; i < classPathElements.size(); i++) {
List<ClassPathResource> resList = classPathElements.get(i)
.getResources(name);
List<ClassPathResource> resList = classPathElements.get(i).getResources(name);
//if the requested name ends with a trailing / we make sure
//that the resource is a directory, and return a URL that ends with a /
//this matches the behaviour of URLClassLoader
Expand All @@ -308,8 +293,7 @@ public Enumeration<URL> getResources(String unsanitisedName, boolean parentAlrea
if (endsWithTrailingSlash) {
if (res.isDirectory()) {
try {
resources.add(new URL(res.getUrl()
.toString() + "/"));
resources.add(new URL(res.getUrl().toString() + "/"));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
Expand Down Expand Up @@ -419,17 +403,15 @@ public URL getResource(String unsanitisedName) {
private static URL getClassPathElementResourceUrl(List<ClassPathElement> classPathElements, String name,
boolean endsWithTrailingSlash) {
for (int i = 0; i < classPathElements.size(); i++) {
ClassPathResource res = classPathElements.get(i)
.getResource(name);
ClassPathResource res = classPathElements.get(i).getResource(name);
if (res != null) {
//if the requested name ends with a trailing / we make sure
//that the resource is a directory, and return a URL that ends with a /
//this matches the behaviour of URLClassLoader
if (endsWithTrailingSlash) {
if (res.isDirectory()) {
try {
return new URL(res.getUrl()
.toString() + "/");
return new URL(res.getUrl().toString() + "/");
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
Expand All @@ -448,8 +430,7 @@ public InputStream getResourceAsStream(String unsanitisedName) {
ensureOpen(unsanitisedName);

for (int i = 0; i < classLoaderEventListeners.size(); i++) {
classLoaderEventListeners.get(i)
.openResourceStream(unsanitisedName, this.name);
classLoaderEventListeners.get(i).openResourceStream(unsanitisedName, this.name);
}
String name = sanitizeName(unsanitisedName);
ClassPathResourceIndex classPathResourceIndex = getClassPathResourceIndex();
Expand Down Expand Up @@ -487,8 +468,7 @@ private static InputStream getClassPathElementResourceInputStream(List<ClassPath
if (res != null) {
if (res.isDirectory()) {
try {
return res.getUrl()
.openStream();
return res.getUrl().openStream();
} catch (IOException e) {
log.debug("Ignoring exception that occurred while opening a stream for resource " + name,
e);
Expand Down Expand Up @@ -609,8 +589,7 @@ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundE
} finally {
if (interrupted) {
//restore interrupt state
Thread.currentThread()
.interrupt();
Thread.currentThread().interrupt();
}
}
}
Expand Down Expand Up @@ -787,8 +766,7 @@ public void close() {
try (InputStream is = getClass().getResourceAsStream("DriverRemover.class")) {
byte[] data = is.readAllBytes();
Runnable r = (Runnable) defineClass(DriverRemover.class.getName(), data, 0, data.length)
.getConstructor(ClassLoader.class)
.newInstance(this);
.getConstructor(ClassLoader.class).newInstance(this);
r.run();
} catch (Exception e) {
log.debug("Failed to clean up DB drivers");
Expand Down Expand Up @@ -856,10 +834,6 @@ public void setStartupAction(StartupAction startupAction) {
this.startupAction = startupAction;
}

public ClassLoader getFacadeClassloader() {
return facade;
}

public static class Builder {
final String name;
final ClassLoader parent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ public class AbstractJvmQuarkusTestExtension extends AbstractQuarkusTestWithCont

protected ClassLoader originalCl;

protected final ClassLoader facade;

// Used to preserve state from the previous run, so we know if we should restart an application
protected static RunningQuarkusApplication runningQuarkusApplication;

Expand All @@ -59,11 +57,6 @@ public class AbstractJvmQuarkusTestExtension extends AbstractQuarkusTestWithCont
protected static final Deque<Class<?>> currentTestClassStack = new ArrayDeque<>();
protected static Class<?> currentJUnitTestClass;

protected AbstractJvmQuarkusTestExtension() {
// TODO where is right place to get this?
facade = Thread.currentThread().getContextClassLoader();
}

// TODO only used by QuarkusMainTest, fix that class and delete this
protected PrepareResult createAugmentor(ExtensionContext context, Class<? extends QuarkusTestProfile> profile,
Collection<Runnable> shutdownTasks) throws Exception {
Expand Down Expand Up @@ -268,44 +261,21 @@ public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext con
System.out.println("OK smallrye " + SmallRyeConfig.class.getClassLoader());

// TODO this should not be necessary, because we want the config provider to be for our class
ClassLoader original = Thread.currentThread().getContextClassLoader();

QuarkusClassLoader mecl = (QuarkusClassLoader) this.getClass().getClassLoader();
ClassLoader facade = mecl.getFacadeClassloader();

// Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
// ClassLoader original = Thread.currentThread().getContextClassLoader();
// Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

// SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
// TestConfig testConfig = config.getConfigMapping(TestConfig.class);

// At this point, the TCCL is the FacadeClassLoader; trying to do getConfig with that TCCL fails with java.util.ServiceConfigurationError: io.smallrye.config.SmallRyeConfigFactory: io.quarkus.runtime.configuration.QuarkusConfigFactory not a subtype
// If we set the TCCL to be this.getClass().getClassLoader(), get config succeeds, but config.getConfigMapping(TestConfig.class) fails, because the mapping was registered when the TCCL was the FacadeClassLoader
// In nested tests and multimodule tests, the TCCL may not be the facade classloader

// ClassLoader facade = FacadeClassLoader.instance(Exception.class.getClassLoader());
// Thread.currentThread().setContextClassLoader(Error.class.getClassLoader());
Thread.currentThread().setContextClassLoader(facade);
System.out.println("HOLLY Config using facade TCCL " + Thread.currentThread().getContextClassLoader());

TestConfig testConfig = null;
System.out.println("HOLLY CONFIG " + " and the class of the mapping is "
+ TestConfig.class.getClassLoader());
try {
testConfig = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class).getConfigMapping(TestConfig.class);
} catch (RuntimeException | Error e) {
System.out.println("HOLLY Config DOOOOOOM " + e);
System.out.println("HOLLY Config TCCL is " + Thread.currentThread().getContextClassLoader()
+ " and the class of the mapping is "
+ TestConfig.class.getClassLoader());
System.out.println("HOLLY Config my class is " + this.getClass().getClassLoader());
throw e;
}
TestConfig testConfig = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class).getConfigMapping(TestConfig.class);

Optional<List<String>> tags = testConfig.profile().tags();
if (tags.isEmpty() || tags.get().isEmpty()) {
return ConditionEvaluationResult.enabled("No Quarkus Test Profile tags");
}
Thread.currentThread().setContextClassLoader(original);
// Thread.currentThread().setContextClassLoader(original);

Class<? extends QuarkusTestProfile> testProfile = getQuarkusTestProfile(context);
if (testProfile == null) {
Expand Down

0 comments on commit e76475a

Please sign in to comment.