- Enclosing class:
ResourceBundle
ResourceBundle.Control
defines a set of callback methods
that are invoked by the ResourceBundle.getBundle
factory
methods during the bundle loading process. In other words, a
ResourceBundle.Control
collaborates with the factory
methods for loading resource bundles. The default implementation of
the callback methods provides the information necessary for the
factory methods to perform the default behavior.
ResourceBundle.Control
is designed for an application deployed
in an unnamed module, for example to support resource bundles in
non-standard formats or package localized resources in a non-traditional
convention. ResourceBundleProvider
is the replacement for
ResourceBundle.Control
when migrating to modules.
UnsupportedOperationException
will be thrown when a factory
method that takes the ResourceBundle.Control
parameter is called.
In addition to the callback methods, the toBundleName
and toResourceName
methods are defined
primarily for convenience in implementing the callback
methods. However, the toBundleName
method could be
overridden to provide different conventions in the organization and
packaging of localized resources. The toResourceName
method is final
to avoid use of wrong resource and class
name separators.
Two factory methods, getControl(List)
and getNoFallbackControl(List)
, provide
ResourceBundle.Control
instances that implement common
variations of the default bundle loading process.
The formats returned by the getFormats
method and candidate locales returned by the getCandidateLocales
method must be consistent in all
ResourceBundle.getBundle
invocations for the same base
bundle. Otherwise, the ResourceBundle.getBundle
methods
may return unintended bundles. For example, if only
"java.class"
is returned by the getFormats
method for the first call to ResourceBundle.getBundle
and only "java.properties"
for the second call, then the
second call will return the class-based one that has been cached
during the first call.
A ResourceBundle.Control
instance must be thread-safe
if it's simultaneously used by multiple threads.
ResourceBundle.getBundle
does not synchronize to call
the ResourceBundle.Control
methods. The default
implementations of the methods are thread-safe.
Applications can specify ResourceBundle.Control
instances returned by the getControl
factory methods or
created from a subclass of ResourceBundle.Control
to
customize the bundle loading process. The following are examples of
changing the default bundle loading process.
Example 1
The following code lets ResourceBundle.getBundle
look
up only properties-based resources.
import java.util.*;
import static java.util.ResourceBundle.Control.*;
...
ResourceBundle bundle =
ResourceBundle.getBundle("MyResources", Locale.forLanguageTag("fr-CH"),
ResourceBundle.Control.getControl(FORMAT_PROPERTIES));
ResourceBundle.getBundle
description, this
ResourceBundle.getBundle
call loads
MyResources_fr_CH.properties
whose parent is
MyResources_fr.properties
whose parent is
MyResources.properties
. (MyResources_fr_CH.properties
is not hidden, but MyResources_fr_CH.class
is.)
Example 2
The following is an example of loading XML-based bundles
using Properties.loadFromXML
.
ResourceBundle rb = ResourceBundle.getBundle("Messages",
new ResourceBundle.Control() {
public List<String> getFormats(String baseName) {
if (baseName == null)
throw new NullPointerException();
return Arrays.asList("xml");
}
public ResourceBundle newBundle(String baseName,
Locale locale,
String format,
ClassLoader loader,
boolean reload)
throws IllegalAccessException,
InstantiationException,
IOException {
if (baseName == null || locale == null
|| format == null || loader == null)
throw new NullPointerException();
ResourceBundle bundle = null;
if (format.equals("xml")) {
String bundleName = toBundleName(baseName, locale);
String resourceName = toResourceName(bundleName, format);
InputStream stream = null;
if (reload) {
URL url = loader.getResource(resourceName);
if (url != null) {
URLConnection connection = url.openConnection();
if (connection != null) {
// Disable caches to get fresh data for
// reloading.
connection.setUseCaches(false);
stream = connection.getInputStream();
}
}
} else {
stream = loader.getResourceAsStream(resourceName);
}
if (stream != null) {
BufferedInputStream bis = new BufferedInputStream(stream);
bundle = new XMLResourceBundle(bis);
bis.close();
}
}
return bundle;
}
});
...
private static class XMLResourceBundle extends ResourceBundle {
private Properties props;
XMLResourceBundle(InputStream stream) throws IOException {
props = new Properties();
props.loadFromXML(stream);
}
protected Object handleGetObject(String key) {
return props.getProperty(key);
}
public Enumeration<String> getKeys() {
...
}
}
- API Note:
ResourceBundle.Control
is not supported in named modules. If theResourceBundle.getBundle
method with aResourceBundle.Control
is called in a named module, the method will throw anUnsupportedOperationException
. Any service providers ofResourceBundleControlProvider
are ignored in named modules.- Since:
- 1.6
- See Also:
-
Field Summary
Modifier and TypeFieldDescriptionThe class-only formatList
containing"java.class"
.The default formatList
, which contains the strings"java.class"
and"java.properties"
, in this order.The properties-only formatList
containing"java.properties"
.static final long
The time-to-live constant for not caching loaded resource bundle instances.static final long
The time-to-live constant for disabling the expiration control for loaded resource bundle instances in the cache. -
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptiongetCandidateLocales
(String baseName, Locale locale) Returns aList
ofLocale
s as candidate locales forbaseName
andlocale
.static final ResourceBundle.Control
getControl
(List<String> formats) getFallbackLocale
(String baseName, Locale locale) Returns aLocale
to be used as a fallback locale for further resource bundle searches by theResourceBundle.getBundle
factory method.getFormats
(String baseName) Returns aList
ofString
s containing formats to be used to load resource bundles for the givenbaseName
.static final ResourceBundle.Control
getNoFallbackControl
(List<String> formats) Returns aResourceBundle.Control
in which thegetFormats
method returns the specifiedformats
and thegetFallbackLocale
method returnsnull
.long
getTimeToLive
(String baseName, Locale locale) Returns the time-to-live (TTL) value for resource bundles that are loaded under thisResourceBundle.Control
.boolean
needsReload
(String baseName, Locale locale, String format, ClassLoader loader, ResourceBundle bundle, long loadTime) Determines if the expiredbundle
in the cache needs to be reloaded based on the loading time given byloadTime
or some other criteria.newBundle
(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) Instantiates a resource bundle for the given bundle name of the given format and locale, using the given class loader if necessary.toBundleName
(String baseName, Locale locale) Converts the givenbaseName
andlocale
to the bundle name.final String
toResourceName
(String bundleName, String suffix) Converts the givenbundleName
to the form required by theClassLoader.getResource
method by replacing all occurrences of'.'
inbundleName
with'/'
and appending a'.'
and the given filesuffix
.
-
Field Details
-
FORMAT_DEFAULT
The default formatList
, which contains the strings"java.class"
and"java.properties"
, in this order. ThisList
is unmodifiable.- See Also:
-
FORMAT_CLASS
The class-only formatList
containing"java.class"
. ThisList
is unmodifiable.- See Also:
-
FORMAT_PROPERTIES
The properties-only formatList
containing"java.properties"
. ThisList
is unmodifiable.- See Also:
-
TTL_DONT_CACHE
public static final long TTL_DONT_CACHEThe time-to-live constant for not caching loaded resource bundle instances.- See Also:
-
TTL_NO_EXPIRATION_CONTROL
public static final long TTL_NO_EXPIRATION_CONTROLThe time-to-live constant for disabling the expiration control for loaded resource bundle instances in the cache.- See Also:
-
-
Constructor Details
-
Control
protected Control()Sole constructor. (For invocation by subclass constructors, typically implicit.)
-
-
Method Details
-
getControl
Returns aResourceBundle.Control
in which thegetFormats
method returns the specifiedformats
. Theformats
must be equal to one ofFORMAT_PROPERTIES
,FORMAT_CLASS
orFORMAT_DEFAULT
.ResourceBundle.Control
instances returned by this method are singletons and thread-safe.Specifying
FORMAT_DEFAULT
is equivalent to instantiating theResourceBundle.Control
class, except that this method returns a singleton.- Parameters:
formats
- the formats to be returned by theResourceBundle.Control.getFormats
method- Returns:
- a
ResourceBundle.Control
supporting the specifiedformats
- Throws:
NullPointerException
- ifformats
isnull
IllegalArgumentException
- ifformats
is unknown
-
getNoFallbackControl
Returns aResourceBundle.Control
in which thegetFormats
method returns the specifiedformats
and thegetFallbackLocale
method returnsnull
. Theformats
must be equal to one ofFORMAT_PROPERTIES
,FORMAT_CLASS
orFORMAT_DEFAULT
.ResourceBundle.Control
instances returned by this method are singletons and thread-safe.- Parameters:
formats
- the formats to be returned by theResourceBundle.Control.getFormats
method- Returns:
- a
ResourceBundle.Control
supporting the specifiedformats
with no fallbackLocale
support - Throws:
NullPointerException
- ifformats
isnull
IllegalArgumentException
- ifformats
is unknown
-
getFormats
Returns aList
ofString
s containing formats to be used to load resource bundles for the givenbaseName
. TheResourceBundle.getBundle
factory method tries to load resource bundles with formats in the order specified by the list. The list returned by this method must have at least oneString
. The predefined formats are"java.class"
for class-based resource bundles and"java.properties"
for properties-based ones. Strings starting with"java."
are reserved for future extensions and must not be used by application-defined formats.It is not a requirement to return an immutable (unmodifiable)
List
. However, the returnedList
must not be mutated after it has been returned bygetFormats
.The default implementation returns
FORMAT_DEFAULT
so that theResourceBundle.getBundle
factory method looks up first class-based resource bundles, then properties-based ones.- Parameters:
baseName
- the base name of the resource bundle, a fully qualified class name- Returns:
- a
List
ofString
s containing formats for loading resource bundles. - Throws:
NullPointerException
- ifbaseName
is null- See Also:
-
getCandidateLocales
Returns aList
ofLocale
s as candidate locales forbaseName
andlocale
. This method is called by theResourceBundle.getBundle
factory method each time the factory method tries finding a resource bundle for a targetLocale
.The sequence of the candidate locales also corresponds to the runtime resource lookup path (also known as the parent chain), if the corresponding resource bundles for the candidate locales exist and their parents are not defined by loaded resource bundles themselves. The last element of the list must be a root locale if it is desired to have the base bundle as the terminal of the parent chain.
If the given locale is equal to
Locale.ROOT
(the root locale), aList
containing only the rootLocale
must be returned. In this case, theResourceBundle.getBundle
factory method loads only the base bundle as the resulting resource bundle.It is not a requirement to return an immutable (unmodifiable)
List
. However, the returnedList
must not be mutated after it has been returned bygetCandidateLocales
.The default implementation returns a
List
containingLocale
s using the rules described below. In the description below, L, S, C and V respectively represent non-empty language, script, country, and variant. For example, [L, C] represents aLocale
that has non-empty values only for language and country. The form L("xx") represents the (non-empty) language value is "xx". For all cases,Locale
s whose final component values are empty strings are omitted.- For an input
Locale
with an empty script value, append candidateLocale
s by omitting the final component one by one as below:- [L, C, V]
- [L, C]
- [L]
-
Locale.ROOT
- For an input
Locale
with a non-empty script value, append candidateLocale
s by omitting the final component up to language, then append candidates generated from theLocale
with country and variant restored:- [L, S, C, V]
- [L, S, C]
- [L, S]
- [L, C, V]
- [L, C]
- [L]
-
Locale.ROOT
- For an input
Locale
with a variant value consisting of multiple subtags separated by underscore, generate candidateLocale
s by omitting the variant subtags one by one, then insert them after every occurrence ofLocale
s with the full variant value in the original list. For example, if the variant consists of two subtags V1 and V2:- [L, S, C, V1, V2]
- [L, S, C, V1]
- [L, S, C]
- [L, S]
- [L, C, V1, V2]
- [L, C, V1]
- [L, C]
- [L]
-
Locale.ROOT
- Special cases for Chinese. When an input
Locale
has the language "zh" (Chinese) and an empty script value, either "Hans" (Simplified) or "Hant" (Traditional) might be supplied, depending on the country. When the country is "CN" (China) or "SG" (Singapore), "Hans" is supplied. When the country is "HK" (Hong Kong SAR China), "MO" (Macau SAR China), or "TW" (Taiwan), "Hant" is supplied. For all other countries or when the country is empty, no script is supplied. For example, forLocale("zh", "CN")
, the candidate list will be:- [L("zh"), S("Hans"), C("CN")]
- [L("zh"), S("Hans")]
- [L("zh"), C("CN")]
- [L("zh")]
-
Locale.ROOT
Locale("zh", "TW")
, the candidate list will be:- [L("zh"), S("Hant"), C("TW")]
- [L("zh"), S("Hant")]
- [L("zh"), C("TW")]
- [L("zh")]
-
Locale.ROOT
- Special cases for Norwegian. Both
Locale("no", "NO", "NY")
andLocale("nn", "NO")
represent Norwegian Nynorsk. When a locale's language is "nn", the standard candidate list is generated up to [L("nn")], and then the following candidates are added:- [L("no"), C("NO"), V("NY")]
- [L("no"), C("NO")]
- [L("no")]
-
Locale.ROOT
Locale("no", "NO", "NY")
, it is first converted toLocale("nn", "NO")
and then the above procedure is followed.Also, Java treats the language "no" as a synonym of Norwegian Bokmål "nb". Except for the single case
Locale("no", "NO", "NY")
(handled above), when an inputLocale
has language "no" or "nb", candidateLocale
s with language code "no" and "nb" are interleaved, first using the requested language, then using its synonym. For example,Locale("nb", "NO", "POSIX")
generates the following candidate list:- [L("nb"), C("NO"), V("POSIX")]
- [L("no"), C("NO"), V("POSIX")]
- [L("nb"), C("NO")]
- [L("no"), C("NO")]
- [L("nb")]
- [L("no")]
-
Locale.ROOT
Locale("no", "NO", "POSIX")
would generate the same list except that locales with "no" would appear before the corresponding locales with "nb".
The default implementation uses an
ArrayList
that overriding implementations may modify before returning it to the caller. However, a subclass must not modify it after it has been returned bygetCandidateLocales
.For example, if the given
baseName
is "Messages" and the givenlocale
isLocale("ja", "", "XX")
, then aList
ofLocale
s:Locale("ja", "", "XX") Locale("ja") Locale.ROOT
is returned. And if the resource bundles for the "ja" and ""Locale
s are found, then the runtime resource lookup path (parent chain) is:Messages_ja -> Messages
- Parameters:
baseName
- the base name of the resource bundle, a fully qualified class namelocale
- the locale for which a resource bundle is desired- Returns:
- a
List
of candidateLocale
s for the givenlocale
- Throws:
NullPointerException
- ifbaseName
orlocale
isnull
- For an input
-
getFallbackLocale
Returns aLocale
to be used as a fallback locale for further resource bundle searches by theResourceBundle.getBundle
factory method. This method is called from the factory method every time when no resulting resource bundle has been found forbaseName
andlocale
, where locale is either the parameter forResourceBundle.getBundle
or the previous fallback locale returned by this method.The method returns
null
if no further fallback search is desired.The default implementation returns the default
Locale
if the givenlocale
isn't the default one. Otherwise,null
is returned.- Parameters:
baseName
- the base name of the resource bundle, a fully qualified class name for whichResourceBundle.getBundle
has been unable to find any resource bundles (except for the base bundle)locale
- theLocale
for whichResourceBundle.getBundle
has been unable to find any resource bundles (except for the base bundle)- Returns:
- a
Locale
for the fallback search, ornull
if no further fallback search is desired. - Throws:
NullPointerException
- ifbaseName
orlocale
isnull
-
newBundle
public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException Instantiates a resource bundle for the given bundle name of the given format and locale, using the given class loader if necessary. This method returnsnull
if there is no resource bundle available for the given parameters. If a resource bundle can't be instantiated due to an unexpected error, the error must be reported by throwing anError
orException
rather than simply returningnull
.If the
reload
flag istrue
, it indicates that this method is being called because the previously loaded resource bundle has expired.- Implementation Requirements:
- Resource bundles in named modules are subject to the encapsulation
rules specified by
Module.getResourceAsStream
. A resource bundle in a named module visible to the given class loader is accessible when the package of the resource file corresponding to the resource bundle is open unconditionally.The default implementation instantiates a
ResourceBundle
as follows.- The bundle name is obtained by calling
toBundleName(baseName, locale)
. - If
format
is"java.class"
, theClass
specified by the bundle name is loaded with the given class loader. If theClass
is found and accessible then theResourceBundle
is instantiated. The resource bundle is accessible if the package of the bundle class file is open unconditionally; otherwise,IllegalAccessException
will be thrown. Note that thereload
flag is ignored for loading class-based resource bundles in this default implementation. - If
format
is"java.properties"
,toResourceName(bundlename, "properties")
is called to get the resource name. Ifreload
istrue
,load.getResource
is called to get aURL
for creating aURLConnection
. ThisURLConnection
is used to disable the caches of the underlying resource loading layers, and to get anInputStream
. Otherwise,loader.getResourceAsStream
is called to get anInputStream
. Then, aPropertyResourceBundle
is constructed with theInputStream
. - If
format
is neither"java.class"
nor"java.properties"
, anIllegalArgumentException
is thrown. - If the
locale
's language is one of the Legacy language codes, either old or new, then repeat the loading process if needed, with the bundle name with the other language. For example, "iw" for "he" and vice versa.
- The bundle name is obtained by calling
- Parameters:
baseName
- the base bundle name of the resource bundle, a fully qualified class namelocale
- the locale for which the resource bundle should be instantiatedformat
- the resource bundle format to be loadedloader
- theClassLoader
to use to load the bundlereload
- the flag to indicate bundle reloading;true
if reloading an expired resource bundle,false
otherwise- Returns:
- the resource bundle instance,
or
null
if none could be found. - Throws:
NullPointerException
- ifbundleName
,locale
,format
, orloader
isnull
, or ifnull
is returned bytoBundleName
IllegalArgumentException
- ifformat
is unknown, or if the resource found for the given parameters contains malformed data.ClassCastException
- if the loaded class cannot be cast toResourceBundle
IllegalAccessException
- if the class or its nullary constructor is not accessible.InstantiationException
- if the instantiation of a class fails for some other reason.ExceptionInInitializerError
- if the initialization provoked by this method fails.SecurityException
- If a security manager is present and creation of new instances is denied. SeeClass.newInstance()
for details.IOException
- if an error occurred when reading resources using any I/O operations- See Also:
-
getTimeToLive
Returns the time-to-live (TTL) value for resource bundles that are loaded under thisResourceBundle.Control
. Positive time-to-live values specify the number of milliseconds a bundle can remain in the cache without being validated against the source data from which it was constructed. The value 0 indicates that a bundle must be validated each time it is retrieved from the cache.TTL_DONT_CACHE
specifies that loaded resource bundles are not put in the cache.TTL_NO_EXPIRATION_CONTROL
specifies that loaded resource bundles are put in the cache with no expiration control.The expiration affects only the bundle loading process by the
ResourceBundle.getBundle
factory method. That is, if the factory method finds a resource bundle in the cache that has expired, the factory method calls theneedsReload
method to determine whether the resource bundle needs to be reloaded. IfneedsReload
returnstrue
, the cached resource bundle instance is removed from the cache. Otherwise, the instance stays in the cache, updated with the new TTL value returned by this method.All cached resource bundles are subject to removal from the cache due to memory constraints of the runtime environment. Returning a large positive value doesn't mean to lock loaded resource bundles in the cache.
The default implementation returns
TTL_NO_EXPIRATION_CONTROL
.- Parameters:
baseName
- the base name of the resource bundle for which the expiration value is specified.locale
- the locale of the resource bundle for which the expiration value is specified.- Returns:
- the time (0 or a positive millisecond offset from the
cached time) to get loaded bundles expired in the cache,
TTL_NO_EXPIRATION_CONTROL
to disable the expiration control, orTTL_DONT_CACHE
to disable caching. - Throws:
NullPointerException
- ifbaseName
orlocale
isnull
-
needsReload
public boolean needsReload(String baseName, Locale locale, String format, ClassLoader loader, ResourceBundle bundle, long loadTime) Determines if the expiredbundle
in the cache needs to be reloaded based on the loading time given byloadTime
or some other criteria. The method returnstrue
if reloading is required;false
otherwise.loadTime
is a millisecond offset since theCalendar
Epoch.The calling
ResourceBundle.getBundle
factory method calls this method on theResourceBundle.Control
instance used for its current invocation, not on the instance used in the invocation that originally loaded the resource bundle.The default implementation compares
loadTime
and the last modified time of the source data of the resource bundle. If it's determined that the source data has been modified sinceloadTime
,true
is returned. Otherwise,false
is returned. This implementation assumes that the givenformat
is the same string as its file suffix if it's not one of the default formats,"java.class"
or"java.properties"
.- Parameters:
baseName
- the base bundle name of the resource bundle, a fully qualified class namelocale
- the locale for which the resource bundle should be instantiatedformat
- the resource bundle format to be loadedloader
- theClassLoader
to use to load the bundlebundle
- the resource bundle instance that has been expired in the cacheloadTime
- the time whenbundle
was loaded and put in the cache- Returns:
true
if the expired bundle needs to be reloaded;false
otherwise.- Throws:
NullPointerException
- ifbaseName
,locale
,format
,loader
, orbundle
isnull
-
toBundleName
Converts the givenbaseName
andlocale
to the bundle name. This method is called from the default implementation of thenewBundle
andneedsReload
methods.This implementation returns the following value:
baseName + "_" + language + "_" + script + "_" + country + "_" + variant
wherelanguage
,script
,country
, andvariant
are the language, script, country, and variant values oflocale
, respectively. Final component values that are empty Strings are omitted along with the preceding '_'. When the script is empty, the script value is omitted along with the preceding '_'. If all of the values are empty strings, thenbaseName
is returned.For example, if
baseName
is"baseName"
andlocale
isLocale("ja", "", "XX")
, then"baseName_ja_ _XX"
is returned. If the given locale isLocale("en")
, then"baseName_en"
is returned.Overriding this method allows applications to use different conventions in the organization and packaging of localized resources.
- Parameters:
baseName
- the base name of the resource bundle, a fully qualified class namelocale
- the locale for which a resource bundle should be loaded- Returns:
- the bundle name for the resource bundle
- Throws:
NullPointerException
- ifbaseName
orlocale
isnull
- See Also:
-
toResourceName
Converts the givenbundleName
to the form required by theClassLoader.getResource
method by replacing all occurrences of'.'
inbundleName
with'/'
and appending a'.'
and the given filesuffix
. For example, ifbundleName
is"foo.bar.MyResources_ja_JP"
andsuffix
is"properties"
, then"foo/bar/MyResources_ja_JP.properties"
is returned.- Parameters:
bundleName
- the bundle namesuffix
- the file type suffix- Returns:
- the converted resource name
- Throws:
NullPointerException
- ifbundleName
orsuffix
isnull
-