com.redhat.rhn.common.localization.XmlMessages.java Source code

Java tutorial

Introduction

Here is the source code for com.redhat.rhn.common.localization.XmlMessages.java

Source

/**
 * Copyright (c) 2009--2014 Red Hat, Inc.
 *
 * This software is licensed to you under the GNU General Public License,
 * version 2 (GPLv2). There is NO WARRANTY for this software, express or
 * implied, including the implied warranties of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
 * along with this software; if not, see
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 *
 * Red Hat trademarks are not licensed under GPLv2. No permission is
 * granted to use or replicate Red Hat trademarks that are incorporated
 * in this software or its documentation.
 */

package com.redhat.rhn.common.localization;

import com.redhat.rhn.common.conf.Config;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

/**
 * Utility (Singleton) class to get and format messages centralized by package.
 * Messages are assumed to be in a {@link ResourceBundle} called
 * <code>StringResource</code>
 * in a given class' package.
 * ie, If the class is <code>my.package.foo.Bar</code>, the
 * methods will look for the ResourceBundle
 * <code>my.package.foo.StringResource</code>. (The actual file can be
 * a subclass of ResourceBundle or a properties file.)
 * The ResourceBundle keys are assumed to be prefixed with the class name.
 * ie, if the class is <code>my.package.foo.Bar</code> and the key is
 * <code>msg</code>, the methods will then
 * look for the key <code>Bar.msg</code>.
 *
 *
 * @version $Rev$
 */
public final class XmlMessages {

    /** The error warning message in case we don't find a message.
     */
    public static final String MESSAGE_NOT_FOUND = "*** MESSAGE NOT FOUND ***";

    /** Set to "StringResource"
     */
    private static final String RESOURCE_BUNDLE_CLASSNAME = "StringResource";

    public static final String PRODUCT_NAME_MACRO = "@@PRODUCT_NAME@@";

    private static final Logger LOG = Logger.getLogger(XmlMessages.class);

    private static XmlMessages instance = new XmlMessages();

    // Store the bundles in memory so we don't load it off disk
    // each time.
    private Map<String, ResourceBundle> bundles;

    /** Private constructor, since this is a singleton
     */
    private XmlMessages() {
        initBundleCache();
    }

    private void initBundleCache() {
        bundles = new HashMap<String, ResourceBundle>();
    }

    /**
     * Get the instance of the singleton class
     * @return The instance
     */
    public static XmlMessages getInstance() {
        return instance;
    }

    /**
     * Reload the XML Messages off the disk.
     */
    public void resetBundleCache() {
        initBundleCache();
    }

