Top Description Inners Fields Constructors Methods
org.springframework.context.support

public Class ResourceBundleMessageSource

extends AbstractResourceBasedMessageSource
implements BeanClassLoaderAware
Class Inheritance
All Implemented Interfaces
org.springframework.beans.factory.BeanClassLoaderAware, org.springframework.beans.factory.Aware
Imports
java.io.IOException, .InputStream, .InputStreamReader, .Reader, java.net.URL, .URLConnection, java.text.MessageFormat, java.util.Locale, .Map, .MissingResourceException, .PropertyResourceBundle, .ResourceBundle, .Set, java.util.concurrent.ConcurrentHashMap, org.springframework.beans.factory.BeanClassLoaderAware, org.springframework.lang.Nullable, org.springframework.util.Assert, .ClassUtils

org.springframework.context.MessageSource implementation that accesses resource bundles using specified basenames. This class relies on the underlying JDK's java.util.ResourceBundle implementation, in combination with the JDK's standard message parsing provided by java.text.MessageFormat.

This MessageSource caches both the accessed ResourceBundle instances and the generated MessageFormats for each message. It also implements rendering of no-arg messages without MessageFormat, as supported by the AbstractMessageSource base class. The caching provided by this MessageSource is significantly faster than the built-in caching of the java.util.ResourceBundle class.

The basenames follow java.util.ResourceBundle conventions: essentially, a fully-qualified classpath location. If it doesn't contain a package qualifier (such as org.mypackage), it will be resolved from the classpath root. Note that the JDK's standard ResourceBundle treats dots as package separators: This means that "test.theme" is effectively equivalent to "test/theme".

On the classpath, bundle resources will be read with the locally configured encoding: by default, ISO-8859-1; consider switching this to UTF-8, or to null for the platform default encoding. On the JDK 9+ module path where locally provided ResourceBundle.Control handles are not supported, this MessageSource always falls back to ResourceBundle#getBundle retrieval with the platform default encoding: UTF-8 with a ISO-8859-1 fallback on JDK 9+ (configurable through the "java.util.PropertyResourceBundle.encoding" system property). Note that loadBundle(Reader)/loadBundle(InputStream) won't be called in this case either, effectively ignoring overrides in subclasses. Consider implementing a JDK 9 java.util.spi.ResourceBundleProvider instead.

Authors
Rod Johnson, Juergen Hoeller, Qimiao Chen
See Also
setBasenames, ReloadableResourceBundleMessageSource, java.util.ResourceBundle, java.text.MessageFormat

Nested and Inner Type Summary

Modifier and TypeClass and Description
private class
ResourceBundleMessageSource.MessageSourceControl

Custom implementation of ResourceBundle.Control, adding support for custom file encodings, deactivating the fallback to the system locale and activating ResourceBundle's native cache, if desired.

Field Summary

Modifier and TypeField and Description
private ClassLoader
private ClassLoader
private final Map<ResourceBundle, Map<String, Map<Locale, MessageFormat>>>
cachedBundleMessageFormats

Cache to hold already generated MessageFormats.

private final Map<String, Map<Locale, ResourceBundle>>
cachedResourceBundles

Cache to hold loaded ResourceBundles.

private volatile ResourceBundleMessageSource.MessageSourceControl

Constructor Summary

AccessConstructor and Description
public

Method Summary

Modifier and TypeMethod and Description
protected ResourceBundle

Returns:

the corresponding ResourceBundle
doGetBundle
(String
the basename to look for
basename
,
Locale
the Locale to look for
locale
)

Obtain the resource bundle for the given basename and Locale.

protected ClassLoader
getBundleClassLoader()

Return the ClassLoader to load resource bundles with.

protected MessageFormat

Returns:

the resulting MessageFormat, or null if no message defined for the given code
getMessageFormat
(ResourceBundle
the ResourceBundle to work on
bundle
,
String
the message code to retrieve
code
,
Locale
the Locale to use to build the MessageFormat
locale
)

Return a MessageFormat for the given bundle and code, fetching already generated MessageFormats from the cache.

protected ResourceBundle

Returns:

the resulting ResourceBundle, or null if none found for the given basename and Locale
getResourceBundle
(String
the basename of the ResourceBundle
basename
,
Locale
the Locale to find the ResourceBundle for
locale
)

