org.wso2.carbon.utils.i18n.ResourceBundle.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.utils.i18n.ResourceBundle.java

Source

/* 
 * Copyright 2005,2006 WSO2, Inc. http://www.wso2.org
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */
package org.wso2.carbon.utils.i18n;

import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * CURRENTLY NOT USED
 * KEEPING FOR REFERENCE  9/19/2002
 * <p/>
 * <p>Wrapper class for resource bundles. Property files are used to store
 * resource strings, which are the only types of resources available.
 * Property files can inherit properties from other files so that
 * a base property file can be used and a small number of properties
 * can be over-ridden by another property file. For example you may
 * create an english version of a resource file named "resource.properties".
 * You then decide that the British English version of all of the properties
 * except one are the same, so there is no need to redefine all of the
 * properties in "resource_en_GB", just the one that is different.</p>
 * <p>The property file lookup searches for classes with various suffixes
 * on the basis if the desired local and the current default local
 * (as returned by Local.getDefault()). As property files are found the
 * property values are merged so that inheritance is preserved.</p>
 * <p>The order of searching is:</p>
 * <dir>
 * basename + "_" + langage + "_" + country + "_" + variant
 * basename + "_" + langage + "_" + country
 * basename + "_" + langage
 * basename + "_" + defaultLanguage + "_" + defaultCountry + "_" + defaultVariant
 * basename + "_" + defaultLanguage + "_" + defaultCountry
 * basename + "_" + defaultLanguage
 * basename
 * </dir>
 * <p>The basename is the name of the property file without the ".properties"
 * extension.</p>
 * <p>Properties will be cached for performance.<p>
 * <p>Property values stored in the property files can also contain dynamic
 * variables. Any dynamic variable defined in PropertiesUtil.getVariableValue()
 * can be used (such as {date}), as well as arguments in the form {0}, {1}, etc.
 * Argument values are specified in the various overloaded getString() methods.</p>
 */
public class ResourceBundle {
    private static Log log = LogFactory.getLog(ResourceBundle.class);
    // The static cache of properties. The key is the basename + the local +
    // the default local and the element is the Properties object containing
    // the resources
    private static Hashtable propertyCache = new Hashtable();

    // The default base name
    public static final String BASE_NAME = "resource";

    // The property file extension
    public static final String PROPERTY_EXT = ".properties";

    // The name of the current base property file (with extension)
    protected String basePropertyFileName;

    // The properties for the current resource bundle
    protected Properties resourceProperties;

    /**
     * Construct a new RB
     *
     * @param name The name of the property file without the ".properties" extension
     */
    public ResourceBundle(String name) {
        this(null, name, null);
    }

    /**
     * Construct a new RB
     *
     * @param caller The calling object. This is used to get the package name
     *               to further construct the basename as well as to get the proper ClassLoader
     * @param name   The name of the property file without the ".properties" extension
     */
    public ResourceBundle(Object caller, String name) {
        this(caller, name, null);
    }

    /**
     * Construct a new RB
     *
     * @param caller The calling object. This is used to get the package name
     *               to further construct the basename as well as to get the proper ClassLoader
     * @param name   The name of the property file without the ".properties" extension
     * @param locale  The locale
     */
    public ResourceBundle(Object caller, String name, Locale locale) {
        ClassLoader cl = null;

        if (caller != null) {

            Class c;
            if (caller instanceof Class) {
                c = (Class) caller;
            } else {
                c = caller.getClass();
            }

            // Get the appropriate class loader
            cl = c.getClassLoader();

            if (name.indexOf('/') == -1) {

                // Create the full basename only if not given
                String fullName = c.getName();

                int pos = fullName.lastIndexOf('.');
                if (pos > 0) {
                    name = fullName.substring(0, pos + 1).replace('.', '/') + name;
                }
            }
        } else {
            // Try the shared default properties file...
            if (name.indexOf('/') == -1) {
                name = "org/apache/axis/default-resource";
            }
        }

        Locale defaultLocale = Locale.getDefault();

        // If the locale given is the same as the default locale, ignore it
        if (locale != null && locale.equals(defaultLocale)) {
            locale = null;
        }

        // Load the properties. If no property files exist then a
        // MissingResourceException will be thrown
        loadProperties(name, cl, locale, defaultLocale);
    }

    /**
     * Gets a string message from the resource bundle for the given key
     *
     * @param key The resource key
     * @return The message
     */
    public String getString(String key) {
        return getString(key, (Object[]) null);
    }

