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