< prev index next >

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

Print this page
rev 16280 : [mq]: 8171189


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


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


 452      * The base bundle name for this bundle.
 453      */
 454     private String name;
 455 
 456     /**
 457      * The flag indicating this bundle has expired in the cache.
 458      */
 459     private volatile boolean expired;
 460 
 461     /**
 462      * The back link to the cache key. null if this bundle isn't in
 463      * the cache (yet) or has expired.
 464      */
 465     private volatile CacheKey cacheKey;
 466 
 467     /**
 468      * A Set of the keys contained only in this ResourceBundle.
 469      */
 470     private volatile Set<String> keySet;
 471 
 472     private static final List<ResourceBundleControlProvider> providers;
 473 
 474     static {
 475         List<ResourceBundleControlProvider> list = null;
 476         ServiceLoader<ResourceBundleControlProvider> serviceLoaders
 477                 = ServiceLoader.loadInstalled(ResourceBundleControlProvider.class);
 478         for (ResourceBundleControlProvider provider : serviceLoaders) {
 479             if (list == null) {
 480                 list = new ArrayList<>();
 481             }
 482             list.add(provider);
 483         }
 484         providers = list;
 485     }
 486 
 487     /**
 488      * Sole constructor.  (For invocation by subclass constructors, typically
 489      * implicit.)
 490      */
 491     public ResourceBundle() {
 492     }
 493 
 494     /**
 495      * Gets a string for the given key from this resource bundle or one of its parents.
 496      * Calling this method is equivalent to calling
 497      * <blockquote>
 498      * <code>(String) {@link #getObject(java.lang.String) getObject}(key)</code>.
 499      * </blockquote>
 500      *
 501      * @param key the key for the desired string
 502      * @exception NullPointerException if <code>key</code> is <code>null</code>
 503      * @exception MissingResourceException if no object for the given key can be found
 504      * @exception ClassCastException if the object found for the given key is not a string
 505      * @return the string for the given key
 506      */


 931      * <blockquote>
 932      * <code>getBundle(baseName, Locale.getDefault(), this.getClass().getClassLoader())</code>,
 933      * </blockquote>
 934      * except that <code>getClassLoader()</code> is run with the security
 935      * privileges of <code>ResourceBundle</code>.
 936      * See {@link #getBundle(String, Locale, ClassLoader) getBundle}
 937      * for a complete description of the search and instantiation strategy.
 938      *
 939      * @param baseName the base name of the resource bundle, a fully qualified class name
 940      * @exception java.lang.NullPointerException
 941      *     if <code>baseName</code> is <code>null</code>
 942      * @exception MissingResourceException
 943      *     if no resource bundle for the specified base name can be found
 944      * @return a resource bundle for the given base name and the default locale
 945      */
 946     @CallerSensitive
 947     public static final ResourceBundle getBundle(String baseName)
 948     {
 949         Class<?> caller = Reflection.getCallerClass();
 950         return getBundleImpl(baseName, Locale.getDefault(),
 951                              caller, getDefaultControl(caller, baseName));
 952     }
 953 
 954     /**
 955      * Returns a resource bundle using the specified base name, the
 956      * default locale and the specified control. Calling this method
 957      * is equivalent to calling
 958      * <pre>
 959      * getBundle(baseName, Locale.getDefault(),
 960      *           this.getClass().getClassLoader(), control),
 961      * </pre>
 962      * except that <code>getClassLoader()</code> is run with the security
 963      * privileges of <code>ResourceBundle</code>.  See {@link
 964      * #getBundle(String, Locale, ClassLoader, Control) getBundle} for the
 965      * complete description of the resource bundle loading process with a
 966      * <code>ResourceBundle.Control</code>.
 967      *
 968      * @param baseName
 969      *        the base name of the resource bundle, a fully qualified class
 970      *        name
 971      * @param control


1005      * privileges of <code>ResourceBundle</code>.
1006      * See {@link #getBundle(String, Locale, ClassLoader) getBundle}
1007      * for a complete description of the search and instantiation strategy.
1008      *
1009      * @param baseName
1010      *        the base name of the resource bundle, a fully qualified class name
1011      * @param locale
1012      *        the locale for which a resource bundle is desired
1013      * @exception NullPointerException
1014      *        if <code>baseName</code> or <code>locale</code> is <code>null</code>
1015      * @exception MissingResourceException
1016      *        if no resource bundle for the specified base name can be found
1017      * @return a resource bundle for the given base name and locale
1018      */
1019     @CallerSensitive
1020     public static final ResourceBundle getBundle(String baseName,
1021                                                  Locale locale)
1022     {
1023         Class<?> caller = Reflection.getCallerClass();
1024         return getBundleImpl(baseName, locale,
1025                              caller, getDefaultControl(caller, baseName));
1026     }
1027 
1028     /**
1029      * Gets a resource bundle using the specified base name and the default locale
1030      * on behalf of the specified module. This method is equivalent to calling
1031      * <blockquote>
1032      * <code>getBundle(baseName, Locale.getDefault(), module)</code>
1033      * </blockquote>
1034      *
1035      * <p> Resource bundles in named modules may be encapsulated.  When
1036      * the resource bundle is loaded from a provider, the caller module
1037      * must have an appropriate <i>uses</i> clause in its <i>module descriptor</i>
1038      * to declare that the module uses implementations of {@code "baseName"Provider}.
1039      * When the resource bundle is loaded from the specified module, it is
1040      * subject to the encapsulation rules specified by
1041      * {@link Module#getResourceAsStream Module.getResourceAsStream}.
1042      *
1043      * @param baseName the base name of the resource bundle,
1044      *                 a fully qualified class name
1045      * @param module   the module for which the resource bundle is searched


1146      *         Note that validation of <code>control</code> is performed as
1147      *         needed.
1148      * @throws UnsupportedOperationException
1149      *         if this method is called in a named module
1150      * @since 1.6
1151      */
1152     @CallerSensitive
1153     public static final ResourceBundle getBundle(String baseName, Locale targetLocale,
1154                                                  Control control) {
1155         Class<?> caller = Reflection.getCallerClass();
1156         checkNamedModule(caller);
1157         return getBundleImpl(baseName, targetLocale, caller, control);
1158     }
1159 
1160     /**
1161      * Gets a resource bundle using the specified base name, locale, and class
1162      * loader.
1163      *
1164      * <p>This method behaves the same as calling
1165      * {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
1166      * default instance of {@link Control} unless another {@link Control} is
1167      * provided with the {@link ResourceBundleControlProvider} SPI. Refer to the
1168      * description of <a href="#modify_default_behavior">modifying the default
1169      * behavior</a>.
1170      *
1171      * <p><a name="default_behavior">The following describes the default
1172      * behavior</a>.
1173      *
1174      * <p>
1175      * Resource bundles in a named module are private to that module.  If
1176      * the caller is in a named module, this method will find resource bundles
1177      * from the service providers of {@link java.util.spi.ResourceBundleProvider}
1178      * and also find resource bundles that are in the caller's module or
1179      * that are visible to the given class loader.
1180      * If the caller is in a named module and the given {@code loader} is
1181      * different than the caller's class loader, or if the caller is not in
1182      * a named module, this method will not find resource bundles from named
1183      * modules.
1184      *
1185      * <p><code>getBundle</code> uses the base name, the specified locale, and
1186      * the default locale (obtained from {@link java.util.Locale#getDefault()
1187      * Locale.getDefault}) to generate a sequence of <a
1188      * name="candidates"><em>candidate bundle names</em></a>.  If the specified
1189      * locale's language, script, country, and variant are all empty strings,


1347      * on behalf on a specific module instead.
1348      *
1349      * @param baseName the base name of the resource bundle, a fully qualified class name
1350      * @param locale the locale for which a resource bundle is desired
1351      * @param loader the class loader from which to load the resource bundle
1352      * @return a resource bundle for the given base name and locale
1353      * @exception java.lang.NullPointerException
1354      *        if <code>baseName</code>, <code>locale</code>, or <code>loader</code> is <code>null</code>
1355      * @exception MissingResourceException
1356      *        if no resource bundle for the specified base name can be found
1357      * @since 1.2
1358      */
1359     @CallerSensitive
1360     public static ResourceBundle getBundle(String baseName, Locale locale,
1361                                            ClassLoader loader)
1362     {
1363         if (loader == null) {
1364             throw new NullPointerException();
1365         }
1366         Class<?> caller = Reflection.getCallerClass();
1367         return getBundleImpl(baseName, locale, caller, loader, getDefaultControl(caller, baseName));
1368     }
1369 
1370     /**
1371      * Returns a resource bundle using the specified base name, target
1372      * locale, class loader and control. Unlike the {@linkplain
1373      * #getBundle(String, Locale, ClassLoader) <code>getBundle</code>
1374      * factory methods with no <code>control</code> argument}, the given
1375      * <code>control</code> specifies how to locate and instantiate resource
1376      * bundles. Conceptually, the bundle loading process with the given
1377      * <code>control</code> is performed in the following steps.
1378      *
1379      * <ol>
1380      * <li>This factory method looks up the resource bundle in the cache for
1381      * the specified <code>baseName</code>, <code>targetLocale</code> and
1382      * <code>loader</code>.  If the requested resource bundle instance is
1383      * found in the cache and the time-to-live periods of the instance and
1384      * all of its parent instances have not expired, the instance is returned
1385      * to the caller. Otherwise, this factory method proceeds with the
1386      * loading process below.</li>
1387      *


1572      * @throws IllegalArgumentException
1573      *         if the given <code>control</code> doesn't perform properly
1574      *         (e.g., <code>control.getCandidateLocales</code> returns null.)
1575      *         Note that validation of <code>control</code> is performed as
1576      *         needed.
1577      * @throws UnsupportedOperationException
1578      *         if this method is called in a named module
1579      * @since 1.6
1580      */
1581     @CallerSensitive
1582     public static ResourceBundle getBundle(String baseName, Locale targetLocale,
1583                                            ClassLoader loader, Control control) {
1584         if (loader == null || control == null) {
1585             throw new NullPointerException();
1586         }
1587         Class<?> caller = Reflection.getCallerClass();
1588         checkNamedModule(caller);
1589         return getBundleImpl(baseName, targetLocale, caller, loader, control);
1590     }
1591 
1592     private static Control getDefaultControl(Class<?> caller, String baseName) {
1593         if (providers != null && !caller.getModule().isNamed()) {
1594             for (ResourceBundleControlProvider provider : providers) {
1595                 Control control = provider.getControl(baseName);
1596                 if (control != null) {
1597                     return control;
1598                 }
1599             }
1600         }
1601         return Control.INSTANCE;
1602     }
1603 
1604     private static void checkNamedModule(Class<?> caller) {
1605         if (caller.getModule().isNamed()) {
1606             throw new UnsupportedOperationException(
1607                     "ResourceBundle.Control not supported in named modules");
1608         }
1609     }
1610 
1611     private static ResourceBundle getBundleImpl(String baseName,
1612                                                 Locale locale,
1613                                                 Class<?> caller,
1614                                                 Control control) {
1615         return getBundleImpl(baseName, locale, caller, getLoader(caller), control);
1616     }
1617 
1618     /**
1619      * This method will find resource bundles using the legacy mechanism
1620      * if the caller is unnamed module or the given class loader is
1621      * not the class loader of the caller module getting the resource
1622      * bundle, i.e. find the class that is visible to the class loader
1623      * and properties from unnamed module.


2556      * ...
2557      *
2558      * private static class XMLResourceBundle extends ResourceBundle {
2559      *     private Properties props;
2560      *     XMLResourceBundle(InputStream stream) throws IOException {
2561      *         props = new Properties();
2562      *         props.loadFromXML(stream);
2563      *     }
2564      *     protected Object handleGetObject(String key) {
2565      *         return props.getProperty(key);
2566      *     }
2567      *     public Enumeration&lt;String&gt; getKeys() {
2568      *         ...
2569      *     }
2570      * }
2571      * </pre>
2572      *
2573      * @apiNote <a name="note">{@code ResourceBundle.Control} is not supported
2574      * in named modules.</a> If the {@code ResourceBundle.getBundle} method with
2575      * a {@code ResourceBundle.Control} is called in a named module, the method
2576      * will throw an {@link UnsupportedOperationException}. Any service providers
2577      * of {@link ResourceBundleControlProvider} are ignored in named modules.
2578      *
2579      * @since 1.6
2580      * @see java.util.spi.ResourceBundleProvider
2581      */
2582     public static class Control {
2583         /**
2584          * The default format <code>List</code>, which contains the strings
2585          * <code>"java.class"</code> and <code>"java.properties"</code>, in
2586          * this order. This <code>List</code> is unmodifiable.
2587          *
2588          * @see #getFormats(String)
2589          */
2590         public static final List<String> FORMAT_DEFAULT
2591             = List.of("java.class", "java.properties");
2592 
2593         /**
2594          * The class-only format <code>List</code> containing
2595          * <code>"java.class"</code>. This <code>List</code> is unmodifiable.
2596          *
2597          * @see #getFormats(String)




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

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


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


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











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


 438      * The base bundle name for this bundle.
 439      */
 440     private String name;
 441 
 442     /**
 443      * The flag indicating this bundle has expired in the cache.
 444      */
 445     private volatile boolean expired;
 446 
 447     /**
 448      * The back link to the cache key. null if this bundle isn't in
 449      * the cache (yet) or has expired.
 450      */
 451     private volatile CacheKey cacheKey;
 452 
 453     /**
 454      * A Set of the keys contained only in this ResourceBundle.
 455      */
 456     private volatile Set<String> keySet;
 457 















 458     /**
 459      * Sole constructor.  (For invocation by subclass constructors, typically
 460      * implicit.)
 461      */
 462     public ResourceBundle() {
 463     }
 464 
 465     /**
 466      * Gets a string for the given key from this resource bundle or one of its parents.
 467      * Calling this method is equivalent to calling
 468      * <blockquote>
 469      * <code>(String) {@link #getObject(java.lang.String) getObject}(key)</code>.
 470      * </blockquote>
 471      *
 472      * @param key the key for the desired string
 473      * @exception NullPointerException if <code>key</code> is <code>null</code>
 474      * @exception MissingResourceException if no object for the given key can be found
 475      * @exception ClassCastException if the object found for the given key is not a string
 476      * @return the string for the given key
 477      */


 902      * <blockquote>
 903      * <code>getBundle(baseName, Locale.getDefault(), this.getClass().getClassLoader())</code>,
 904      * </blockquote>
 905      * except that <code>getClassLoader()</code> is run with the security
 906      * privileges of <code>ResourceBundle</code>.
 907      * See {@link #getBundle(String, Locale, ClassLoader) getBundle}
 908      * for a complete description of the search and instantiation strategy.
 909      *
 910      * @param baseName the base name of the resource bundle, a fully qualified class name
 911      * @exception java.lang.NullPointerException
 912      *     if <code>baseName</code> is <code>null</code>
 913      * @exception MissingResourceException
 914      *     if no resource bundle for the specified base name can be found
 915      * @return a resource bundle for the given base name and the default locale
 916      */
 917     @CallerSensitive
 918     public static final ResourceBundle getBundle(String baseName)
 919     {
 920         Class<?> caller = Reflection.getCallerClass();
 921         return getBundleImpl(baseName, Locale.getDefault(),
 922                              caller, Control.INSTANCE);
 923     }
 924 
 925     /**
 926      * Returns a resource bundle using the specified base name, the
 927      * default locale and the specified control. Calling this method
 928      * is equivalent to calling
 929      * <pre>
 930      * getBundle(baseName, Locale.getDefault(),
 931      *           this.getClass().getClassLoader(), control),
 932      * </pre>
 933      * except that <code>getClassLoader()</code> is run with the security
 934      * privileges of <code>ResourceBundle</code>.  See {@link
 935      * #getBundle(String, Locale, ClassLoader, Control) getBundle} for the
 936      * complete description of the resource bundle loading process with a
 937      * <code>ResourceBundle.Control</code>.
 938      *
 939      * @param baseName
 940      *        the base name of the resource bundle, a fully qualified class
 941      *        name
 942      * @param control


 976      * privileges of <code>ResourceBundle</code>.
 977      * See {@link #getBundle(String, Locale, ClassLoader) getBundle}
 978      * for a complete description of the search and instantiation strategy.
 979      *
 980      * @param baseName
 981      *        the base name of the resource bundle, a fully qualified class name
 982      * @param locale
 983      *        the locale for which a resource bundle is desired
 984      * @exception NullPointerException
 985      *        if <code>baseName</code> or <code>locale</code> is <code>null</code>
 986      * @exception MissingResourceException
 987      *        if no resource bundle for the specified base name can be found
 988      * @return a resource bundle for the given base name and locale
 989      */
 990     @CallerSensitive
 991     public static final ResourceBundle getBundle(String baseName,
 992                                                  Locale locale)
 993     {
 994         Class<?> caller = Reflection.getCallerClass();
 995         return getBundleImpl(baseName, locale,
 996                              caller, Control.INSTANCE);
 997     }
 998 
 999     /**
1000      * Gets a resource bundle using the specified base name and the default locale
1001      * on behalf of the specified module. This method is equivalent to calling
1002      * <blockquote>
1003      * <code>getBundle(baseName, Locale.getDefault(), module)</code>
1004      * </blockquote>
1005      *
1006      * <p> Resource bundles in named modules may be encapsulated.  When
1007      * the resource bundle is loaded from a provider, the caller module
1008      * must have an appropriate <i>uses</i> clause in its <i>module descriptor</i>
1009      * to declare that the module uses implementations of {@code "baseName"Provider}.
1010      * When the resource bundle is loaded from the specified module, it is
1011      * subject to the encapsulation rules specified by
1012      * {@link Module#getResourceAsStream Module.getResourceAsStream}.
1013      *
1014      * @param baseName the base name of the resource bundle,
1015      *                 a fully qualified class name
1016      * @param module   the module for which the resource bundle is searched


1117      *         Note that validation of <code>control</code> is performed as
1118      *         needed.
1119      * @throws UnsupportedOperationException
1120      *         if this method is called in a named module
1121      * @since 1.6
1122      */
1123     @CallerSensitive
1124     public static final ResourceBundle getBundle(String baseName, Locale targetLocale,
1125                                                  Control control) {
1126         Class<?> caller = Reflection.getCallerClass();
1127         checkNamedModule(caller);
1128         return getBundleImpl(baseName, targetLocale, caller, control);
1129     }
1130 
1131     /**
1132      * Gets a resource bundle using the specified base name, locale, and class
1133      * loader.
1134      *
1135      * <p>This method behaves the same as calling
1136      * {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
1137      * default instance of {@link Control}.



1138      *
1139      * <p><a name="default_behavior">The following describes the default
1140      * behavior</a>.
1141      *
1142      * <p>
1143      * Resource bundles in a named module are private to that module.  If
1144      * the caller is in a named module, this method will find resource bundles
1145      * from the service providers of {@link java.util.spi.ResourceBundleProvider}
1146      * and also find resource bundles that are in the caller's module or
1147      * that are visible to the given class loader.
1148      * If the caller is in a named module and the given {@code loader} is
1149      * different than the caller's class loader, or if the caller is not in
1150      * a named module, this method will not find resource bundles from named
1151      * modules.
1152      *
1153      * <p><code>getBundle</code> uses the base name, the specified locale, and
1154      * the default locale (obtained from {@link java.util.Locale#getDefault()
1155      * Locale.getDefault}) to generate a sequence of <a
1156      * name="candidates"><em>candidate bundle names</em></a>.  If the specified
1157      * locale's language, script, country, and variant are all empty strings,


1315      * on behalf on a specific module instead.
1316      *
1317      * @param baseName the base name of the resource bundle, a fully qualified class name
1318      * @param locale the locale for which a resource bundle is desired
1319      * @param loader the class loader from which to load the resource bundle
1320      * @return a resource bundle for the given base name and locale
1321      * @exception java.lang.NullPointerException
1322      *        if <code>baseName</code>, <code>locale</code>, or <code>loader</code> is <code>null</code>
1323      * @exception MissingResourceException
1324      *        if no resource bundle for the specified base name can be found
1325      * @since 1.2
1326      */
1327     @CallerSensitive
1328     public static ResourceBundle getBundle(String baseName, Locale locale,
1329                                            ClassLoader loader)
1330     {
1331         if (loader == null) {
1332             throw new NullPointerException();
1333         }
1334         Class<?> caller = Reflection.getCallerClass();
1335         return getBundleImpl(baseName, locale, caller, loader, Control.INSTANCE);
1336     }
1337 
1338     /**
1339      * Returns a resource bundle using the specified base name, target
1340      * locale, class loader and control. Unlike the {@linkplain
1341      * #getBundle(String, Locale, ClassLoader) <code>getBundle</code>
1342      * factory methods with no <code>control</code> argument}, the given
1343      * <code>control</code> specifies how to locate and instantiate resource
1344      * bundles. Conceptually, the bundle loading process with the given
1345      * <code>control</code> is performed in the following steps.
1346      *
1347      * <ol>
1348      * <li>This factory method looks up the resource bundle in the cache for
1349      * the specified <code>baseName</code>, <code>targetLocale</code> and
1350      * <code>loader</code>.  If the requested resource bundle instance is
1351      * found in the cache and the time-to-live periods of the instance and
1352      * all of its parent instances have not expired, the instance is returned
1353      * to the caller. Otherwise, this factory method proceeds with the
1354      * loading process below.</li>
1355      *


1540      * @throws IllegalArgumentException
1541      *         if the given <code>control</code> doesn't perform properly
1542      *         (e.g., <code>control.getCandidateLocales</code> returns null.)
1543      *         Note that validation of <code>control</code> is performed as
1544      *         needed.
1545      * @throws UnsupportedOperationException
1546      *         if this method is called in a named module
1547      * @since 1.6
1548      */
1549     @CallerSensitive
1550     public static ResourceBundle getBundle(String baseName, Locale targetLocale,
1551                                            ClassLoader loader, Control control) {
1552         if (loader == null || control == null) {
1553             throw new NullPointerException();
1554         }
1555         Class<?> caller = Reflection.getCallerClass();
1556         checkNamedModule(caller);
1557         return getBundleImpl(baseName, targetLocale, caller, loader, control);
1558     }
1559 












1560     private static void checkNamedModule(Class<?> caller) {
1561         if (caller.getModule().isNamed()) {
1562             throw new UnsupportedOperationException(
1563                     "ResourceBundle.Control not supported in named modules");
1564         }
1565     }
1566 
1567     private static ResourceBundle getBundleImpl(String baseName,
1568                                                 Locale locale,
1569                                                 Class<?> caller,
1570                                                 Control control) {
1571         return getBundleImpl(baseName, locale, caller, getLoader(caller), control);
1572     }
1573 
1574     /**
1575      * This method will find resource bundles using the legacy mechanism
1576      * if the caller is unnamed module or the given class loader is
1577      * not the class loader of the caller module getting the resource
1578      * bundle, i.e. find the class that is visible to the class loader
1579      * and properties from unnamed module.


2512      * ...
2513      *
2514      * private static class XMLResourceBundle extends ResourceBundle {
2515      *     private Properties props;
2516      *     XMLResourceBundle(InputStream stream) throws IOException {
2517      *         props = new Properties();
2518      *         props.loadFromXML(stream);
2519      *     }
2520      *     protected Object handleGetObject(String key) {
2521      *         return props.getProperty(key);
2522      *     }
2523      *     public Enumeration&lt;String&gt; getKeys() {
2524      *         ...
2525      *     }
2526      * }
2527      * </pre>
2528      *
2529      * @apiNote <a name="note">{@code ResourceBundle.Control} is not supported
2530      * in named modules.</a> If the {@code ResourceBundle.getBundle} method with
2531      * a {@code ResourceBundle.Control} is called in a named module, the method
2532      * will throw an {@link UnsupportedOperationException}.

2533      *
2534      * @since 1.6
2535      * @see java.util.spi.ResourceBundleProvider
2536      */
2537     public static class Control {
2538         /**
2539          * The default format <code>List</code>, which contains the strings
2540          * <code>"java.class"</code> and <code>"java.properties"</code>, in
2541          * this order. This <code>List</code> is unmodifiable.
2542          *
2543          * @see #getFormats(String)
2544          */
2545         public static final List<String> FORMAT_DEFAULT
2546             = List.of("java.class", "java.properties");
2547 
2548         /**
2549          * The class-only format <code>List</code> containing
2550          * <code>"java.class"</code>. This <code>List</code> is unmodifiable.
2551          *
2552          * @see #getFormats(String)


< prev index next >