Class ResourceBundle.Control

java.lang.Object
java.util.ResourceBundle.Control
Enclosing class:
ResourceBundle

public static classResourceBundle.ControlextendsObject
ResourceBundle.Control defines a set of callback methods that are invoked by theResourceBundle.getBundle factory methods during the bundle loading process. In other words, aResourceBundle.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 thedefault 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 forResourceBundle.Control when migrating to modules.UnsupportedOperationException will be thrown when a factory method that takes theResourceBundle.Control parameter is called.

In addition to the callback methods, thetoBundleName andtoResourceName methods are defined primarily for convenience in implementing the callback methods. However, thetoBundleName method could be overridden to provide different conventions in the organization and packaging of localized resources. ThetoResourceName method isfinal to avoid use of wrong resource and class name separators.

Two factory methods,getControl(List) andgetNoFallbackControl(List), provideResourceBundle.Control instances that implement common variations of the default bundle loading process.

The formats returned by thegetFormats method and candidate locales returned by thegetCandidateLocales method must be consistent in allResourceBundle.getBundle invocations for the same base bundle. Otherwise, theResourceBundle.getBundle methods may return unintended bundles. For example, if only"java.class" is returned by thegetFormats method for the first call toResourceBundle.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.

AResourceBundle.Control instance must be thread-safe if it's simultaneously used by multiple threads.ResourceBundle.getBundle does not synchronize to call theResourceBundle.Control methods. The default implementations of the methods are thread-safe.

Applications can specifyResourceBundle.Control instances returned by thegetControl factory methods or created from a subclass ofResourceBundle.Control to customize the bundle loading process. The following are examples of changing the default bundle loading process.

Example 1

The following code letsResourceBundle.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));
Given the resource bundles in theexample in theResourceBundle.getBundle description, thisResourceBundle.getBundle call loadsMyResources_fr_CH.properties whose parent isMyResources_fr.properties whose parent isMyResources.properties. (MyResources_fr_CH.properties is not hidden, butMyResources_fr_CH.class is.)

Example 2

The following is an example of loading XML-based bundles usingProperties.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 Details

    • FORMAT_DEFAULT

      public static final List<String> FORMAT_DEFAULT
      The default formatList, which contains the strings"java.class" and"java.properties", in this order. ThisList is unmodifiable.
      See Also:
    • FORMAT_CLASS

      public static final List<String> FORMAT_CLASS
      The class-only formatList containing"java.class". ThisList is unmodifiable.
      See Also:
    • FORMAT_PROPERTIES

      public static final List<String> FORMAT_PROPERTIES
      The properties-only formatList containing"java.properties". ThisList is unmodifiable.
      See Also:
    • TTL_DONT_CACHE

      public static final long TTL_DONT_CACHE
      The time-to-live constant for not caching loaded resource bundle instances.
      See Also:
    • TTL_NO_EXPIRATION_CONTROL

      public static final long TTL_NO_EXPIRATION_CONTROL
      The 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

      public static final ResourceBundle.Control getControl(List<String> formats)
      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.

      SpecifyingFORMAT_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:
      aResourceBundle.Control supporting the specifiedformats
      Throws:
      NullPointerException - ifformats isnull
      IllegalArgumentException - ifformats is unknown
    • getNoFallbackControl

      public static final ResourceBundle.Control getNoFallbackControl(List<String> formats)
      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:
      aResourceBundle.Control supporting the specifiedformats with no fallbackLocale support
      Throws:
      NullPointerException - ifformats isnull
      IllegalArgumentException - ifformats is unknown
    • getFormats

      public List<String> getFormats(String baseName)
      Returns aList ofStrings 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" forproperties-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 returnsFORMAT_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:
      aList ofStrings containing formats for loading resource bundles.
      Throws:
      NullPointerException - ifbaseName is null
      See Also:
    • getCandidateLocales

      public List<Locale> getCandidateLocales(String baseName,Locale locale)
      Returns aList ofLocales 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 theparent 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 aroot locale if it is desired to have the base bundle as the terminal of the parent chain.

      If the given locale is equal toLocale.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 aList containingLocales using the rules described below. In the description below,L,S,C andV 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 formL("xx") represents the (non-empty) language value is "xx". For all cases,Locales whose final component values are empty strings are omitted.

      1. For an inputLocale with an empty script value, append candidateLocales by omitting the final component one by one as below:
        • [L,C,V]
        • [L,C]
        • [L]
        • Locale.ROOT
      2. For an inputLocale with a non-empty script value, append candidateLocales 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
      3. For an inputLocale with a variant value consisting of multiple subtags separated by underscore, generate candidateLocales by omitting the variant subtags one by one, then insert them after every occurrence of Locales with the full variant value in the original list. For example, if the variant consists of two subtagsV1 andV2:
        • [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
      4. Special cases for Chinese. When an inputLocale 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
        ForLocale("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
      5. Special cases for Norwegian. BothLocale("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
        If the locale is exactlyLocale("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 caseLocale("no", "NO", "NY") (handled above), when an inputLocale has language "no" or "nb", candidateLocales 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 anArrayList 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 givenbaseName is "Messages" and the givenlocale isLocale("ja", "", "XX"), then aList ofLocales:

           Locale("ja", "", "XX")     Locale("ja")     Locale.ROOT
      is returned. And if the resource bundles for the "ja" and ""Locales 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 name
      locale - the locale for which a resource bundle is desired
      Returns:
      aList of candidateLocales for the givenlocale
      Throws:
      NullPointerException - ifbaseName orlocale isnull
    • getFallbackLocale

      public Locale getFallbackLocale(String baseName,Locale locale)
      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 returnsnull if no further fallback search is desired.

      The default implementation returns thedefaultLocale 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:
      aLocale 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) throwsIllegalAccessException,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 thereload 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 byModule.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 aResourceBundle as follows.

      • The bundle name is obtained by callingtoBundleName(baseName, locale).
      • Ifformat 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.
      • Ifformat 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 todisable the caches of the underlying resource loading layers, and toget anInputStream. Otherwise,loader.getResourceAsStream is called to get anInputStream. Then, aPropertyResourceBundle is constructed with theInputStream.
      • Ifformat is neither"java.class" nor"java.properties", anIllegalArgumentException is thrown.
      • If thelocale's language is one of theLegacy 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.

      Parameters:
      baseName - the base bundle name of the resource bundle, a fully qualified class name
      locale - the locale for which the resource bundle should be instantiated
      format - the resource bundle format to be loaded
      loader - theClassLoader to use to load the bundle
      reload - the flag to indicate bundle reloading;true if reloading an expired resource bundle,false otherwise
      Returns:
      the resource bundle instance, ornull 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.
      IOException - if an error occurred when reading resources using any I/O operations
      See Also:
    • getTimeToLive

      public long getTimeToLive(String baseName,Locale locale)
      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 theResourceBundle.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 returnsTTL_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 callingResourceBundle.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 comparesloadTime 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 name
      locale - the locale for which the resource bundle should be instantiated
      format - the resource bundle format to be loaded
      loader - theClassLoader to use to load the bundle
      bundle - the resource bundle instance that has been expired in the cache
      loadTime - 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

      public String toBundleName(String baseName,Locale locale)
      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, ifbaseName 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 name
      locale - 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

      public 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. 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 name
      suffix - the file type suffix
      Returns:
      the converted resource name
      Throws:
      NullPointerException - ifbundleName orsuffix isnull