Skip to content

Commit

Permalink
Debug + WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
loicottet committed Jan 24, 2024
1 parent 01d32b0 commit e1a6add
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,13 @@ public boolean isNotIncluded(String bundleName) {
}

@Override
public void prepareBundle(String bundleName, ResourceBundle bundle, Function<String, Optional<Module>> findModule, Locale locale) {
super.prepareBundle(bundleName, bundle, findModule, locale);
public void prepareBundle(String bundleName, ResourceBundle bundle, Function<String, Optional<Module>> findModule, Locale locale, boolean jdkLocale) {
super.prepareBundle(bundleName, bundle, findModule, locale, jdkLocale);
/* Initialize ResourceBundle.keySet eagerly */
bundle.keySet();
this.existingBundles.add(control.toBundleName(bundleName, locale));
if (!jdkLocale) {
this.existingBundles.add(control.toBundleName(bundleName, locale));
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@

import static com.oracle.svm.util.StringUtil.toDotSeparated;
import static com.oracle.svm.util.StringUtil.toSlashSeparated;
import static sun.util.locale.provider.LocaleProviderAdapter.Type.CLDR;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -62,8 +62,6 @@
import com.oracle.svm.util.ReflectionUtil;

import jdk.graal.compiler.debug.GraalError;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.ResourceBundleBasedAdapter;
import sun.util.resources.Bundles;

/**
Expand All @@ -84,6 +82,8 @@ public class LocalizationSupport {

public final ResourceBundle.Control control = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);

private final Bundles.Strategy strategy = getLocaleDataStrategy();

public final Charset defaultCharset;

private final EconomicMap<String, Set<Locale>> registeredBundles = EconomicMap.create();
Expand Down Expand Up @@ -116,13 +116,23 @@ public Map<String, Object> getBundleContentOf(Object bundle) {
throw VMError.unsupportedFeature("Resource bundle lookup must be loaded during native image generation: " + bundle.getClass());
}

private static Bundles.Strategy getLocaleDataStrategy() {
try {
Class<?> localeDataStrategy = ReflectionUtil.lookupClass(false, "sun.util.resources.LocaleData$LocaleDataStrategy");
Field strategyInstance = ReflectionUtil.lookupField(localeDataStrategy, "INSTANCE");
return (Bundles.Strategy) strategyInstance.get(null);
} catch (IllegalAccessException e) {
throw VMError.shouldNotReachHere(e);
}
}

@Platforms(Platform.HOSTED_ONLY.class)
public void prepareBundle(String bundleName, ResourceBundle bundle, Function<String, Optional<Module>> findModule, Locale locale) {
public void prepareBundle(String bundleName, ResourceBundle bundle, Function<String, Optional<Module>> findModule, Locale locale, boolean jdkBundle) {
/*
* Class-based bundle lookup happens on every query, but we don't need to register the
* constructor for a property resource bundle since the class lookup will fail.
*/
registerRequiredReflectionAndResourcesForBundle(bundleName, Set.of(locale));
registerRequiredReflectionAndResourcesForBundle(bundleName, Set.of(locale), jdkBundle);
if (!(bundle instanceof PropertyResourceBundle)) {
registerNullaryConstructor(bundle.getClass());
}
Expand Down Expand Up @@ -180,49 +190,48 @@ private String getBundleName(String fixedBundleName, Locale locale) {
}
}

public void registerRequiredReflectionAndResourcesForBundle(String baseName, Collection<Locale> wantedLocales) {
int i = baseName.lastIndexOf('.');
if (i > 0) {
String name = baseName.substring(i + 1) + "Provider";
String providerName = baseName.substring(0, i) + ".spi." + name;
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerClassLookup(ConfigurationCondition.alwaysTrue(), providerName);
public void registerRequiredReflectionAndResourcesForBundle(String baseName, Collection<Locale> wantedLocales, boolean jdkBundle) {
if (!jdkBundle) {
int i = baseName.lastIndexOf('.');
if (i > 0) {
String name = baseName.substring(i + 1) + "Provider";
String providerName = baseName.substring(0, i) + ".spi." + name;
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerClassLookup(ConfigurationCondition.alwaysTrue(), providerName);
}
}

ImageSingletons.lookup(RuntimeReflectionSupport.class).registerClassLookup(ConfigurationCondition.alwaysTrue(), baseName);

for (Locale locale : wantedLocales) {
registerRequiredReflectionAndResourcesForBundleAndLocale(baseName, locale);
registerRequiredReflectionAndResourcesForBundleAndLocale(baseName, locale, jdkBundle);
}
}

public void registerRequiredReflectionAndResourcesForBundleAndLocale(String baseName, Locale baseLocale) {
public void registerRequiredReflectionAndResourcesForBundleAndLocale(String baseName, Locale baseLocale, boolean jdkBundle) {
/*
* Bundles in the sun.(text|util).resources.cldr packages are loaded with an alternative
* strategy which tries parent aliases defined in CLDRBaseLocaleDataMetaInfo.parentLocales.
*/
List<Locale> candidateLocales = isCLDRBundle(baseName)
? ((ResourceBundleBasedAdapter) LocaleProviderAdapter.forType(CLDR)).getCandidateLocales(baseName, baseLocale)
List<Locale> candidateLocales = jdkBundle
? strategy.getCandidateLocales(baseName, baseLocale)
: control.getCandidateLocales(baseName, baseLocale);

for (Locale locale : candidateLocales) {
String bundleWithLocale = control.toBundleName(baseName, locale);
String bundleWithLocale = jdkBundle ? strategy.toBundleName(baseName, locale) : control.toBundleName(baseName, locale);
RuntimeReflection.registerClassLookup(bundleWithLocale);
Class<?> bundleClass = ReflectionUtil.lookupClass(true, bundleWithLocale);
if (bundleClass != null) {
registerNullaryConstructor(bundleClass);
}
Resources.singleton().registerNegativeQuery(bundleWithLocale.replace('.', '/') + ".properties");
String otherBundleName = Bundles.toOtherBundleName(baseName, bundleWithLocale, locale);
if (!otherBundleName.equals(bundleWithLocale)) {
RuntimeReflection.registerClassLookup(otherBundleName);

if (jdkBundle) {
String otherBundleName = Bundles.toOtherBundleName(baseName, bundleWithLocale, locale);
if (!otherBundleName.equals(bundleWithLocale)) {
RuntimeReflection.registerClassLookup(otherBundleName);
}
}
}
}

private boolean isCLDRBundle(String baseName) {
return baseName.startsWith(CLDR.getUtilResourcesPackage()) || baseName.startsWith(CLDR.getTextResourcesPackage());
}

/**
* Template method for subclasses to perform additional tasks.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ public void prepareClassResourceBundle(String basename, Class<?> bundleClass) {
bundleLocaleField.set(bundle, locale);

// override in this class does not use findModule
prepareBundle(basename, bundle, null, locale);
prepareBundle(basename, bundle, null, locale, false);
} catch (ReflectionUtil.ReflectionUtilError | ReflectiveOperationException e) {
throw UserError.abort(e, "Failed to instantiated bundle from class %s, reason %s", bundleClass, e.getCause().getMessage());
}
}

@Platforms(Platform.HOSTED_ONLY.class)
@Override
public void prepareBundle(String bundleName, ResourceBundle bundle, Function<String, Optional<Module>> findModule, Locale locale) {
public void prepareBundle(String bundleName, ResourceBundle bundle, Function<String, Optional<Module>> findModule, Locale locale, boolean jdkBundle) {
bundle.keySet();
this.resourceBundles.put(Pair.create(bundleName, locale), bundle);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ protected void addResourceBundles() {
/* Make sure the `bundle` content is complete. */
localeData.setSupplementary((ParallelListResourceBundle) bundle);
}
prepareBundle(bundle, locale);
prepareJDKBundle(bundle, locale);
}
}
});
Expand Down Expand Up @@ -562,7 +562,7 @@ public void prepareClassResourceBundle(String basename, String className) {
Class<?> bundleClass = findClassByName.apply(className);
UserError.guarantee(ResourceBundle.class.isAssignableFrom(bundleClass), "%s is not a subclass of ResourceBundle", bundleClass.getName());
trace("Adding class based resource bundle: " + className + " " + bundleClass);
support.registerRequiredReflectionAndResourcesForBundle(basename, Set.of());
support.registerRequiredReflectionAndResourcesForBundle(basename, Set.of(), false);
support.prepareClassResourceBundle(basename, bundleClass);
}

Expand Down Expand Up @@ -609,7 +609,7 @@ private void prepareBundleInternal(String baseName, Collection<Locale> wantedLoc
}
somethingFound |= !resourceBundle.isEmpty();
for (ResourceBundle bundle : resourceBundle) {
prepareBundle(baseName, bundle, locale);
prepareBundle(baseName, bundle, locale, false);
}
}

