KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ibm > icu > util > UResourceBundle


1 /*
2  *******************************************************************************
3  * Copyright (C) 2004-2007, International Business Machines Corporation and *
4  * others. All Rights Reserved. *
5  *******************************************************************************
6  */

7
8 package com.ibm.icu.util;
9
10 import java.lang.ref.SoftReference JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.Locale JavaDoc;
13 import java.util.Map JavaDoc;
14 import java.util.MissingResourceException JavaDoc;
15 import java.util.ResourceBundle JavaDoc;
16
17 import com.ibm.icu.impl.ICUResourceBundle;
18 import com.ibm.icu.impl.ICUResourceBundleReader;
19 import com.ibm.icu.impl.ResourceBundleWrapper;
20 import com.ibm.icu.util.ULocale;
21
22 /**
23  * A class representing a collection of resource information pertaining to a given
24  * locale. A resource bundle provides a way of accessing locale- specfic information in
25  * a data file. You create a resource bundle that manages the resources for a given
26  * locale and then ask it for individual resources.
27  * <P>
28  * In ResourceBundle class, an object is created
29  * and the sub items are fetched using getString, getObject methods.
30  * In UResourceBundle,each individual element of a resource is a resource by itself.
31  *
32  * <P>
33  * Resource bundles in ICU are currently defined using text files which conform to the following
34  * <a HREF="http://dev.icu-project.org/cgi-bin/viewcvs.cgi/icuhtml/design/bnf_rb.txt">BNF definition</a>.
35  * More on resource bundle concepts and syntax can be found in the
36  * <a HREF="http://icu.sourceforge.net/userguide/ResourceManagement.html">Users Guide</a>.
37  * <P>
38  *
39  * The packaging of ICU *.res files can be of two types
40  * ICU4C:
41  * <pre>
42  * root.res
43  * |
44  * --------
45  * | |
46  * fr.res en.res
47  * |
48  * --------
49  * | |
50  * fr_CA.res fr_FR.res
51  * </pre>
52  * JAVA/JDK:
53  * <pre>
54  * LocaleElements.res
55  * |
56  * -------------------
57  * | |
58  * LocaleElements_fr.res LocaleElements_en.res
59  * |
60  * ---------------------------
61  * | |
62  * LocaleElements_fr_CA.res LocaleElements_fr_FR.res
63  * </pre>
64  * Depending on the organization of your resources, the syntax to getBundleInstance will change.
65  * To open ICU style organization use:
66  * <pre>
67  * UResourceBundle bundle = UResourceBundle.getBundleInstance("com/ibm/icu/impl/data/icudt30b", "en_US");
68  * </pre>
69  * To open Java/JDK style organization use:
70  * <pre>
71  * UResourceBundle bundle = UResourceBundle.getBundleInstance("com.ibm.icu.impl.data.LocaleElements", "en_US");
72  * </pre>
73  * @stable ICU 3.0
74  * @author ram
75  */