    /**
     * <p>Gets a string message from the resource bundle for the given key. The
     * message may contain variables that will be substituted with the given
     * arguments. Variables have the format:</p>
     * <dir>
     * This message has two variables: {0} and {1}
     * </dir>
     *
     * @param key  The resource key
     * @param arg0 The argument to place in variable {0}
     * @return The message
     */
    public String getString(String key, Object arg0) {
        Object[] o = new Object[1];
        o[0] = arg0;
        return getString(key, o);
    }

    /**
     * <p>Gets a string message from the resource bundle for the given key. The
     * message may contain variables that will be substituted with the given
     * arguments. Variables have the format:</p>
     * <dir>
     * This message has two variables: {0} and {1}
     * </dir>
     *
     * @param key  The resource key
     * @param arg0 The argument to place in variable {0}
     * @param arg1 The argument to place in variable {1}
     * @return The message
     */
    public String getString(String key, Object arg0, Object arg1) {
        Object[] o = new Object[2];
        o[0] = arg0;
        o[1] = arg1;
        return getString(key, o);
    }

    /**
     * <p>Gets a string message from the resource bundle for the given key. The
     * message may contain variables that will be substituted with the given
     * arguments. Variables have the format:</p>
     * <dir>
     * This message has two variables: {0} and {1}
     * </dir>
     *
     * @param key  The resource key
     * @param arg0 The argument to place in variable {0}
     * @param arg1 The argument to place in variable {1}
     * @param arg2 The argument to place in variable {1}
     * @return The message
     */
    public String getString(String key, Object arg0, Object arg1, Object arg2) {
        Object[] o = new Object[3];
        o[0] = arg0;
        o[1] = arg1;
        o[2] = arg2;
        return getString(key, o);
    }

    /**
     * <p>Gets a string message from the resource bundle for the given key. The
     * message may contain variables that will be substituted with the given
     * arguments. Variables have the format:</p>
     * <dir>
     * This message has two variables: {0} and {1}
     * </dir>
     *
     * @param key   The resource key
     * @param array An array of objects to place in corresponding variables
     * @return The message
     */
    public String getString(String key, Object[] array) {
        String msg = null;
        if (resourceProperties != null) {
            msg = resourceProperties.getProperty(key);
        }

        if (msg == null) {
            throw new MissingResourceException(
                    "Cannot find resource key \"" + key + "\" in base name " + basePropertyFileName,
                    basePropertyFileName, key);
        }

        msg = MessageFormat.format(msg, array);
        return msg;
    }

    protected void loadProperties(String basename, ClassLoader loader, Locale locale, Locale defaultLocale) {
        // Check the cache first
        String loaderName = "";
        if (loader != null) {
            loaderName = ":" + loader.hashCode();
        }
        String cacheKey = basename + ":" + locale + ":" + defaultLocale + loaderName;
        Properties p = (Properties) propertyCache.get(cacheKey);
        basePropertyFileName = basename + PROPERTY_EXT;

        if (p == null) {
            // The properties were not found in the cache. Search the given locale first
            p = new Properties();
            if (locale != null) {
                p = loadProperties(basename, loader, locale, p);
            }

            // Search the default locale
            if (defaultLocale != null) {
                p = loadProperties(basename, loader, defaultLocale, p);
            }

            // Search for the basename
            p = merge(p, loadProperties(basePropertyFileName, loader));

            if (p == null) {
                throw new MissingResourceException("Cannot find resource for base name " + basePropertyFileName,
                        basePropertyFileName, "");
            }

            // Cache the properties
            propertyCache.put(cacheKey, p);

        }

        resourceProperties = p;
    }

    protected Properties loadProperties(String basename, ClassLoader loader, Locale locale, Properties props) {

        String language = locale.getLanguage();
        String country = locale.getCountry();
        String variant = locale.getVariant();
        if (variant != null && variant.trim().length() == 0) {
            variant = null;
        }

        if (language != null) {

            if (country != null) {

                if (variant != null) {
                    props = merge(props, loadProperties(
                            basename + "_" + language + "_" + country + "_" + variant + PROPERTY_EXT, loader));
                }
                props = merge(props,
                        loadProperties(basename + "_" + language + "_" + country + PROPERTY_EXT, loader));
            }
            props = merge(props, loadProperties(basename + "_" + language + PROPERTY_EXT, loader));
        }
        return props;
    }

    protected Properties loadProperties(String resname, ClassLoader loader) {
        Properties props = null;

        // Attempt to open and load the properties
        InputStream in = null;
        try {
            if (loader != null) {
                in = loader.getResourceAsStream(resname);
            }

            // Either we're using the system class loader or we didn't find the
            // resource using the given class loader
            if (in == null) {
                in = ClassLoader.getSystemResourceAsStream(resname);
            }
            if (in != null) {
                props = new Properties();
                try {
                    props.load(in);
                } catch (IOException ex) {
                    // On error, clear the props
                    props = null;
                }
            }
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (Exception ex) {
                    // Ignore error on close
                    if (log.isDebugEnabled()) {
                        log.debug("Error closing input stream", ex);
                    }
                }
            }
        }
        return props;
    }

    /**
     * Merge two Properties objects
     */
    protected Properties merge(Properties p1, Properties p2) {
        if ((p1 == null) && (p2 == null)) {
            return null;
        } else if (p1 == null) {
            return p2;
        } else if (p2 == null) {
            return p1;
        }

        // Now merge. p1 takes precedence
        Enumeration enumeration = p2.keys();
        while (enumeration.hasMoreElements()) {
            String key = (String) enumeration.nextElement();
            if (p1.getProperty(key) == null) {
                p1.put(key, p2.getProperty(key));
            }
        }

        return p1;
    }

    /**
     * Get the underlying properties
     */
    public Properties getProperties() {
        return resourceProperties;
    }

    // STATIC ACCESSORS

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param key    The resource key
     * @return The formatted message
     */
    public static String getString(Object caller, String key) {
        return getMessage(caller, BASE_NAME, null, key, null);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param key    The resource key
     * @param arg0   The argument to place in variable {0}
     * @return The formatted message
     */
    public static String getString(Object caller, String key, Object arg0) {
        Object[] o = new Object[1];
        o[0] = arg0;
        return getMessage(caller, BASE_NAME, null, key, o);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param key    The resource key
     * @param arg0   The argument to place in variable {0}
     * @param arg1   The argument to place in variable {1}
     * @return The formatted message
     */
    public static String getString(Object caller, String key, Object arg0, Object arg1) {
        Object[] o = new Object[2];
        o[0] = arg0;
        o[1] = arg1;
        return getMessage(caller, BASE_NAME, null, key, o);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param key    The resource key
     * @param arg0   The argument to place in variable {0}
     * @param arg1   The argument to place in variable {1}
     * @param arg2   The argument to place in variable {2}
     * @return The formatted message
     */
    public static String getString(Object caller, String key, Object arg0, Object arg1, Object arg2) {
        Object[] o = new Object[3];
        o[0] = arg0;
        o[1] = arg1;
        o[2] = arg2;
        return getMessage(caller, BASE_NAME, null, key, o);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param key    The resource key
     * @param arg0   The argument to place in variable {0}
     * @param arg1   The argument to place in variable {1}
     * @param arg2   The argument to place in variable {2}
     * @param arg3   The argument to place in variable {3}
     * @return The formatted message
     */
    public static String getString(Object caller, String key, Object arg0, Object arg1, Object arg2, Object arg3) {
        Object[] o = new Object[4];
        o[0] = arg0;
        o[1] = arg1;
        o[2] = arg2;
        o[3] = arg3;
        return getMessage(caller, BASE_NAME, null, key, o);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param key    The resource key
     * @param arg0   The argument to place in variable {0}
     * @param arg1   The argument to place in variable {1}
     * @param arg2   The argument to place in variable {2}
     * @param arg3   The argument to place in variable {3}
     * @param arg4   The argument to place in variable {4}
     * @return Returns the formatted message.
     */
    public static String getString(Object caller, String key, Object arg0, Object arg1, Object arg2, Object arg3,
            Object arg4) {
        Object[] o = new Object[5];
        o[0] = arg0;
        o[1] = arg1;
        o[2] = arg2;
        o[3] = arg3;
        o[4] = arg4;
        return getMessage(caller, BASE_NAME, null, key, o);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param key    The resource key
     * @param args  An array of objects to place in corresponding variables
     * @return Returns the formatted message.
     */
    public static String getString(Object caller, String key, Object[] args) {
        return getMessage(caller, BASE_NAME, null, key, args);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param locale The locale
     * @param key    The resource key
     * @return The formatted message
     */
    public static String getString(Object caller, Locale locale, String key) {
        return getMessage(caller, BASE_NAME, locale, key, null);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param locale The locale
     * @param key    The resource key
     * @param arg0   The argument to place in variable {0}
     * @return The formatted message
     */
    public static String getString(Object caller, Locale locale, String key, Object arg0) {
        Object[] o = new Object[1];
        o[0] = arg0;
        return getMessage(caller, BASE_NAME, locale, key, o);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param locale The locale
     * @param key    The resource key
     * @param arg0   The argument to place in variable {0}
     * @param arg1   The argument to place in variable {1}
     * @return The formatted message
     */
    public static String getString(Object caller, Locale locale, String key, Object arg0, Object arg1) {
        Object[] o = new Object[2];
        o[0] = arg0;
        o[1] = arg1;
        return getMessage(caller, BASE_NAME, locale, key, o);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param locale The locale
     * @param key    The resource key
     * @param arg0   The argument to place in variable {0}
     * @param arg1   The argument to place in variable {1}
     * @param arg2   The argument to place in variable {2}
     * @return The formatted message
     */
    public static String getString(Object caller, Locale locale, String key, Object arg0, Object arg1,
            Object arg2) {
        Object[] o = new Object[3];
        o[0] = arg0;
        o[1] = arg1;
        o[2] = arg2;
        return getMessage(caller, BASE_NAME, locale, key, o);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param locale The locale
     * @param key    The resource key
     * @param arg0   The argument to place in variable {0}
     * @param arg1   The argument to place in variable {1}
     * @param arg2   The argument to place in variable {2}
     * @param arg3   The argument to place in variable {3}
     * @return The formatted message
     */
    public static String getString(Object caller, Locale locale, String key, Object arg0, Object arg1, Object arg2,
            Object arg3) {
        Object[] o = new Object[4];
        o[0] = arg0;
        o[1] = arg1;
        o[2] = arg2;
        o[3] = arg3;
        return getMessage(caller, BASE_NAME, locale, key, o);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param locale The locale
     * @param key    The resource key
     * @param arg0   The argument to place in variable {0}
     * @param arg1   The argument to place in variable {1}
     * @param arg2   The argument to place in variable {2}
     * @param arg3   The argument to place in variable {3}
     * @return Returns the formatted message.
     */
    public static String getString(Object caller, Locale locale, String key, Object arg0, Object arg1, Object arg2,
            Object arg3, Object arg4) {
        Object[] o = new Object[5];
        o[0] = arg0;
        o[1] = arg1;
        o[2] = arg2;
        o[3] = arg3;
        o[4] = arg4;
        return getMessage(caller, BASE_NAME, locale, key, o);
    }

    /**
     * Get a message from resource.properties from the package of the given object.
     *
     * @param caller The calling object, used to get the package name and class loader
     * @param locale The locale
     * @param key    The resource key
     * @param args  An array of objects to place in corresponding variables
     * @return Returns the formatted message.
     */
    public static String getString(Object caller, Locale locale, String key, Object[] args) {
        return getMessage(caller, BASE_NAME, locale, key, args);
    }

    // Workhorse that does the resource loading and key lookup
    public static String getMessage(Object caller, String basename, Locale locale, String key, Object[] args) {
        String msg = null;
        MissingResourceException firstEx = null;
        String fullName = null;
        Class curClass = null;
        boolean didNull = false;

        if (caller != null) {
            if (caller instanceof Class) {
                curClass = (Class) caller;
            } else {
                curClass = caller.getClass();
            }
        }

        while (msg == null) {

            // Get the full name of the resource
            if (curClass != null) {

                // Create the full basename
                String pkgName = curClass.getName();

                int pos = pkgName.lastIndexOf('.');
                if (pos > 0) {
                    fullName = pkgName.substring(0, pos + 1).replace('.', '/') + basename;
                } else {
                    fullName = basename;
                }
            } else {
                fullName = basename;
            }

            try {
                ResourceBundle resourceBundle = new ResourceBundle(caller, fullName, locale);
                msg = resourceBundle.getString(key, args);
            } catch (MissingResourceException ex) {
                if (curClass == null) {
                    throw ex;
                }

                // Save the first exception
                if (firstEx == null) {
                    firstEx = ex;
                }

                // Get the superclass
                curClass = curClass.getSuperclass();
                if (curClass == null) {
                    if (didNull) {
                        throw firstEx;
                    }
                    didNull = true;
                    caller = null;
                } else {
                    String cname = curClass.getName();
                    if (cname.startsWith("java.") || cname.startsWith("javax.")) {
                        if (didNull) {
                            throw firstEx;
                        }
                        didNull = true;
                        caller = null;
                        curClass = null;
                    }
                }
            }

        }
        return msg;
    }

    /**
     * Clears the internal cache.
     */
    public static void clearCache() {
        propertyCache.clear();
    }
}