Expand Down Expand Up @@ -653,33 +653,32 @@ private void prepareBundleInternal(String baseName, Collection<Locale> wantedLoc
@Platforms(Platform.HOSTED_ONLY.class)
protected void prepareNegativeBundle(String baseName, Locale locale) {
support.registerBundleLookup(baseName, locale);
support.registerRequiredReflectionAndResourcesForBundleAndLocale(baseName, locale);
support.registerRequiredReflectionAndResourcesForBundleAndLocale(baseName, locale, false);
}

@Platforms(Platform.HOSTED_ONLY.class)
protected void prepareBundle(ResourceBundle bundle, Locale locale) {
protected void prepareJDKBundle(ResourceBundle bundle, Locale locale) {
String baseName = bundle.getBaseBundleName();
support.registerBundleLookup(baseName, locale);
prepareBundle(baseName, bundle, locale);
prepareBundle(baseName, bundle, locale, true);
}

@Platforms(Platform.HOSTED_ONLY.class)
private void prepareBundle(String bundleName, ResourceBundle bundle, Locale locale) {
private void prepareBundle(String bundleName, ResourceBundle bundle, Locale locale, boolean jdkBundle) {
trace("Adding bundle " + bundleName + ", locale " + locale);
/*
* Ensure that the bundle contents are loaded. We need to walk the whole bundle parent chain
* down to the root.
*/
for (ResourceBundle cur = bundle; cur != null; cur = SharedSecrets.getJavaUtilResourceBundleAccess().getParent(cur)) {
/* Register all bundles with their corresponding locales */
support.prepareBundle(bundleName, cur, this.imageClassLoader::findModule, cur.getLocale());
support.prepareBundle(bundleName, cur, this.imageClassLoader::findModule, cur.getLocale(), jdkBundle);
}

/*
* Finally, register the requested bundle with requested locale (Requested might be more
* specific than the actual bundle locale
*/
support.prepareBundle(bundleName, bundle, this.imageClassLoader::findModule, locale);
support.prepareBundle(bundleName, bundle, this.imageClassLoader::findModule, locale, jdkBundle);
}

@Platforms(Platform.HOSTED_ONLY.class)
Expand Down

0 comments on commit e1a6add

Please sign in to comment.