From 3d9c0086445f910edbf11a1d7f7432ec42b1b36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 10 Jul 2025 10:25:10 +0200 Subject: [PATCH 1/5] Update documentation of module-based resource bundle inclusion request --- docs/reference-manual/native-image/ReachabilityMetadata.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference-manual/native-image/ReachabilityMetadata.md b/docs/reference-manual/native-image/ReachabilityMetadata.md index 83a5bfd81d78..f6872c950a3b 100644 --- a/docs/reference-manual/native-image/ReachabilityMetadata.md +++ b/docs/reference-manual/native-image/ReachabilityMetadata.md @@ -612,7 +612,8 @@ To request a bundle from a specific module: { "resources": [ { - "bundle": "app.module:module.pkg.Bundle" + "module": "app.module" + "bundle": "your.pkg.Bundle" } ] } From f93ebe6c60a6ee789148b06499633f201cd68888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 10 Jul 2025 12:09:20 +0200 Subject: [PATCH 2/5] Fix MissingResourceRegistration behaviour for resource bundle access via module --- .../Target_java_util_ResourceBundle.java | 23 +++++++++++++++++-- .../MissingResourceRegistrationUtils.java | 7 ++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_util_ResourceBundle.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_util_ResourceBundle.java index 92702d223fe4..8d5469094dc5 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_util_ResourceBundle.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_util_ResourceBundle.java @@ -25,7 +25,10 @@ package com.oracle.svm.core.jdk.localization.substitutions; import java.util.Locale; +import java.util.MissingResourceException; +import java.util.Objects; import java.util.ResourceBundle; +import java.util.ResourceBundle.Control; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Supplier; @@ -115,7 +118,7 @@ private static ResourceBundle getBundleImpl(String baseName, // get resource bundles for a named module only if loader is the module's class loader if (callerModule.isNamed() && loader == getLoader(callerModule)) { if (!ImageSingletons.lookup(LocalizationSupport.class).isRegisteredBundleLookup(baseName, locale, control)) { - MissingResourceRegistrationUtils.reportResourceBundleAccess(baseName); + MissingResourceRegistrationUtils.reportResourceBundleAccess(callerModule, baseName); } return MissingRegistrationUtils.runIgnoringMissingRegistrations(new Supplier() { @Override @@ -134,7 +137,7 @@ public ResourceBundle get() { : BootLoader.getUnnamedModule(); if (!ImageSingletons.lookup(LocalizationSupport.class).isRegisteredBundleLookup(baseName, locale, control)) { - MissingResourceRegistrationUtils.reportResourceBundleAccess(baseName); + MissingResourceRegistrationUtils.reportResourceBundleAccess(unnamedModule, baseName); } return MissingRegistrationUtils.runIgnoringMissingRegistrations(new Supplier() { @Override @@ -144,6 +147,22 @@ public ResourceBundle get() { }); } + @Substitute + private static ResourceBundle getBundleFromModule(Class caller, + Module module, + String baseName, + Locale locale, + Control control) { + Objects.requireNonNull(module); + Module callerModule = getCallerModule(caller); + try { + return MissingRegistrationUtils.runIgnoringMissingRegistrations(() -> getBundleImpl(callerModule, module, baseName, locale, control)); + } catch (MissingResourceException mre) { + MissingResourceRegistrationUtils.reportResourceBundleAccess(module, baseName); + throw mre; + } + } + @Alias private static native Module getCallerModule(Class caller); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/MissingResourceRegistrationUtils.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/MissingResourceRegistrationUtils.java index 31b3459e6174..1f06736f8f9a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/MissingResourceRegistrationUtils.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/MissingResourceRegistrationUtils.java @@ -29,6 +29,7 @@ import java.nio.file.Files; import java.nio.file.spi.FileSystemProvider; import java.util.Map; +import java.util.Objects; import java.util.ResourceBundle; import java.util.Set; @@ -61,7 +62,7 @@ public static void reportResourceAccess(Module module, String resourcePath) { report(exception); } - public static void reportResourceBundleAccess(String baseName) { + public static void reportResourceBundleAccess(Module module, String baseName) { var bundleConfig = new ResourceConfiguration.BundleConfiguration(UnresolvedConfigurationCondition.alwaysTrue(), baseName); StringWriter json = new StringWriter(); try { @@ -69,8 +70,10 @@ public static void reportResourceBundleAccess(String baseName) { } catch (IOException e) { throw VMError.shouldNotReachHere("In memory JSON printing should not fail"); } + Objects.requireNonNull(module); + String moduleMessage = module.isNamed() ? " from module " + quote(module.getName()) : ""; MissingResourceRegistrationError exception = new MissingResourceRegistrationError( - resourceError("resource bundle with name " + quote(baseName), json.toString(), "resource-bundles"), + resourceError("resource bundle" + moduleMessage + " with name " + quote(baseName), json.toString(), "resource-bundles"), baseName); report(exception); } From 0e9791b3e448d70b9476f73c9479cd5e0239f337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Thu, 10 Jul 2025 14:33:51 +0200 Subject: [PATCH 3/5] Add missing module property in BundleConfiguration and JSON printing --- .../svm/configure/config/ResourceConfiguration.java | 13 +++++++++++-- .../resources/MissingResourceRegistrationUtils.java | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java index c26c11fba484..1b80fb7b6fed 100644 --- a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java +++ b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java @@ -116,17 +116,23 @@ public void addClassBasedResourceBundle(UnresolvedConfigurationCondition conditi public static final class BundleConfiguration { public final UnresolvedConfigurationCondition condition; + public final String module; public final String baseName; public final Set locales = ConcurrentHashMap.newKeySet(); public final Set classNames = ConcurrentHashMap.newKeySet(); - public BundleConfiguration(UnresolvedConfigurationCondition condition, String baseName) { + public BundleConfiguration(UnresolvedConfigurationCondition condition, String module, String baseName) { this.condition = condition; + this.module = module; this.baseName = baseName; } + public BundleConfiguration(UnresolvedConfigurationCondition condition, String baseName) { + this(condition, null, baseName); + } + private BundleConfiguration(BundleConfiguration other) { - this(other.condition, other.baseName); + this(other.condition, other.module, other.baseName); locales.addAll(other.locales); classNames.addAll(other.classNames); } @@ -389,6 +395,9 @@ public ConfigurationParser createParser(boolean combinedFileSchema, EnumSet Date: Mon, 14 Jul 2025 17:05:21 +0200 Subject: [PATCH 4/5] Add MODULE_KEY to optionalAttrs in ResourceBundle configuration parsing --- .../com/oracle/svm/configure/ResourceConfigurationParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/ResourceConfigurationParser.java b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/ResourceConfigurationParser.java index dcb4936d8b8f..42d47a551f18 100644 --- a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/ResourceConfigurationParser.java +++ b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/ResourceConfigurationParser.java @@ -71,12 +71,13 @@ protected void parseBundlesObject(Object bundlesObject) { protected void parseBundle(Object bundle, boolean inResourcesSection) { EconomicMap resource = asMap(bundle, "Elements of 'bundles' list must be a bundle descriptor object"); String bundleNameAttribute = inResourcesSection ? BUNDLE_KEY : NAME_KEY; - checkAttributes(resource, "bundle descriptor object", Collections.singletonList(bundleNameAttribute), Arrays.asList("locales", "classNames", "condition")); + checkAttributes(resource, "bundle descriptor object", Collections.singletonList(bundleNameAttribute), Arrays.asList(MODULE_KEY, "locales", "classNames", "condition")); String basename = asString(resource.get(bundleNameAttribute)); TypeResult resolvedConfigurationCondition = conditionResolver.resolveCondition(parseCondition(resource)); if (!resolvedConfigurationCondition.isPresent()) { return; } + // TODO GR-67556 - Add full support for MODULE_KEY in ResourceBundle configurations Object locales = resource.get("locales"); if (locales != null) { List asList = asList(locales, "Attribute 'locales' must be a list of locales") From ebd0112e21abd0211e11bc929209097499dbac88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20W=C3=B6gerer?= Date: Tue, 15 Jul 2025 12:55:15 +0200 Subject: [PATCH 5/5] Switch to using .isRegisteredBundleLookup to decide if we should show MissingResourceRegistrationError --- .../Target_java_util_ResourceBundle.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_util_ResourceBundle.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_util_ResourceBundle.java index 8d5469094dc5..f7696306ce6b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_util_ResourceBundle.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_util_ResourceBundle.java @@ -25,7 +25,6 @@ package com.oracle.svm.core.jdk.localization.substitutions; import java.util.Locale; -import java.util.MissingResourceException; import java.util.Objects; import java.util.ResourceBundle; import java.util.ResourceBundle.Control; @@ -155,12 +154,14 @@ private static ResourceBundle getBundleFromModule(Class caller, Control control) { Objects.requireNonNull(module); Module callerModule = getCallerModule(caller); - try { - return MissingRegistrationUtils.runIgnoringMissingRegistrations(() -> getBundleImpl(callerModule, module, baseName, locale, control)); - } catch (MissingResourceException mre) { + /* + * TODO GR-67556 - Implement proper module-aware LocalizationSupport bundle registration to + * ensure we show MissingResourceRegistrationError in all relevant situations. + */ + if (!ImageSingletons.lookup(LocalizationSupport.class).isRegisteredBundleLookup(baseName, locale, control)) { MissingResourceRegistrationUtils.reportResourceBundleAccess(module, baseName); - throw mre; } + return MissingRegistrationUtils.runIgnoringMissingRegistrations(() -> getBundleImpl(callerModule, module, baseName, locale, control)); } @Alias