Return a ResourceBundle for the given basename and Locale, fetching already generated ResourceBundle from the cache.

protected String

Returns:

the associated value, or null if none
getStringOrNull
(ResourceBundle
the ResourceBundle to perform the lookup in
bundle
,
String
the key to look up
key
)

Efficiently retrieve the String value for the specified key, or return null if not found.

protected ResourceBundle

Returns:

the fully loaded bundle
loadBundle
(Reader
the reader for the target resource
reader
)

Load a property-based resource bundle from the given reader.

protected ResourceBundle

Returns:

the fully loaded bundle
loadBundle
(InputStream
the input stream for the target resource
inputStream
)

Load a property-based resource bundle from the given input stream, picking up the default properties encoding on JDK 9+.

protected MessageFormat
resolveCode(String
the code of the message to resolve
code
,
Locale
the locale to resolve the code for (subclasses are encouraged to support internationalization)
locale
)

Implements abstract org.springframework.context.support.AbstractMessageSource.resolveCode.

Resolves the given message code as key in the registered resource bundles, using a cached MessageFormat instance per message code.

protected String
resolveCodeWithoutArguments(String
the code of the message to resolve
code
,
Locale
the locale to resolve the code for (subclasses are encouraged to support internationalization)
locale
)

Overrides org.springframework.context.support.AbstractMessageSource.resolveCodeWithoutArguments.

Resolves the given message code as key in the registered resource bundles, returning the value found in the bundle as-is (without MessageFormat parsing).

public void
setBeanClassLoader(ClassLoader
the owning class loader
classLoader
)

Implements org.springframework.beans.factory.BeanClassLoaderAware.setBeanClassLoader.

Callback that supplies the bean class loader to a bean instance.

public void
setBundleClassLoader(ClassLoader classLoader)

Set the ClassLoader to load resource bundles with.

public String
toString()

Overrides java.lang.Object.toString.

Show the configuration of this MessageSource.

Inherited from org.springframework.context.support.AbstractResourceBasedMessageSource:
addBasenamesgetBasenameSetgetCacheMillisgetDefaultEncodinggetDefaultLocaleisFallbackToSystemLocalesetBasenamesetBasenamessetCacheMillissetCacheSecondssetDefaultEncodingsetDefaultLocalesetFallbackToSystemLocale

Field Detail

beanClassLoaderback to summary
private ClassLoader beanClassLoader
Annotations
@Nullable
bundleClassLoaderback to summary
private ClassLoader bundleClassLoader
Annotations
@Nullable
cachedBundleMessageFormatsback to summary
private final Map<ResourceBundle, Map<String, Map<Locale, MessageFormat>>> cachedBundleMessageFormats

Cache to hold already generated MessageFormats. This Map is keyed with the ResourceBundle, which holds a Map that is keyed with the message code, which in turn holds a Map that is keyed with the Locale and holds the MessageFormat values. This allows for very efficient hash lookups without concatenated keys.

See Also
getMessageFormat
cachedResourceBundlesback to summary
private final Map<String, Map<Locale, ResourceBundle>> cachedResourceBundles

Cache to hold loaded ResourceBundles. This Map is keyed with the bundle basename, which holds a Map that is keyed with the Locale and in turn holds the ResourceBundle instances. This allows for very efficient hash lookups, significantly faster than the ResourceBundle class's own cache.

controlback to summary
private volatile ResourceBundleMessageSource.MessageSourceControl control
Annotations
@Nullable

Constructor Detail

ResourceBundleMessageSourceback to summary
public ResourceBundleMessageSource()

Method Detail

doGetBundleback to summary
protected ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException

Obtain the resource bundle for the given basename and Locale.

Parameters
basename:String

the basename to look for

locale:Locale

the Locale to look for

Returns:ResourceBundle

the corresponding ResourceBundle

Exceptions
MissingResourceException:
if no matching bundle could be found
See Also
java.util.ResourceBundle#getBundle(String, Locale, ClassLoader), getBundleClassLoader()
getBundleClassLoaderback to summary
protected ClassLoader getBundleClassLoader()

Return the ClassLoader to load resource bundles with.

Default is the containing BeanFactory's bean ClassLoader.

