< prev index next >

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

Print this page
rev 16532 : [mq]: 8172365


  44 import java.io.InputStream;
  45 import java.io.UncheckedIOException;
  46 import java.lang.ref.Reference;
  47 import java.lang.ref.ReferenceQueue;
  48 import java.lang.ref.SoftReference;
  49 import java.lang.ref.WeakReference;
  50 import java.lang.reflect.Constructor;
  51 import java.lang.reflect.InvocationTargetException;
  52 import java.lang.reflect.Modifier;
  53 import java.lang.reflect.Module;
  54 import java.net.JarURLConnection;
  55 import java.net.URL;
  56 import java.net.URLConnection;
  57 import java.security.AccessController;
  58 import java.security.PrivilegedAction;
  59 import java.security.PrivilegedActionException;
  60 import java.security.PrivilegedExceptionAction;
  61 import java.util.concurrent.ConcurrentHashMap;
  62 import java.util.concurrent.ConcurrentMap;
  63 import java.util.jar.JarEntry;

  64 import java.util.spi.ResourceBundleProvider;


  65 
  66 import jdk.internal.loader.BootLoader;
  67 import jdk.internal.misc.JavaUtilResourceBundleAccess;
  68 import jdk.internal.misc.SharedSecrets;
  69 import jdk.internal.reflect.CallerSensitive;
  70 import jdk.internal.reflect.Reflection;
  71 import sun.security.action.GetPropertyAction;
  72 import sun.util.locale.BaseLocale;
  73 import sun.util.locale.LocaleObjectCache;
  74 import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION;
  75 
  76 
  77 /**
  78  *
  79  * Resource bundles contain locale-specific objects.  When your program needs a
  80  * locale-specific resource, a <code>String</code> for example, your program can
  81  * load it from the resource bundle that is appropriate for the current user's
  82  * locale. In this way, you can write program code that is largely independent
  83  * of the user's locale isolating most, if not all, of the locale-specific
  84  * information in resource bundles.


 215  * providers of {@link ResourceBundleProvider}. The caller module must declare
 216  * "{@code uses}" and the service interface name is the concatenation of the
 217  * base name of the bundles and the string "{@code Provider}". The
 218  * <em>bundle provider modules</em> containing resource bundles must
 219  * declare "{@code provides}" with the service interface name and
 220  * its implementation class name. For example, if the base name is
 221  * "{@code com.example.app.MyResources}", the caller module must declare
 222  * "{@code uses com.example.app.MyResourcesProvider;}" and a module containing resource
 223  * bundles must declare "{@code provides com.example.app.MyResourcesProvider
 224  * with com.example.app.internal.MyResourcesProviderImpl;}"
 225  * where {@code com.example.app.internal.MyResourcesProviderImpl} is an
 226  * implementation class of {@code com.example.app.MyResourcesProvider}.</li>
 227  * <li>If you want to use non-standard formats in named modules, such as XML,
 228  * {@link ResourceBundleProvider} needs to be used.</li>
 229  * <li>The {@code getBundle} method with a {@code ClassLoader} may not be able to
 230  * find resource bundles using the given {@code ClassLoader} in named modules.
 231  * The {@code getBundle} method with a {@code Module} can be used, instead.</li>
 232  * <li>{@code ResourceBundle.Control} is <em>not</em> supported in named modules.
 233  * If the {@code getBundle} method with a {@code ResourceBundle.Control} is called
 234  * in a named module, the method will throw an {@code UnsupportedOperationException}.


 235  * </li>
 236  * </ul>
 237  *
 238  * <h3><a name="RBP_support">ResourceBundleProvider Service Providers</a></h3>
 239  *
 240  * The {@code getBundle} factory methods load service providers of
 241  * {@link ResourceBundleProvider}, if available, using {@link ServiceLoader}.
 242  * The service type is designated by {@code basename+"Provider"}. For
 243  * example, if the base name is "{@code com.example.app.MyResources}", the service
 244  * type is {@code com.example.app.MyResourcesProvider}.
 245  * <p>
 246  * In named modules, the loaded service providers for the given base name are
 247  * used to load resource bundles. If no service provider is available, or if
 248  * none of the service providers returns a resource bundle and the caller module
 249  * doesn't have its own service provider, the {@code getBundle} factory method
 250  * searches for resource bundles that are local in the caller module and that
 251  * are visible to the class loader of the caller module.  The resource bundle
 252  * formats for local module searching are "java.class" and "java.properties".
 253  *
 254  * <h3>ResourceBundle.Control</h3>
 255  *
 256  * The {@link ResourceBundle.Control} class provides information necessary
 257  * to perform the bundle loading process by the <code>getBundle</code>
 258  * factory methods that take a <code>ResourceBundle.Control</code>
 259  * instance. You can implement your own subclass in order to enable
 260  * non-standard resource bundle formats, change the search strategy, or
 261  * define caching parameters. Refer to the descriptions of the class and the
 262  * {@link #getBundle(String, Locale, ClassLoader, Control) getBundle}
 263  * factory method for details.
 264  *












 265  * <h3>Cache Management</h3>
 266  *
 267  * Resource bundle instances created by the <code>getBundle</code> factory
 268  * methods are cached by default, and the factory methods return the same
 269  * resource bundle instance multiple times if it has been
 270  * cached. <code>getBundle</code> clients may clear the cache, manage the
 271  * lifetime of cached resource bundle instances using time-to-live values,
 272  * or specify not to cache resource bundle instances. Refer to the
 273  * descriptions of the {@linkplain #getBundle(String, Locale, ClassLoader,
 274  * Control) <code>getBundle</code> factory method}, {@link
 275  * #clearCache(ClassLoader) clearCache}, {@link
 276  * Control#getTimeToLive(String, Locale)
 277  * ResourceBundle.Control.getTimeToLive}, and {@link
 278  * Control#needsReload(String, Locale, String, ClassLoader, ResourceBundle,
 279  * long) ResourceBundle.Control.needsReload} for details.
 280  *
 281  * <h3>Example</h3>
 282  *
 283  * The following is a very simple example of a <code>ResourceBundle</code>
 284  * subclass, <code>MyResources</code>, that manages two resources (for a larger number of


 350 
 351                 @Override
 352                 public ResourceBundle getParent(ResourceBundle bundle) {
 353                     return bundle.parent;
 354                 }
 355 
 356                 @Override
 357                 public void setLocale(ResourceBundle bundle, Locale locale) {
 358                     bundle.locale = locale;
 359                 }
 360 
 361                 @Override
 362                 public void setName(ResourceBundle bundle, String name) {
 363                     bundle.name = name;
 364                 }
 365 
 366                 @Override
 367                 public ResourceBundle getBundle(String baseName, Locale locale, Module module) {
 368                     // use the given module as the caller to bypass the access check
 369                     return getBundleImpl(module, module,
 370                                          baseName, locale, Control.INSTANCE);

 371                 }
 372 
 373                 @Override
 374                 public ResourceBundle newResourceBundle(Class<? extends ResourceBundle> bundleClass) {
 375                     return ResourceBundleProviderHelper.newResourceBundle(bundleClass);
 376                 }
 377             });
 378     }
 379 
 380     /** constant indicating that no resource bundle exists */
 381     private static final ResourceBundle NONEXISTENT_BUNDLE = new ResourceBundle() {
 382             public Enumeration<String> getKeys() { return null; }
 383             protected Object handleGetObject(String key) { return null; }
 384             public String toString() { return "NONEXISTENT_BUNDLE"; }
 385         };
 386 
 387 
 388     /**
 389      * The cache is a map from cache keys (with bundle base name, locale, and
 390      * class loader) to either a resource bundle or NONEXISTENT_BUNDLE wrapped by a


 798      * <blockquote>
 799      * <code>getBundle(baseName, Locale.getDefault(), this.getClass().getClassLoader())</code>,
 800      * </blockquote>
 801      * except that <code>getClassLoader()</code> is run with the security
 802      * privileges of <code>ResourceBundle</code>.
 803      * See {@link #getBundle(String, Locale, ClassLoader) getBundle}
 804      * for a complete description of the search and instantiation strategy.
 805      *
 806      * @param baseName the base name of the resource bundle, a fully qualified class name
 807      * @exception java.lang.NullPointerException
 808      *     if <code>baseName</code> is <code>null</code>
 809      * @exception MissingResourceException
 810      *     if no resource bundle for the specified base name can be found
 811      * @return a resource bundle for the given base name and the default locale
 812      */
 813     @CallerSensitive
 814     public static final ResourceBundle getBundle(String baseName)
 815     {
 816         Class<?> caller = Reflection.getCallerClass();
 817         return getBundleImpl(baseName, Locale.getDefault(),
 818                              caller, Control.INSTANCE);
 819     }
 820 
 821     /**
 822      * Returns a resource bundle using the specified base name, the
 823      * default locale and the specified control. Calling this method
 824      * is equivalent to calling
 825      * <pre>
 826      * getBundle(baseName, Locale.getDefault(),
 827      *           this.getClass().getClassLoader(), control),
 828      * </pre>
 829      * except that <code>getClassLoader()</code> is run with the security
 830      * privileges of <code>ResourceBundle</code>.  See {@link
 831      * #getBundle(String, Locale, ClassLoader, Control) getBundle} for the
 832      * complete description of the resource bundle loading process with a
 833      * <code>ResourceBundle.Control</code>.
 834      *
 835      * @param baseName
 836      *        the base name of the resource bundle, a fully qualified class
 837      *        name
 838      * @param control


 872      * privileges of <code>ResourceBundle</code>.
 873      * See {@link #getBundle(String, Locale, ClassLoader) getBundle}
 874      * for a complete description of the search and instantiation strategy.
 875      *
 876      * @param baseName
 877      *        the base name of the resource bundle, a fully qualified class name
 878      * @param locale
 879      *        the locale for which a resource bundle is desired
 880      * @exception NullPointerException
 881      *        if <code>baseName</code> or <code>locale</code> is <code>null</code>
 882      * @exception MissingResourceException
 883      *        if no resource bundle for the specified base name can be found
 884      * @return a resource bundle for the given base name and locale
 885      */
 886     @CallerSensitive
 887     public static final ResourceBundle getBundle(String baseName,
 888                                                  Locale locale)
 889     {
 890         Class<?> caller = Reflection.getCallerClass();
 891         return getBundleImpl(baseName, locale,
 892                              caller, Control.INSTANCE);
 893     }
 894 
 895     /**
 896      * Gets a resource bundle using the specified base name and the default locale
 897      * on behalf of the specified module. This method is equivalent to calling
 898      * <blockquote>
 899      * <code>getBundle(baseName, Locale.getDefault(), module)</code>
 900      * </blockquote>
 901      *
 902      * <p> Resource bundles in named modules may be encapsulated.  When
 903      * the resource bundle is loaded from a provider, the caller module
 904      * must have an appropriate <i>uses</i> clause in its <i>module descriptor</i>
 905      * to declare that the module uses implementations of {@code "baseName"Provider}.
 906      * When the resource bundle is loaded from the specified module, it is
 907      * subject to the encapsulation rules specified by
 908      * {@link Module#getResourceAsStream Module.getResourceAsStream}.
 909      *
 910      * @param baseName the base name of the resource bundle,
 911      *                 a fully qualified class name
 912      * @param module   the module for which the resource bundle is searched
 913      * @throws NullPointerException
 914      *         if {@code baseName} or {@code module} is {@code null}
 915      * @throws SecurityException
 916      *         if a security manager exists and the caller is not the specified
 917      *         module and doesn't have {@code RuntimePermission("getClassLoader")}
 918      * @throws MissingResourceException
 919      *         if no resource bundle for the specified base name can be found in the
 920      *         specified module
 921      * @return a resource bundle for the given base name and the default locale
 922      * @since 9
 923      * @see ResourceBundleProvider
 924      */
 925     @CallerSensitive
 926     public static ResourceBundle getBundle(String baseName, Module module) {
 927         return getBundleFromModule(Reflection.getCallerClass(), module, baseName,
 928                                    Locale.getDefault(), Control.INSTANCE);

 929     }
 930 
 931     /**
 932      * Gets a resource bundle using the specified base name and locale
 933      * on behalf of the specified module.
 934      *
 935      * <p> Resource bundles in named modules may be encapsulated.  When
 936      * the resource bundle is loaded from a provider, the caller module
 937      * must have an appropriate <i>uses</i> clause in its <i>module descriptor</i>
 938      * to declare that the module uses implementations of {@code "baseName"Provider}.
 939      * When the resource bundle is loaded from the specified module, it is
 940      * subject to the encapsulation rules specified by
 941      * {@link Module#getResourceAsStream Module.getResourceAsStream}.
 942      *
 943      * <p>
 944      * If the given {@code module} is a named module, this method will
 945      * load the service providers for {@link java.util.spi.ResourceBundleProvider}
 946      * and also resource bundles that are local in the given module or that
 947      * are visible to the class loader of the given module (refer to the
 948      * <a href="#bundleprovider">Resource Bundles in Named Modules</a> section


 957      *
 958      * @param baseName the base name of the resource bundle,
 959      *                 a fully qualified class name
 960      * @param targetLocale the locale for which a resource bundle is desired
 961      * @param module   the module for which the resource bundle is searched
 962      * @throws NullPointerException
 963      *         if {@code baseName}, {@code targetLocale}, or {@code module} is
 964      *         {@code null}
 965      * @throws SecurityException
 966      *         if a security manager exists and the caller is not the specified
 967      *         module and doesn't have {@code RuntimePermission("getClassLoader")}
 968      * @throws MissingResourceException
 969      *         if no resource bundle for the specified base name and locale can
 970      *         be found in the specified {@code module}
 971      * @return a resource bundle for the given base name and locale in the module
 972      * @since 9
 973      */
 974     @CallerSensitive
 975     public static ResourceBundle getBundle(String baseName, Locale targetLocale, Module module) {
 976         return getBundleFromModule(Reflection.getCallerClass(), module, baseName, targetLocale,
 977                                    Control.INSTANCE);
 978     }
 979 
 980     /**
 981      * Returns a resource bundle using the specified base name, target
 982      * locale and control, and the caller's class loader. Calling this
 983      * method is equivalent to calling
 984      * <pre>
 985      * getBundle(baseName, targetLocale, this.getClass().getClassLoader(),
 986      *           control),
 987      * </pre>
 988      * except that <code>getClassLoader()</code> is run with the security
 989      * privileges of <code>ResourceBundle</code>.  See {@link
 990      * #getBundle(String, Locale, ClassLoader, Control) getBundle} for the
 991      * complete description of the resource bundle loading process with a
 992      * <code>ResourceBundle.Control</code>.
 993      *
 994      * @param baseName
 995      *        the base name of the resource bundle, a fully qualified
 996      *        class name
 997      * @param targetLocale


1013      *         Note that validation of <code>control</code> is performed as
1014      *         needed.
1015      * @throws UnsupportedOperationException
1016      *         if this method is called in a named module
1017      * @since 1.6
1018      */
1019     @CallerSensitive
1020     public static final ResourceBundle getBundle(String baseName, Locale targetLocale,
1021                                                  Control control) {
1022         Class<?> caller = Reflection.getCallerClass();
1023         checkNamedModule(caller);
1024         return getBundleImpl(baseName, targetLocale, caller, control);
1025     }
1026 
1027     /**
1028      * Gets a resource bundle using the specified base name, locale, and class
1029      * loader.
1030      *
1031      * <p>This method behaves the same as calling
1032      * {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
1033      * default instance of {@link Control}.



1034      *
1035      * <p><a name="default_behavior">The following describes the default
1036      * behavior</a>.
1037      *
1038      * <p>
1039      * Resource bundles in a named module are private to that module.  If
1040      * the caller is in a named module, this method will find resource bundles
1041      * from the service providers of {@link java.util.spi.ResourceBundleProvider}
1042      * and also find resource bundles that are in the caller's module or
1043      * that are visible to the given class loader.
1044      * If the caller is in a named module and the given {@code loader} is
1045      * different than the caller's class loader, or if the caller is not in
1046      * a named module, this method will not find resource bundles from named
1047      * modules.
1048      *
1049      * <p><code>getBundle</code> uses the base name, the specified locale, and
1050      * the default locale (obtained from {@link java.util.Locale#getDefault()
1051      * Locale.getDefault}) to generate a sequence of <a
1052      * name="candidates"><em>candidate bundle names</em></a>.  If the specified
1053      * locale's language, script, country, and variant are all empty strings,


1211      * on behalf on a specific module instead.
1212      *
1213      * @param baseName the base name of the resource bundle, a fully qualified class name
1214      * @param locale the locale for which a resource bundle is desired
1215      * @param loader the class loader from which to load the resource bundle
1216      * @return a resource bundle for the given base name and locale
1217      * @exception java.lang.NullPointerException
1218      *        if <code>baseName</code>, <code>locale</code>, or <code>loader</code> is <code>null</code>
1219      * @exception MissingResourceException
1220      *        if no resource bundle for the specified base name can be found
1221      * @since 1.2
1222      */
1223     @CallerSensitive
1224     public static ResourceBundle getBundle(String baseName, Locale locale,
1225                                            ClassLoader loader)
1226     {
1227         if (loader == null) {
1228             throw new NullPointerException();
1229         }
1230         Class<?> caller = Reflection.getCallerClass();
1231         return getBundleImpl(baseName, locale, caller, loader, Control.INSTANCE);
1232     }
1233 
1234     /**
1235      * Returns a resource bundle using the specified base name, target
1236      * locale, class loader and control. Unlike the {@linkplain
1237      * #getBundle(String, Locale, ClassLoader) <code>getBundle</code>
1238      * factory methods with no <code>control</code> argument}, the given
1239      * <code>control</code> specifies how to locate and instantiate resource
1240      * bundles. Conceptually, the bundle loading process with the given
1241      * <code>control</code> is performed in the following steps.
1242      *
1243      * <ol>
1244      * <li>This factory method looks up the resource bundle in the cache for
1245      * the specified <code>baseName</code>, <code>targetLocale</code> and
1246      * <code>loader</code>.  If the requested resource bundle instance is
1247      * found in the cache and the time-to-live periods of the instance and
1248      * all of its parent instances have not expired, the instance is returned
1249      * to the caller. Otherwise, this factory method proceeds with the
1250      * loading process below.</li>
1251      *


1436      * @throws IllegalArgumentException
1437      *         if the given <code>control</code> doesn't perform properly
1438      *         (e.g., <code>control.getCandidateLocales</code> returns null.)
1439      *         Note that validation of <code>control</code> is performed as
1440      *         needed.
1441      * @throws UnsupportedOperationException
1442      *         if this method is called in a named module
1443      * @since 1.6
1444      */
1445     @CallerSensitive
1446     public static ResourceBundle getBundle(String baseName, Locale targetLocale,
1447                                            ClassLoader loader, Control control) {
1448         if (loader == null || control == null) {
1449             throw new NullPointerException();
1450         }
1451         Class<?> caller = Reflection.getCallerClass();
1452         checkNamedModule(caller);
1453         return getBundleImpl(baseName, targetLocale, caller, loader, control);
1454     }
1455 

































