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" } ] } 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") 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() { @Override @@ -134,7 +136,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 +146,24 @@ 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); + /* + * 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); + } + return MissingRegistrationUtils.runIgnoringMissingRegistrations(() -> getBundleImpl(callerModule, module, baseName, locale, control)); + } + @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..2281edab5828 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,16 +62,18 @@ public static void reportResourceAccess(Module module, String resourcePath) { report(exception); } - public static void reportResourceBundleAccess(String baseName) { - var bundleConfig = new ResourceConfiguration.BundleConfiguration(UnresolvedConfigurationCondition.alwaysTrue(), baseName); + public static void reportResourceBundleAccess(Module module, String baseName) { + Objects.requireNonNull(module); + var bundleConfig = new ResourceConfiguration.BundleConfiguration(UnresolvedConfigurationCondition.alwaysTrue(), module.getName(), baseName); StringWriter json = new StringWriter(); try { ResourceConfiguration.printResourceBundle(bundleConfig, getJSONWriter(json), true); } catch (IOException e) { throw VMError.shouldNotReachHere("In memory JSON printing should not fail"); } + 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); }