KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ibm > icu > impl > ICUListResourceBundle


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

7
8 /**
9  * A list resource bundle that does redirection
10  * because otherwise some of our resource class files
11  * are too big for the java runtime to handle.
12  */

13
14 package com.ibm.icu.impl;
15
16 import java.io.InputStream JavaDoc;
17 import java.io.InputStreamReader JavaDoc;
18 import java.io.IOException JavaDoc;
19 import java.io.UnsupportedEncodingException JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.ListResourceBundle JavaDoc;
22 import java.util.Locale JavaDoc;
23 import java.util.ResourceBundle JavaDoc;
24 import java.util.MissingResourceException JavaDoc;
25 import java.util.Hashtable JavaDoc;
26
27 public class ICUListResourceBundle extends ListResourceBundle JavaDoc {
28     private static final String JavaDoc ICUDATA = "ICUDATA";
29     private static final String JavaDoc ICU_BUNDLE_NAME = "LocaleElements";
30     private static final String JavaDoc ICU_PACKAGE_NAME ="com.ibm.icu.impl.data";
31     private static final String JavaDoc ENCODING="UTF-8";
32
33     /* package */ Locale JavaDoc icuLocale;
34     /* package */ void setParentX(ResourceBundle JavaDoc b) {
35         setParent(b);
36     }
37
38     public Locale JavaDoc getLocale() {
39         return icuLocale;
40     }
41
42     protected ICUListResourceBundle() {
43     }
44
45     private Hashtable JavaDoc visited = new Hashtable JavaDoc();
46     /**
47      * Subclassers must statically initialize this
48      */

49     protected Object JavaDoc[][] contents;
50
51     /**
52      * This is our cache
53      */

54     private Object JavaDoc[][] realContents;
55
56     /**
57      * See base class description
58      */

59     protected Object JavaDoc[][] getContents(){
60         // we replace any redirected values with real values in a cloned array
61
if (realContents == null) {
62             realContents = contents;
63             for (int i = 0; i < contents.length; ++i) {
64                 Object JavaDoc newValue = getRedirectedResource((String JavaDoc)contents[i][0],contents[i][1], -1);
65                 if (newValue != null) {
66                     if (realContents == contents) {
67                         realContents = (Object JavaDoc[][])contents.clone();
68                     }
69                     realContents[i] = new Object JavaDoc[] { contents[i][0], newValue };
70                 }
71             }
72         }
73         return realContents;
74     }
75
76     /**
77      * Return null if value is already in existing contents array, otherwise fetch the
78      * real value and return it.
79      */

80     private Object JavaDoc getRedirectedResource(String JavaDoc key, Object JavaDoc value, int index) {
81
82         if (value instanceof Object JavaDoc[][]) {
83             Object JavaDoc[][] aValue = (Object JavaDoc[][])value;
84             int i=0;
85             while(i < aValue.length){
86                 int j=0;
87                 while(j < aValue[i].length){
88                     aValue[i][j] = getRedirectedResource((String JavaDoc)aValue[i][0],aValue[i][j], i);
89                     j++;
90                 }
91                 i++;
92             }
93         }else if (value instanceof Object JavaDoc[]){
94             Object JavaDoc[] aValue = (Object JavaDoc[]) value;
95             int i=0;
96             while( i < aValue.length){
97                 aValue[i] = getRedirectedResource(key,aValue[i], i);
98                 i++;
99             }
100         }else if(value instanceof Alias){
101         
102             String JavaDoc cName = this.getClass().getName();
103             visited.clear();
104             visited.put(cName+key,"");
105             return ((Alias)value).getResource(cName,key,index, visited);
106         }else if(value instanceof RedirectedResource){
107             return ((RedirectedResource)value).getResource(this);
108         }
109
110         return value;
111     }
112
113     private static byte[] readToEOS(InputStream JavaDoc stream) {
114         // As of 3.0 this method reads streams of length 264..274008
115
// from the core data. We progressively double the buffer
116
// size to reduce the number of allocations required.
117
try {
118             ArrayList JavaDoc vec = new ArrayList JavaDoc();
119             int count = 0;
120             int length = 0x200; // smallest 2^n >= min stream len
121
final int MAXLENGTH = 0x8000;
122             int pos = -1;
123             for (;;) {
124                 byte[] buffer = new byte[length];
125                 pos = 0;
126                 do {
127                     int n = stream.read(buffer, pos, length - pos);
128                     if (n == -1) {
129                         break;
130                     }
131                     pos += n;
132                 } while (pos < length);
133                 count += pos;
134                 vec.add(buffer);
135                 if (pos < length) {
136                     break;
137                 }
138                 if (length < MAXLENGTH) {
139                     length <<= 1;
140                 }
141             }
142
143             // System.out.println("\ncount " + count + " bytes from " + stream);
144

145             byte[] data = new byte[count];
146             pos = 0;
147             for (int i = 0; i < vec.size(); ++i) {
148                 byte[] buf = (byte[])vec.get(i);
149                 int len = Math.min(buf.length, count - pos);
150                 System.arraycopy(buf, 0, data, pos, len);
151                 pos += len;
152             }
153             // assert pos==count;
154
return data;
155         } catch (IOException JavaDoc e) {
156             throw new MissingResourceException JavaDoc(e.getMessage(),"","");
157         }
158     }
159
160     private static char[] readToEOS(InputStreamReader JavaDoc stream) {
161         // As of 3.0 this method reads streams of length 41990..41994
162
// from the core data. The IBM 1.4 UTF8 converter doesn't
163
// handle buffering reliably (it throws an exception) so we
164
// are forced to read everything in one chunk.
165
try {
166             int length = 0x10000; // smallest 2^n >= max stream len
167
final int MAXLENGTH = 0x40000000;
168             int n;
169             char[] buffer;
170             for (;;) {
171                 buffer = new char[length];
172                 n = stream.read(buffer, 0, length);
173                 if (n >= 0 && n < length) {
174                     break;
175                 }
176                 if (length < MAXLENGTH) {
177                     stream.reset();
178                     length <<= 1;
179                 } else {
180                     throw new IllegalStateException JavaDoc("maximum input stream length exceeded");
181                 }
182             }
183
184             // System.out.println("\ncount " + n + " chars from " + stream);
185

186             char[] data = new char[n];
187             System.arraycopy(buffer, 0, data, 0, n);
188             return data;
189         } catch (IOException JavaDoc e) {
190             throw new MissingResourceException JavaDoc(e.getMessage(),"","");
191         }
192     }
193     /*
194     public static class CompressedString implements RedirectedResource{
195         private String expanded=null;
196         private String compressed=null;
197         public CompressedString(String str){
198            compressed=str;
199         }
200         public Object getResource(Object obj){
201             if(compressed==null){
202                 return null;
203             }
204             if(expanded==null){
205                 expanded= new String(Utility.RLEStringToCharArray(compressed));
206             }
207             return expanded;
208         }
209     }
210     */

211     public static class CompressedBinary implements RedirectedResource{
212         private byte[] expanded=null;
213         private String JavaDoc compressed=null;
214         public CompressedBinary(String JavaDoc str){
215            compressed = str;
216         }
217         public Object JavaDoc getResource(Object JavaDoc obj){
218             if(compressed==null){
219                 return new byte[0];
220             }
221
222             if(expanded==null){
223                 expanded= Utility.RLEStringToByteArray(compressed);
224             }
225             return expanded ==null ? new byte[0]: expanded;
226         }
227
228     }
229     private interface RedirectedResource{
230         public Object JavaDoc getResource(Object JavaDoc obj);
231     }
232
233     public static class ResourceBinary implements RedirectedResource{
234         private byte[] expanded=null;
235         private String JavaDoc resName=null;
236         public ResourceBinary(String JavaDoc name){
237             resName="data/" + name;
238         }
239         public Object JavaDoc getResource(Object JavaDoc obj) {
240             if(expanded==null){
241                 InputStream JavaDoc stream = ICUData.getStream(resName);
242                 if(stream!=null){
243                     //throw new MissingResourceException("",obj.getClass().getName(),resName);
244
expanded = readToEOS(stream);
245                     return expanded;
246                 }
247             }
248             return "";
249         }
250     }
251
252     public static class ResourceString implements RedirectedResource{
253         private char[] expanded=null;
254         private String JavaDoc resName=null;
255         public ResourceString(String JavaDoc name){
256             resName="data/"+name;
257         }
258         public Object JavaDoc getResource(Object JavaDoc obj) {
259             if(expanded==null){
260                 // Resource strings are always UTF-8
261
InputStream JavaDoc stream = ICUData.getStream(resName);
262                 if(stream!=null){
263                     //throw new MissingResourceException("",obj.getClass().getName(),resName);
264

265                     try{
266                         InputStreamReader JavaDoc reader = new InputStreamReader JavaDoc(stream,ENCODING);
267                         expanded = readToEOS(reader);
268                     }catch(UnsupportedEncodingException JavaDoc ex){
269                         throw new RuntimeException JavaDoc("Could open converter for encoding: " +ENCODING);
270                     }
271                     return new String JavaDoc(expanded);
272                 }
273
274             }
275             return "";
276         }
277     }
278     
279     private static final char RES_PATH_SEP_CHAR = '/';
280     
281     public static class Alias{
282         public Alias(String JavaDoc path){
283             pathToResource = path;
284         }
285         
286         private String JavaDoc pathToResource;
287
288         private Object JavaDoc getResource(String JavaDoc className, String JavaDoc parentKey, int index, Hashtable JavaDoc visited){
289             String JavaDoc packageName=null,bundleName=null, locale=null, keyPath=null;
290
291             if(pathToResource.indexOf(RES_PATH_SEP_CHAR)==0){
292                 int i =pathToResource.indexOf(RES_PATH_SEP_CHAR,1);
293                 int j =pathToResource.indexOf(RES_PATH_SEP_CHAR,i+1);
294                 bundleName=pathToResource.substring(1,i);
295                 locale=pathToResource.substring(i+1);
296                 if(j!=-1){
297                     locale=pathToResource.substring(i+1,j);
298                     keyPath=pathToResource.substring(j+1,pathToResource.length());
299                 }
300                 //there is a path included
301
if(bundleName.equals(ICUDATA)){
302                     bundleName = ICU_BUNDLE_NAME;
303                     packageName = ICU_PACKAGE_NAME;
304                 }
305
306             }else{
307                 //no path start with locale
308
int i =pathToResource.indexOf(RES_PATH_SEP_CHAR);
309                 //If this is a bundle with locale name following it
310
//then it should be of type <bundle name>_<locale>
311
//if not we donot guarantee that this will work
312
int j = className.lastIndexOf(".");
313                 packageName=className.substring(0,j);
314                 int underScoreIndex = className.indexOf("_");
315                 if(underScoreIndex>=0){
316                     bundleName=className.substring(j+1,className.indexOf("_"));
317                 }else{
318                     bundleName = className.substring(j+1,className.length());
319                 }
320                 keyPath=pathToResource.substring(i+1);
321
322                 if(i!=-1){
323                     locale = pathToResource.substring(0,i);
324                 }else{
325                     locale=keyPath;
326                     keyPath=parentKey;
327                     if(locale==null || locale.equals("root")){
328                         className=packageName+"."+bundleName;
329                     }else{
330                         className=packageName+"."+bundleName+"_"+ locale;
331                     }
332                     
333                 }
334
335             }
336             
337             ResourceBundle JavaDoc bundle = null;
338             // getResourceBundle guarantees that the CLASSPATH will be searched
339
// for loading the resource with name <bundleName>_<localeName>.class
340
if(locale==null || locale.equals("root")){
341                 bundle = ICULocaleData.getResourceBundle(packageName,bundleName,"");
342             }else{
343                 bundle = ICULocaleData.getResourceBundle(packageName,bundleName,locale);
344             }
345             
346             return findResource(bundle, className, parentKey, index, keyPath, visited);
347         
348         }
349         
350         private Object JavaDoc findResource(Object JavaDoc[][] contents, String JavaDoc key){
351             for (int i = 0; i < contents.length; ++i) {
352                 // key must be non-null String, value must be non-null
353
String JavaDoc tempKey = (String JavaDoc) contents[i][0];
354                 Object JavaDoc value = contents[i][1];
355                 if (tempKey == null || value == null) {
356                     throw new NullPointerException JavaDoc();
357                 }
358                 if(tempKey.equals(key)){
359                     return value;
360                 }
361             }
362             return null;
363         }
364         
365         private Object JavaDoc findResource(Object JavaDoc o , String JavaDoc[] keys, int start, int index){
366             Object JavaDoc obj = o;
367             if( start < keys.length && keys[start] !=null){
368                 if(obj instanceof Object JavaDoc[][]){
369                     obj = findResource((Object JavaDoc[][])obj,keys[start]);
370                 }else if(obj instanceof Object JavaDoc[] && isIndex(keys[start])){
371                     obj = ((Object JavaDoc[])obj)[getIndex(keys[start])];
372                 }
373                 if(start+1 < keys.length && keys[start+1] !=null){
374                     obj = findResource(obj,keys,start+1, index);
375                 }
376             }else{
377                 //try to find the corresponding index resource
378
if(index>=0){
379                     if(obj instanceof Object JavaDoc[][]){
380                         obj = findResource((Object JavaDoc[][])obj,Integer.toString(index));
381                     }else if(obj instanceof Object JavaDoc[]){
382                         obj = ((Object JavaDoc[])obj)[index];
383                     }
384                 }
385             }
386             return obj;
387         }
388         private Object JavaDoc findResource(ResourceBundle JavaDoc bundle, String JavaDoc className, String JavaDoc requestedKey, int index, String JavaDoc aliasKey, Hashtable JavaDoc visited){
389
390             if(aliasKey != null && visited.get(className+aliasKey)!=null){
391                 throw new MissingResourceException JavaDoc("Circular Aliases in bundle.",bundle.getClass().getName(),requestedKey);
392             }
393             if(aliasKey==null){
394                 // currently we do an implicit key lookup
395
// return ((ICUListResourceBundle)bundle).getContents();
396
aliasKey = requestedKey;
397             }
398             
399             visited.put(className+requestedKey,"");
400
401             String JavaDoc[] keys = split(aliasKey,RES_PATH_SEP_CHAR);
402             Object JavaDoc o =null;
403             if(keys.length>0){
404                 o = bundle.getObject(keys[0]);
405                 o = findResource(o, keys, 1, index);
406             }
407             o=resolveAliases(o,className,aliasKey,visited);
408             return o;
409         }
410         private Object JavaDoc resolveAliases(Object JavaDoc o,String JavaDoc className,String JavaDoc key, Hashtable JavaDoc visited){
411             if(o instanceof Object JavaDoc[][]){
412                 o = resolveAliases((Object JavaDoc[][])o,className,key, visited);
413             }else if(o instanceof Object JavaDoc[]){
414                  o = resolveAliases((Object JavaDoc[])o,className,key, visited);
415             }else if(o instanceof Alias){
416                 return ((Alias)o).getResource(className,key, -1, visited);
417             }
418             return o;
419         }
420         private Object JavaDoc resolveAliases(Object JavaDoc[][] o,String JavaDoc className, String JavaDoc key,Hashtable JavaDoc visited){
421             int i =0;
422             while(i<o.length){
423                 o[i][1]=resolveAliases(o[i][1],className,key,visited);
424                 i++;
425             }
426             return o;
427         }
428         private Object JavaDoc resolveAliases(Object JavaDoc[] o,String JavaDoc className, String JavaDoc key,Hashtable JavaDoc visited){
429             int i =0;
430             while(i<o.length){
431                 o[i]=resolveAliases(o[i],className,key,visited);
432                 i++;
433             }
434             return o;
435         }
436
437
438     }
439     private static String JavaDoc[] split(String JavaDoc source, char delimiter){
440
441         char[] src = source.toCharArray();
442         int index = 0;
443         int numdelimit=0;
444         // first count the number of delimiters
445
for(int i=0;i<source.length();i++){
446             if(src[i]==delimiter){
447                 numdelimit++;
448             }
449         }
450         String JavaDoc[] values =null;
451         values = new String JavaDoc[numdelimit+2];
452         // now split
453
int old=0;
454         for(int j=0;j<src.length;j++){
455             if(src[j]==delimiter){
456                 values[index++] = new String JavaDoc(src,old,j-old);
457                 old=j+1/* skip after the delimiter*/;
458             }
459         }
460         if(old <src.length)
461             values[index++]=new String JavaDoc(src,old,src.length-old);
462         return values;
463     }
464     
465     /**
466      * This method performs multilevel fallback for fetching items from the bundle
467      * e.g:
468      * If resource is in the form
469      * de__PHONEBOOK{
470      * collations{
471      * default{ "phonebook"}
472      * }
473      * }
474      * If the value of "default" key needs to be accessed, then do:
475      * <code>
476      * ResourceBundle bundle = new ResourceBundle(getLocaleFromString("de__PHONEBOOK"));
477      * Object result = null;
478      * if(bundle instanceof ICUListResourceBundle){
479      * result = ((ICUListResourceBundle) bundle).getObjectWithFallback("collations/default");
480      * }
481      * </code>
482      * @param path The path to the required resource key
483      * @return Object represented by the key
484      * @exception MissingResourceException
485      */

486     public final Object JavaDoc getObjectWithFallback(String JavaDoc path)
487                   throws MissingResourceException JavaDoc{
488         String JavaDoc[] keys = split(path, RES_PATH_SEP_CHAR);
489         Object JavaDoc result = null;
490         ICUListResourceBundle actualBundle = this;
491         
492         
493         // now recuse to pick up sub levels of the items
494
result = findResourceWithFallback(keys, actualBundle);
495                     
496         if(result == null){
497             throw new MissingResourceException JavaDoc("Could not find the resource in ",this.getClass().getName(),path);
498         }
499         return result;
500     }
501     
502
503     private Object JavaDoc findResourceWithFallback(String JavaDoc[] keys,
504                                             ICUListResourceBundle actualBundle){
505
506         Object JavaDoc obj = null;
507         
508         while(actualBundle != null){
509             // get the top level resource
510
// getObject is a method on the ResourceBundle class that
511
// performs the normal fallback
512
obj = actualBundle.getObject(keys[0], actualBundle);
513             
514             // now find the bundle from the actual bundle
515
// if this bundle does not contain the top level resource,
516
// then we can be sure that it does not contain the sub elements
517
obj = findResourceWithFallback(obj, keys, 1, 0);
518             // did we get the contents? the break
519
if(obj != null){
520                 break;
521             }
522             // if not try the parent bundle
523
actualBundle = (ICUListResourceBundle) actualBundle.parent;
524         
525         }
526         
527         return obj;
528     }
529     private Object JavaDoc findResourceWithFallback(Object JavaDoc o , String JavaDoc[] keys, int start,
530                                             int index){
531         Object JavaDoc obj = o;
532         
533         
534             if( start < keys.length && keys[start] !=null){
535                 if(obj instanceof Object JavaDoc[][]){
536                     obj = findResourceWithFallback((Object JavaDoc[][])obj,keys[start]);
537                 }else if(obj instanceof Object JavaDoc[] && isIndex(keys[start])){
538                     obj = ((Object JavaDoc[])obj)[getIndex(keys[start])];
539                 }
540                 if(start+1 < keys.length && keys[start+1] !=null){
541                     obj = findResourceWithFallback(obj,keys,start+1, index);
542                 }
543             }else{
544                 //try to find the corresponding index resource
545
if(index>=0){
546                     if(obj instanceof Object JavaDoc[][]){
547                         obj = findResourceWithFallback((Object JavaDoc[][])obj,
548                                                         Integer.toString(index));
549                     }else if(obj instanceof Object JavaDoc[]){
550                         obj = ((Object JavaDoc[])obj)[index];
551                     }
552                 }
553             }
554
555         return obj;
556     }
557     
558     private Object JavaDoc findResourceWithFallback(Object JavaDoc[][] cnts, String JavaDoc key){
559         Object JavaDoc obj = null;
560
561         for (int i = 0; i < cnts.length; ++i) {
562             // key must be non-null String
563
String JavaDoc tempKey = (String JavaDoc) cnts[i][0];
564             obj = cnts[i][1];
565             if(tempKey != null && tempKey.equals(key)){
566                 return obj;
567             }
568         }
569
570         return null;
571     }
572     
573     private final Object JavaDoc getObject(String JavaDoc key,
574                                    ICUListResourceBundle actualBundle) {
575         Object JavaDoc obj = handleGetObject(key);
576         if (obj == null) {
577             ICUListResourceBundle p = (ICUListResourceBundle) this.parent;
578             while( p!=null){
579                 obj = p.handleGetObject(key);
580                 if(obj != null){
581                     actualBundle = p;
582                     break;
583                 }
584                 p = (ICUListResourceBundle) p.parent;
585             }
586         }
587         return obj;
588     }
589     private static boolean isIndex(String JavaDoc s){
590          if(s.length()==1){
591             char c = s.charAt(0);
592             return Character.isDigit(c);
593          }
594          return false;
595     }
596     private static int getIndex(String JavaDoc s){
597          if(s.length()==1){
598             char c = s.charAt(0);
599             if(Character.isDigit(c)){
600               return Integer.valueOf(s).intValue();
601             }
602          }
603          return -1;
604     }
605 }
606
607
Popular Tags