Annotations
@Nullable
See Also
setBundleClassLoader
getMessageFormatback to summary
protected MessageFormat getMessageFormat(ResourceBundle bundle, String code, Locale locale) throws MissingResourceException

Return a MessageFormat for the given bundle and code, fetching already generated MessageFormats from the cache.

Parameters
bundle:ResourceBundle

the ResourceBundle to work on

code:String

the message code to retrieve

locale:Locale

the Locale to use to build the MessageFormat

Returns:MessageFormat

the resulting MessageFormat, or null if no message defined for the given code

Annotations
@Nullable
Exceptions
MissingResourceException:
if thrown by the ResourceBundle
getResourceBundleback to summary
protected ResourceBundle getResourceBundle(String basename, Locale locale)

Return a ResourceBundle for the given basename and Locale, fetching already generated ResourceBundle from the cache.

Parameters
basename:String

the basename of the ResourceBundle

locale:Locale

the Locale to find the ResourceBundle for

Returns:ResourceBundle

the resulting ResourceBundle, or null if none found for the given basename and Locale

Annotations
@Nullable
getStringOrNullback to summary
protected String getStringOrNull(ResourceBundle bundle, String key)

Efficiently retrieve the String value for the specified key, or return null if not found.

As of 4.2, the default implementation checks containsKey before it attempts to call getString (which would require catching MissingResourceException for key not found).

Can be overridden in subclasses.

Parameters
bundle:ResourceBundle

the ResourceBundle to perform the lookup in

key:String

the key to look up

Returns:String

the associated value, or null if none

Annotations
@Nullable
Since
4.2
See Also
ResourceBundle#getString(String), ResourceBundle#containsKey(String)
loadBundleback to summary
protected ResourceBundle loadBundle(Reader reader) throws IOException

Load a property-based resource bundle from the given reader.

This will be called in case of a "defaultEncoding", including ResourceBundleMessageSource's default ISO-8859-1 encoding. Note that this method can only be called with a ResourceBundle.Control: When running on the JDK 9+ module path where such control handles are not supported, any overrides in custom subclasses will effectively get ignored.

The default implementation returns a PropertyResourceBundle.

Parameters
reader:Reader

the reader for the target resource

Returns:ResourceBundle

the fully loaded bundle

Exceptions
IOException:
in case of I/O failure
Since
4.2
See Also
loadBundle(InputStream), PropertyResourceBundle#PropertyResourceBundle(Reader)
loadBundleback to summary
protected ResourceBundle loadBundle(InputStream inputStream) throws IOException

Load a property-based resource bundle from the given input stream, picking up the default properties encoding on JDK 9+.

This will only be called with "defaultEncoding" set to null, explicitly enforcing the platform default encoding (which is UTF-8 with a ISO-8859-1 fallback on JDK 9+ but configurable through the "java.util.PropertyResourceBundle.encoding" system property). Note that this method can only be called with a ResourceBundle.Control: When running on the JDK 9+ module path where such control handles are not supported, any overrides in custom subclasses will effectively get ignored.

The default implementation returns a PropertyResourceBundle.

Parameters
inputStream:InputStream

the input stream for the target resource

Returns:ResourceBundle

the fully loaded bundle

Exceptions
IOException:
in case of I/O failure
Since
5.1
See Also
loadBundle(Reader), PropertyResourceBundle#PropertyResourceBundle(InputStream)
resolveCodeback to summary
protected MessageFormat resolveCode(String code, Locale locale)

Implements abstract org.springframework.context.support.AbstractMessageSource.resolveCode.

Resolves the given message code as key in the registered resource bundles, using a cached MessageFormat instance per message code.

Parameters
code:String

Doc from org.springframework.context.support.AbstractMessageSource.resolveCode.

the code of the message to resolve

locale:Locale

Doc from org.springframework.context.support.AbstractMessageSource.resolveCode.

the locale to resolve the code for (subclasses are encouraged to support internationalization)

Returns:MessageFormat

Doc from org.springframework.context.support.AbstractMessageSource.resolveCode.

the MessageFormat for the message, or null if not found

Annotations
@Override
@Nullable
resolveCodeWithoutArgumentsback to summary
protected String resolveCodeWithoutArguments(String code, Locale locale)

Overrides org.springframework.context.support.AbstractMessageSource.resolveCodeWithoutArguments.

