Home | History | Annotate | Download | only in impl
      1 /* GENERATED SOURCE. DO NOT MODIFY. */
      2 //  2016 and later: Unicode, Inc. and others.
      3 // License & terms of use: http://www.unicode.org/copyright.html#License
      4 /*
      5 ******************************************************************************
      6 * Copyright (C) 2004-2016, International Business Machines Corporation and
      7 * others. All Rights Reserved.
      8 ******************************************************************************
      9 */
     10 
     11 package android.icu.impl;
     12 
     13 import java.io.InputStream;
     14 import java.util.ArrayList;
     15 import java.util.Collections;
     16 import java.util.Enumeration;
     17 import java.util.List;
     18 import java.util.MissingResourceException;
     19 import java.util.PropertyResourceBundle;
     20 import java.util.ResourceBundle;
     21 
     22 import android.icu.util.ULocale;
     23 import android.icu.util.UResourceBundle;
     24 
     25 /**
     26  * just a wrapper for Java ListResourceBundles and
     27  * @author ram
     28  * @hide Only a subset of ICU is exposed in Android
     29  *
     30  */
     31 public final class ResourceBundleWrapper extends UResourceBundle {
     32     private ResourceBundle bundle = null;
     33     private String localeID = null;
     34     private String baseName = null;
     35     private List<String> keys = null;
     36 
     37     /** Loader for bundle instances, for caching. */
     38     private static abstract class Loader {
     39         abstract ResourceBundleWrapper load();
     40     }
     41 
     42     private static CacheBase<String, ResourceBundleWrapper, Loader> BUNDLE_CACHE =
     43             new SoftCache<String, ResourceBundleWrapper, Loader>() {
     44         @Override
     45         protected ResourceBundleWrapper createInstance(String unusedKey, Loader loader) {
     46             return loader.load();
     47         }
     48     };
     49 
     50     private ResourceBundleWrapper(ResourceBundle bundle){
     51         this.bundle=bundle;
     52     }
     53 
     54     @Override
     55     protected Object handleGetObject(String aKey){
     56         ResourceBundleWrapper current = this;
     57         Object obj = null;
     58         while(current!=null){
     59             try{
     60                 obj = current.bundle.getObject(aKey);
     61                 break;
     62             }catch(MissingResourceException ex){
     63                 current = (ResourceBundleWrapper)current.getParent();
     64             }
     65         }
     66         if (obj == null){
     67             throw new MissingResourceException("Can't find resource for bundle "
     68                                                +baseName
     69                                                +", key "+aKey,
     70                                                this.getClass().getName(),
     71                                                aKey);
     72         }
     73         return obj;
     74     }
     75 
     76     @Override
     77     public Enumeration<String> getKeys(){
     78         return Collections.enumeration(keys);
     79     }
     80 
     81     private void initKeysVector(){
     82         ResourceBundleWrapper current = this;
     83         keys = new ArrayList<String>();
     84         while(current!=null){
     85             Enumeration<String> e = current.bundle.getKeys();
     86             while(e.hasMoreElements()){
     87                 String elem = e.nextElement();
     88                 if(!keys.contains(elem)){
     89                     keys.add(elem);
     90                 }
     91             }
     92             current = (ResourceBundleWrapper)current.getParent();
     93         }
     94     }
     95     @Override
     96     protected String getLocaleID(){
     97         return localeID;
     98     }
     99 
    100     @Override
    101     protected String getBaseName(){
    102         return bundle.getClass().getName().replace('.','/');
    103     }
    104 
    105     @Override
    106     public ULocale getULocale(){
    107         return new ULocale(localeID);
    108     }
    109 
    110     @Override
    111     public UResourceBundle getParent(){
    112         return (UResourceBundle)parent;
    113     }
    114 
    115     // Flag for enabling/disabling debugging code
    116     private static final boolean DEBUG = ICUDebug.enabled("resourceBundleWrapper");
    117 
    118     // This method is for super class's instantiateBundle method
    119     public static ResourceBundleWrapper getBundleInstance(String baseName, String localeID,
    120             ClassLoader root, boolean disableFallback) {
    121         if (root == null) {
    122             root = ClassLoaderUtil.getClassLoader();
    123         }
    124         ResourceBundleWrapper b;
    125         if (disableFallback) {
    126             b = instantiateBundle(baseName, localeID, null, root, disableFallback);
    127         } else {
    128             b = instantiateBundle(baseName, localeID, ULocale.getDefault().getBaseName(),
    129                     root, disableFallback);
    130         }
    131         if(b==null){
    132             String separator ="_";
    133             if(baseName.indexOf('/')>=0){
    134                 separator = "/";
    135             }
    136             throw new MissingResourceException("Could not find the bundle "+ baseName+separator+ localeID,"","");
    137         }
    138         return b;
    139     }
    140 
    141     private static boolean localeIDStartsWithLangSubtag(String localeID, String lang) {
    142         return localeID.startsWith(lang) &&
    143                 (localeID.length() == lang.length() || localeID.charAt(lang.length()) == '_');
    144     }
    145 
    146     private static ResourceBundleWrapper instantiateBundle(
    147              final String baseName, final String localeID, final String defaultID,
    148              final ClassLoader root, final boolean disableFallback) {
    149         final String name = localeID.isEmpty() ? baseName : baseName + '_' + localeID;
    150         String cacheKey = disableFallback ? name : name + '#' + defaultID;
    151         return BUNDLE_CACHE.getInstance(cacheKey, new Loader() {
    152                 @Override
    153                 public ResourceBundleWrapper load() {
    154             ResourceBundleWrapper parent = null;
    155             int i = localeID.lastIndexOf('_');
    156 
    157             boolean loadFromProperties = false;
    158             boolean parentIsRoot = false;
    159             if (i != -1) {
    160                 String locName = localeID.substring(0, i);
    161                 parent = instantiateBundle(baseName, locName, defaultID, root, disableFallback);
    162             }else if(!localeID.isEmpty()){
    163                 parent = instantiateBundle(baseName, "", defaultID, root, disableFallback);
    164                 parentIsRoot = true;
    165             }
    166             ResourceBundleWrapper b = null;
    167             try {
    168                 Class<? extends ResourceBundle> cls =
    169                         root.loadClass(name).asSubclass(ResourceBundle.class);
    170                 ResourceBundle bx = cls.newInstance();
    171                 b = new ResourceBundleWrapper(bx);
    172                 if (parent != null) {
    173                     b.setParent(parent);
    174                 }
    175                 b.baseName=baseName;
    176                 b.localeID = localeID;
    177             } catch (ClassNotFoundException e) {
    178                 loadFromProperties = true;
    179             } catch (NoClassDefFoundError e) {
    180                 loadFromProperties = true;
    181             } catch (Exception e) {
    182                 if (DEBUG)
    183                     System.out.println("failure");
    184                 if (DEBUG)
    185                     System.out.println(e);
    186             }
    187 
    188             if (loadFromProperties) {
    189                 try {
    190                     final String resName = name.replace('.', '/') + ".properties";
    191                     InputStream stream = java.security.AccessController.doPrivileged(
    192                         new java.security.PrivilegedAction<InputStream>() {
    193                             @Override
    194                             public InputStream run() {
    195                                 return root.getResourceAsStream(resName);
    196                             }
    197                         }
    198                     );
    199                     if (stream != null) {
    200                         // make sure it is buffered
    201                         stream = new java.io.BufferedInputStream(stream);
    202                         try {
    203                             b = new ResourceBundleWrapper(new PropertyResourceBundle(stream));
    204                             if (parent != null) {
    205                                 b.setParent(parent);
    206                             }
    207                             b.baseName=baseName;
    208                             b.localeID=localeID;
    209                         } catch (Exception ex) {
    210                             // throw away exception
    211                         } finally {
    212                             try {
    213                                 stream.close();
    214                             } catch (Exception ex) {
    215                                 // throw away exception
    216                             }
    217                         }
    218                     }
    219 
    220                     // if a bogus locale is passed then the parent should be
    221                     // the default locale not the root locale!
    222                     if (b == null && !disableFallback &&
    223                             !localeID.isEmpty() && localeID.indexOf('_') < 0 &&
    224                             !localeIDStartsWithLangSubtag(defaultID, localeID)) {
    225                         // localeID is only a language subtag, different from the default language.
    226                         b = instantiateBundle(baseName, defaultID, defaultID, root, disableFallback);
    227                     }
    228                     // if still could not find the bundle then return the parent
    229                     if(b==null && (!parentIsRoot || !disableFallback)){
    230                         b=parent;
    231                     }
    232                 } catch (Exception e) {
    233                     if (DEBUG)
    234                         System.out.println("failure");
    235                     if (DEBUG)
    236                         System.out.println(e);
    237                 }
    238             }
    239             if(b!=null){
    240                 b.initKeysVector();
    241             }else{
    242                 if(DEBUG)System.out.println("Returning null for "+baseName+"_"+localeID);
    243             }
    244             return b;
    245         }});
    246     }
    247 }
    248