Author: kfujino Date: Thu May 21 09:46:45 2015 New Revision: 1680783 URL: http://svn.apache.org/r1680783 Log: Align tribes.util.StringManager implementation with tomcat.util.StringManager implementation.
Modified: tomcat/trunk/java/org/apache/catalina/tribes/util/StringManager.java Modified: tomcat/trunk/java/org/apache/catalina/tribes/util/StringManager.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/tribes/util/StringManager.java?rev=1680783&r1=1680782&r2=1680783&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/tribes/util/StringManager.java (original) +++ tomcat/trunk/java/org/apache/catalina/tribes/util/StringManager.java Thu May 21 09:46:45 2015 @@ -18,11 +18,15 @@ package org.apache.catalina.tribes.util; import java.text.MessageFormat; +import java.util.Enumeration; import java.util.Hashtable; +import java.util.LinkedHashMap; import java.util.Locale; +import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; + /** * An internationalization / localization helper class which reduces * the bother of handling ResourceBundles and takes care of the @@ -49,12 +53,15 @@ import java.util.ResourceBundle; */ public class StringManager { + private static int LOCALE_CACHE_SIZE = 10; + /** * The ResourceBundle for this StringManager. */ private final ResourceBundle bundle; private final Locale locale; + /** * Creates a new StringManager for a given package. This is a * private method and all access to it is arbitrated by the @@ -63,58 +70,67 @@ public class StringManager { * * @param packageName Name of package to create StringManager for. */ - private StringManager(String packageName) { - ResourceBundle b = null; - + private StringManager(String packageName, Locale locale) { String bundleName = packageName + ".LocalStrings"; + ResourceBundle bnd = null; try { - b = ResourceBundle.getBundle(bundleName, Locale.getDefault()); - } catch( MissingResourceException ex ) { + bnd = ResourceBundle.getBundle(bundleName, locale); + } catch (MissingResourceException ex) { // Try from the current loader (that's the case for trusted apps) // Should only be required if using a TC5 style classloader structure // where common != shared != server ClassLoader cl = Thread.currentThread().getContextClassLoader(); - if( cl != null ) { + if (cl != null) { try { - b = ResourceBundle.getBundle( - bundleName, Locale.getDefault(), cl); - } catch(MissingResourceException ex2) { + bnd = ResourceBundle.getBundle(bundleName, locale, cl); + } catch (MissingResourceException ex2) { // Ignore } } } + bundle = bnd; // Get the actual locale, which may be different from the requested one - this.bundle = b; if (bundle != null) { - locale = bundle.getLocale(); + Locale bundleLocale = bundle.getLocale(); + if (bundleLocale.equals(Locale.ROOT)) { + this.locale = Locale.ENGLISH; + } else { + this.locale = bundleLocale; + } } else { - locale = null; + this.locale = null; } } - /** - Get a string from the underlying resource bundle or return - null if the String is not found. - @param key to desired resource String - @return resource String matching <i>key</i> from underlying - bundle or null if not found. - @throws IllegalArgumentException if <i>key</i> is null. + /** + * Get a string from the underlying resource bundle or return null if the + * String is not found. + * + * @param key to desired resource String + * + * @return resource String matching <i>key</i> from underlying bundle or + * null if not found. + * + * @throws IllegalArgumentException if <i>key</i> is null */ public String getString(String key) { - if(key == null){ + if (key == null){ String msg = "key may not have a null value"; - throw new IllegalArgumentException(msg); } String str = null; try { - str = bundle.getString(key); - } catch(MissingResourceException mre) { + // Avoid NPE if bundle is null and treat it like an MRE + if (bundle != null) { + str = bundle.getString(key); + } + } catch (MissingResourceException mre) { //bad: shouldn't mask an exception the following way: - // str = "[cannot find message associated with key '" + key + "' due to " + mre + "]"; + // str = "[cannot find message associated with key '" + key + + // "' due to " + mre + "]"; // because it hides the fact that the String was missing // from the calling code. //good: could just throw the exception (or wrap it in another) @@ -129,12 +145,13 @@ public class StringManager { return str; } + /** * Get a string from the underlying resource bundle and format * it with the given set of arguments. * - * @param key - * @param args + * @param key The key for the required message + * @param args The values to insert into the message */ public String getString(final String key, final Object... args) { String value = getString(key); @@ -147,12 +164,35 @@ public class StringManager { return mf.format(args, new StringBuffer(), null).toString(); } + + /** + * Identify the Locale this StringManager is associated with + */ + public Locale getLocale() { + return locale; + } + + // -------------------------------------------------------------- // STATIC SUPPORT METHODS // -------------------------------------------------------------- - private static final Hashtable<String, StringManager> managers = - new Hashtable<>(); + private static final Map<String, Map<Locale,StringManager>> managers = + new Hashtable<>(); + + + /** + * Get the StringManager for a given class. The StringManager will be + * returned for the package in which the class is located. If a manager for + * that package already exists, it will be reused, else a new + * StringManager will be created and returned. + * + * @param clazz The class for which to retrieve the StringManager + */ + public static final StringManager getManager(Class<?> clazz) { + return getManager(clazz.getPackage().getName()); + } + /** * Get the StringManager for a particular package. If a manager for @@ -161,13 +201,73 @@ public class StringManager { * * @param packageName The package name */ - public static final synchronized StringManager getManager(String packageName) { - StringManager mgr = managers.get(packageName); + public static final StringManager getManager(String packageName) { + return getManager(packageName, Locale.getDefault()); + } + + + /** + * Get the StringManager for a particular package and Locale. If a manager + * for a package/Locale combination already exists, it will be reused, else + * a new StringManager will be created and returned. + * + * @param packageName The package name + * @param locale The Locale + */ + public static final synchronized StringManager getManager( + String packageName, Locale locale) { + + Map<Locale,StringManager> map = managers.get(packageName); + if (map == null) { + /* + * Don't want the HashMap to be expanded beyond LOCALE_CACHE_SIZE. + * Expansion occurs when size() exceeds capacity. Therefore keep + * size at or below capacity. + * removeEldestEntry() executes after insertion therefore the test + * for removal needs to use one less than the maximum desired size + * + */ + map = new LinkedHashMap<Locale,StringManager>(LOCALE_CACHE_SIZE, 1, true) { + private static final long serialVersionUID = 1L; + @Override + protected boolean removeEldestEntry( + Map.Entry<Locale,StringManager> eldest) { + if (size() > (LOCALE_CACHE_SIZE - 1)) { + return true; + } + return false; + } + }; + managers.put(packageName, map); + } + + StringManager mgr = map.get(locale); if (mgr == null) { - mgr = new StringManager(packageName); - managers.put(packageName, mgr); + mgr = new StringManager(packageName, locale); + map.put(locale, mgr); } return mgr; } + + /** + * Retrieve the StringManager for a list of Locales. The first StringManager + * found will be returned. + * + * @param requestedLocales the list of Locales + * + * @return the found StringManager or the default StringManager + */ + public static StringManager getManager(String packageName, + Enumeration<Locale> requestedLocales) { + while (requestedLocales.hasMoreElements()) { + Locale locale = requestedLocales.nextElement(); + StringManager result = getManager(packageName, locale); + if (result.getLocale().equals(locale)) { + return result; + } + } + // Return the default + return getManager(packageName); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org