• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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