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/> * acme/<br/> * package.properties<br/> * actions/<br/> * package.properties<br/> * FooAction.java<br/> * 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 + -
显示快捷键?