1456     private static void checkNamedModule(Class<?> caller) {
1457         if (caller.getModule().isNamed()) {
1458             throw new UnsupportedOperationException(
1459                     "ResourceBundle.Control not supported in named modules");
1460         }
1461     }
1462 
1463     private static ResourceBundle getBundleImpl(String baseName,
1464                                                 Locale locale,
1465                                                 Class<?> caller,
1466                                                 Control control) {
1467         return getBundleImpl(baseName, locale, caller, caller.getClassLoader(), control);
1468     }
1469 
1470     /**
1471      * This method will find resource bundles using the legacy mechanism
1472      * if the caller is unnamed module or the given class loader is
1473      * not the class loader of the caller module getting the resource
1474      * bundle, i.e. find the class that is visible to the class loader
1475      * and properties from unnamed module.


2397      * ...
2398      *
2399      * private static class XMLResourceBundle extends ResourceBundle {
2400      *     private Properties props;
2401      *     XMLResourceBundle(InputStream stream) throws IOException {
2402      *         props = new Properties();
2403      *         props.loadFromXML(stream);
2404      *     }
2405      *     protected Object handleGetObject(String key) {
2406      *         return props.getProperty(key);
2407      *     }
2408      *     public Enumeration&lt;String&gt; getKeys() {
2409      *         ...
2410      *     }
2411      * }
2412      * </pre>
2413      *
2414      * @apiNote <a name="note">{@code ResourceBundle.Control} is not supported
2415      * in named modules.</a> If the {@code ResourceBundle.getBundle} method with
2416      * a {@code ResourceBundle.Control} is called in a named module, the method
2417      * will throw an {@link UnsupportedOperationException}.

2418      *
2419      * @since 1.6
2420      * @see java.util.spi.ResourceBundleProvider
2421      */
2422     public static class Control {
2423         /**
2424          * The default format <code>List</code>, which contains the strings
2425          * <code>"java.class"</code> and <code>"java.properties"</code>, in
2426          * this order. This <code>List</code> is unmodifiable.
2427          *
2428          * @see #getFormats(String)
2429          */
2430         public static final List<String> FORMAT_DEFAULT
2431             = List.of("java.class", "java.properties");
2432 
2433         /**
2434          * The class-only format <code>List</code> containing
2435          * <code>"java.class"</code>. This <code>List</code> is unmodifiable.
2436          *
2437          * @see #getFormats(String)




  44 import java.io.InputStream;
  45 import java.io.UncheckedIOException;
  46 import java.lang.ref.Reference;
  47 import java.lang.ref.ReferenceQueue;
  48 import java.lang.ref.SoftReference;
  49 import java.lang.ref.WeakReference;
  50 import java.lang.reflect.Constructor;
  51 import java.lang.reflect.InvocationTargetException;
  52 import java.lang.reflect.Modifier;
  53 import java.lang.reflect.Module;
  54 import java.net.JarURLConnection;
  55 import java.net.URL;
  56 import java.net.URLConnection;
  57 import java.security.AccessController;
  58 import java.security.PrivilegedAction;
  59 import java.security.PrivilegedActionException;
  60 import java.security.PrivilegedExceptionAction;
  61 import java.util.concurrent.ConcurrentHashMap;
  62 import java.util.concurrent.ConcurrentMap;
  63 import java.util.jar.JarEntry;
  64 import java.util.spi.ResourceBundleControlProvider;
  65 import java.util.spi.ResourceBundleProvider;
  66 import java.util.stream.Collectors;
  67 import java.util.stream.Stream;
  68 
  69 import jdk.internal.loader.BootLoader;
  70 import jdk.internal.misc.JavaUtilResourceBundleAccess;
  71 import jdk.internal.misc.SharedSecrets;
  72 import jdk.internal.reflect.CallerSensitive;
  73 import jdk.internal.reflect.Reflection;
  74 import sun.security.action.GetPropertyAction;
  75 import sun.util.locale.BaseLocale;
  76 import sun.util.locale.LocaleObjectCache;
  77 import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION;
  78 
  79 
  80 /**
  81  *
  82  * Resource bundles contain locale-specific objects.  When your program needs a
  83  * locale-specific resource, a <code>String</code> for example, your program can
  84  * load it from the resource bundle that is appropriate for the current user's
  85  * locale. In this way, you can write program code that is largely independent
  86  * of the user's locale isolating most, if not all, of the locale-specific
  87  * information in resource bundles.


 218  * providers of {@link ResourceBundleProvider}. The caller module must declare
 219  * "{@code uses}" and the service interface name is the concatenation of the
 220  * base name of the bundles and the string "{@code Provider}". The
 221  * <em>bundle provider modules</em> containing resource bundles must
 222  * declare "{@code provides}" with the service interface name and
 223  * its implementation class name. For example, if the base name is
 224  * "{@code com.example.app.MyResources}", the caller module must declare
 225  * "{@code uses com.example.app.MyResourcesProvider;}" and a module containing resource
 226  * bundles must declare "{@code provides com.example.app.MyResourcesProvider
 227  * with com.example.app.internal.MyResourcesProviderImpl;}"
 228  * where {@code com.example.app.internal.MyResourcesProviderImpl} is an
 229  * implementation class of {@code com.example.app.MyResourcesProvider}.</li>
 230  * <li>If you want to use non-standard formats in named modules, such as XML,
 231  * {@link ResourceBundleProvider} needs to be used.</li>
 232  * <li>The {@code getBundle} method with a {@code ClassLoader} may not be able to
 233  * find resource bundles using the given {@code ClassLoader} in named modules.
 234  * The {@code getBundle} method with a {@code Module} can be used, instead.</li>
 235  * <li>{@code ResourceBundle.Control} is <em>not</em> supported in named modules.
 236  * If the {@code getBundle} method with a {@code ResourceBundle.Control} is called
 237  * in a named module, the method will throw an {@code UnsupportedOperationException}.
 238  * Any service providers of {@link ResourceBundleControlProvider} are ignored in
 239  * named modules.
 240  * </li>
 241  * </ul>
 242  *
 243  * <h3><a name="RBP_support">ResourceBundleProvider Service Providers</a></h3>
 244  *
 245  * The {@code getBundle} factory methods load service providers of
 246  * {@link ResourceBundleProvider}, if available, using {@link ServiceLoader}.
 247  * The service type is designated by {@code basename+"Provider"}. For
 248  * example, if the base name is "{@code com.example.app.MyResources}", the service
 249  * type is {@code com.example.app.MyResourcesProvider}.
 250  * <p>
 251  * In named modules, the loaded service providers for the given base name are
 252  * used to load resource bundles. If no service provider is available, or if
 253  * none of the service providers returns a resource bundle and the caller module
 254  * doesn't have its own service provider, the {@code getBundle} factory method
 255  * searches for resource bundles that are local in the caller module and that
 256  * are visible to the class loader of the caller module.  The resource bundle
 257  * formats for local module searching are "java.class" and "java.properties".
 258  *
 259  * <h3>ResourceBundle.Control</h3>
 260  *
 261  * The {@link ResourceBundle.Control} class provides information necessary
 262  * to perform the bundle loading process by the <code>getBundle</code>
 263  * factory methods that take a <code>ResourceBundle.Control</code>
 264  * instance. You can implement your own subclass in order to enable
 265  * non-standard resource bundle formats, change the search strategy, or
 266  * define caching parameters. Refer to the descriptions of the class and the
 267  * {@link #getBundle(String, Locale, ClassLoader, Control) getBundle}
 268  * factory method for details.
 269  *
 270  * <p><a name="modify_default_behavior">For the {@code getBundle} factory</a>
 271  * methods that take no {@link Control} instance, their <a
 272  * href="#default_behavior"> default behavior</a> of resource bundle loading
 273  * can be modified with custom {@link
 274  * ResourceBundleControlProvider} implementations. 
 275  * If any of the
 276  * providers provides a {@link Control} for the given base name, that {@link
 277  * Control} will be used instead of the default {@link Control}. If there is
 278  * more than one service provider for supporting the same base name,
 279  * the first one returned from {@link ServiceLoader} will be used.
 280  * A custom {@link Control} implementation is ignored by named modules.
 281  *
 282  * <h3>Cache Management</h3>
 283  *
 284  * Resource bundle instances created by the <code>getBundle</code> factory
 285  * methods are cached by default, and the factory methods return the same
 286  * resource bundle instance multiple times if it has been
 287  * cached. <code>getBundle</code> clients may clear the cache, manage the
 288  * lifetime of cached resource bundle instances using time-to-live values,
 289  * or specify not to cache resource bundle instances. Refer to the
 290  * descriptions of the {@linkplain #getBundle(String, Locale, ClassLoader,
 291  * Control) <code>getBundle</code> factory method}, {@link
 292  * #clearCache(ClassLoader) clearCache}, {@link
 293  * Control#getTimeToLive(String, Locale)
 294  * ResourceBundle.Control.getTimeToLive}, and {@link
 295  * Control#needsReload(String, Locale, String, ClassLoader, ResourceBundle,
 296  * long) ResourceBundle.Control.needsReload} for details.
 297  *
 298  * <h3>Example</h3>
 299  *
 300  * The following is a very simple example of a <code>ResourceBundle</code>
 301  * subclass, <code>MyResources</code>, that manages two resources (for a larger number of


 367 
 368                 @Override
 369                 public ResourceBundle getParent(ResourceBundle bundle) {
 370                     return bundle.parent;
 371                 }
 372 
 373                 @Override
 374                 public void setLocale(ResourceBundle bundle, Locale locale) {
 375                     bundle.locale = locale;
 376                 }
 377 
 378                 @Override
 379                 public void setName(ResourceBundle bundle, String name) {
 380                     bundle.name = name;
 381                 }
 382 
 383                 @Override
 384                 public ResourceBundle getBundle(String baseName, Locale locale, Module module) {
 385                     // use the given module as the caller to bypass the access check
 386                     return getBundleImpl(module, module,
 387                                          baseName, locale,
 388                                          getDefaultControl(module, baseName));
 389                 }
 390 
 391                 @Override
 392                 public ResourceBundle newResourceBundle(Class<? extends ResourceBundle> bundleClass) {
 393                     return ResourceBundleProviderHelper.newResourceBundle(bundleClass);
 394                 }
 395             });
 396     }
 397 
 398     /** constant indicating that no resource bundle exists */
 399     private static final ResourceBundle NONEXISTENT_BUNDLE = new ResourceBundle() {
 400             public Enumeration<String> getKeys() { return null; }
 401             protected Object handleGetObject(String key) { return null; }
 402             public String toString() { return "NONEXISTENT_BUNDLE"; }
 403         };
 404 
 405 
 406     /**
 407      * The cache is a map from cache keys (with bundle base name, locale, and
 408      * class loader) to either a resource bundle or NONEXISTENT_BUNDLE wrapped by a


 816      * <blockquote>
 817      * <code>getBundle(baseName, Locale.getDefault(), this.getClass().getClassLoader())</code>,
 818      * </blockquote>
 819      * except that <code>getClassLoader()</code> is run with the security
 820      * privileges of <code>ResourceBundle</code>.
 821      * See {@link #getBundle(String, Locale, ClassLoader) getBundle}
 822      * for a complete description of the search and instantiation strategy.
 823      *
 824      * @param baseName the base name of the resource bundle, a fully qualified class name
 825      * @exception java.lang.NullPointerException
 826      *     if <code>baseName</code> is <code>null</code>
 827      * @exception MissingResourceException
 828      *     if no resource bundle for the specified base name can be found
 829      * @return a resource bundle for the given base name and the default locale
 830      */
 831     @CallerSensitive
 832     public static final ResourceBundle getBundle(String baseName)
 833     {
 834         Class<?> caller = Reflection.getCallerClass();
 835         return getBundleImpl(baseName, Locale.getDefault(),
 836                              caller, getDefaultControl(caller, baseName));
 837     }
 838 
 839     /**
 840      * Returns a resource bundle using the specified base name, the
 841      * default locale and the specified control. Calling this method
 842      * is equivalent to calling
 843      * <pre>
 844      * getBundle(baseName, Locale.getDefault(),
 845      *           this.getClass().getClassLoader(), control),
 846      * </pre>
 847      * except that <code>getClassLoader()</code> is run with the security
 848      * privileges of <code>ResourceBundle</code>.  See {@link
 849      * #getBundle(String, Locale, ClassLoader, Control) getBundle} for the
 850      * complete description of the resource bundle loading process with a
 851      * <code>ResourceBundle.Control</code>.
 852      *
 853      * @param baseName
 854      *        the base name of the resource bundle, a fully qualified class
 855      *        name
 856      * @param control


 890      * privileges of <code>ResourceBundle</code>.
 891      * See {@link #getBundle(String, Locale, ClassLoader) getBundle}
 892      * for a complete description of the search and instantiation strategy.
 893      *
 894      * @param baseName
 895      *        the base name of the resource bundle, a fully qualified class name
 896      * @param locale
 897      *        the locale for which a resource bundle is desired
 898      * @exception NullPointerException
 899      *        if <code>baseName</code> or <code>locale</code> is <code>null</code>
 900      * @exception MissingResourceException
 901      *        if no resource bundle for the specified base name can be found
 902      * @return a resource bundle for the given base name and locale
 903      */
 904     @CallerSensitive
 905     public static final ResourceBundle getBundle(String baseName,
 906                                                  Locale locale)
 907     {
 908         Class<?> caller = Reflection.getCallerClass();
 909         return getBundleImpl(baseName, locale,
 910                              caller, getDefaultControl(caller, baseName));
 911     }
 912 
 913     /**
 914      * Gets a resource bundle using the specified base name and the default locale
 915      * on behalf of the specified module. This method is equivalent to calling
 916      * <blockquote>
 917      * <code>getBundle(baseName, Locale.getDefault(), module)</code>
 918      * </blockquote>
 919      *
 920      * <p> Resource bundles in named modules may be encapsulated.  When
 921      * the resource bundle is loaded from a provider, the caller module
 922      * must have an appropriate <i>uses</i> clause in its <i>module descriptor</i>
 923      * to declare that the module uses implementations of {@code "baseName"Provider}.
 924      * When the resource bundle is loaded from the specified module, it is
 925      * subject to the encapsulation rules specified by
 926      * {@link Module#getResourceAsStream Module.getResourceAsStream}.
 927      *
 928      * @param baseName the base name of the resource bundle,
 929      *                 a fully qualified class name
 930      * @param module   the module for which the resource bundle is searched
 931      * @throws NullPointerException
 932      *         if {@code baseName} or {@code module} is {@code null}
 933      * @throws SecurityException
 934      *         if a security manager exists and the caller is not the specified
 935      *         module and doesn't have {@code RuntimePermission("getClassLoader")}
 936      * @throws MissingResourceException
 937      *         if no resource bundle for the specified base name can be found in the
 938      *         specified module
 939      * @return a resource bundle for the given base name and the default locale
 940      * @since 9
 941      * @see ResourceBundleProvider
 942      */
 943     @CallerSensitive
 944     public static ResourceBundle getBundle(String baseName, Module module) {
 945         return getBundleFromModule(Reflection.getCallerClass(), module, baseName,
 946                                    Locale.getDefault(),
 947                                    getDefaultControl(module, baseName));
 948     }
 949 
 950     /**
 951      * Gets a resource bundle using the specified base name and locale
 952      * on behalf of the specified module.
 953      *
 954      * <p> Resource bundles in named modules may be encapsulated.  When
 955      * the resource bundle is loaded from a provider, the caller module
 956      * must have an appropriate <i>uses</i> clause in its <i>module descriptor</i>
 957      * to declare that the module uses implementations of {@code "baseName"Provider}.
 958      * When the resource bundle is loaded from the specified module, it is
 959      * subject to the encapsulation rules specified by
 960      * {@link Module#getResourceAsStream Module.getResourceAsStream}.
 961      *
 962      * <p>
 963      * If the given {@code module} is a named module, this method will
 964      * load the service providers for {@link java.util.spi.ResourceBundleProvider}
 965      * and also resource bundles that are local in the given module or that
 966      * are visible to the class loader of the given module (refer to the
 967      * <a href="#bundleprovider">Resource Bundles in Named Modules</a> section


 976      *
 977      * @param baseName the base name of the resource bundle,
 978      *                 a fully qualified class name
 979      * @param targetLocale the locale for which a resource bundle is desired
 980      * @param module   the module for which the resource bundle is searched
 981      * @throws NullPointerException
 982      *         if {@code baseName}, {@code targetLocale}, or {@code module} is
 983      *         {@code null}
 984      * @throws SecurityException
 985      *         if a security manager exists and the caller is not the specified
 986      *         module and doesn't have {@code RuntimePermission("getClassLoader")}
 987      * @throws MissingResourceException
 988      *         if no resource bundle for the specified base name and locale can
 989      *         be found in the specified {@code module}
 990      * @return a resource bundle for the given base name and locale in the module
 991      * @since 9
 992      */
 993     @CallerSensitive
 994     public static ResourceBundle getBundle(String baseName, Locale targetLocale, Module module) {
 995         return getBundleFromModule(Reflection.getCallerClass(), module, baseName, targetLocale,
 996                                    getDefaultControl(module, baseName));
 997     }
 998 
 999     /**
1000      * Returns a resource bundle using the specified base name, target
1001      * locale and control, and the caller's class loader. Calling this
1002      * method is equivalent to calling
1003      * <pre>
1004      * getBundle(baseName, targetLocale, this.getClass().getClassLoader(),
1005      *           control),
1006      * </pre>
1007      * except that <code>getClassLoader()</code> is run with the security
1008      * privileges of <code>ResourceBundle</code>.  See {@link
1009      * #getBundle(String, Locale, ClassLoader, Control) getBundle} for the
1010      * complete description of the resource bundle loading process with a
1011      * <code>ResourceBundle.Control</code>.
1012      *
1013      * @param baseName
1014      *        the base name of the resource bundle, a fully qualified
1015      *        class name
1016      * @param targetLocale


1032      *         Note that validation of <code>control</code> is performed as
1033      *         needed.
1034      * @throws UnsupportedOperationException
1035      *         if this method is called in a named module
1036      * @since 1.6
1037      */
1038     @CallerSensitive
1039     public static final ResourceBundle getBundle(String baseName, Locale targetLocale,
1040                                                  Control control) {
1041         Class<?> caller = Reflection.getCallerClass();
1042         checkNamedModule(caller);
1043         return getBundleImpl(baseName, targetLocale, caller, control);
1044     }
1045 
1046     /**
1047      * Gets a resource bundle using the specified base name, locale, and class
1048      * loader.
1049      *
1050      * <p>This method behaves the same as calling
1051      * {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
1052      * default instance of {@link Control} unless another {@link Control} is
1053      * provided with the {@link ResourceBundleControlProvider} SPI. Refer to the
1054      * description of <a href="#modify_default_behavior">modifying the default
1055      * behavior</a>.
1056      *
1057      * <p><a name="default_behavior">The following describes the default
1058      * behavior</a>.
1059      *
1060      * <p>
1061      * Resource bundles in a named module are private to that module.  If
1062      * the caller is in a named module, this method will find resource bundles
1063      * from the service providers of {@link java.util.spi.ResourceBundleProvider}
1064      * and also find resource bundles that are in the caller's module or
1065      * that are visible to the given class loader.
1066      * If the caller is in a named module and the given {@code loader} is
1067      * different than the caller's class loader, or if the caller is not in
1068      * a named module, this method will not find resource bundles from named
1069      * modules.
1070      *
1071      * <p><code>getBundle</code> uses the base name, the specified locale, and
1072      * the default locale (obtained from {@link java.util.Locale#getDefault()
1073      * Locale.getDefault}) to generate a sequence of <a
1074      * name="candidates"><em>candidate bundle names</em></a>.  If the specified
1075      * locale's language, script, country, and variant are all empty strings,


1233      * on behalf on a specific module instead.
1234      *
1235      * @param baseName the base name of the resource bundle, a fully qualified class name
1236      * @param locale the locale for which a resource bundle is desired
1237      * @param loader the class loader from which to load the resource bundle
1238      * @return a resource bundle for the given base name and locale
1239      * @exception java.lang.NullPointerException
1240      *        if <code>baseName</code>, <code>locale</code>, or <code>loader</code> is <code>null</code>
1241      * @exception MissingResourceException
1242      *        if no resource bundle for the specified base name can be found
1243      * @since 1.2
1244      */
1245     @CallerSensitive
1246     public static ResourceBundle getBundle(String baseName, Locale locale,
1247                                            ClassLoader loader)
1248     {
1249         if (loader == null) {
1250             throw new NullPointerException();
1251         }
1252         Class<?> caller = Reflection.getCallerClass();
1253         return getBundleImpl(baseName, locale, caller, loader, getDefaultControl(caller, baseName));
1254     }
1255 
1256     /**
1257      * Returns a resource bundle using the specified base name, target
1258      * locale, class loader and control. Unlike the {@linkplain
1259      * #getBundle(String, Locale, ClassLoader) <code>getBundle</code>
1260      * factory methods with no <code>control</code> argument}, the given
1261      * <code>control</code> specifies how to locate and instantiate resource
1262      * bundles. Conceptually, the bundle loading process with the given
1263      * <code>control</code> is performed in the following steps.
1264      *
1265      * <ol>
1266      * <li>This factory method looks up the resource bundle in the cache for
1267      * the specified <code>baseName</code>, <code>targetLocale</code> and
1268      * <code>loader</code>.  If the requested resource bundle instance is
1269      * found in the cache and the time-to-live periods of the instance and
1270      * all of its parent instances have not expired, the instance is returned
1271      * to the caller. Otherwise, this factory method proceeds with the
1272      * loading process below.</li>
1273      *


1458      * @throws IllegalArgumentException
1459      *         if the given <code>control</code> doesn't perform properly
1460      *         (e.g., <code>control.getCandidateLocales</code> returns null.)
1461      *         Note that validation of <code>control</code> is performed as
1462      *         needed.
1463      * @throws UnsupportedOperationException
1464      *         if this method is called in a named module
1465      * @since 1.6
1466      */
1467     @CallerSensitive
1468     public static ResourceBundle getBundle(String baseName, Locale targetLocale,
1469                                            ClassLoader loader, Control control) {
1470         if (loader == null || control == null) {
1471             throw new NullPointerException();
1472         }
1473         Class<?> caller = Reflection.getCallerClass();
1474         checkNamedModule(caller);
1475         return getBundleImpl(baseName, targetLocale, caller, loader, control);
1476     }
1477 
1478     private static Control getDefaultControl(Class<?> caller, String baseName) {
1479         return getDefaultControl(caller.getModule(), baseName);
1480     }
1481     
1482     private static Control getDefaultControl(Module targetModule, String baseName) {
1483         return targetModule.isNamed() ?
1484             Control.INSTANCE :
1485             ResourceBundleControlProviderHolder.getControl(baseName);
1486     }
1487 
1488     private static class ResourceBundleControlProviderHolder {
1489         private static final PrivilegedAction<List<ResourceBundleControlProvider>> pa =
1490             () -> {
1491                 return Collections.unmodifiableList(
1492                     ServiceLoader.load(ResourceBundleControlProvider.class,
1493                                        ClassLoader.getSystemClassLoader()).stream()
1494                         .map(ServiceLoader.Provider::get)
1495                         .collect(Collectors.toList()));
1496             };
1497 
1498         private static final List<ResourceBundleControlProvider> CONTROL_PROVIDERS =
1499             AccessController.doPrivileged(pa);
1500 
1501         private static Control getControl(String baseName) {
1502             return CONTROL_PROVIDERS.isEmpty() ?
1503                 Control.INSTANCE :
1504                 CONTROL_PROVIDERS.stream()
1505                     .flatMap(provider -> Stream.ofNullable(provider.getControl(baseName)))
1506                     .findFirst()
1507                     .orElse(Control.INSTANCE);
1508         }
1509     }
1510 
1511     private static void checkNamedModule(Class<?> caller) {
1512         if (caller.getModule().isNamed()) {
1513             throw new UnsupportedOperationException(
1514                     "ResourceBundle.Control not supported in named modules");
1515         }
1516     }
1517 
1518     private static ResourceBundle getBundleImpl(String baseName,
1519                                                 Locale locale,
1520                                                 Class<?> caller,
1521                                                 Control control) {
1522         return getBundleImpl(baseName, locale, caller, caller.getClassLoader(), control);
1523     }
1524 
1525     /**
1526      * This method will find resource bundles using the legacy mechanism
1527      * if the caller is unnamed module or the given class loader is
1528      * not the class loader of the caller module getting the resource
1529      * bundle, i.e. find the class that is visible to the class loader
1530      * and properties from unnamed module.


2452      * ...
2453      *
2454      * private static class XMLResourceBundle extends ResourceBundle {
2455      *     private Properties props;
2456      *     XMLResourceBundle(InputStream stream) throws IOException {
2457      *         props = new Properties();
2458      *         props.loadFromXML(stream);
2459      *     }
2460      *     protected Object handleGetObject(String key) {
2461      *         return props.getProperty(key);
2462      *     }
2463      *     public Enumeration&lt;String&gt; getKeys() {
2464      *         ...
2465      *     }
2466      * }
2467      * </pre>
2468      *
2469      * @apiNote <a name="note">{@code ResourceBundle.Control} is not supported
2470      * in named modules.</a> If the {@code ResourceBundle.getBundle} method with
2471      * a {@code ResourceBundle.Control} is called in a named module, the method
2472      * will throw an {@link UnsupportedOperationException}. Any service providers
2473      * of {@link ResourceBundleControlProvider} are ignored in named modules.
2474      *
2475      * @since 1.6
2476      * @see java.util.spi.ResourceBundleProvider
2477      */
2478     public static class Control {
2479         /**
2480          * The default format <code>List</code>, which contains the strings
2481          * <code>"java.class"</code> and <code>"java.properties"</code>, in
2482          * this order. This <code>List</code> is unmodifiable.
2483          *
2484          * @see #getFormats(String)
2485          */
2486         public static final List<String> FORMAT_DEFAULT
2487             = List.of("java.class", "java.properties");
2488 
2489         /**
2490          * The class-only format <code>List</code> containing
2491          * <code>"java.class"</code>. This <code>List</code> is unmodifiable.
2492          *
2493          * @see #getFormats(String)


< prev index next >