| /* Copyright (C) 1998, 1999, 2000 Free Software Foundation |
| |
| This file is part of libgcj. |
| |
| This software is copyrighted work licensed under the terms of the |
| Libgcj License. Please consult the file "LIBGCJ_LICENSE" for |
| details. */ |
| |
| package java.util; |
| |
| import java.io.InputStream; |
| |
| /** |
| * @author Anthony Green <green@cygnus.com> |
| * @date November 26, 1998. |
| */ |
| |
| /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3, |
| * and "The Java Language Specification", ISBN 0-201-63451-1. */ |
| |
| public abstract class ResourceBundle |
| { |
| protected ResourceBundle parent; |
| |
| // This is used to cache resource bundles. |
| private static Hashtable resource_cache = new Hashtable (); |
| |
| public ResourceBundle () |
| { |
| } |
| |
| public Locale getLocale() |
| { |
| // FIXME: Stub added for this missing method because it is needed for AWT. |
| return null; |
| } |
| |
| public final String getString (String key) throws MissingResourceException |
| { |
| return (String) getObject(key); |
| } |
| |
| public final String[] getStringArray (String key) |
| throws MissingResourceException |
| { |
| return (String[]) getObject(key); |
| } |
| |
| public final Object getObject(String key) throws MissingResourceException |
| { |
| Object result; |
| |
| try |
| { |
| return handleGetObject (key); |
| } |
| catch (MissingResourceException ex) |
| { |
| if (parent != null) |
| return parent.getObject(key); |
| else |
| throw ex; |
| } |
| } |
| |
| public static final ResourceBundle getBundle(String baseName) |
| throws MissingResourceException |
| { |
| return getBundle(baseName, Locale.getDefault()); |
| } |
| |
| // Start searching with the name bundleName. Continue searching by |
| // stripping off the '_' delimited tails until the search name is |
| // the same as stopHere. |
| private static final ResourceBundle trySomeGetBundle (String bundleName, |
| String stopHere, |
| ClassLoader loader) |
| { |
| Class rbc; |
| ResourceBundle needs_parent = null, r, result = null; |
| |
| while (true) |
| { |
| try |
| { |
| // This call is wrong by the spec, but it will have to |
| // do until our Class.forName is fixed. |
| rbc = Class.forName(bundleName, loader); |
| r = null; |
| try |
| { |
| r = (ResourceBundle) rbc.newInstance(); |
| } |
| catch (IllegalAccessException ex) |
| { |
| // Fall through |
| } |
| catch (InstantiationException ex) |
| { |
| // Fall through |
| } |
| if (r != null) |
| { |
| if (result == null) |
| result = r; |
| if (needs_parent != null) |
| { |
| // We've been through the loop one or more times |
| // already. Set the parent and keep going. |
| needs_parent.setParent(r); |
| } |
| needs_parent = r; |
| } |
| } |
| catch (ClassNotFoundException ex) |
| { |
| // Fall through. |
| } |
| |
| // Look for a properties file. |
| InputStream i = loader.getResourceAsStream (bundleName.replace ('.', |
| '/') |
| + ".properties"); |
| if (i != null) |
| { |
| try |
| { |
| return new PropertyResourceBundle (i); |
| } |
| catch (java.io.IOException e) |
| { |
| // The docs don't appear to define what happens in |
| // this case, but it seems like continuing the |
| // search is a reasonable thing to do. |
| } |
| } |
| |
| if (bundleName.equals(stopHere)) |
| return result; |
| else |
| { |
| int last = bundleName.lastIndexOf('_'); |
| |
| // No more underscores? |
| if (last == -1) |
| return result; |
| |
| // Loop around, testing this new shorter name. |
| bundleName = bundleName.substring(0, last); |
| } |
| } |
| } |
| |
| // Search for bundles, but stop at baseName_language (if required). |
| // This is synchronized so that the cache works correctly. |
| private static final synchronized ResourceBundle |
| partialGetBundle (String baseName, Locale locale, boolean langStop, |
| ClassLoader loader) |
| { |
| ResourceBundle rb; |
| |
| // Explicitly invoke locale.toString() to force a |
| // NullPointerException when required. |
| String bundleName = baseName + "_" + locale.toString(); |
| |
| // Check the cache. |
| Object obj = resource_cache.get(bundleName); |
| if (obj != null) |
| return (ResourceBundle) obj; |
| |
| String stopHere = (baseName |
| + (langStop ? ("_" + locale.getLanguage()) : "")); |
| |
| |
| rb = trySomeGetBundle(bundleName, stopHere, loader); |
| if (rb != null) |
| resource_cache.put(bundleName, rb); |
| |
| return rb; |
| } |
| |
| public static final ResourceBundle getBundle (String baseName, |
| Locale locale) |
| { |
| return getBundle (baseName, locale, ClassLoader.getSystemClassLoader ()); |
| } |
| |
| public static final ResourceBundle getBundle (String baseName, |
| Locale locale, |
| ClassLoader loader) |
| throws MissingResourceException |
| { |
| ResourceBundle rb; |
| Class rbc; |
| |
| if (baseName == null) |
| throw new NullPointerException (); |
| |
| rb = partialGetBundle(baseName, locale, false, loader); |
| if (rb != null) |
| return rb; |
| |
| // Finally, try the default locale. |
| if (! locale.equals(Locale.getDefault())) |
| { |
| rb = partialGetBundle(baseName, Locale.getDefault(), true, loader); |
| if (rb != null) |
| return rb; |
| } |
| |
| throw new MissingResourceException("can't load bundle", |
| baseName, |
| "bundle"); |
| } |
| |
| protected void setParent(ResourceBundle parent) |
| { |
| this.parent = parent; |
| } |
| |
| protected abstract Object handleGetObject(String key) |
| throws MissingResourceException; |
| |
| public abstract Enumeration getKeys(); |
| } |