001: //##header
002: /*
003: ******************************************************************************
004: * Copyright (C) 2004-2006, International Business Machines Corporation and *
005: * others. All Rights Reserved. *
006: ******************************************************************************
007: */
008: package com.ibm.icu.impl;
009:
010: import java.util.HashMap;
011: import java.util.MissingResourceException;
012: import java.util.ResourceBundle;
013:
014: import com.ibm.icu.util.StringTokenizer;
015: import com.ibm.icu.util.ULocale;
016: import com.ibm.icu.util.UResourceBundle;
017: import com.ibm.icu.util.UResourceTypeMismatchException;
018:
019: //#ifndef FOUNDATION
020: import java.nio.ByteBuffer;
021:
022: //#endif
023:
024: /**
025: * @author ram
026: */
027: public class ICUResourceBundleImpl extends ICUResourceBundle {
028: //protected byte[] version;
029: private byte[] rawData;
030: private long rootResource;
031: private boolean noFallback;
032:
033: private String localeID;
034: private String baseName;
035: private ULocale ulocale;
036: private ClassLoader loader;
037:
038: private static final boolean ASSERT = false;
039:
040: /**
041: *
042: * @param baseName
043: * @param localeID
044: * @param root
045: * @return the new bundle
046: */
047: public static ICUResourceBundle createBundle(String baseName,
048: String localeID, ClassLoader root) {
049:
050: ICUResourceBundleReader reader = ICUResourceBundleReader
051: .getReader(baseName, localeID, root);
052:
053: // could not open the .res file so return null
054: if (reader == null) {
055: return null;
056: }
057:
058: ICUResourceBundleImpl bundle = new ICUResourceBundleImpl(
059: reader, baseName, localeID, root);
060: return bundle.getBundle();
061: }
062:
063: protected String getLocaleID() {
064: return localeID;
065: }
066:
067: protected String getBaseName() {
068: return baseName;
069: }
070:
071: public ULocale getULocale() {
072: return ulocale;
073: }
074:
075: public UResourceBundle getParent() {
076: return (UResourceBundle) parent;
077: }
078:
079: protected void setParent(ResourceBundle parent) {
080: this .parent = parent;
081: }
082:
083: /**
084: * Get the noFallback flag specified in the loaded bundle.
085: * @return The noFallback flag.
086: */
087: protected boolean getNoFallback() {
088: return noFallback;
089: }
090:
091: private ICUResourceBundle getBundle() {
092: int type = RES_GET_TYPE(rootResource);
093: if (type == TABLE) {
094: ResourceTable table = new ResourceTable(null, rootResource,
095: "", true);
096: if (table.size == 1) {
097: ICUResourceBundle b = table.handleGet(0, table);
098: String itemKey = b.getKey();
099:
100: // %%ALIAS is such a hack!
101: if (itemKey.equals("%%ALIAS")) {
102: String locale = b.getString();
103: ICUResourceBundle actual = (ICUResourceBundle) UResourceBundle
104: .getBundleInstance(baseName, locale);
105: return (ResourceTable) actual;
106: } else {
107: return table;
108: }
109: } else {
110: return table;
111: }
112: } else if (type == TABLE32) {
113:
114: // genrb does not generate Table32 with %%ALIAS
115: return new ResourceTable32(null, rootResource, "", true);
116: } else {
117: throw new IllegalStateException("Invalid format error");
118: }
119: }
120:
121: private ICUResourceBundleImpl(ICUResourceBundleReader reader,
122: String baseName, String localeID, ClassLoader loader) {
123: this .rawData = reader.getData();
124: this .rootResource = (UNSIGNED_INT_MASK)
125: & reader.getRootResource();
126: this .noFallback = reader.getNoFallback();
127: this .baseName = baseName;
128: this .localeID = localeID;
129: this .ulocale = new ULocale(localeID);
130: this .loader = loader;
131: }
132:
133: static final int RES_GET_TYPE(long res) {
134: return (int) ((res) >> 28L);
135: }
136:
137: private static final int RES_GET_OFFSET(long res) {
138: return (int) ((res & 0x0fffffff) * 4);
139: }
140:
141: /* get signed and unsigned integer values directly from the Resource handle */
142: private static final int RES_GET_INT(long res) {
143: return (((int) ((res) << 4L)) >> 4L);
144: }
145:
146: private static final long RES_GET_UINT(long res) {
147: long t = ((res) & 0x0fffffffL);
148: return t;
149: }
150:
151: private static final StringBuffer RES_GET_KEY(byte[] rawData,
152: int keyOffset) {
153: char ch = 0xFFFF; //sentinel
154: StringBuffer key = new StringBuffer();
155: while ((ch = (char) rawData[keyOffset]) != 0) {
156: key.append(ch);
157: keyOffset++;
158: }
159: return key;
160: }
161:
162: private static final int getIntOffset(int offset) {
163: return (offset * 4);
164: }
165:
166: private static final int getCharOffset(int offset) {
167: return (offset * 2);
168: }
169:
170: private final ICUResourceBundle createBundleObject(String key,
171: long resource, String resPath, HashMap table,
172: ICUResourceBundle requested) {
173: //if (resource != RES_BOGUS) {
174: switch (RES_GET_TYPE(resource)) {
175: case STRING: {
176: return new ResourceString(key, resPath, resource);
177: }
178: case BINARY: {
179: return new ResourceBinary(key, resPath, resource);
180: }
181: case ALIAS: {
182: return findResource(key, resource, table, requested);
183: }
184: case INT: {
185: return new ResourceInt(key, resPath, resource);
186: }
187: case INT_VECTOR: {
188: return new ResourceIntVector(key, resPath, resource);
189: }
190: case ARRAY: {
191: return new ResourceArray(key, resPath, resource);
192: }
193: case TABLE32: {
194: return new ResourceTable32(key, resPath, resource);
195: }
196: case TABLE: {
197: return new ResourceTable(key, resPath, resource);
198: }
199: default:
200: throw new IllegalStateException(
201: "The resource type is unknown");
202: }
203: //}
204: //return null;
205: }
206:
207: private int findKey(int size, int currentOffset, Resource res,
208: String target) {
209: int mid = 0, start = 0, limit = size, rc;
210: int lastMid = -1;
211: //int myCharOffset = 0, keyOffset = 0;
212: for (;;) {
213: mid = ((start + limit) / 2);
214: if (lastMid == mid) { /* Have we moved? */
215: break; /* We haven't moved, and it wasn't found. */
216: }
217: lastMid = mid;
218: String comp = res.getKey(currentOffset, mid);
219: rc = target.compareTo(comp);
220: if (rc < 0) {
221: limit = mid;
222: } else if (rc > 0) {
223: start = mid;
224: } else {
225: return mid;
226: }
227: }
228: return -1;
229: }
230:
231: private interface Resource {
232: public String getKey(int currentOfset, int index);
233: }
234:
235: private class ResourceTable extends ICUResourceBundle implements
236: Resource {
237:
238: protected ICUResourceBundle handleGet(String key,
239: ICUResourceBundle requested) {
240: return handleGet(key, null, requested);
241: }
242:
243: protected ICUResourceBundle handleGet(String key,
244: HashMap table, ICUResourceBundle requested) {
245: if (size <= 0) {
246: return null;
247: }
248: int offset = RES_GET_OFFSET(resource);
249: // offset+0 contains number of entries
250: // offset+1 contains the keyOffset
251: int currentOffset = (offset) + getCharOffset(1);
252: //int keyOffset = rawData.getChar(currentOffset);
253: /* do a binary search for the key */
254: int foundOffset = findKey(size, currentOffset, this , key);
255: if (foundOffset == -1) {
256: //throw new MissingResourceException(ICUResourceBundleReader.getFullName(baseName, localeID),
257: // localeID,
258: // key);
259: return null;
260: }
261: currentOffset += getCharOffset(size + (~size & 1))
262: + getIntOffset(foundOffset);
263: long resource = (UNSIGNED_INT_MASK)
264: & ICUResourceBundleImpl.getInt(rawData,
265: currentOffset);
266: String path = (isTopLevel == true) ? key : resPath + "/"
267: + key;
268: return createBundleObject(key, resource, path, table,
269: requested);
270: }
271:
272: protected ICUResourceBundle handleGet(int index,
273: ICUResourceBundle requested) {
274: return handleGet(index, null, requested);
275: }
276:
277: public String getKey(int currentOffset, int index) {
278: int charOffset = currentOffset + getCharOffset(index);
279: int keyOffset = getChar(rawData, charOffset);
280: return RES_GET_KEY(rawData, keyOffset).toString();
281: }
282:
283: protected ICUResourceBundle handleGet(int index, HashMap table,
284: ICUResourceBundle requested) {
285: if (index > size) {
286: throw new IndexOutOfBoundsException();
287: }
288: int offset = RES_GET_OFFSET(resource);
289: // offset+0 contains number of entries
290: // offset+1 contains the keyOffset
291: int currentOffset = (offset) + getCharOffset(1);
292: String itemKey = getKey(currentOffset, index);
293: currentOffset += getCharOffset(size + (~size & 1))
294: + getIntOffset(index);
295: long resource = (UNSIGNED_INT_MASK)
296: & ICUResourceBundleImpl.getInt(rawData,
297: currentOffset);
298: String path = (isTopLevel == true) ? Integer
299: .toString(index) : resPath + "/" + index;
300: return createBundleObject(itemKey, resource, path, table,
301: requested);
302: }
303:
304: private int countItems() {
305: int offset = RES_GET_OFFSET(resource);
306: int value = getChar(rawData, offset);
307: return value;
308: }
309:
310: private ResourceTable(String key, String resPath, long resource) {
311: this (key, resource, resPath, false);
312: }
313:
314: private ResourceTable(String key, long resource,
315: String resPath, boolean isTopLevel) {
316: this .key = key;
317: this .resource = resource;
318: this .isTopLevel = isTopLevel;
319: this .size = countItems();
320: this .resPath = resPath;
321: }
322:
323: protected String getLocaleID() {
324: return localeID;
325: }
326:
327: protected String getBaseName() {
328: return baseName;
329: }
330:
331: public ULocale getULocale() {
332: return ulocale;
333: }
334:
335: public UResourceBundle getParent() {
336: return ICUResourceBundleImpl.this .getParent();
337: }
338:
339: protected void setParent(ResourceBundle parent) {
340: ICUResourceBundleImpl.this .setParent(parent);
341: }
342: }
343:
344: private class ResourceTable32 extends ICUResourceBundle implements
345: Resource {
346:
347: protected ICUResourceBundle handleGet(String key,
348: ICUResourceBundle requested) {
349: if (size <= 0) {
350: return null;
351: }
352: return handleGet(key, null, requested);
353: }
354:
355: protected ICUResourceBundle handleGet(String key,
356: HashMap table, ICUResourceBundle requested) {
357: int offset = RES_GET_OFFSET(resource);
358: // offset+0 contains number of entries
359: // offset+1 contains the keyOffset
360: int currentOffset = (offset) + getIntOffset(1);
361: //int keyOffset = rawData.getChar(currentOffset);
362: /* do a binary search for the key */
363: int foundOffset = findKey(size, currentOffset, this , key);
364: if (foundOffset == -1) {
365: throw new MissingResourceException(
366: "Could not find resource ",
367: ICUResourceBundleReader.getFullName(baseName,
368: localeID), key);
369: }
370: currentOffset += getIntOffset(size)
371: + getIntOffset(foundOffset);
372: long resource = (UNSIGNED_INT_MASK)
373: & ICUResourceBundleImpl.getInt(rawData,
374: currentOffset);
375: String path = (isTopLevel == true) ? key : resPath + "/"
376: + key;
377: return createBundleObject(key, resource, path, table,
378: requested);
379: }
380:
381: protected ICUResourceBundle handleGet(int index,
382: ICUResourceBundle requested) {
383: return handleGet(index, null, requested);
384: }
385:
386: public String getKey(int currentOffset, int index) {
387: int charOffset = currentOffset + getIntOffset(index);
388: int keyOffset = ICUResourceBundleImpl.getInt(rawData,
389: charOffset);
390: return RES_GET_KEY(rawData, keyOffset).toString();
391: }
392:
393: protected ICUResourceBundle handleGet(int index, HashMap table,
394: ICUResourceBundle requested) {
395: if (index > size) {
396: throw new IndexOutOfBoundsException();
397: }
398: int offset = RES_GET_OFFSET(resource);
399: // offset+0 contains number of entries
400: // offset+1 contains the keyOffset
401: int currentOffset = (offset) + getIntOffset(1)
402: + getIntOffset(index);
403: String itemKey = getKey(currentOffset, 0);
404: currentOffset += getIntOffset(size);
405: long resource = (UNSIGNED_INT_MASK)
406: & ICUResourceBundleImpl.getInt(rawData,
407: currentOffset);
408: String path = (isTopLevel == true) ? Integer
409: .toString(index) : resPath + "/" + index;
410: return createBundleObject(itemKey, resource, path, table,
411: requested);
412: }
413:
414: private int countItems() {
415: int offset = RES_GET_OFFSET(resource);
416: int value = ICUResourceBundleImpl.getInt(rawData, offset);
417: return value;
418: }
419:
420: private ResourceTable32(String key, long resource,
421: String resPath, boolean isTopLevel) {
422: this .resource = resource;
423: this .key = key;
424: this .isTopLevel = isTopLevel;
425: this .size = countItems();
426: this .resPath = resPath;
427: }
428:
429: private ResourceTable32(String key, String resPath,
430: long resource) {
431: this (key, resource, resPath, false);
432: }
433:
434: protected String getLocaleID() {
435: return localeID;
436: }
437:
438: protected String getBaseName() {
439: return baseName;
440: }
441:
442: public ULocale getULocale() {
443: return ulocale;
444: }
445:
446: public UResourceBundle getParent() {
447: return ICUResourceBundleImpl.this .getParent();
448: }
449:
450: protected void setParent(ResourceBundle parent) {
451: ICUResourceBundleImpl.this .setParent(parent);
452: }
453:
454: }
455:
456: private class ResourceString extends ICUResourceBundle {
457: private String value;
458:
459: public String getString() {
460: return value;
461: }
462:
463: private ResourceString(String key, String resPath, long resource) {
464: value = getStringValue(resource);
465: this .key = key;
466: this .resource = resource;
467: this .resPath = resPath;
468: }
469:
470: protected String getLocaleID() {
471: return localeID;
472: }
473:
474: protected String getBaseName() {
475: return baseName;
476: }
477:
478: public ULocale getULocale() {
479: return ulocale;
480: }
481:
482: public UResourceBundle getParent() {
483: return ICUResourceBundleImpl.this .getParent();
484: }
485: }
486:
487: private class ResourceInt extends ICUResourceBundle {
488: public int getInt() {
489: return RES_GET_INT(resource);
490: }
491:
492: public int getUInt() {
493: long ret = RES_GET_UINT(resource);
494: return (int) ret;
495: }
496:
497: private ResourceInt(String key, String resPath, long resource) {
498: this .key = key;
499: this .resource = resource;
500: this .resPath = resPath;
501: }
502:
503: protected String getLocaleID() {
504: return localeID;
505: }
506:
507: protected String getBaseName() {
508: return baseName;
509: }
510:
511: public ULocale getULocale() {
512: return ulocale;
513: }
514:
515: public UResourceBundle getParent() {
516: return ICUResourceBundleImpl.this .getParent();
517: }
518: }
519:
520: private class ResourceArray extends ICUResourceBundle {
521: protected String[] handleGetStringArray() {
522: String[] strings = new String[size];
523: ICUResourceBundleIterator iter = getIterator();
524: int i = 0;
525: while (iter.hasNext()) {
526: strings[i++] = iter.next().getString();
527: }
528: return strings;
529: }
530:
531: /**
532: * @internal ICU 3.0
533: */
534: public String[] getStringArray() {
535: return handleGetStringArray();
536: }
537:
538: protected ICUResourceBundle handleGet(String index,
539: ICUResourceBundle requested) {
540: return handleGet(index, null, requested);
541: }
542:
543: protected ICUResourceBundle handleGet(String index,
544: HashMap table, ICUResourceBundle requested) {
545: int val = getIndex(index);
546: if (val > -1) {
547: return handleGet(val, table, requested);
548: }
549: throw new UResourceTypeMismatchException(
550: "Could not get the correct value for index: "
551: + index);
552: }
553:
554: protected ICUResourceBundle handleGet(int index,
555: ICUResourceBundle requested) {
556: return handleGet(index, null, requested);
557: }
558:
559: protected ICUResourceBundle handleGet(int index, HashMap table,
560: ICUResourceBundle requested) {
561: if (index > size) {
562: throw new IndexOutOfBoundsException();
563: }
564: int offset = RES_GET_OFFSET(resource);
565: int itemOffset = offset + getIntOffset(index + 1);
566: long itemResource = (UNSIGNED_INT_MASK)
567: & ICUResourceBundleImpl.getInt(rawData, itemOffset);
568: String path = (isTopLevel == true) ? Integer
569: .toString(index) : resPath + "/" + index;
570: return createBundleObject(null, itemResource, path, table,
571: requested);
572: }
573:
574: private int countItems() {
575: int offset = RES_GET_OFFSET(resource);
576: int value = ICUResourceBundleImpl.getInt(rawData, offset);
577: return value;
578: }
579:
580: private ResourceArray(String key, String resPath, long resource) {
581: this .resource = resource;
582: this .key = key;
583: this .size = countItems();
584: this .resPath = resPath;
585: }
586:
587: protected String getLocaleID() {
588: return localeID;
589: }
590:
591: protected String getBaseName() {
592: return baseName;
593: }
594:
595: public ULocale getULocale() {
596: return ulocale;
597: }
598:
599: public UResourceBundle getParent() {
600: return ICUResourceBundleImpl.this .getParent();
601: }
602: }
603:
604: private static char makeChar(byte b1, byte b0) {
605: return (char) ((b1 << 8) | (b0 & 0xff));
606: }
607:
608: private static char getChar(byte[] data, int offset) {
609: return makeChar(data[offset], data[offset + 1]);
610: }
611:
612: private static int makeInt(byte b3, byte b2, byte b1, byte b0) {
613: return (int) ((((b3 & 0xff) << 24) | ((b2 & 0xff) << 16)
614: | ((b1 & 0xff) << 8) | ((b0 & 0xff) << 0)));
615: }
616:
617: private static int getInt(byte[] data, int offset) {
618: if (ASSERT)
619: Assert.assrt("offset < data.length", offset < data.length);
620: return makeInt(data[offset], data[offset + 1],
621: data[offset + 2], data[offset + 3]);
622: }
623:
624: private class ResourceBinary extends ICUResourceBundle {
625: private byte[] value;
626:
627: public ByteBuffer getBinary() {
628: return ByteBuffer.wrap(value);
629: }
630:
631: public byte[] getBinary(byte[] ba) {
632: return value;
633: }
634:
635: private byte[] getValue() {
636: int offset = RES_GET_OFFSET(resource);
637: int length = ICUResourceBundleImpl.getInt(rawData, offset);
638: int byteOffset = offset + getIntOffset(1);
639: byte[] dst = new byte[length];
640: if (ASSERT)
641: Assert.assrt("byteOffset+length < rawData.length",
642: byteOffset + length < rawData.length);
643: System.arraycopy(rawData, byteOffset, dst, 0, length);
644: return dst;
645: }
646:
647: public ResourceBinary(String key, String resPath, long resource) {
648: this .resource = resource;
649: this .key = key;
650: this .resPath = resPath;
651: value = getValue();
652: }
653:
654: protected String getLocaleID() {
655: return localeID;
656: }
657:
658: protected String getBaseName() {
659: return baseName;
660: }
661:
662: public ULocale getULocale() {
663: return ulocale;
664: }
665:
666: public UResourceBundle getParent() {
667: return ICUResourceBundleImpl.this .getParent();
668: }
669: }
670:
671: private class ResourceIntVector extends ICUResourceBundle {
672: private int[] value;
673:
674: public int[] getIntVector() {
675: return value;
676: }
677:
678: private int[] getValue() {
679: int offset = RES_GET_OFFSET(resource);
680: int length = ICUResourceBundleImpl.getInt(rawData, offset);
681: int intOffset = offset + getIntOffset(1);
682: int[] val = new int[length];
683: int byteLength = getIntOffset(length);
684:
685: if (ASSERT)
686: Assert.assrt("(intOffset+byteLength)<rawData.length",
687: (intOffset + byteLength) < rawData.length);
688:
689: for (int i = 0; i < length; i++) {
690: val[i] = ICUResourceBundleImpl.getInt(rawData,
691: intOffset + getIntOffset(i));
692: }
693: return val;
694: }
695:
696: public ResourceIntVector(String key, String resPath,
697: long resource) {
698: this .key = key;
699: this .resource = resource;
700: this .size = 1;
701: this .resPath = resPath;
702: value = getValue();
703: }
704:
705: protected String getLocaleID() {
706: return localeID;
707: }
708:
709: protected String getBaseName() {
710: return baseName;
711: }
712:
713: public ULocale getULocale() {
714: return ulocale;
715: }
716:
717: public UResourceBundle getParent() {
718: return ICUResourceBundleImpl.this .getParent();
719: }
720: }
721:
722: private String getStringValue(long resource) {
723: if (resource == 0) {
724: /*
725: * The data structure is documented as supporting resource==0 for empty strings.
726: * Return a fixed pointer in such a case.
727: * This was dropped in uresdata.c 1.17 as part of Jitterbug 1005 work
728: * on code coverage for ICU 2.0.
729: * Re-added for consistency with the design and with other code.
730: */
731: return "";
732: }
733: int offset = RES_GET_OFFSET(resource);
734: int length = getInt(rawData, offset);
735: int stringOffset = offset + getIntOffset(1);
736: char[] dst = new char[length];
737: if (ASSERT)
738: Assert
739: .assrt(
740: "(stringOffset+getCharOffset(length)) < rawData.length",
741: (stringOffset + getCharOffset(length)) < rawData.length);
742: for (int i = 0; i < length; i++) {
743: dst[i] = getChar(rawData, stringOffset + getCharOffset(i));
744: }
745: return new String(dst);
746: }
747:
748: private static final char RES_PATH_SEP_CHAR = '/';
749: private static final String RES_PATH_SEP_STR = "/";
750: private static final String ICUDATA = "ICUDATA";
751: private static final char HYPHEN = '-';
752: private static final String LOCALE = "LOCALE";
753:
754: private static final int getIndex(String s) {
755: if (s.length() >= 1) {
756: return Integer.valueOf(s).intValue();
757: }
758: return -1;
759: }
760:
761: private ICUResourceBundle findResource(String key, long resource,
762: HashMap table, ICUResourceBundle requested) {
763: ClassLoader loaderToUse = loader;
764: String locale = null, keyPath = null;
765: String bundleName;
766: String resPath = getStringValue(resource);
767: if (table == null) {
768: table = new HashMap();
769: }
770: if (table.get(resPath) != null) {
771: throw new IllegalArgumentException(
772: "Circular references in the resource bundles");
773: }
774: table.put(resPath, "");
775: if (resPath.indexOf(RES_PATH_SEP_CHAR) == 0) {
776: int i = resPath.indexOf(RES_PATH_SEP_CHAR, 1);
777: int j = resPath.indexOf(RES_PATH_SEP_CHAR, i + 1);
778: bundleName = resPath.substring(1, i);
779: locale = resPath.substring(i + 1);
780: if (j != -1) {
781: locale = resPath.substring(i + 1, j);
782: keyPath = resPath.substring(j + 1, resPath.length());
783: }
784: //there is a path included
785: if (bundleName.equals(ICUDATA)) {
786: bundleName = ICU_BASE_NAME;
787: loaderToUse = ICU_DATA_CLASS_LOADER;
788: } else if (bundleName.indexOf(ICUDATA) > -1) {
789: int idx = bundleName.indexOf(HYPHEN);
790: if (idx > -1) {
791: bundleName = ICU_BASE_NAME
792: + RES_PATH_SEP_STR
793: + bundleName.substring(idx + 1, bundleName
794: .length());
795: loaderToUse = ICU_DATA_CLASS_LOADER;
796: }
797: }
798: } else {
799: //no path start with locale
800: int i = resPath.indexOf(RES_PATH_SEP_CHAR);
801: keyPath = resPath.substring(i + 1);
802: if (i != -1) {
803: locale = resPath.substring(0, i);
804: } else {
805: locale = keyPath;
806: keyPath = null;//keyPath.substring(i, keyPath.length());
807: }
808: bundleName = baseName;
809: }
810: ICUResourceBundle bundle = null;
811: ICUResourceBundle sub = null;
812: if (bundleName.equals(LOCALE)) {
813: bundleName = baseName;
814: bundle = requested;
815: keyPath = resPath
816: .substring(
817: LOCALE.length() + 2/* prepending and appending / */,
818: resPath.length());
819: locale = requested.getLocaleID();
820: sub = ICUResourceBundle.findResourceWithFallback(keyPath,
821: requested, null);
822: sub.resPath = "/" + sub.getLocaleID() + "/" + keyPath;
823: } else {
824: if (locale == null) {
825: // {dlf} must use requestor's class loader to get resources from same jar
826: bundle = (ICUResourceBundle) getBundleInstance(
827: bundleName, "", loaderToUse, false);
828: } else {
829: bundle = (ICUResourceBundle) getBundleInstance(
830: bundleName, locale, loaderToUse, false);
831: }
832: if (keyPath != null) {
833: StringTokenizer st = new StringTokenizer(keyPath, "/");
834: ICUResourceBundle current = bundle;
835: while (st.hasMoreTokens()) {
836: String subKey = st.nextToken();
837: sub = current.getImpl(subKey, table, requested);
838: if (sub == null) {
839: break;
840: }
841: current = sub;
842: }
843: } else {
844: // if the sub resource is not found
845: // try fetching the sub resource with
846: // the key of this alias resource
847: sub = bundle.get(key);
848: }
849: sub.resPath = resPath;
850: }
851: if (sub == null) {
852: throw new MissingResourceException(localeID, baseName, key);
853: }
854: return sub;
855: }
856: }
|