    /** Gets the resource bundle, first checking our internal cache
       * @param bundleName name of the resource bundle
       * @param locale locale used to retrieve the resource bundle
       * @return the resource bundle for the given bundleName and locale,
       * always non-null. (An exception is thrown if the bundle can't be found.)
       */
    protected ResourceBundle getBundle(final String bundleName, final Locale locale) {

        // Construct the key to the Map of Bundles
        // that is a combination of the bundlename
        // plus the locale
        StringBuilder bundleBuff = new StringBuilder(bundleName);
        if (locale != null) {
            bundleBuff.append(".");
            bundleBuff.append(locale.toString());
        }
        String bundleKey = bundleBuff.toString();
        // Check the local in memory cache of the bundles
        // to see if it has been loaded already.
        ResourceBundle retval = bundles.get(bundleKey);

        if (retval != null) {
            // System.out.println("Got bundle from cache, returning : " + bundleKey);
            return retval;
        }
        // System.out.println("Reloading BUNDLE : " + bundleKey);

        StringBuilder urlName = new StringBuilder("/" + bundleName.replace('.', '/'));

        // if we specified a locale
        // then make sure we tack it on to the filename
        // to be loaded.
        if (locale != null) {
            urlName.append("_");
            urlName.append(locale.toString());
        }
        urlName.append(".xml");

        try {
            synchronized (this) {
                retval = new XmlResourceBundle(urlName.toString());
                bundles.put(bundleKey, retval);
            }

        } catch (IOException ioe) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Resource bundle not found: " + ioe.toString() + ", url: " + urlName);
            }
            throw new java.util.MissingResourceException("Resource bundle not found", bundleName, "");
        }
        return retval;

    }

    /**
    * Obtain a string from the resource file that doesn't require formatting.
    * See the format() methods for obtaining strings that require formatting.
     * @param clazz the class to which the string belongs
     * @param locale the locale used to find the resource bundle
     * @param key the key for the string to be obtained from the resource bundle
    * @return the message for the given key
    */
    public String getMessage(final Class clazz, final Locale locale, final String key) {
        return format(clazz, locale, key, (Object[]) null);
    }

    /**
     * Convenience method to format a string from the resource bundle, which
     * takes a single argument.
     * @param clazz the class to which the string belongs
     * @param locale the locale used to find the resource bundle
     * @param key the key for the string to be obtained from the resource bundle
     * @param arg1 the first argument to use in the formatted text
     * @return the formatted message for the given key and argument
     */
    public String format(final Class clazz, final Locale locale, final String key, final String arg1) {
        return format(clazz, locale, key, new Object[] { arg1 });
    }

    /**
     * Convenience method to format a string from the resource bundle, which
     * takes two arguments.
     * @param clazz the class to which the string belongs
     * @param locale the locale used to find the resource bundle
     * @param key the key for the string to be obtained from the resource bundle
     * @param arg1 the first argument to use in the formatted text
     * @param arg2 the second argument to use in the formatted text
     * @return the formatted message for the given key and arguments
     */
    public String format(final Class clazz, final Locale locale, final String key, final String arg1,
            final String arg2) {
        return format(clazz, locale, key, new Object[] { arg1, arg2 });
    }

    /**
     * Convenience method to format a string from the resource bundle, which
     * takes three arguments.
     * @param clazz the class to which the string belongs
     * @param locale the locale used to find the resource bundle
     * @param key the key for the string to be obtained from the resource bundle
     * @param arg1 the first argument to use in the formatted text
     * @param arg2 the second argument to use in the formatted text
     * @param arg3 the third argument to use in the formatted text
     * @return the formatted message for the given key and arguments
     */
    public String format(final Class clazz, final Locale locale, final String key, final String arg1,
            final String arg2, final String arg3) {
        return format(clazz, locale, key, new Object[] { arg1, arg2, arg3 });
    }

    /**
     * Method to format a string from the resource bundle.  This
     * method allows the user of this class to directly specify the
     * bundle package name to be used.  Allows us to have
     * resource bundles in packages without classes.  Eliminates
     * the need for "Dummy" classes.
     *
     * @param clazz the class to which the string belongs
     * @param locale the locale used to find the resource bundle
     * @param key the key for the string to be obtained from the resource bundle
     * @param args the arguments that should be applied to the string obtained
     * from the resource bundle. Can be null, to represent no arguments
     * @return the formatted message for the given key and arguments
     */
    public String format(final Class clazz, final Locale locale, final String key, final Object... args) {

        // Fetch the bundle
        ResourceBundle bundle = getBundle(getBundleName(clazz), locale);
        String pattern = StringEscapeUtils.unescapeHtml(bundle.getString(key));

        pattern = pattern.replaceAll(PRODUCT_NAME_MACRO, Config.get().getString("web.product_name"));

        if (args == null || args.length == 0) {
            return pattern;
        }

        //MessageFormat uses single quotes to escape text. Therefore, we have to
        //escape the single quote so that MessageFormat keeps the single quote and
        //does replace all arguments after it.
        String escapedPattern = pattern.replaceAll("'", "''");
        MessageFormat mf = new MessageFormat(escapedPattern, locale);
        return mf.format(args);
    }

    private String getBundleName(final Class clazz) {
        String fullyQualifiedClassName = clazz.getName();
        int idx = fullyQualifiedClassName.lastIndexOf('.');
        String bundleName = fullyQualifiedClassName.substring(0, idx + 1) + RESOURCE_BUNDLE_CLASSNAME;
        return bundleName;
    }

    /**
     * Gets the keys of all the strings in the specified class and locale's
     * resource bundle.
     *
     * @param clazz Class of the resource bundle
     * @param locale locale used to retrieve the resource bundle
     * @return the Iterator of all the keys
    */
    public Enumeration getKeys(final Class clazz, final Locale locale) {
        return getBundle(getBundleName(clazz), locale).getKeys();
    }

}