From 8dd1faef327a792b1df26312cdbfc331560160f7 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 7 Jul 2026 05:15:40 +0000 Subject: [PATCH] CAMEL-23912: Address review feedback on ThemeTest fix - Handle null classloader from Theme.class.getClassLoader() to avoid NPE when the class is bootstrap-loaded (Copilot feedback) - Soften javadoc wording: classloader access is not "guaranteed", it falls back to TCCL when the primary lookup returns null (ammachado) - Revert ConcurrentHashMap to HashMap since all CACHE access is already inside synchronized methods (ammachado) Co-Authored-By: Claude Opus 4.6 --- .../dsl/jbang/core/commands/tui/Theme.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java index 6b62c45fa96a4..e3c6661745231 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java +++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java @@ -20,10 +20,10 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; import dev.tamboui.css.Styleable; import dev.tamboui.css.engine.StyleEngine; @@ -73,7 +73,7 @@ final class Theme { private static final Style FALLBACK_MCP_DOWN = Style.EMPTY.fg(Color.LIGHT_RED); private static final Color FALLBACK_ZEBRA = Color.rgb(0x1C, 0x1C, 0x1C); - private static final Map CACHE = new ConcurrentHashMap<>(); + private static final Map CACHE = new HashMap<>(); private static boolean initialized; private static boolean fallbackLogged; @@ -262,14 +262,19 @@ private static synchronized StyleEngine engine() { } /** - * Reads a CSS resource from the classpath using this class's own classloader, which is guaranteed to have access to - * project resources regardless of classloader hierarchy. + * Reads a CSS resource from the classpath using this class's own classloader, which in the normal Camel + * class-loading hierarchy has access to project resources. Falls back to the thread-context classloader when the + * primary lookup returns null (e.g., in OSGi or custom classloader setups) or when the class is bootstrap-loaded. */ private static String loadCssResource(String path) throws IOException { - InputStream is = Theme.class.getClassLoader().getResourceAsStream(path); + InputStream is = null; + ClassLoader cl = Theme.class.getClassLoader(); + if (cl != null) { + is = cl.getResourceAsStream(path); + } if (is == null) { // Fallback to the thread context classloader in case the class's own classloader - // doesn't have visibility (e.g., in OSGi or custom classloader setups). + // doesn't have visibility or is null (bootstrap-loaded classes). ClassLoader tccl = Thread.currentThread().getContextClassLoader(); if (tccl != null) { is = tccl.getResourceAsStream(path);