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<String> 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<String> 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)
|