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