package org.gbif.ipt.struts2; import java.text.MessageFormat; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Set; import com.opensymphony.xwork2.LocaleProvider; import org.apache.log4j.Logger; /** * A basic text provider for internationalised messages that can replace the native struts2 one. It uses only a single * bundle name to speed up the lookup which increases performance of page rendering with many text blocks by sometimes * more than 100%. */ public class SimpleTextProvider { private static final Logger LOG = Logger.getLogger(SimpleTextProvider.class); private static final String DEFAULT_BUNDLE = "ApplicationResources"; private final Set<String> baseBundleNames = new HashSet<String>(); public SimpleTextProvider() { baseBundleNames.add(DEFAULT_BUNDLE); } /** * Finds the given resource bundle by it's name and locale. * <br/> * Will use <code>Thread.currentThread().getContextClassLoader()</code> as the classloader. * * @param aBundleName the name of the bundle (usually it's FQN classname). * @param locale the locale. * * @return the bundle, defaulting to the English bundle if no match for locale found or if Exception occurred */ public ResourceBundle findResourceBundle(String aBundleName, Locale locale) { Locale currentLocale = Locale.getDefault(); try { // override default Locale in case incoming locale isn't matched - see ResourceBundle.getFallbackLocale() Locale.setDefault(Locale.ENGLISH); return ResourceBundle.getBundle(aBundleName, locale, Thread.currentThread().getContextClassLoader()); } catch (Exception e) { return ResourceBundle.getBundle(aBundleName, Locale.ENGLISH, Thread.currentThread().getContextClassLoader()); } finally { Locale.setDefault(currentLocale); } } public String findText(ResourceBundle bundle, String aTextName, String defaultMessage, Object[] args) { try { String message = bundle.getString(aTextName); String text; try { text = MessageFormat.format(message, args); } catch (IllegalArgumentException e) { // message and arguments dont match? LOG.debug(e); text = message; } return text; } catch (MissingResourceException e) { // return default message } return defaultMessage != null ? defaultMessage : aTextName; } /** * Gets a message based on a key using the supplied args, as defined in {@link MessageFormat}, or, if the * message is not found, a supplied default value is returned. Instead of using the value stack in the ActionContext * this version of the getText() method uses the provided value stack. * * @param localeProvider LocaleProvider * @param key the resource bundle key that is to be searched for * @param defaultValue the default value which will be returned if no message is found. If null the key name will be * used instead * @param args a list args to be used in a {@link MessageFormat} message * @return the message as found in the resource bundle, or defaultValue if none is found */ public String getText(LocaleProvider localeProvider, String key, String defaultValue, List args) { Object[] argsArray = args != null ? args.toArray() : null; return getText(localeProvider, key, defaultValue, argsArray); } public String getText(LocaleProvider localeProvider, String key, String defaultValue, Object[] args) { // Locale, defaulting to English if it cannot be determined Locale locale = (localeProvider.getLocale() == null) ? Locale.ENGLISH : localeProvider.getLocale(); String text = null; for (String resName : baseBundleNames) { ResourceBundle bundle = findResourceBundle(resName, locale); text = findText(bundle, key, defaultValue, args); if (text != null) { break; } } return text; } public ResourceBundle getTexts(Locale locale) { return findResourceBundle(DEFAULT_BUNDLE, locale); } public ResourceBundle getTexts(String bundleName, Locale locale) { return findResourceBundle(bundleName, locale); } }