Resolves the given message code as key in the registered resource bundles, returning the value found in the bundle as-is (without MessageFormat parsing).

Parameters
code:String

Doc from org.springframework.context.support.AbstractMessageSource.resolveCodeWithoutArguments.

the code of the message to resolve

locale:Locale

Doc from org.springframework.context.support.AbstractMessageSource.resolveCodeWithoutArguments.

the locale to resolve the code for (subclasses are encouraged to support internationalization)

Returns:String

Doc from org.springframework.context.support.AbstractMessageSource.resolveCodeWithoutArguments.

the message String, or null if not found

Annotations
@Override
setBeanClassLoaderback to summary
public void setBeanClassLoader(ClassLoader classLoader)

Implements org.springframework.beans.factory.BeanClassLoaderAware.setBeanClassLoader.

Doc from org.springframework.beans.factory.BeanClassLoaderAware.setBeanClassLoader.

Callback that supplies the bean class loader to a bean instance.

Invoked after the population of normal bean properties but before an initialization callback such as InitializingBean's InitializingBean#afterPropertiesSet() method or a custom init-method.

Parameters
classLoader:ClassLoader

the owning class loader

Annotations
@Override
setBundleClassLoaderback to summary
public void setBundleClassLoader(ClassLoader classLoader)

Set the ClassLoader to load resource bundles with.

Default is the containing BeanFactory's bean ClassLoader, or the default ClassLoader determined by org.springframework.util.ClassUtils#getDefaultClassLoader() if not running within a BeanFactory.

toStringback to summary
public String toString()

Overrides java.lang.Object.toString.

Show the configuration of this MessageSource.

Returns:String

Doc from java.lang.Object.toString.

a string representation of the object

Annotations
@Override
org.springframework.context.support back to summary

private Class ResourceBundleMessageSource.MessageSourceControl

extends Control
Class Inheritance

Custom implementation of ResourceBundle.Control, adding support for custom file encodings, deactivating the fallback to the system locale and activating ResourceBundle's native cache, if desired.

Field Summary

Inherited from java.util.ResourceBundle.Control:
FORMAT_CLASSFORMAT_DEFAULTFORMAT_PROPERTIESTTL_DONT_CACHETTL_NO_EXPIRATION_CONTROL

Constructor Summary

AccessConstructor and Description
private

Method Summary

Modifier and TypeMethod and Description
public Locale
getFallbackLocale(String
the base name of the resource bundle, a fully qualified class name for which ResourceBundle.getBundle has been unable to find any resource bundles (except for the base bundle)
baseName
,
Locale
the Locale for which ResourceBundle.getBundle has been unable to find any resource bundles (except for the base bundle)
locale
)

Overrides java.util.ResourceBundle.Control.getFallbackLocale.

Returns a Locale to be used as a fallback locale for further resource bundle searches by the ResourceBundle.getBundle factory method.

public long
getTimeToLive(String
the base name of the resource bundle for which the expiration value is specified.
baseName
,
Locale
the locale of the resource bundle for which the expiration value is specified.
locale
)

Overrides java.util.ResourceBundle.Control.getTimeToLive.

Returns the time-to-live (TTL) value for resource bundles that are loaded under this ResourceBundle.Control.

public boolean
needsReload(String
the base bundle name of the resource bundle, a fully qualified class name
baseName
,
Locale
the locale for which the resource bundle should be instantiated
locale
,
String
the resource bundle format to be loaded
format
,
ClassLoader
the ClassLoader to use to load the bundle
loader
,
ResourceBundle
the resource bundle instance that has been expired in the cache
bundle
,
long
the time when bundle was loaded and put in the cache
loadTime
)

Overrides java.util.ResourceBundle.Control.needsReload.

Determines if the expired bundle in the cache needs to be reloaded based on the loading time given by loadTime or some other criteria.

public ResourceBundle
newBundle(String
the base bundle name of the resource bundle, a fully qualified class name
baseName
,
Locale
the locale for which the resource bundle should be instantiated
locale
,
String
the resource bundle format to be loaded
format
,
ClassLoader
the ClassLoader to use to load the bundle
loader
,
boolean
the flag to indicate bundle reloading; true if reloading an expired resource bundle, false otherwise
reload
)

Overrides java.util.ResourceBundle.Control.newBundle.

