diff --git a/core/src/main/java/jenkins/util/ResourceBundleUtil.java b/core/src/main/java/jenkins/util/ResourceBundleUtil.java index f663926e8263..f9f9310f5662 100644 --- a/core/src/main/java/jenkins/util/ResourceBundleUtil.java +++ b/core/src/main/java/jenkins/util/ResourceBundleUtil.java @@ -24,15 +24,12 @@ package jenkins.util; -import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; -import hudson.PluginWrapper; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Logger; import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.kohsuke.accmod.Restricted; @@ -44,9 +41,8 @@ * @since 2.0 */ @Restricted(NoExternalUse.class) -public class ResourceBundleUtil { - - private static final Logger logger = Logger.getLogger("jenkins.util.ResourceBundle"); +public final class ResourceBundleUtil { + // TODO proper cache eviction private static final Map bundles = new ConcurrentHashMap<>(); private ResourceBundleUtil() { @@ -70,55 +66,20 @@ private ResourceBundleUtil() { * @throws MissingResourceException Missing resource bundle. */ public static @NonNull JSONObject getBundle(@NonNull String baseName, @NonNull Locale locale) throws MissingResourceException { - String bundleKey = baseName + ":" + locale; - JSONObject bundleJSON = bundles.get(bundleKey); + var bundleKey = baseName + ":" + locale; + var bundleJSON = bundles.get(bundleKey); if (bundleJSON != null) { return bundleJSON; } - - ResourceBundle bundle = getBundle(baseName, locale, Jenkins.class.getClassLoader()); - if (bundle == null) { - // Not in Jenkins core. Check the plugins. - Jenkins jenkins = Jenkins.getInstanceOrNull(); - if (jenkins != null) { - for (PluginWrapper plugin : jenkins.getPluginManager().getPlugins()) { - bundle = getBundle(baseName, locale, plugin.classLoader); - if (bundle != null) { - break; - } - } - } - } - if (bundle == null) { - throw new MissingResourceException("Can't find bundle for base name " - + baseName + ", locale " + locale, baseName + "_" + locale, ""); - } - - bundleJSON = toJSONObject(bundle); + var noFallbackControl = ResourceBundle.Control.getNoFallbackControl(ResourceBundle.Control.FORMAT_DEFAULT); + var uberClassLoader = Jenkins.get().getPluginManager().uberClassLoader; + bundleJSON = toJSONObject(ResourceBundle.getBundle(baseName, locale, uberClassLoader, noFallbackControl)); bundles.put(bundleKey, bundleJSON); return bundleJSON; } - /** - * Get a plugin bundle using the supplied Locale and classLoader - * - * @param baseName The bundle base name. - * @param locale The Locale. - * @param classLoader The classLoader - * @return The bundle JSON. - */ - private static @CheckForNull ResourceBundle getBundle(@NonNull String baseName, @NonNull Locale locale, @NonNull ClassLoader classLoader) { - try { - return ResourceBundle.getBundle(baseName, locale, classLoader); - } catch (MissingResourceException e) { - // fall through and return null. - logger.finer(e.getMessage()); - } - return null; - } - /** * Create a JSON representation of a resource bundle * diff --git a/core/src/test/java/jenkins/util/ResourceBundleUtilTest.java b/test/src/test/java/jenkins/util/ResourceBundleUtilTest.java similarity index 61% rename from core/src/test/java/jenkins/util/ResourceBundleUtilTest.java rename to test/src/test/java/jenkins/util/ResourceBundleUtilTest.java index a6265f0136db..d62ecdefd862 100644 --- a/core/src/test/java/jenkins/util/ResourceBundleUtilTest.java +++ b/test/src/test/java/jenkins/util/ResourceBundleUtilTest.java @@ -24,18 +24,23 @@ package jenkins.util; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThrows; import java.util.Locale; import java.util.MissingResourceException; import net.sf.json.JSONObject; -import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; /** * @author tom.fennelly@gmail.com */ public class ResourceBundleUtilTest { + @Rule + public JenkinsRule j = new JenkinsRule(); /** * Test resource bundle loading for a defined locale. @@ -43,12 +48,20 @@ public class ResourceBundleUtilTest { @Test public void test_known_locale() { JSONObject bundle = ResourceBundleUtil.getBundle("hudson.logging.Messages", Locale.GERMAN); - Assert.assertEquals("Initialisiere Log-Rekorder", bundle.getString("LogRecorderManager.init")); + assertEquals("Initialisiere Log-Rekorder", bundle.getString("LogRecorderManager.init")); bundle = ResourceBundleUtil.getBundle("hudson.logging.Messages", new Locale("de")); - Assert.assertEquals("Initialisiere Log-Rekorder", bundle.getString("LogRecorderManager.init")); + assertEquals("Initialisiere Log-Rekorder", bundle.getString("LogRecorderManager.init")); // Test caching - should get the same bundle instance back... - Assert.assertSame(ResourceBundleUtil.getBundle("hudson.logging.Messages", new Locale("de")), bundle); + assertSame(ResourceBundleUtil.getBundle("hudson.logging.Messages", new Locale("de")), bundle); + } + + @Test + public void noFallbackLocale() { + try (var ignored = new DefaultLocale(new Locale("fr"))) { + var bundle = ResourceBundleUtil.getBundle("hudson.logging.Messages", new Locale("en")); + assertEquals("System Log", bundle.getString("LogRecorderManager.DisplayName")); + } } /** @@ -56,16 +69,8 @@ public void test_known_locale() { */ @Test public void test_unknown_locale() { - Locale defaultOSLocale = Locale.getDefault(); - try { - //Set Default-Locale to english - Locale.setDefault(new Locale("en", "US")); - - JSONObject bundle = ResourceBundleUtil.getBundle("hudson.logging.Messages", new Locale("kok")); // konkani - Assert.assertEquals("Initializing log recorders", bundle.getString("LogRecorderManager.init")); - } finally { - Locale.setDefault(defaultOSLocale); - } + JSONObject bundle = ResourceBundleUtil.getBundle("hudson.logging.Messages", new Locale("kok")); // konkani + assertEquals("Initializing log recorders", bundle.getString("LogRecorderManager.init")); } /** @@ -75,4 +80,18 @@ public void test_unknown_locale() { public void test_unknown_bundle() { assertThrows(MissingResourceException.class, () -> ResourceBundleUtil.getBundle("hudson.blah.Whatever")); } + + private static class DefaultLocale implements AutoCloseable { + private Locale previous; + + DefaultLocale(Locale locale) { + previous = Locale.getDefault(); + Locale.setDefault(locale); + } + + @Override + public void close() { + Locale.setDefault(previous); + } + } }