resourcebundle.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 619 行 · 第 1/2 页

JAVA
619
字号
   * <li>baseName + "_" + language1 + "_" + country1 + "_" + variant1</li>
   * <li>baseName + "_" + language1 + "_" + country1</li>
   * <li>baseName + "_" + language1</li>
   * <li>baseName + "_" + language2 + "_" + country2 + "_" + variant2</li>
   * <li>baseName + "_" + language2 + "_" + country2</li>
   * <li>baseName + "_" + language2<li>
   * <li>baseName</li>
   * </ul>
   *
   * <p>In the sequence, entries with an empty string are ignored. Next,
   * <code>getBundle</code> tries to instantiate the resource bundle:<ul>
   * <li>First, an attempt is made to load a class in the specified classloader
   * which is a subclass of ResourceBundle, and which has a public constructor
   * with no arguments, via reflection.</li>
   * <li>Next, a search is made for a property resource file, by replacing
   * '.' with '/' and appending ".properties", and using
   * ClassLoader.getResource(). If a file is found, then a
   * PropertyResourceBundle is created from the file's contents.</li>
   * </ul>
   * If no resource bundle was found, a MissingResourceException is thrown.
   *
   * <p>Next, the parent chain is implemented. The remaining candidate names
   * in the above sequence are tested in a similar manner, and if any results
   * in a resource bundle, it is assigned as the parent of the first bundle
   * using the <code>setParent</code> method (unless the first bundle already
   * has a parent).
   *
   * <p>For example, suppose the following class and property files are
   * provided: MyResources.class, MyResources_fr_CH.properties,
   * MyResources_fr_CH.class, MyResources_fr.properties,
   * MyResources_en.properties, and MyResources_es_ES.class. The contents of
   * all files are valid (that is, public non-abstract subclasses of
   * ResourceBundle with public nullary constructors for the ".class" files,
   * syntactically correct ".properties" files). The default locale is
   * Locale("en", "UK").
   *
   * <p>Calling getBundle with the shown locale argument values instantiates
   * resource bundles from the following sources:<ul>
   * <li>Locale("fr", "CH"): result MyResources_fr_CH.class, parent
   *   MyResources_fr.properties, parent MyResources.class</li>
   * <li>Locale("fr", "FR"): result MyResources_fr.properties, parent
   *   MyResources.class</li>
   * <li>Locale("de", "DE"): result MyResources_en.properties, parent
   *   MyResources.class</li>
   * <li>Locale("en", "US"): result MyResources_en.properties, parent
   *   MyResources.class</li>
   * <li>Locale("es", "ES"): result MyResources_es_ES.class, parent
   *   MyResources.class</li>
   * </ul>
   * The file MyResources_fr_CH.properties is never used because it is hidden
   * by MyResources_fr_CH.class.
   *
   * @param baseName the name of the ResourceBundle
   * @param locale A locale
   * @param classloader a ClassLoader
   * @return the desired resource bundle
   * @throws MissingResourceException if the resource bundle can't be found
   * @throws NullPointerException if any argument is null
   * @since 1.2
   */
  // This method is synchronized so that the cache is properly
  // handled.
  public static final synchronized ResourceBundle getBundle
    (String baseName, Locale locale, ClassLoader classLoader)
  {
    // This implementation searches the bundle in the reverse direction
    // and builds the parent chain on the fly.
    Locale defaultLocale = Locale.getDefault();
    if (defaultLocale != lastDefaultLocale)
      {
	resourceBundleCache = new HashMap();
	lastDefaultLocale = defaultLocale;
      }
    HashMap cache = (HashMap) resourceBundleCache.get(classLoader);
    StringBuffer sb = new StringBuffer(60);
    sb.append(baseName).append('_').append(locale);
    String name = sb.toString();

    if (cache == null)
      {
        cache = new HashMap();
        resourceBundleCache.put(classLoader, cache);
      }
    else if (cache.containsKey(name))
      {
	Reference ref = (Reference) cache.get(name);
	ResourceBundle result = null;
	// If REF is null, that means that we added a `null' value to
	// the hash map.  That means we failed to find the bundle
	// previously, and we cached that fact.  The JDK does this, so
	// it must be ok.
	if (ref == null)
	  throw new MissingResourceException("Bundle " + baseName
					     + " not found",
					     baseName, "");
	else
	  {
	    ResourceBundle rb = (ResourceBundle) ref.get();
	    if (rb != null)
	      {
		// RB should already have the right parent, except if
		// something very strange happened.
		return rb;
	      }
	    // If RB is null, then we previously found it but it was
	    // collected.  So we try again.
	  }
      }

    // It is ok if this returns null.  We aren't required to have the
    // base bundle.
    ResourceBundle baseBundle = tryBundle(baseName, emptyLocale,
                                          classLoader, null, cache);

    // Now use our locale, followed by the default locale.  We only
    // need to try the default locale if our locale is different, and
    // if our locale failed to yield a result other than the base
    // bundle.
    ResourceBundle bundle = tryLocalBundle(baseName, locale,
                                           classLoader, baseBundle, cache);
    if (bundle == baseBundle && !locale.equals(defaultLocale))
      {
	bundle = tryLocalBundle(baseName, defaultLocale,
				classLoader, baseBundle, cache);
	// We need to record that the argument locale maps to the
	// bundle we just found.  If we didn't find a bundle, record
	// that instead.
	if (bundle == null)
	  cache.put(name, null);
	else
	  cache.put(name, new SoftReference(bundle));
      }

    if (bundle == null)
      throw new MissingResourceException("Bundle " + baseName + " not found",
					 baseName, "");

    return bundle;
  }

  /**
   * Override this method to provide the resource for a keys. This gets
   * called by <code>getObject</code>. If you don't have a resource
   * for the given key, you should return null instead throwing a
   * MissingResourceException. You don't have to ask the parent, getObject()
   * already does this; nor should you throw a MissingResourceException.
   *
   * @param key the key of the resource
   * @return the resource for the key, or null if not in bundle
   * @throws NullPointerException if key is null
   */
  protected abstract Object handleGetObject(String key);

  /**
   * This method should return all keys for which a resource exists; you
   * should include the enumeration of any parent's keys, after filtering out
   * duplicates.
   *
   * @return an enumeration of the keys
   */
  public abstract Enumeration getKeys();

  /**
   * Tries to load a class or a property file with the specified name.
   *
   * @param localizedName the name
   * @param locale the locale, that must be used exactly
   * @param classloader the classloader
   * @param bundle the backup (parent) bundle
   * @return the resource bundle if it was loaded, otherwise the backup
   */
  private static final ResourceBundle tryBundle(String localizedName,
                                                Locale locale,
                                                ClassLoader classloader,
                                                ResourceBundle bundle,
                                                HashMap cache)
  {
    // First look into the cache.
    if (cache.containsKey(localizedName))
      {
	Reference ref = (Reference) cache.get(localizedName);
	ResourceBundle result = null;
	// If REF is null, that means that we added a `null' value to
	// the hash map.  That means we failed to find the bundle
	// previously, and we cached that fact.  The JDK does this, so
	// it must be ok.
	if (ref == null)
	  return null;
	else
	  {
	    ResourceBundle rb = (ResourceBundle) ref.get();
	    if (rb != null)
	      {
		// RB should already have the right parent, except if
		// something very strange happened.
		return rb;
	      }
	    // If RB is null, then we previously found it but it was
	    // collected.  So we try again.
	  }
      }

    // foundBundle holds exact matches for the localizedName resource
    // bundle, which may later be cached.
    ResourceBundle foundBundle = null;
    try
      {
        Class rbClass;
        if (classloader == null)
          rbClass = Class.forName(localizedName);
        else
          rbClass = classloader.loadClass(localizedName);
        foundBundle = (ResourceBundle) rbClass.newInstance();
        foundBundle.parent = bundle;
        foundBundle.locale = locale;
      }
    catch (Exception ex)
      {
        // ignore them all
	foundBundle = null;
      }
    if (foundBundle == null)
      {
	try
	  {
	    InputStream is;
	    final String resourceName
	      = localizedName.replace('.', '/') + ".properties";
	    if (classloader == null)
	      is = ClassLoader.getSystemResourceAsStream(resourceName);
	    else
	      is = classloader.getResourceAsStream(resourceName);
	    if (is != null)
	      {
		foundBundle = new PropertyResourceBundle(is);
		foundBundle.parent = bundle;
		foundBundle.locale = locale;
	      }
	  }
	catch (IOException ex)
	  {
	  }
      }

    // Put the result into the hash table.  If we didn't find anything
    // here, we record our parent bundle.  If we record `null' that means
    // nothing, not even the base, was found.
    if (foundBundle == null)
      foundBundle = bundle;
    if (foundBundle == null)
      cache.put(localizedName, null);
    else
      cache.put(localizedName, new SoftReference(foundBundle));
    return foundBundle;
  }

  /**
   * Tries to load a the bundle for a given locale, also loads the backup
   * locales with the same language.
   *
   * @param name the name
   * @param locale the locale
   * @param classloader the classloader
   * @param bundle the backup (parent) bundle
   * @return the resource bundle if it was loaded, otherwise the backup
   */
  private static final ResourceBundle tryLocalBundle(String baseName,
						     Locale locale,
                                                     ClassLoader classloader,
                                                     ResourceBundle bundle,
                                                     HashMap cache)
  {
    final String language = locale.getLanguage();
    final String country = locale.getCountry();
    final String variant = locale.getVariant();

    StringBuffer sb = new StringBuffer(60);
    sb.append(baseName);
    sb.append('_');

    if (language.length() > 0)
      {
	sb.append(language);
	bundle = tryBundle(sb.toString(), new Locale(language),
			   classloader, bundle, cache);
      }
    // If LANGUAGE was empty, we still need to try the other
    // components, and the `_' is required.
    sb.append('_');

    if (country.length() > 0)
      {
	sb.append(country);
	bundle = tryBundle(sb.toString(), new Locale(language, country),
			   classloader, bundle, cache);
      }
    sb.append('_');

    if (variant.length() > 0)
      {
	sb.append(variant);
	bundle = tryBundle(sb.toString(), locale,
			   classloader, bundle, cache);
      }

    return bundle;
  }
}

⌨️ 快捷键说明

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