76 public abstract class UResourceBundle extends ResourceBundle JavaDoc{
77
78     
79     /**
80      * Creates a resource bundle using the specified base name and locale.
81      * ICU_DATA_CLASS is used as the default root.
82      * @param baseName the base name of the resource bundle, a fully qualified class name
83      * @param localeName the locale for which a resource bundle is desired
84      * @exception MissingResourceException
85      * if no resource bundle for the specified base name can be found
86      * @return a resource bundle for the given base name and locale
87      * @stable ICU 3.0
88      */

89     public static UResourceBundle getBundleInstance(String JavaDoc baseName, String JavaDoc localeName){
90         return getBundleInstance(baseName, localeName, ICUResourceBundle.ICU_DATA_CLASS_LOADER, false);
91     }
92     
93     /**
94      * Creates a resource bundle using the specified base name, locale, and class root.
95      *
96      * @param baseName the base name of the resource bundle, a fully qualified class name
97      * @param localeName the locale for which a resource bundle is desired
98      * @param root the class object from which to load the resource bundle
99      * @exception MissingResourceException
100      * if no resource bundle for the specified base name can be found
101      * @return a resource bundle for the given base name and locale
102      * @stable ICU 3.0
103      */

104     public static UResourceBundle getBundleInstance(String JavaDoc baseName, String JavaDoc localeName, ClassLoader JavaDoc root){
105         return getBundleInstance(baseName, localeName, root, false);
106     }
107     
108     /**
109      * Creates a resource bundle using the specified base name, locale, and class root.
110      *
111      * @param baseName the base name of the resource bundle, a fully qualified class name
112      * @param localeName the locale for which a resource bundle is desired
113      * @param root the class object from which to load the resource bundle
114      * @param disableFallback Option to disable locale inheritence.
115      * If true the fallback chain will not be built.
116      * @exception MissingResourceException
117      * if no resource bundle for the specified base name can be found
118      * @return a resource bundle for the given base name and locale
119      * @stable ICU 3.0
120      *
121      */

122     protected static UResourceBundle getBundleInstance(String JavaDoc baseName, String JavaDoc localeName, ClassLoader JavaDoc root, boolean disableFallback){
123         return instantiateBundle(baseName, localeName, root, disableFallback);
124     }
125
126     /**
127      * Sole constructor. (For invocation by subclass constructors, typically
128      * implicit.) This is public for compatibility with Java, whose compiler
129      * will generate public default constructors for an abstract class.
130      * @stable ICU 3.0
131      */

132     public UResourceBundle() {
133     }
134     
135     /**
136      * Creates a UResourceBundle for the locale specified, from which users can extract resources by using
137      * their corresponding keys.
138      * @param locale specifies the locale for which we want to open the resource.
139      * If null the bundle for default locale is opened.
140      * @return a resource bundle for the given locale
141      * @stable ICU 3.0
142      */

143     public static UResourceBundle getBundleInstance(ULocale locale){
144         if(locale==null){
145             locale = ULocale.getDefault();
146         }
147         return getBundleInstance( ICUResourceBundle.ICU_BASE_NAME, locale.toString(), ICUResourceBundle.ICU_DATA_CLASS_LOADER );
148     }
149     /**
150      * Creates a UResourceBundle for the default locale and specified base name,
151      * from which users can extract resources by using their corresponding keys.
152      * @param baseName specifies the locale for which we want to open the resource.
153      * If null the bundle for default locale is opened.
154      * @return a resource bundle for the given base name and default locale
155      * @stable ICU 3.0
156      */

157     public static UResourceBundle getBundleInstance(String JavaDoc baseName){
158         return getBundleInstance( baseName, ULocale.getDefault().toString(), ICUResourceBundle.ICU_DATA_CLASS_LOADER );
159     }
160     /**
161      * Creates a UResourceBundle for the specified locale and specified base name,
162      * from which users can extract resources by using their corresponding keys.
163      * @param baseName specifies the locale for which we want to open the resource.
164      * If null the bundle for default locale is opened.
165      * @param locale specifies the locale for which we want to open the resource.
166      * If null the bundle for default locale is opened.
167      * @return a resource bundle for the given base name and locale
168      * @stable ICU 3.0
169      */

170
171     public static UResourceBundle getBundleInstance(String JavaDoc baseName, Locale JavaDoc locale){
172         return getBundleInstance(baseName, ULocale.forLocale(locale));
173     }
174    
175     /**
176      * Creates a UResourceBundle, from which users can extract resources by using
177      * their corresponding keys.
178      * @param baseName string containing the name of the data package.
179      * If null the default ICU package name is used.
180      * @param locale specifies the locale for which we want to open the resource.
181      * If null the bundle for default locale is opened.
182      * @return a resource bundle for the given base name and locale
183      * @stable ICU 3.0
184      */

185     public static UResourceBundle getBundleInstance(String JavaDoc baseName, ULocale locale){
186          return getBundleInstance(baseName, locale.toString(),ICUResourceBundle.ICU_DATA_CLASS_LOADER);
187     }
188     
189     /**
190      * Creates a UResourceBundle for the specified locale and specified base name,
191      * from which users can extract resources by using their corresponding keys.
192      * @param baseName specifies the locale for which we want to open the resource.
193      * If null the bundle for default locale is opened.
194      * @param locale specifies the locale for which we want to open the resource.
195      * If null the bundle for default locale is opened.
196      * @param loader the loader to use
197      * @return a resource bundle for the given base name and locale
198      * @internal revisit for ICU 3.6
199      * @deprecated This API is ICU internal only.
200      */

201     public static UResourceBundle getBundleInstance(String JavaDoc baseName, Locale JavaDoc locale, ClassLoader JavaDoc loader){
202         return getBundleInstance(baseName, ULocale.forLocale(locale), loader);
203     }
204    
205     /**
206      * Creates a UResourceBundle, from which users can extract resources by using
207      * their corresponding keys.
208      * @param baseName string containing the name of the data package.
209      * If null the default ICU package name is used.
210      * @param locale specifies the locale for which we want to open the resource.
211      * If null the bundle for default locale is opened.
212      * @param loader the loader to use
213      * @return a resource bundle for the given base name and locale
214      * @internal revisit for ICU 3.6
215      * @deprecated This API is ICU internal only.
216      */

217     public static UResourceBundle getBundleInstance(String JavaDoc baseName, ULocale locale, ClassLoader JavaDoc loader){
218          return getBundleInstance(baseName, locale.toString(),loader);
219     }
220     
221     /**
222      * Returns the RFC 3066 conformant locale id of this resource bundle.
223      * This method can be used after a call to getBundleInstance() to
224      * determine whether the resource bundle returned really
225      * corresponds to the requested locale or is a fallback.
226      *
227      * @return the locale of this resource bundle
228      * @stable ICU 3.0
229      */

230     public abstract ULocale getULocale();
231     
232     /**
233      * Gets the localeID
234      * @return The string representation of the localeID
235      * @stable ICU 3.0
236      */

237     protected abstract String JavaDoc getLocaleID();
238     /**
239      * Gets the base name of the resource bundle
240      * @return The string representation of the base name
241      * @stable ICU 3.0
242      */

243     protected abstract String JavaDoc getBaseName();
244     /**
245      * Gets the parent bundle
246      * @return The parent bundle
247      * @stable ICU 3.0
248      */

249     protected abstract UResourceBundle getParent();
250     
251     
252     /**
253      * Get the locale of this bundle
254      * @return the locale of this resource bundle
255      * @stable ICU 3.0
256      */

257     public Locale JavaDoc getLocale(){
258         return getULocale().toLocale();
259     }
260
261     // Cache for ResourceBundle instantiation
262
private static SoftReference JavaDoc BUNDLE_CACHE;
263
264     private static void addToCache(ResourceCacheKey key, UResourceBundle b) {
265         Map JavaDoc m = null;
266         if (BUNDLE_CACHE != null) {
267             m = (Map JavaDoc)BUNDLE_CACHE.get();
268         }
269         if (m == null) {
270             m = new HashMap JavaDoc();
271             BUNDLE_CACHE = new SoftReference JavaDoc(m);
272         }
273         m.put(key, b);
274     }
275
276     /**
277      * @internal revisit for ICU 3.6
278      * @deprecated This API is ICU internal only.
279      */

280     protected static void addToCache(ClassLoader JavaDoc cl, String JavaDoc fullName, ULocale defaultLocale, UResourceBundle b){
281         synchronized(cacheKey){
282             cacheKey.setKeyValues(cl, fullName, defaultLocale);
283             addToCache((ResourceCacheKey)cacheKey.clone(), b);
284         }
285     }
286     /**
287      * @internal revisit for ICU 3.6
288      * @deprecated This API is ICU internal only.
289      */

290     protected static UResourceBundle loadFromCache(ClassLoader JavaDoc cl, String JavaDoc fullName, ULocale defaultLocale){
291         synchronized(cacheKey){
292             cacheKey.setKeyValues(cl, fullName, defaultLocale);
293             return loadFromCache(cacheKey);
294         }
295     }
296     private static UResourceBundle loadFromCache(ResourceCacheKey key) {
297         if (BUNDLE_CACHE != null) {
298             Map JavaDoc m = (Map JavaDoc)BUNDLE_CACHE.get();
299             if (m != null) {
300                 return (UResourceBundle)m.get(key);
301             }
302         }
303         return null;
304     }
305     
306     /**
307      * Key used for cached resource bundles. The key checks
308      * the resource name, the class root, and the default
309      * locale to determine if the resource is a match to the
310      * requested one. The root may be null, but the
311      * searchName and the default locale must have a non-null value.
312      * Note that the default locale may change over time, and
313      * lookup should always be based on the current default
314      * locale (if at all).
315      */

316     private static final class ResourceCacheKey implements Cloneable JavaDoc {
317         private SoftReference JavaDoc loaderRef;
318         private String JavaDoc searchName;
319         private ULocale defaultLocale;
320         private int hashCodeCache;
321         ///CLOVER:OFF
322
public boolean equals(Object JavaDoc other) {
323             if (this == other) {
324                 return true;
325             }
326             try {
327                 final ResourceCacheKey otherEntry = (ResourceCacheKey) other;
328                 //quick check to see if they are not equal
329
if (hashCodeCache != otherEntry.hashCodeCache) {
330                     return false;
331                 }
332                 //are the names the same?
333
if (!searchName.equals(otherEntry.searchName)) {
334                     return false;
335                 }
336                 // are the default locales the same?
337
if (defaultLocale == null) {
338                     if (otherEntry.defaultLocale != null) {
339                         return false;
340                     }
341                 } else {
342                     if (!defaultLocale.equals(otherEntry.defaultLocale)) {
343                         return false;
344                     }
345                 }
346                 //are refs (both non-null) or (both null)?
347
if (loaderRef == null) {
348                     return otherEntry.loaderRef == null;
349                 } else {
350                     return (otherEntry.loaderRef != null)
351                             && (loaderRef.get() == otherEntry.loaderRef.get());
352                 }
353             } catch (NullPointerException JavaDoc e) {
354                 return false;
355             } catch (ClassCastException JavaDoc e) {
356                 return false;
357             }
358         }
359         public int hashCode() {
360             return hashCodeCache;
361         }
362         public Object JavaDoc clone() {
363             try {
364                 return super.clone();
365             } catch (CloneNotSupportedException JavaDoc e) {
366                 //this should never happen
367
throw new IllegalStateException JavaDoc();
368             }
369         }
370         ///CLOVER:ON
371
private synchronized void setKeyValues(ClassLoader JavaDoc root, String JavaDoc searchName, ULocale defaultLocale) {
372             this.searchName = searchName;
373             hashCodeCache = searchName.hashCode();
374             this.defaultLocale = defaultLocale;
375             if (defaultLocale != null) {
376                 hashCodeCache ^= defaultLocale.hashCode();
377             }
378             if (root == null) {
379                 this.loaderRef = null;
380             } else {
381                 loaderRef = new SoftReference JavaDoc(root);
382                 hashCodeCache ^= root.hashCode();
383             }
384         }
385         /*private void clear() {
386             setKeyValues(null, "", null);
387         }*/

388     }
389     
390     private static final ResourceCacheKey cacheKey = new ResourceCacheKey();
391                              
392     private static final int ROOT_MISSING = 0;
393     private static final int ROOT_ICU = 1;
394     private static final int ROOT_JAVA = 2;
395     
396     private static SoftReference JavaDoc ROOT_CACHE;
397
398     private static int getRootType(String JavaDoc baseName, ClassLoader JavaDoc root)
399     {
400         Map JavaDoc m = null;
401         Integer JavaDoc rootType;
402         
403         if (ROOT_CACHE != null) {
404             m = (Map JavaDoc) ROOT_CACHE.get();
405         }
406         
407         if (m == null) {
408             m = new HashMap JavaDoc();
409             ROOT_CACHE = new SoftReference JavaDoc(m);
410         }
411
412         rootType = (Integer JavaDoc) m.get(baseName);
413         
414         if (rootType == null) {
415             String JavaDoc rootLocale = (baseName.indexOf('.')==-1) ? "root" : "";
416             int rt = ROOT_MISSING; // value set on success
417
try{
418                 ICUResourceBundle.getBundleInstance(baseName, rootLocale, root, true);
419                 rt = ROOT_ICU;
420             }catch(MissingResourceException JavaDoc ex){
421                 try{
422                     ResourceBundleWrapper.getBundleInstance(baseName, rootLocale, root, true);
423                     rt = ROOT_JAVA;
424                 }catch(MissingResourceException JavaDoc e){
425                     //throw away the exception
426
}
427             }
428             
429             rootType = new Integer JavaDoc(rt);
430             m.put(baseName, rootType);
431         }
432         
433         return rootType.intValue();
434     }
435     
436     private static void setRootType(String JavaDoc baseName, int rootType)
437     {
438         Integer JavaDoc rt = new Integer JavaDoc(rootType);
439         Map JavaDoc m = null;
440         
441         if (ROOT_CACHE != null) {
442             m = (Map JavaDoc) ROOT_CACHE.get();
443         } else {
444             m = new HashMap JavaDoc();
445             ROOT_CACHE = new SoftReference JavaDoc(m);
446         }
447         
448         m.put(baseName, rt);
449     }
450     
451     /**
452      * Loads a new resource bundle for the give base name, locale and class loader.
453      * Optionally will disable loading of fallback bundles.
454      * @param baseName the base name of the resource bundle, a fully qualified class name
455      * @param localeName the locale for which a resource bundle is desired
456      * @param root the class object from which to load the resource bundle
457      * @param disableFallback disables loading of fallback lookup chain
458      * @exception MissingResourceException
459      * if no resource bundle for the specified base name can be found
460      * @return a resource bundle for the given base name and locale
461      * @stable ICU 3.0
462      */

463     protected static UResourceBundle instantiateBundle(String JavaDoc baseName, String JavaDoc localeName,
464                                                        ClassLoader JavaDoc root, boolean disableFallback){
465         UResourceBundle b = null;
466         int rootType = getRootType(baseName, root);
467
468         ULocale defaultLocale = ULocale.getDefault();
469         
470         switch (rootType)
471         {
472         case ROOT_ICU:
473             if(disableFallback) {
474                 String JavaDoc fullName = ICUResourceBundleReader.getFullName(baseName, localeName);
475                 synchronized(cacheKey){
476                     cacheKey.setKeyValues(root, fullName, defaultLocale);
477                     b = loadFromCache(cacheKey);
478                 }
479                 
480                 if (b == null) {
481                     b = ICUResourceBundle.getBundleInstance(baseName, localeName, root, disableFallback);
482                     //cacheKey.setKeyValues(root, fullName, defaultLocale);
483
addToCache(cacheKey, b);
484                 }
485             } else {
486                 b = ICUResourceBundle.getBundleInstance(baseName, localeName, root, disableFallback);
487             }
488             
489             return b;
490             
491         case ROOT_JAVA:
492             return ResourceBundleWrapper.getBundleInstance(baseName, localeName, root, disableFallback);
493             
494         default:
495             try{
496                 b = ICUResourceBundle.getBundleInstance(baseName, localeName, root, disableFallback);
497                 setRootType(baseName, ROOT_ICU);
498             }catch(MissingResourceException JavaDoc ex){
499                 b = ResourceBundleWrapper.getBundleInstance(baseName, localeName, root, disableFallback);
500                 setRootType(baseName, ROOT_JAVA);
501             }
502             return b;
503         }
504     }
505
506     /**
507      * @internal
508      * @deprecated This API is ICU internal only.
509      */

510     protected abstract void setLoadingStatus(int newStatus);
511 }
512
Popular Tags