From: Markus Scherer Date: Wed, 18 May 2016 20:29:26 +0000 (+0000) Subject: ICU-7434 switch UResourceBundle.BUNDLE_CACHE from SimpleCache to SoftCache, move... X-Git-Tag: milestone-59-0-1~427 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=37701877e3b3caddec82caee2b749c94ee5a31d4;p=icu ICU-7434 switch UResourceBundle.BUNDLE_CACHE from SimpleCache to SoftCache, move/split BUNDLE_CACHE into impl subclasses to avoid protected @internal hacks X-SVN-Rev: 38751 --- diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundle.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundle.java index 635e9841641..410ed0bc157 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundle.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundle.java @@ -78,6 +78,19 @@ public class ICUResourceBundle extends UResourceBundle { WholeBundle wholeBundle; private ICUResourceBundle container; + /** Loader for bundle instances, for caching. */ + private static abstract class Loader { + abstract ICUResourceBundle load(); + } + + private static CacheBase BUNDLE_CACHE = + new SoftCache() { + @Override + protected ICUResourceBundle createInstance(String unusedKey, Loader loader) { + return loader.load(); + } + }; + /** * Returns a functionally equivalent locale, considering keywords as well, for the specified keyword. * @param baseName resource specifier @@ -139,7 +152,7 @@ public class ICUResourceBundle extends UResourceBundle { // Ignore error and continue search. } if (defLoc == null) { - r = (ICUResourceBundle) r.getParent(); + r = r.getParent(); defDepth++; } } while ((r != null) && (defLoc == null)); @@ -165,7 +178,7 @@ public class ICUResourceBundle extends UResourceBundle { // Ignore error, } if (fullBase == null) { - r = (ICUResourceBundle) r.getParent(); + r = r.getParent(); resDepth++; } } while ((r != null) && (fullBase == null)); @@ -182,14 +195,14 @@ public class ICUResourceBundle extends UResourceBundle { do { try { ICUResourceBundle irb = (ICUResourceBundle)r.get(resName); - UResourceBundle urb = irb.get(kwVal); + ICUResourceBundle urb = (ICUResourceBundle)irb.get(kwVal); // if we didn't fail before this.. fullBase = r.getULocale(); // If the fetched item (urb) is in a different locale than our outer locale (r/fullBase) // then we are in a 'fallback' situation. treat as a missing resource situation. - if(!fullBase.toString().equals(urb.getLocale().toString())) { + if(!fullBase.getBaseName().equals(urb.getULocale().getBaseName())) { fullBase = null; // fallback condition. Loop and try again. } @@ -204,7 +217,7 @@ public class ICUResourceBundle extends UResourceBundle { // Ignore error, continue search. } if (fullBase == null) { - r = (ICUResourceBundle) r.getParent(); + r = r.getParent(); resDepth++; } } while ((r != null) && (fullBase == null)); @@ -221,7 +234,7 @@ public class ICUResourceBundle extends UResourceBundle { && resDepth <= defDepth) { // default was set in same locale or child return fullBase; // Keyword value is default - no keyword needed in locale } else { - return new ULocale(fullBase.toString() + "@" + keyword + "=" + kwVal); + return new ULocale(fullBase.getBaseName() + "@" + keyword + "=" + kwVal); } } @@ -848,7 +861,7 @@ public class ICUResourceBundle extends UResourceBundle { base = sub; } // Try the parent bundle of the last-found resource. - ICUResourceBundle nextBase = (ICUResourceBundle)base.getParent(); + ICUResourceBundle nextBase = base.getParent(); if (nextBase == null) { return null; } @@ -961,7 +974,7 @@ public class ICUResourceBundle extends UResourceBundle { } } // Try the parent bundle of the last-found resource. - ICUResourceBundle nextBase = (ICUResourceBundle)base.getParent(); + ICUResourceBundle nextBase = base.getParent(); if (nextBase == null) { return null; } @@ -1100,37 +1113,34 @@ public class ICUResourceBundle extends UResourceBundle { }; // This method is for super class's instantiateBundle method - public static UResourceBundle getBundleInstance(String baseName, String localeID, - ClassLoader root, boolean disableFallback){ - UResourceBundle b = instantiateBundle(baseName, localeID, root, - disableFallback ? OpenType.DIRECT : OpenType.LOCALE_DEFAULT_ROOT); - if(b==null){ - throw new MissingResourceException("Could not find the bundle "+ baseName+"/"+ localeID+".res","",""); - } - return b; - } - - protected static UResourceBundle instantiateBundle(String baseName, String localeID, - ClassLoader root, boolean disableFallback){ - return instantiateBundle(baseName, localeID, root, + public static ICUResourceBundle getBundleInstance(String baseName, String localeID, + ClassLoader root, boolean disableFallback) { + return getBundleInstance(baseName, localeID, root, disableFallback ? OpenType.DIRECT : OpenType.LOCALE_DEFAULT_ROOT); } - public static UResourceBundle getBundleInstance( + public static ICUResourceBundle getBundleInstance( String baseName, ULocale locale, OpenType openType) { if (locale == null) { locale = ULocale.getDefault(); } - return getBundleInstance(baseName, locale.toString(), + return getBundleInstance(baseName, locale.getBaseName(), ICUResourceBundle.ICU_DATA_CLASS_LOADER, openType); } - public static UResourceBundle getBundleInstance(String baseName, String localeID, + public static ICUResourceBundle getBundleInstance(String baseName, String localeID, ClassLoader root, OpenType openType) { if (baseName == null) { baseName = ICUData.ICU_BASE_NAME; } - UResourceBundle b = instantiateBundle(baseName, localeID, root, openType); + localeID = ULocale.getBaseName(localeID); + ICUResourceBundle b; + if (openType == OpenType.LOCALE_DEFAULT_ROOT) { + b = instantiateBundle(baseName, localeID, ULocale.getDefault().getBaseName(), + root, openType); + } else { + b = instantiateBundle(baseName, localeID, null, root, openType); + } if(b==null){ throw new MissingResourceException( "Could not find the bundle "+ baseName+"/"+ localeID+".res","",""); @@ -1138,33 +1148,35 @@ public class ICUResourceBundle extends UResourceBundle { return b; } - // recursively build bundle - private synchronized static UResourceBundle instantiateBundle(String baseName, String localeID, - ClassLoader root, OpenType openType) { - ULocale defaultLocale = ULocale.getDefault(); - String localeName = localeID; - if(localeName.indexOf('@')>=0){ - localeName = ULocale.getBaseName(localeID); - } - String fullName = ICUResourceBundleReader.getFullName(baseName, localeName); - ICUResourceBundle b = (ICUResourceBundle)loadFromCache(fullName, defaultLocale); - - // here we assume that java type resource bundle organization - // is required then the base name contains '.' else - // the resource organization is of ICU type - // so clients can instantiate resources of the type - // com.mycompany.data.MyLocaleElements_en.res and - // com.mycompany.data.MyLocaleElements.res - // - final String rootLocale = (baseName.indexOf('.')==-1) ? "root" : ""; - final String defaultID = defaultLocale.getBaseName(); - - if(localeName.equals("")){ - localeName = rootLocale; - } - if(DEBUG) System.out.println("Creating "+fullName+ " currently b is "+b); - if (b == null) { - b = ICUResourceBundle.createBundle(baseName, localeName, root); + private static boolean localeIDStartsWithLangSubtag(String localeID, String lang) { + return localeID.startsWith(lang) && + (localeID.length() == lang.length() || localeID.charAt(lang.length()) == '_'); + } + + private static ICUResourceBundle instantiateBundle( + final String baseName, final String localeID, final String defaultID, + final ClassLoader root, final OpenType openType) { + assert localeID.indexOf('@') < 0; + assert defaultID == null || defaultID.indexOf('@') < 0; + final String fullName = ICUResourceBundleReader.getFullName(baseName, localeID); + char openTypeChar = (char)('0' + openType.ordinal()); + String cacheKey = openType != OpenType.LOCALE_DEFAULT_ROOT ? + fullName + '#' + openTypeChar : + fullName + '#' + openTypeChar + '#' + defaultID; + return BUNDLE_CACHE.getInstance(cacheKey, new Loader() { + @Override + public ICUResourceBundle load() { + if(DEBUG) System.out.println("Creating "+fullName); + // here we assume that java type resource bundle organization + // is required then the base name contains '.' else + // the resource organization is of ICU type + // so clients can instantiate resources of the type + // com.mycompany.data.MyLocaleElements_en.res and + // com.mycompany.data.MyLocaleElements.res + // + final String rootLocale = (baseName.indexOf('.')==-1) ? "root" : ""; + String localeName = localeID.isEmpty() ? rootLocale : localeID; + ICUResourceBundle b = ICUResourceBundle.createBundle(baseName, localeName, root); if(DEBUG)System.out.println("The bundle created is: "+b+" and openType="+openType+" and bundle.getNoFallback="+(b!=null && b.getNoFallback())); if (openType == OpenType.DIRECT || (b != null && b.getNoFallback())) { @@ -1179,7 +1191,7 @@ public class ICUResourceBundle extends UResourceBundle { // for a bundle that does not have nofallback. // Are the relevant test cases just disabled? // Do item aliases not get followed via "direct" loading? - return addToCache(fullName, defaultLocale, b); + return b; } // fallback to locale ID parent @@ -1188,13 +1200,13 @@ public class ICUResourceBundle extends UResourceBundle { if (i != -1) { // Chop off the last underscore and the subtag after that. String temp = localeName.substring(0, i); - b = (ICUResourceBundle)instantiateBundle(baseName, temp, root, openType); + b = instantiateBundle(baseName, temp, defaultID, root, openType); }else{ // No underscore, only a base language subtag. if(openType == OpenType.LOCALE_DEFAULT_ROOT && - !defaultLocale.getLanguage().equals(localeName)) { + !localeIDStartsWithLangSubtag(defaultID, localeName)) { // Go to the default locale before root. - b = (ICUResourceBundle)instantiateBundle(baseName, defaultID, root, openType); + b = instantiateBundle(baseName, defaultID, defaultID, root, openType); } else if(openType != OpenType.LOCALE_ONLY && !rootLocale.isEmpty()) { // Ultimately go to root. b = ICUResourceBundle.createBundle(baseName, rootLocale, root); @@ -1205,32 +1217,31 @@ public class ICUResourceBundle extends UResourceBundle { localeName = b.getLocaleID(); int i = localeName.lastIndexOf('_'); - b = (ICUResourceBundle)addToCache(fullName, defaultLocale, b); - // TODO: C++ uresbund.cpp also checks for %%ParentIsRoot. Why not Java? String parentLocaleName = ((ICUResourceBundleImpl.ResourceTable)b).findString("%%Parent"); if (parentLocaleName != null) { - parent = instantiateBundle(baseName, parentLocaleName, root, openType); + parent = instantiateBundle(baseName, parentLocaleName, defaultID, root, openType); } else if (i != -1) { - parent = instantiateBundle(baseName, localeName.substring(0, i), root, openType); + parent = instantiateBundle(baseName, localeName.substring(0, i), defaultID, root, openType); } else if (!localeName.equals(rootLocale)){ - parent = instantiateBundle(baseName, rootLocale, root, true); + parent = instantiateBundle(baseName, rootLocale, defaultID, root, openType); } if (!b.equals(parent)){ b.setParent(parent); } } - } - return b; + return b; + }}); } - UResourceBundle get(String aKey, HashMap aliasesVisited, UResourceBundle requested) { + + ICUResourceBundle get(String aKey, HashMap aliasesVisited, UResourceBundle requested) { ICUResourceBundle obj = (ICUResourceBundle)handleGet(aKey, aliasesVisited, requested); if (obj == null) { - obj = (ICUResourceBundle)getParent(); + obj = getParent(); if (obj != null) { //call the get method to recursively fetch the resource - obj = (ICUResourceBundle)obj.get(aKey, aliasesVisited, requested); + obj = obj.get(aKey, aliasesVisited, requested); } if (obj == null) { String fullName = ICUResourceBundleReader.getFullName(getBaseName(), getLocaleID()); @@ -1319,8 +1330,8 @@ public class ICUResourceBundle extends UResourceBundle { return wholeBundle.localeID.isEmpty() || wholeBundle.localeID.equals("root"); } - public UResourceBundle getParent() { - return (UResourceBundle) parent; + public ICUResourceBundle getParent() { + return (ICUResourceBundle) parent; } protected void setParent(ResourceBundle parent) { @@ -1462,11 +1473,9 @@ public class ICUResourceBundle extends UResourceBundle { }else{ if (locale == null) { // {dlf} must use requestor's class loader to get resources from same jar - bundle = (ICUResourceBundle) getBundleInstance(bundleName, "", - loaderToUse, false); + bundle = getBundleInstance(bundleName, "", loaderToUse, false); } else { - bundle = (ICUResourceBundle) getBundleInstance(bundleName, locale, - loaderToUse, false); + bundle = getBundleInstance(bundleName, locale, loaderToUse, false); } int numKeys; @@ -1488,7 +1497,7 @@ public class ICUResourceBundle extends UResourceBundle { if (numKeys > 0) { sub = bundle; for (int i = 0; sub != null && i < numKeys; ++i) { - sub = (ICUResourceBundle)sub.get(keys[i], aliasesVisited, requested); + sub = sub.get(keys[i], aliasesVisited, requested); } } } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/ResourceBundleWrapper.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/ResourceBundleWrapper.java index 3c4419ad100..2cc8493c9a5 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/ResourceBundleWrapper.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/ResourceBundleWrapper.java @@ -24,12 +24,25 @@ import com.ibm.icu.util.UResourceBundle; * @author ram * */ -public class ResourceBundleWrapper extends UResourceBundle { +public final class ResourceBundleWrapper extends UResourceBundle { private ResourceBundle bundle = null; private String localeID = null; private String baseName = null; private List keys = null; + /** Loader for bundle instances, for caching. */ + private static abstract class Loader { + abstract ResourceBundleWrapper load(); + } + + private static CacheBase BUNDLE_CACHE = + new SoftCache() { + @Override + protected ResourceBundleWrapper createInstance(String unusedKey, Loader loader) { + return loader.load(); + } + }; + private ResourceBundleWrapper(ResourceBundle bundle){ this.bundle=bundle; } @@ -93,9 +106,18 @@ public class ResourceBundleWrapper extends UResourceBundle { private static final boolean DEBUG = ICUDebug.enabled("resourceBundleWrapper"); // This method is for super class's instantiateBundle method - public static UResourceBundle getBundleInstance(String baseName, String localeID, - ClassLoader root, boolean disableFallback){ - UResourceBundle b = instantiateBundle(baseName, localeID, root, disableFallback); + public static ResourceBundleWrapper getBundleInstance(String baseName, String localeID, + ClassLoader root, boolean disableFallback) { + if (root == null) { + root = ClassLoaderUtil.getClassLoader(); + } + ResourceBundleWrapper b; + if (disableFallback) { + b = instantiateBundle(baseName, localeID, null, root, disableFallback); + } else { + b = instantiateBundle(baseName, localeID, ULocale.getDefault().getBaseName(), + root, disableFallback); + } if(b==null){ String separator ="_"; if(baseName.indexOf('/')>=0){ @@ -105,47 +127,43 @@ public class ResourceBundleWrapper extends UResourceBundle { } return b; } - // recursively build bundle and override the super-class method - protected static synchronized UResourceBundle instantiateBundle(String baseName, String localeID, - ClassLoader root, boolean disableFallback) { - if (root == null) { - root = ClassLoaderUtil.getClassLoader(); - } - final ClassLoader cl = root; - String name = baseName; - ULocale defaultLocale = ULocale.getDefault(); - if (localeID.length() != 0) { - name = name + "_" + localeID; - } - ResourceBundleWrapper b = (ResourceBundleWrapper)loadFromCache(name, defaultLocale); - if(b==null){ + private static boolean localeIDStartsWithLangSubtag(String localeID, String lang) { + return localeID.startsWith(lang) && + (localeID.length() == lang.length() || localeID.charAt(lang.length()) == '_'); + } + + private static ResourceBundleWrapper instantiateBundle( + final String baseName, final String localeID, final String defaultID, + final ClassLoader root, final boolean disableFallback) { + final String name = localeID.isEmpty() ? baseName : baseName + '_' + localeID; + String cacheKey = disableFallback ? name : name + '#' + defaultID; + return BUNDLE_CACHE.getInstance(cacheKey, new Loader() { + @Override + public ResourceBundleWrapper load() { ResourceBundleWrapper parent = null; int i = localeID.lastIndexOf('_'); - + boolean loadFromProperties = false; + boolean parentIsRoot = false; if (i != -1) { String locName = localeID.substring(0, i); - parent = (ResourceBundleWrapper)loadFromCache(baseName+"_"+locName,defaultLocale); - if(parent == null){ - parent = (ResourceBundleWrapper)instantiateBundle(baseName, locName , cl, disableFallback); - } - }else if(localeID.length()>0){ - parent = (ResourceBundleWrapper)loadFromCache(baseName,defaultLocale); - if(parent==null){ - parent = (ResourceBundleWrapper)instantiateBundle(baseName, "", cl, disableFallback); - } + parent = instantiateBundle(baseName, locName, defaultID, root, disableFallback); + }else if(!localeID.isEmpty()){ + parent = instantiateBundle(baseName, "", defaultID, root, disableFallback); + parentIsRoot = true; } + ResourceBundleWrapper b = null; try { - Class cls = cl.loadClass(name).asSubclass(ResourceBundle.class); + Class cls = + root.loadClass(name).asSubclass(ResourceBundle.class); ResourceBundle bx = cls.newInstance(); b = new ResourceBundleWrapper(bx); if (parent != null) { b.setParent(parent); } b.baseName=baseName; - b.localeID = localeID; - + b.localeID = localeID; } catch (ClassNotFoundException e) { loadFromProperties = true; } catch (NoClassDefFoundError e) { @@ -163,11 +181,7 @@ public class ResourceBundleWrapper extends UResourceBundle { InputStream stream = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public InputStream run() { - if (cl != null) { - return cl.getResourceAsStream(resName); - } else { - return ClassLoader.getSystemResourceAsStream(resName); - } + return root.getResourceAsStream(resName); } } ); @@ -191,22 +205,19 @@ public class ResourceBundleWrapper extends UResourceBundle { } } } - + // if a bogus locale is passed then the parent should be // the default locale not the root locale! - if (b==null) { - String defaultName = defaultLocale.toString(); - if (localeID.length()>0 && localeID.indexOf('_')< 0 && defaultName.indexOf(localeID) == -1) { - b = (ResourceBundleWrapper)loadFromCache(baseName+"_"+defaultName, defaultLocale); - if(b==null){ - b = (ResourceBundleWrapper)instantiateBundle(baseName , defaultName, cl, disableFallback); - } - } + if (b == null && !disableFallback && + !localeID.isEmpty() && localeID.indexOf('_') < 0 && + !localeIDStartsWithLangSubtag(defaultID, localeID)) { + // localeID is only a language subtag, different from the default language. + b = instantiateBundle(baseName, defaultID, defaultID, root, disableFallback); } // if still could not find the bundle then return the parent - if(b==null){ + if(b==null && (!parentIsRoot || !disableFallback)){ b=parent; - } + } } catch (Exception e) { if (DEBUG) System.out.println("failure"); @@ -214,15 +225,12 @@ public class ResourceBundleWrapper extends UResourceBundle { System.out.println(e); } } - b = (ResourceBundleWrapper)addToCache(name, defaultLocale, b); - } - - if(b!=null){ - b.initKeysVector(); - }else{ - if(DEBUG)System.out.println("Returning null for "+baseName+"_"+localeID); - } - - return b; + if(b!=null){ + b.initKeysVector(); + }else{ + if(DEBUG)System.out.println("Returning null for "+baseName+"_"+localeID); + } + return b; + }}); } } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/UResourceBundle.java b/icu4j/main/classes/core/src/com/ibm/icu/util/UResourceBundle.java index 7456590ec53..55ce1f5456c 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/util/UResourceBundle.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/util/UResourceBundle.java @@ -19,12 +19,10 @@ import java.util.Set; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; -import com.ibm.icu.impl.ICUCache; import com.ibm.icu.impl.ICUData; import com.ibm.icu.impl.ICUResourceBundle; import com.ibm.icu.impl.ICUResourceBundleReader; import com.ibm.icu.impl.ResourceBundleWrapper; -import com.ibm.icu.impl.SimpleCache; /** * {@icuenhanced java.util.ResourceBundle}.{@icu _usage_} @@ -98,7 +96,8 @@ public abstract class UResourceBundle extends ResourceBundle { /** * {@icu} Creates a resource bundle using the specified base name and locale. * ICU_DATA_CLASS is used as the default root. - * @param baseName the base name of the resource bundle, a fully qualified class name + * @param baseName string containing the name of the data package. + * If null the default ICU package name is used. * @param localeName the locale for which a resource bundle is desired * @throws MissingResourceException If no resource bundle for the specified base name * can be found @@ -113,7 +112,8 @@ public abstract class UResourceBundle extends ResourceBundle { /** * {@icu} Creates a resource bundle using the specified base name, locale, and class root. * - * @param baseName the base name of the resource bundle, a fully qualified class name + * @param baseName string containing the name of the data package. + * If null the default ICU package name is used. * @param localeName the locale for which a resource bundle is desired * @param root the class object from which to load the resource bundle * @throws MissingResourceException If no resource bundle for the specified base name @@ -130,7 +130,8 @@ public abstract class UResourceBundle extends ResourceBundle { * {@icu} Creates a resource bundle using the specified base name, locale, and class * root. * - * @param baseName the base name of the resource bundle, a fully qualified class name + * @param baseName string containing the name of the data package. + * If null the default ICU package name is used. * @param localeName the locale for which a resource bundle is desired * @param root the class object from which to load the resource bundle * @param disableFallback Option to disable locale inheritence. @@ -167,15 +168,15 @@ public abstract class UResourceBundle extends ResourceBundle { if (locale==null) { locale = ULocale.getDefault(); } - return getBundleInstance(ICUData.ICU_BASE_NAME, locale.toString(), + return getBundleInstance(ICUData.ICU_BASE_NAME, locale.getBaseName(), ICUResourceBundle.ICU_DATA_CLASS_LOADER, false); } /** * {@icu} Creates a UResourceBundle for the default locale and specified base name, * from which users can extract resources by using their corresponding keys. - * @param baseName specifies the locale for which we want to open the resource. - * If null the bundle for default locale is opened. + * @param baseName string containing the name of the data package. + * If null the default ICU package name is used. * @return a resource bundle for the given base name and default locale * @stable ICU 3.0 */ @@ -184,15 +185,15 @@ public abstract class UResourceBundle extends ResourceBundle { baseName = ICUData.ICU_BASE_NAME; } ULocale uloc = ULocale.getDefault(); - return getBundleInstance(baseName, uloc.toString(), ICUResourceBundle.ICU_DATA_CLASS_LOADER, + return getBundleInstance(baseName, uloc.getBaseName(), ICUResourceBundle.ICU_DATA_CLASS_LOADER, false); } /** * {@icu} Creates a UResourceBundle for the specified locale and specified base name, * from which users can extract resources by using their corresponding keys. - * @param baseName specifies the locale for which we want to open the resource. - * If null the bundle for default locale is opened. + * @param baseName string containing the name of the data package. + * If null the default ICU package name is used. * @param locale specifies the locale for which we want to open the resource. * If null the bundle for default locale is opened. * @return a resource bundle for the given base name and locale @@ -205,8 +206,8 @@ public abstract class UResourceBundle extends ResourceBundle { } ULocale uloc = locale == null ? ULocale.getDefault() : ULocale.forLocale(locale); - return getBundleInstance(baseName, uloc.toString(), ICUResourceBundle.ICU_DATA_CLASS_LOADER, - false); + return getBundleInstance(baseName, uloc.getBaseName(), + ICUResourceBundle.ICU_DATA_CLASS_LOADER, false); } /** @@ -226,15 +227,15 @@ public abstract class UResourceBundle extends ResourceBundle { if (locale == null) { locale = ULocale.getDefault(); } - return getBundleInstance(baseName, locale.toString(), + return getBundleInstance(baseName, locale.getBaseName(), ICUResourceBundle.ICU_DATA_CLASS_LOADER, false); } /** * {@icu} Creates a UResourceBundle for the specified locale and specified base name, * from which users can extract resources by using their corresponding keys. - * @param baseName specifies the locale for which we want to open the resource. - * If null the bundle for default locale is opened. + * @param baseName string containing the name of the data package. + * If null the default ICU package name is used. * @param locale specifies the locale for which we want to open the resource. * If null the bundle for default locale is opened. * @param loader the loader to use @@ -247,7 +248,7 @@ public abstract class UResourceBundle extends ResourceBundle { baseName = ICUData.ICU_BASE_NAME; } ULocale uloc = locale == null ? ULocale.getDefault() : ULocale.forLocale(locale); - return getBundleInstance(baseName, uloc.toString(), loader, false); + return getBundleInstance(baseName, uloc.getBaseName(), loader, false); } /** @@ -272,7 +273,7 @@ public abstract class UResourceBundle extends ResourceBundle { if (locale == null) { locale = ULocale.getDefault(); } - return getBundleInstance(baseName, locale.toString(), loader, false); + return getBundleInstance(baseName, locale.getBaseName(), loader, false); } /** @@ -317,122 +318,6 @@ public abstract class UResourceBundle extends ResourceBundle { return getULocale().toLocale(); } - // Cache for ResourceBundle instantiation - private static ICUCache BUNDLE_CACHE = - new SimpleCache(); - - /** - * Method used by subclasses to add a resource bundle object to the managed - * cache. Works like a putIfAbsent(): If the cache already contains a matching - * bundle, that one will be retained and returned. - * @internal - * @deprecated This API is ICU internal only. - */ - @Deprecated - protected static UResourceBundle addToCache(String fullName, ULocale defaultLocale, UResourceBundle b) { - synchronized(cacheKey){ - cacheKey.setKeyValues(fullName, defaultLocale); - UResourceBundle cachedBundle = BUNDLE_CACHE.get(cacheKey); - if (cachedBundle != null) { - return cachedBundle; - } - BUNDLE_CACHE.put((ResourceCacheKey)cacheKey.clone(), b); - return b; - } - } - - /** - * Method used by sub classes to load a resource bundle object from the managed cache - * @internal - * @deprecated This API is ICU internal only. - */ - @Deprecated - protected static UResourceBundle loadFromCache(String fullName, ULocale defaultLocale) { - synchronized(cacheKey){ - cacheKey.setKeyValues(fullName, defaultLocale); - return BUNDLE_CACHE.get(cacheKey); - } - } - - /** - * Key used for cached resource bundles. The key checks - * the resource name and the default - * locale to determine if the resource is a match to the - * requested one. The default locale may be null, but the - * searchName must have a non-null value. - * Note that the default locale may change over time, and - * lookup should always be based on the current default - * locale (if at all). - */ - private static final class ResourceCacheKey implements Cloneable { - private String searchName; - private ULocale defaultLocale; - private int hashCodeCache; - ///CLOVER:OFF - public boolean equals(Object other) { - if (other == null) { - return false; - } - if (this == other) { - return true; - } - try { - final ResourceCacheKey otherEntry = (ResourceCacheKey) other; - //quick check to see if they are not equal - if (hashCodeCache != otherEntry.hashCodeCache) { - return false; - } - //are the names the same? - if (!searchName.equals(otherEntry.searchName)) { - return false; - } - // are the default locales the same? - if (defaultLocale == null) { - if (otherEntry.defaultLocale != null) { - return false; - } - } else { - if (!defaultLocale.equals(otherEntry.defaultLocale)) { - return false; - } - } - return true; - } catch (NullPointerException e) { - return false; - } catch (ClassCastException e) { - return false; - } - } - - public int hashCode() { - return hashCodeCache; - } - - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - //this should never happen - throw new ICUCloneNotSupportedException(e); - } - } - - ///CLOVER:ON - private synchronized void setKeyValues(String searchName, ULocale defaultLocale) { - this.searchName = searchName; - hashCodeCache = searchName.hashCode(); - this.defaultLocale = defaultLocale; - if (defaultLocale != null) { - hashCodeCache ^= defaultLocale.hashCode(); - } - } - /*private void clear() { - setKeyValues(null, "", null); - }*/ - } - - private static final ResourceCacheKey cacheKey = new ResourceCacheKey(); - private enum RootType { MISSING, ICU, JAVA } private static Map ROOT_CACHE = new ConcurrentHashMap(); @@ -468,7 +353,8 @@ public abstract class UResourceBundle extends ResourceBundle { /** * {@icu} Loads a new resource bundle for the given base name, locale and class loader. * Optionally will disable loading of fallback bundles. - * @param baseName the base name of the resource bundle, a fully qualified class name + * @param baseName string containing the name of the data package. + * If null the default ICU package name is used. * @param localeName the locale for which a resource bundle is desired * @param root the class object from which to load the resource bundle * @param disableFallback disables loading of fallback lookup chain @@ -479,26 +365,11 @@ public abstract class UResourceBundle extends ResourceBundle { */ protected static UResourceBundle instantiateBundle(String baseName, String localeName, ClassLoader root, boolean disableFallback) { - UResourceBundle b = null; RootType rootType = getRootType(baseName, root); - ULocale defaultLocale = ULocale.getDefault(); - switch (rootType) { case ICU: - if(disableFallback) { - String fullName = ICUResourceBundleReader.getFullName(baseName, localeName); - b = loadFromCache(fullName, defaultLocale); - if (b == null) { - b = ICUResourceBundle.getBundleInstance(baseName, localeName, root, - disableFallback); - } - } else { - b = ICUResourceBundle.getBundleInstance(baseName, localeName, root, - disableFallback); - } - - return b; + return ICUResourceBundle.getBundleInstance(baseName, localeName, root, disableFallback); case JAVA: return ResourceBundleWrapper.getBundleInstance(baseName, localeName, root, @@ -506,6 +377,7 @@ public abstract class UResourceBundle extends ResourceBundle { case MISSING: default: + UResourceBundle b; try{ b = ICUResourceBundle.getBundleInstance(baseName, localeName, root, disableFallback);