< prev index next >

src/java.base/share/classes/java/util/ResourceBundle.java

Print this page
rev 16532 : [mq]: 8172365

*** 59,69 **** --- 59,72 ---- import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.jar.JarEntry; + import java.util.spi.ResourceBundleControlProvider; import java.util.spi.ResourceBundleProvider; + import java.util.stream.Collectors; + import java.util.stream.Stream; import jdk.internal.loader.BootLoader; import jdk.internal.misc.JavaUtilResourceBundleAccess; import jdk.internal.misc.SharedSecrets; import jdk.internal.reflect.CallerSensitive;
*** 230,239 **** --- 233,244 ---- * find resource bundles using the given {@code ClassLoader} in named modules. * The {@code getBundle} method with a {@code Module} can be used, instead.</li> * <li>{@code ResourceBundle.Control} is <em>not</em> supported in named modules. * If the {@code getBundle} method with a {@code ResourceBundle.Control} is called * in a named module, the method will throw an {@code UnsupportedOperationException}. + * Any service providers of {@link ResourceBundleControlProvider} are ignored in + * named modules. * </li> * </ul> * * <h3><a name="RBP_support">ResourceBundleProvider Service Providers</a></h3> *
*** 260,269 **** --- 265,286 ---- * non-standard resource bundle formats, change the search strategy, or * define caching parameters. Refer to the descriptions of the class and the * {@link #getBundle(String, Locale, ClassLoader, Control) getBundle} * factory method for details. * + * <p><a name="modify_default_behavior">For the {@code getBundle} factory</a> + * methods that take no {@link Control} instance, their <a + * href="#default_behavior"> default behavior</a> of resource bundle loading + * can be modified with custom {@link + * ResourceBundleControlProvider} implementations. + * If any of the + * providers provides a {@link Control} for the given base name, that {@link + * Control} will be used instead of the default {@link Control}. If there is + * more than one service provider for supporting the same base name, + * the first one returned from {@link ServiceLoader} will be used. + * A custom {@link Control} implementation is ignored by named modules. + * * <h3>Cache Management</h3> * * Resource bundle instances created by the <code>getBundle</code> factory * methods are cached by default, and the factory methods return the same * resource bundle instance multiple times if it has been
*** 365,375 **** @Override public ResourceBundle getBundle(String baseName, Locale locale, Module module) { // use the given module as the caller to bypass the access check return getBundleImpl(module, module, ! baseName, locale, Control.INSTANCE); } @Override public ResourceBundle newResourceBundle(Class<? extends ResourceBundle> bundleClass) { return ResourceBundleProviderHelper.newResourceBundle(bundleClass); --- 382,393 ---- @Override public ResourceBundle getBundle(String baseName, Locale locale, Module module) { // use the given module as the caller to bypass the access check return getBundleImpl(module, module, ! baseName, locale, ! getDefaultControl(module, baseName)); } @Override public ResourceBundle newResourceBundle(Class<? extends ResourceBundle> bundleClass) { return ResourceBundleProviderHelper.newResourceBundle(bundleClass);
*** 813,823 **** @CallerSensitive public static final ResourceBundle getBundle(String baseName) { Class<?> caller = Reflection.getCallerClass(); return getBundleImpl(baseName, Locale.getDefault(), ! caller, Control.INSTANCE); } /** * Returns a resource bundle using the specified base name, the * default locale and the specified control. Calling this method --- 831,841 ---- @CallerSensitive public static final ResourceBundle getBundle(String baseName) { Class<?> caller = Reflection.getCallerClass(); return getBundleImpl(baseName, Locale.getDefault(), ! caller, getDefaultControl(caller, baseName)); } /** * Returns a resource bundle using the specified base name, the * default locale and the specified control. Calling this method
*** 887,897 **** public static final ResourceBundle getBundle(String baseName, Locale locale) { Class<?> caller = Reflection.getCallerClass(); return getBundleImpl(baseName, locale, ! caller, Control.INSTANCE); } /** * Gets a resource bundle using the specified base name and the default locale * on behalf of the specified module. This method is equivalent to calling --- 905,915 ---- public static final ResourceBundle getBundle(String baseName, Locale locale) { Class<?> caller = Reflection.getCallerClass(); return getBundleImpl(baseName, locale, ! caller, getDefaultControl(caller, baseName)); } /** * Gets a resource bundle using the specified base name and the default locale * on behalf of the specified module. This method is equivalent to calling
*** 923,933 **** * @see ResourceBundleProvider */ @CallerSensitive public static ResourceBundle getBundle(String baseName, Module module) { return getBundleFromModule(Reflection.getCallerClass(), module, baseName, ! Locale.getDefault(), Control.INSTANCE); } /** * Gets a resource bundle using the specified base name and locale * on behalf of the specified module. --- 941,952 ---- * @see ResourceBundleProvider */ @CallerSensitive public static ResourceBundle getBundle(String baseName, Module module) { return getBundleFromModule(Reflection.getCallerClass(), module, baseName, ! Locale.getDefault(), ! getDefaultControl(module, baseName)); } /** * Gets a resource bundle using the specified base name and locale * on behalf of the specified module.
*** 972,982 **** * @since 9 */ @CallerSensitive public static ResourceBundle getBundle(String baseName, Locale targetLocale, Module module) { return getBundleFromModule(Reflection.getCallerClass(), module, baseName, targetLocale, ! Control.INSTANCE); } /** * Returns a resource bundle using the specified base name, target * locale and control, and the caller's class loader. Calling this --- 991,1001 ---- * @since 9 */ @CallerSensitive public static ResourceBundle getBundle(String baseName, Locale targetLocale, Module module) { return getBundleFromModule(Reflection.getCallerClass(), module, baseName, targetLocale, ! getDefaultControl(module, baseName)); } /** * Returns a resource bundle using the specified base name, target * locale and control, and the caller's class loader. Calling this
*** 1028,1038 **** * Gets a resource bundle using the specified base name, locale, and class * loader. * * <p>This method behaves the same as calling * {@link #getBundle(String, Locale, ClassLoader, Control)} passing a ! * default instance of {@link Control}. * * <p><a name="default_behavior">The following describes the default * behavior</a>. * * <p> --- 1047,1060 ---- * Gets a resource bundle using the specified base name, locale, and class * loader. * * <p>This method behaves the same as calling * {@link #getBundle(String, Locale, ClassLoader, Control)} passing a ! * default instance of {@link Control} unless another {@link Control} is ! * provided with the {@link ResourceBundleControlProvider} SPI. Refer to the ! * description of <a href="#modify_default_behavior">modifying the default ! * behavior</a>. * * <p><a name="default_behavior">The following describes the default * behavior</a>. * * <p>
*** 1226,1236 **** { if (loader == null) { throw new NullPointerException(); } Class<?> caller = Reflection.getCallerClass(); ! return getBundleImpl(baseName, locale, caller, loader, Control.INSTANCE); } /** * Returns a resource bundle using the specified base name, target * locale, class loader and control. Unlike the {@linkplain --- 1248,1258 ---- { if (loader == null) { throw new NullPointerException(); } Class<?> caller = Reflection.getCallerClass(); ! return getBundleImpl(baseName, locale, caller, loader, getDefaultControl(caller, baseName)); } /** * Returns a resource bundle using the specified base name, target * locale, class loader and control. Unlike the {@linkplain
*** 1451,1460 **** --- 1473,1515 ---- Class<?> caller = Reflection.getCallerClass(); checkNamedModule(caller); return getBundleImpl(baseName, targetLocale, caller, loader, control); } + private static Control getDefaultControl(Class<?> caller, String baseName) { + return getDefaultControl(caller.getModule(), baseName); + } + + private static Control getDefaultControl(Module targetModule, String baseName) { + return targetModule.isNamed() ? + Control.INSTANCE : + ResourceBundleControlProviderHolder.getControl(baseName); + } + + private static class ResourceBundleControlProviderHolder { + private static final PrivilegedAction<List<ResourceBundleControlProvider>> pa = + () -> { + return Collections.unmodifiableList( + ServiceLoader.load(ResourceBundleControlProvider.class, + ClassLoader.getSystemClassLoader()).stream() + .map(ServiceLoader.Provider::get) + .collect(Collectors.toList())); + }; + + private static final List<ResourceBundleControlProvider> CONTROL_PROVIDERS = + AccessController.doPrivileged(pa); + + private static Control getControl(String baseName) { + return CONTROL_PROVIDERS.isEmpty() ? + Control.INSTANCE : + CONTROL_PROVIDERS.stream() + .flatMap(provider -> Stream.ofNullable(provider.getControl(baseName))) + .findFirst() + .orElse(Control.INSTANCE); + } + } + private static void checkNamedModule(Class<?> caller) { if (caller.getModule().isNamed()) { throw new UnsupportedOperationException( "ResourceBundle.Control not supported in named modules"); }
*** 2412,2422 **** * </pre> * * @apiNote <a name="note">{@code ResourceBundle.Control} is not supported * in named modules.</a> If the {@code ResourceBundle.getBundle} method with * a {@code ResourceBundle.Control} is called in a named module, the method ! * will throw an {@link UnsupportedOperationException}. * * @since 1.6 * @see java.util.spi.ResourceBundleProvider */ public static class Control { --- 2467,2478 ---- * </pre> * * @apiNote <a name="note">{@code ResourceBundle.Control} is not supported * in named modules.</a> If the {@code ResourceBundle.getBundle} method with * a {@code ResourceBundle.Control} is called in a named module, the method ! * will throw an {@link UnsupportedOperationException}. Any service providers ! * of {@link ResourceBundleControlProvider} are ignored in named modules. * * @since 1.6 * @see java.util.spi.ResourceBundleProvider */ public static class Control {
< prev index next >