/* Copyright (C) 1998, 1999 Cygnus Solutions 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; /** * @author Anthony Green * @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 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) { Class rbc; ResourceBundle needs_parent = null, r, result = null; while (true) { try { rbc = Class.forName(bundleName); 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. } 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) { 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); if (rb != null) resource_cache.put(bundleName, rb); return rb; } public static final ResourceBundle getBundle (String baseName, Locale locale) throws MissingResourceException { ResourceBundle rb; Class rbc; if (baseName == null) throw new NullPointerException (); rb = partialGetBundle(baseName, locale, false); if (rb != null) return rb; // Finally, try the default locale. if (! locale.equals(Locale.getDefault())) { rb = partialGetBundle(baseName, Locale.getDefault(), true); 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(); }