com.ibm.icu.impl.ResourceBundleWrapper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of icu4j Show documentation
Show all versions of icu4j Show documentation
International Component for Unicode for Java (ICU4J) is a mature, widely used Java library
providing Unicode and Globalization support
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
******************************************************************************
* Copyright (C) 2004-2016, International Business Machines Corporation and
* others. All Rights Reserved.
******************************************************************************
*/
package com.ibm.icu.impl;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.MissingResourceException;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;
/**
* just a wrapper for Java ListResourceBundles and
* @author ram
*
*/
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;
}
@Override
protected Object handleGetObject(String aKey){
ResourceBundleWrapper current = this;
Object obj = null;
while(current!=null){
try{
obj = current.bundle.getObject(aKey);
break;
}catch(MissingResourceException ex){
current = (ResourceBundleWrapper)current.getParent();
}
}
if (obj == null){
throw new MissingResourceException("Can't find resource for bundle "
+baseName
+", key "+aKey,
this.getClass().getName(),
aKey);
}
return obj;
}
@Override
public Enumeration getKeys(){
return Collections.enumeration(keys);
}
private void initKeysVector(){
ResourceBundleWrapper current = this;
keys = new ArrayList();
while(current!=null){
Enumeration e = current.bundle.getKeys();
while(e.hasMoreElements()){
String elem = e.nextElement();
if(!keys.contains(elem)){
keys.add(elem);
}
}
current = (ResourceBundleWrapper)current.getParent();
}
}
@Override
protected String getLocaleID(){
return localeID;
}
@Override
protected String getBaseName(){
return bundle.getClass().getName().replace('.','/');
}
@Override
public ULocale getULocale(){
return new ULocale(localeID);
}
@Override
public UResourceBundle getParent(){
return (UResourceBundle)parent;
}
// Flag for enabling/disabling debugging code
private static final boolean DEBUG = ICUDebug.enabled("resourceBundleWrapper");
// This method is for super class's instantiateBundle method
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){
separator = "/";
}
throw new MissingResourceException("Could not find the bundle "+ baseName+separator+ localeID,"","");
}
return b;
}
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 = 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 =
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;
} catch (ClassNotFoundException e) {
loadFromProperties = true;
} catch (NoClassDefFoundError e) {
loadFromProperties = true;
} catch (Exception e) {
if (DEBUG)
System.out.println("failure");
if (DEBUG)
System.out.println(e);
}
if (loadFromProperties) {
try {
final String resName = name.replace('.', '/') + ".properties";
InputStream stream = java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
@Override
public InputStream run() {
return root.getResourceAsStream(resName);
}
}
);
if (stream != null) {
// make sure it is buffered
stream = new java.io.BufferedInputStream(stream);
try {
b = new ResourceBundleWrapper(new PropertyResourceBundle(stream));
if (parent != null) {
b.setParent(parent);
}
b.baseName=baseName;
b.localeID=localeID;
} catch (Exception ex) {
// throw away exception
} finally {
try {
stream.close();
} catch (Exception ex) {
// throw away exception
}
}
}
// if a bogus locale is passed then the parent should be
// the default locale not the root locale!
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 && (!parentIsRoot || !disableFallback)){
b=parent;
}
} catch (Exception e) {
if (DEBUG)
System.out.println("failure");
if (DEBUG)
System.out.println(e);
}
}
if(b!=null){
b.initKeysVector();
}else{
if(DEBUG)System.out.println("Returning null for "+baseName+"_"+localeID);
}
return b;
}});
}
}