localizedtextutil.java

来自「在Struts2中的jar包xwork的源代码.版本为2.0.7」· Java 代码 · 共 806 行 · 第 1/3 页

JAVA
806
字号
/* * Copyright (c) 2002-2006 by OpenSymphony * All rights reserved. */package com.opensymphony.xwork2.util;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.ModelDriven;import ognl.OgnlRuntime;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import java.beans.PropertyDescriptor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.InvocationTargetException;import java.text.MessageFormat;import java.util.*;/** * Provides support for localization in XWork. * * <!-- START SNIPPET: searchorder --> * Resource bundles are searched in the following order:<p/> * <p/> * <ol> * <li>ActionClass.properties</li> * <li>BaseClass.properties (all the way to Object.properties)</li> * <li>Interface.properties (every interface and sub-interface)</li> * <li>ModelDriven's model (if implements ModelDriven), for the model object repeat from 1</li> * <li>package.properties (of the directory where class is located and every parent directory all the way to the root directory)</li> * <li>search up the i18n message key hierarchy itself</li> * <li>global resource properties</li> * </ol> * <p/> * <!-- END SNIPPET: searchorder --> * * <!-- START SNIPPET: packagenote --> * To clarify #5, while traversing the package hierarchy, WW will look for a file package.properties:<p/> * com/<br/> * &nbsp; acme/<br/> * &nbsp; &nbsp; package.properties<br/> * &nbsp; &nbsp; actions/<br/> * &nbsp; &nbsp; &nbsp; package.properties<br/> * &nbsp; &nbsp; &nbsp; FooAction.java<br/> * &nbsp; &nbsp; &nbsp; FooAction.properties<br/> * <p/> * If FooAction.properties does not exist, com/acme/action/package.properties will be searched for, if * not found com/acme/package.properties, if not found com/package.properties, etc. * <p/> * <!-- END SNIPPET: packagenote --> * * <!-- START SNIPPET: globalresource --> * A global resource bundle could be specified programatically, as well as the locale. * <p/> * <!-- END SNIPPET: globalresource --> * * @author Jason Carreira * @author Mark Woon * @author Rainer Hermanns * @author tm_jee *  * @version $Date: 2007-09-03 05:36:45 +0200 (Mon, 03 Sep 2007) $ $Id: LocalizedTextUtil.java 1590 2007-09-03 03:36:45Z mrdon $ */public class LocalizedTextUtil {		private static final Log _log = LogFactory.getLog(LocalizedTextUtil.class);    private static List DEFAULT_RESOURCE_BUNDLES = null;    private static final Log LOG = LogFactory.getLog(LocalizedTextUtil.class);    private static boolean reloadBundles = false;    private static final Map<String, String> misses = new HashMap<String, String>();    private static final Map messageFormats = new HashMap();    static {        clearDefaultResourceBundles();    }    /**     * Clears the internal list of resource bundles.     */    public static void clearDefaultResourceBundles() {    	if (DEFAULT_RESOURCE_BUNDLES != null) {    		DEFAULT_RESOURCE_BUNDLES.clear();    	}        DEFAULT_RESOURCE_BUNDLES = Collections.synchronizedList(new ArrayList());        DEFAULT_RESOURCE_BUNDLES.add("com/opensymphony/xwork2/xwork-messages");    }    /**     * Should resorce bundles be reloaded.     * @param reloadBundles  reload bundles?       */    public static void setReloadBundles(boolean reloadBundles) {        LocalizedTextUtil.reloadBundles = reloadBundles;    }    /**     * Add's the bundle to the internal list of default bundles.     * <p/>     * If the bundle already exists in the list it will be readded.     *      * @param resourceBundleName   the name of the bundle to add.     */    public static void addDefaultResourceBundle(String resourceBundleName) {        //make sure this doesn't get added more than once        DEFAULT_RESOURCE_BUNDLES.remove(resourceBundleName);        DEFAULT_RESOURCE_BUNDLES.add(0, resourceBundleName);        if (LOG.isDebugEnabled()) {            LOG.debug("Added default resource bundle '" + resourceBundleName + "' to default resource bundles = " + DEFAULT_RESOURCE_BUNDLES);        }    }    /**     * Builds a {@link java.util.Locale} from a String of the form en_US_foo into a Locale     * with language "en", country "US" and variant "foo". This will parse the output of     * {@link java.util.Locale#toString()}.     *     * @param localeStr The locale String to parse.     * @param defaultLocale The locale to use if localeStr is <tt>null</tt>.     * @return requested Locale     */    public static Locale localeFromString(String localeStr, Locale defaultLocale) {        if ((localeStr == null) || (localeStr.trim().length() == 0) || (localeStr.equals("_"))) {            if ( defaultLocale != null) {                return defaultLocale;            }            return Locale.getDefault();        }        int index = localeStr.indexOf('_');        if (index < 0) {            return new Locale(localeStr);        }        String language = localeStr.substring(0, index);        if (index == localeStr.length()) {            return new Locale(language);        }        localeStr = localeStr.substring(index + 1);        index = localeStr.indexOf('_');        if (index < 0) {            return new Locale(language, localeStr);        }        String country = localeStr.substring(0, index);        if (index == localeStr.length()) {            return new Locale(language, country);        }        localeStr = localeStr.substring(index + 1);        return new Locale(language, country, localeStr);    }    /**     * Returns a localized message for the specified key, aTextName.  Neither the key nor the     * message is evaluated.     *     * @param aTextName the message key     * @param locale    the locale the message should be for     * @return a localized message based on the specified key, or null if no localized message can be found for it     */    public static String findDefaultText(String aTextName, Locale locale) {        List localList = DEFAULT_RESOURCE_BUNDLES; // it isn't sync'd, but this is so rare, let's do it anyway        for (Iterator iterator = localList.iterator(); iterator.hasNext();) {            String bundleName = (String) iterator.next();            ResourceBundle bundle = findResourceBundle(bundleName, locale);            if (bundle != null) {                reloadBundles();                try {                    return bundle.getString(aTextName);                } catch (MissingResourceException e) {                    // ignore and try others                }            }        }        return null;    }    /**     * Returns a localized message for the specified key, aTextName, substituting variables from the     * array of params into the message.  Neither the key nor the message is evaluated.     *     * @param aTextName the message key     * @param locale    the locale the message should be for     * @param params    an array of objects to be substituted into the message text     * @return A formatted message based on the specified key, or null if no localized message can be found for it     */    public static String findDefaultText(String aTextName, Locale locale, Object[] params) {        String defaultText = findDefaultText(aTextName, locale);        if (defaultText != null) {            MessageFormat mf = buildMessageFormat(defaultText, locale);            return mf.format(params);        }        return null;    }    /**     * Finds the given resorce bundle by it's name.     * <p/>     * 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, <tt>null</tt> if not found.     */    public static ResourceBundle findResourceBundle(String aBundleName, Locale locale) {        synchronized (misses) {            String key = createMissesKey(aBundleName, locale);            try {                if (!misses.containsKey(key)) {                    return ResourceBundle.getBundle(aBundleName, locale, Thread.currentThread().getContextClassLoader());                }            } catch (MissingResourceException ex) {                misses.put(key, aBundleName);            }        }        return null;    }    /**     * Creates a key to used for lookup/storing in the bundle misses cache.     *     * @param aBundleName  the name of the bundle (usually it's FQN classname).     * @param locale       the locale.     * @return the key to use for lookup/storing in the bundle misses cache.     */    private static String createMissesKey(String aBundleName, Locale locale) {        return aBundleName + "_" + locale.toString();    }    /**     * Calls {@link #findText(Class aClass, String aTextName, Locale locale, String defaultMessage, Object[] args)}     * with aTextName as the default message.     *     * @see #findText(Class aClass, String aTextName, Locale locale, String defaultMessage, Object[] args)     */    public static String findText(Class aClass, String aTextName, Locale locale) {        return findText(aClass, aTextName, locale, aTextName, new Object[0]);    }    /**     * Finds a localized text message for the given key, aTextName. Both the key and the message     * itself is evaluated as required.  The following algorithm is used to find the requested     * message:     * <p/>     * <ol>     * <li>Look for message in aClass' class hierarchy.     * <ol>     * <li>Look for the message in a resource bundle for aClass</li>     * <li>If not found, look for the message in a resource bundle for any implemented interface</li>     * <li>If not found, traverse up the Class' hierarchy and repeat from the first sub-step</li>     * </ol></li>     * <li>If not found and aClass is a {@link ModelDriven} Action, then look for message in     * the model's class hierarchy (repeat sub-steps listed above).</li>     * <li>If not found, look for message in child property.  This is determined by evaluating     * the message key as an OGNL expression.  For example, if the key is     * <i>user.address.state</i>, then it will attempt to see if "user" can be resolved into an

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?