org.springframework.context.support
Class ResourceBundleMessageSource

java.lang.Object
  extended by org.springframework.context.support.MessageSourceSupport
      extended by org.springframework.context.support.AbstractMessageSource
          extended by org.springframework.context.support.ResourceBundleMessageSource
All Implemented Interfaces:
BeanClassLoaderAware, HierarchicalMessageSource, MessageSource

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.

Author:
Rod Johnson, Juergen Hoeller
See Also:
setBasenames(java.lang.String[]), ReloadableResourceBundleMessageSource, ResourceBundle, MessageFormat

Field Summary
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.
 
Fields inherited from class org.springframework.context.support.MessageSourceSupport
logger
 
Constructor Summary
ResourceBundleMessageSource()
           
 
Method Summary
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.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.
 java.lang.String toString()
          Show the configuration of this MessageSource.
 
Methods inherited from class org.springframework.context.support.AbstractMessageSource
getDefaultMessage, getMessage, getMessage, getMessage, getMessageFromParent, getMessageInternal, getParentMessageSource, isUseCodeAsDefaultMessage, resolveArguments, setParentMessageSource, setUseCodeAsDefaultMessage
 
Methods inherited from class org.springframework.context.support.MessageSourceSupport
createMessageFormat, formatMessage, isAlwaysUseMessageFormat, renderDefaultMessage, setAlwaysUseMessageFormat
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

basenames

private java.lang.String[] basenames

bundleClassLoader

private java.lang.ClassLoader bundleClassLoader

beanClassLoader

private java.lang.ClassLoader beanClassLoader

cachedResourceBundles

private final java.util.Map<java.lang.String,java.util.Map<java.util.Locale,java.util.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.


cachedBundleMessageFormats

private final 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. 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(java.util.ResourceBundle, java.lang.String, java.util.Locale)
Constructor Detail

ResourceBundleMessageSource

public ResourceBundleMessageSource()
Method Detail

setBasename

public void setBasename(java.lang.String basename)
Set a single basename, following 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.

See Also:
setBasenames(java.lang.String[]), ResourceBundle.getBundle(String)

setBasenames

public void setBasenames(java.lang.String[] basenames)
Set an array of basenames, each following 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.

See Also:
setBasename(java.lang.String), ResourceBundle.getBundle(String)

setBundleClassLoader

public void setBundleClassLoader(java.lang.ClassLoader classLoader)
Set the ClassLoader to load resource bundles with.

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


getBundleClassLoader

protected java.lang.ClassLoader getBundleClassLoader()
Return the ClassLoader to load resource bundles with.

Default is the containing BeanFactory's bean ClassLoader.

See Also:
setBundleClassLoader(java.lang.ClassLoader)

setBeanClassLoader

public void setBeanClassLoader(java.lang.ClassLoader classLoader)
Description copied from interface: BeanClassLoaderAware
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.

Specified by:
setBeanClassLoader in interface BeanClassLoaderAware
Parameters:
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()

resolveCodeWithoutArguments

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

Overrides:
resolveCodeWithoutArguments in class AbstractMessageSource
Parameters:
code - the code of the message to resolve
locale - the Locale to resolve the code for (subclasses are encouraged to support internationalization)
Returns:
the message String, or null if not found
See Also:
AbstractMessageSource.resolveCode(java.lang.String, java.util.Locale), MessageFormat

resolveCode

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.

Specified by:
resolveCode in class AbstractMessageSource
Parameters:
code - the code of the message to resolve
locale - the Locale to resolve the code for (subclasses are encouraged to support internationalization)
Returns:
the MessageFormat for the message, or null if not found
See Also:
AbstractMessageSource.resolveCodeWithoutArguments(String, java.util.Locale)

getResourceBundle

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.

Parameters:
basename - the basename of the ResourceBundle
locale - the Locale to find the ResourceBundle for
Returns:
the resulting ResourceBundle, or null if none found for the given basename and Locale

doGetBundle

protected java.util.ResourceBundle doGetBundle(java.lang.String basename,
                                               java.util.Locale locale)
                                        throws java.util.MissingResourceException
Obtain the resource bundle for the given basename and Locale.

Parameters:
basename - the basename to look for
locale - the Locale to look for
Returns:
the corresponding ResourceBundle
Throws:
java.util.MissingResourceException - if no matching bundle could be found
See Also:
ResourceBundle.getBundle(String, java.util.Locale, ClassLoader), getBundleClassLoader()

getMessageFormat

protected java.text.MessageFormat getMessageFormat(java.util.ResourceBundle bundle,
                                                   java.lang.String code,
                                                   java.util.Locale locale)
                                            throws java.util.MissingResourceException
Return a MessageFormat for the given bundle and code, fetching already generated MessageFormats from the cache.

Parameters:
bundle - the ResourceBundle to work on
code - the message code to retrieve
locale - the Locale to use to build the MessageFormat
Returns:
the resulting MessageFormat, or null if no message defined for the given code
Throws:
java.util.MissingResourceException - if thrown by the ResourceBundle

getStringOrNull

private java.lang.String getStringOrNull(java.util.ResourceBundle bundle,
                                         java.lang.String key)

toString

public java.lang.String toString()
Show the configuration of this MessageSource.

Overrides:
toString in class java.lang.Object