Instantiates a resource bundle for the given bundle name of the given format and locale, using the given class loader if necessary.

Inherited from java.util.ResourceBundle.Control:
getCandidateLocalesgetControlgetFormatsgetNoFallbackControltoBundleNametoResourceName

Constructor Detail

MessageSourceControlback to summary
private MessageSourceControl()

Method Detail

getFallbackLocaleback to summary
public Locale getFallbackLocale(String baseName, Locale locale)

Overrides java.util.ResourceBundle.Control.getFallbackLocale.

Doc from java.util.ResourceBundle.Control.getFallbackLocale.

Returns a Locale to be used as a fallback locale for further resource bundle searches by the ResourceBundle.getBundle factory method. This method is called from the factory method every time when no resulting resource bundle has been found for baseName and locale, where locale is either the parameter for ResourceBundle.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 given locale isn't the default one. Otherwise, null is returned.

Parameters
baseName:String

the base name of the resource bundle, a fully qualified class name for which ResourceBundle.getBundle has been unable to find any resource bundles (except for the base bundle)

locale:Locale

the Locale for which ResourceBundle.getBundle has been unable to find any resource bundles (except for the base bundle)

Returns:Locale

a Locale for the fallback search, or null if no further fallback search is desired.

Annotations
@Override
@Nullable
getTimeToLiveback to summary
public long getTimeToLive(String baseName, Locale locale)

Overrides java.util.ResourceBundle.Control.getTimeToLive.

Doc from java.util.ResourceBundle.Control.getTimeToLive.

Returns the time-to-live (TTL) value for resource bundles that are loaded under this ResourceBundle.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 the needsReload method to determine whether the resource bundle needs to be reloaded. If needsReload returns true, 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:String

the base name of the resource bundle for which the expiration value is specified.

locale:Locale

the locale of the resource bundle for which the expiration value is specified.

Returns:long

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, or TTL_DONT_CACHE to disable caching.

Annotations
@Override
needsReloadback to summary
public boolean needsReload(String baseName, Locale locale, String format, ClassLoader loader, ResourceBundle bundle, long loadTime)

Overrides java.util.ResourceBundle.Control.needsReload.

Doc from java.util.ResourceBundle.Control.needsReload.

Determines if the expired bundle in the cache needs to be reloaded based on the loading time given by loadTime or some other criteria. The method returns true if reloading is required; false otherwise. loadTime is a millisecond offset since the Calendar Epoch.

The calling ResourceBundle.getBundle factory method calls this method on the ResourceBundle.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 since loadTime, true is returned. Otherwise, false is returned. This implementation assumes that the given format is the same string as its file suffix if it's not one of the default formats, "java.class" or "java.properties".

Parameters
baseName:String

the base bundle name of the resource bundle, a fully qualified class name

locale:Locale

the locale for which the resource bundle should be instantiated

format:String

the resource bundle format to be loaded

loader:ClassLoader

the ClassLoader to use to load the bundle

bundle:ResourceBundle

the resource bundle instance that has been expired in the cache

loadTime:long

the time when bundle was loaded and put in the cache

Returns:boolean

true if the expired bundle needs to be reloaded; false otherwise.

Annotations
@Override
newBundleback to summary
public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException

Overrides java.util.ResourceBundle.Control.newBundle.

Doc from java.util.ResourceBundle.Control.newBundle.

Instantiates a resource bundle for the given bundle name of the given format and locale, using the given class loader if necessary. This method returns null 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 an Error or Exception rather than simply returning null.

If the reload flag is true, it indicates that this method is being called because the previously loaded resource bundle has expired.

Parameters
baseName:String

the base bundle name of the resource bundle, a fully qualified class name

locale:Locale

the locale for which the resource bundle should be instantiated

format:String

the resource bundle format to be loaded

loader:ClassLoader

the ClassLoader to use to load the bundle

reload:boolean

the flag to indicate bundle reloading; true if reloading an expired resource bundle, false otherwise

Returns:ResourceBundle

the resource bundle instance, or null if none could be found.

Annotations
@Override
@Nullable
Exceptions
IllegalAccessException:
if the class or its nullary constructor is not accessible.
InstantiationException:
if the instantiation of a class fails for some other reason.
IOException:
if an error occurred when reading resources using any I/O operations