public class ResourceBundleMessageSource extends AbstractMessageSource implements BeanClassLoaderAware
MessageSource
implementation that
accesses resource bundles using specified basenames. This class relies
on the underlying JDK's ResourceBundle
implementation,
in combination with the JDK's standard message parsing provided by
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.
Unfortunately, java.util.ResourceBundle
caches loaded bundles
forever: Reloading a bundle during VM execution is not possible.
As this MessageSource relies on ResourceBundle, it faces the same limitation.
Consider ReloadableResourceBundleMessageSource
for an alternative
that is capable of refreshing the underlying bundle files.
setBasenames(java.lang.String...)
,
ReloadableResourceBundleMessageSource
,
ResourceBundle
,
MessageFormat
Modifier and Type | Class and Description |
---|---|
private class |
ResourceBundleMessageSource.MessageSourceControl
Custom implementation of Java 6's
ResourceBundle.Control ,
adding support for custom file encodings, deactivating the fallback to the
system locale and activating ResourceBundle's native cache, if desired. |
Modifier and Type | Field and Description |
---|---|
private java.lang.String[] |
basenames |
private java.lang.ClassLoader |
beanClassLoader |
private java.lang.ClassLoader |
bundleClassLoader |
private java.util.Map<java.util.ResourceBundle,java.util.Map<java.lang.String,java.util.Map<java.util.Locale,java.text.MessageFormat>>> |
cachedBundleMessageFormats
Cache to hold already generated MessageFormats.
|
private java.util.Map<java.lang.String,java.util.Map<java.util.Locale,java.util.ResourceBundle>> |
cachedResourceBundles
Cache to hold loaded ResourceBundles.
|
private long |
cacheMillis |
private java.lang.String |
defaultEncoding |
private boolean |
fallbackToSystemLocale |
logger
Constructor and Description |
---|
ResourceBundleMessageSource() |
Modifier and Type | Method and Description |
---|---|
protected java.util.ResourceBundle |
doGetBundle(java.lang.String basename,
java.util.Locale locale)
Obtain the resource bundle for the given basename and Locale.
|
protected java.lang.ClassLoader |
getBundleClassLoader()
Return the ClassLoader to load resource bundles with.
|
protected java.text.MessageFormat |
getMessageFormat(java.util.ResourceBundle bundle,
java.lang.String code,
java.util.Locale locale)
Return a MessageFormat for the given bundle and code,
fetching already generated MessageFormats from the cache.
|
protected java.util.ResourceBundle |
getResourceBundle(java.lang.String basename,
java.util.Locale locale)
Return a ResourceBundle for the given basename and code,
fetching already generated MessageFormats from the cache.
|
private java.lang.String |
getStringOrNull(java.util.ResourceBundle bundle,
java.lang.String key) |
protected java.util.ResourceBundle |
loadBundle(java.io.Reader reader)
Load a property-based resource bundle from the given reader.
|
protected java.text.MessageFormat |
resolveCode(java.lang.String code,
java.util.Locale locale)
Resolves the given message code as key in the registered resource bundles,
using a cached MessageFormat instance per message code.
|
protected java.lang.String |
resolveCodeWithoutArguments(java.lang.String code,
java.util.Locale locale)
Resolves the given message code as key in the registered resource bundles,
returning the value found in the bundle as-is (without MessageFormat parsing).
|
void |
setBasename(java.lang.String basename)
Set a single basename, following
ResourceBundle conventions:
essentially, a fully-qualified classpath location. |
void |
setBasenames(java.lang.String... basenames)
Set an array of basenames, each following
ResourceBundle
conventions: essentially, a fully-qualified classpath location. |
void |
setBeanClassLoader(java.lang.ClassLoader classLoader)
Callback that supplies the bean
class loader to
a bean instance. |
void |
setBundleClassLoader(java.lang.ClassLoader classLoader)
Set the ClassLoader to load resource bundles with.
|
void |
setCacheSeconds(int cacheSeconds)
Set the number of seconds to cache loaded resource bundle files.
|
void |
setDefaultEncoding(java.lang.String defaultEncoding)
Set the default charset to use for parsing resource bundle files.
|
void |
setFallbackToSystemLocale(boolean fallbackToSystemLocale)
Set whether to fall back to the system Locale if no files for a specific
Locale have been found.
|
java.lang.String |
toString()
Show the configuration of this MessageSource.
|
getCommonMessages, getDefaultMessage, getMessage, getMessage, getMessage, getMessageFromParent, getMessageInternal, getParentMessageSource, isUseCodeAsDefaultMessage, resolveArguments, setCommonMessages, setParentMessageSource, setUseCodeAsDefaultMessage
createMessageFormat, formatMessage, isAlwaysUseMessageFormat, renderDefaultMessage, setAlwaysUseMessageFormat
private java.lang.String[] basenames
private java.lang.String defaultEncoding
private boolean fallbackToSystemLocale
private long cacheMillis
private java.lang.ClassLoader bundleClassLoader
private java.lang.ClassLoader beanClassLoader
private final java.util.Map<java.lang.String,java.util.Map<java.util.Locale,java.util.ResourceBundle>> cachedResourceBundles
private final java.util.Map<java.util.ResourceBundle,java.util.Map<java.lang.String,java.util.Map<java.util.Locale,java.text.MessageFormat>>> cachedBundleMessageFormats
public void setBasename(java.lang.String basename)
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.
Messages will normally be held in the "/lib" or "/classes" directory of a web application's WAR structure. They can also be held in jar files on the class path.
Note that ResourceBundle names are effectively classpath locations: As a
consequence, the JDK's standard ResourceBundle treats dots as package separators.
This means that "test.theme" is effectively equivalent to "test/theme",
just like it is for programmatic java.util.ResourceBundle
usage.
setBasenames(java.lang.String...)
,
ResourceBundle.getBundle(String)
public void setBasenames(java.lang.String... basenames)
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.
The associated resource bundles will be checked sequentially when resolving a message code. Note that message definitions in a previous resource bundle will override ones in a later bundle, due to the sequential lookup.
Note that ResourceBundle names are effectively classpath locations: As a
consequence, the JDK's standard ResourceBundle treats dots as package separators.
This means that "test.theme" is effectively equivalent to "test/theme",
just like it is for programmatic java.util.ResourceBundle
usage.
setBasename(java.lang.String)
,
ResourceBundle.getBundle(String)
public void setDefaultEncoding(java.lang.String defaultEncoding)
Default is the java.util.ResourceBundle
default encoding:
ISO-8859-1.
public void setFallbackToSystemLocale(boolean fallbackToSystemLocale)
Falling back to the system Locale is the default behavior of
java.util.ResourceBundle
. However, this is often not desirable
in an application server environment, where the system Locale is not relevant
to the application at all: Set this flag to "false" in such a scenario.
public void setCacheSeconds(int cacheSeconds)
ReloadableResourceBundleMessageSource
in combination
with resource bundle files in a non-classpath location.
public void setBundleClassLoader(java.lang.ClassLoader classLoader)
Default is the containing BeanFactory's
bean ClassLoader
,
or the default ClassLoader determined by
ClassUtils.getDefaultClassLoader()
if not running within a BeanFactory.
protected java.lang.ClassLoader getBundleClassLoader()
Default is the containing BeanFactory's bean ClassLoader.
public void setBeanClassLoader(java.lang.ClassLoader classLoader)
BeanClassLoaderAware
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.
setBeanClassLoader
in interface BeanClassLoaderAware
classLoader
- the owning class loader; may be null
in
which case a default ClassLoader
must be used, for example
the ClassLoader
obtained via
ClassUtils.getDefaultClassLoader()
protected java.lang.String resolveCodeWithoutArguments(java.lang.String code, java.util.Locale locale)
resolveCodeWithoutArguments
in class AbstractMessageSource
code
- the code of the message to resolvelocale
- the Locale to resolve the code for
(subclasses are encouraged to support internationalization)null
if not foundAbstractMessageSource.resolveCode(java.lang.String, java.util.Locale)
,
MessageFormat
protected java.text.MessageFormat resolveCode(java.lang.String code, java.util.Locale locale)
resolveCode
in class AbstractMessageSource
code
- the code of the message to resolvelocale
- the Locale to resolve the code for
(subclasses are encouraged to support internationalization)null
if not foundAbstractMessageSource.resolveCodeWithoutArguments(String, java.util.Locale)
protected java.util.ResourceBundle getResourceBundle(java.lang.String basename, java.util.Locale locale)
basename
- the basename of the ResourceBundlelocale
- the Locale to find the ResourceBundle fornull
if none
found for the given basename and Localeprotected java.util.ResourceBundle doGetBundle(java.lang.String basename, java.util.Locale locale) throws java.util.MissingResourceException
basename
- the basename to look forlocale
- the Locale to look forjava.util.MissingResourceException
- if no matching bundle could be foundResourceBundle.getBundle(String, Locale, ClassLoader)
,
getBundleClassLoader()
protected java.util.ResourceBundle loadBundle(java.io.Reader reader) throws java.io.IOException
The default implementation returns a PropertyResourceBundle
.
reader
- the reader for the target resourcejava.io.IOException
- in case of I/O failurePropertyResourceBundle.PropertyResourceBundle(Reader)
protected java.text.MessageFormat getMessageFormat(java.util.ResourceBundle bundle, java.lang.String code, java.util.Locale locale) throws java.util.MissingResourceException
bundle
- the ResourceBundle to work oncode
- the message code to retrievelocale
- the Locale to use to build the MessageFormatnull
if no message
defined for the given codejava.util.MissingResourceException
- if thrown by the ResourceBundleprivate java.lang.String getStringOrNull(java.util.ResourceBundle bundle, java.lang.String key)
public java.lang.String toString()
toString
in class java.lang.Object