mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
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
This commit is contained in:
parent
1824b6f66c
commit
37701877e3
3 changed files with 169 additions and 280 deletions
|
@ -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<String, ICUResourceBundle, Loader> BUNDLE_CACHE =
|
||||
new SoftCache<String, ICUResourceBundle, Loader>() {
|
||||
@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);
|
||||
private static boolean localeIDStartsWithLangSubtag(String localeID, String lang) {
|
||||
return localeID.startsWith(lang) &&
|
||||
(localeID.length() == lang.length() || localeID.charAt(lang.length()) == '_');
|
||||
}
|
||||
|
||||
// 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 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<String, String> aliasesVisited, UResourceBundle requested) {
|
||||
|
||||
ICUResourceBundle get(String aKey, HashMap<String, String> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String> keys = null;
|
||||
|
||||
/** Loader for bundle instances, for caching. */
|
||||
private static abstract class Loader {
|
||||
abstract ResourceBundleWrapper load();
|
||||
}
|
||||
|
||||
private static CacheBase<String, ResourceBundleWrapper, Loader> BUNDLE_CACHE =
|
||||
new SoftCache<String, ResourceBundleWrapper, Loader>() {
|
||||
@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<? extends ResourceBundle> cls = cl.loadClass(name).asSubclass(ResourceBundle.class);
|
||||
Class<? extends ResourceBundle> 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<InputStream>() {
|
||||
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;
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<ResourceCacheKey, UResourceBundle> BUNDLE_CACHE =
|
||||
new SimpleCache<ResourceCacheKey, UResourceBundle>();
|
||||
|
||||
/**
|
||||
* 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<String, RootType> ROOT_CACHE = new ConcurrentHashMap<String, RootType>();
|
||||
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue