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 { load()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 ResourceBundleWrapper(ResourceBundle bundle)50 private ResourceBundleWrapper(ResourceBundle bundle){ 51 this.bundle=bundle; 52 } 53 54 @Override handleGetObject(String aKey)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 getKeys()77 public Enumeration<String> getKeys(){ 78 return Collections.enumeration(keys); 79 } 80 initKeysVector()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 getLocaleID()96 protected String getLocaleID(){ 97 return localeID; 98 } 99 100 @Override getBaseName()101 protected String getBaseName(){ 102 return bundle.getClass().getName().replace('.','/'); 103 } 104 105 @Override getULocale()106 public ULocale getULocale(){ 107 return new ULocale(localeID); 108 } 109 110 @Override getParent()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 getBundleInstance(String baseName, String localeID, ClassLoader root, boolean disableFallback)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 localeIDStartsWithLangSubtag(String localeID, String lang)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 instantiateBundle( final String baseName, final String localeID, final String defaultID, final ClassLoader root, final boolean disableFallback)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