OSDN Git Service

AI 145650: am: CL 145613 am: CL 145289 Fixes for tests in the text module.
[android-x86/dalvik.git] / libcore / icu / src / main / native / ResourceInterface.cpp
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "JNIHelp.h"
18 #include "AndroidSystemNatives.h"
19 #include "unicode/numfmt.h"
20 #include "unicode/locid.h"
21 #include "unicode/ucal.h"
22 #include "unicode/gregocal.h"
23 #include "unicode/ucurr.h"
24 #include "unicode/calendar.h"
25 #include "unicode/datefmt.h"
26 #include "unicode/dtfmtsym.h"
27 #include "unicode/decimfmt.h"
28 #include "unicode/dcfmtsym.h"
29 #include "unicode/uclean.h"
30 #include "unicode/smpdtfmt.h"
31 #include "unicode/strenum.h"
32 #include "unicode/ustring.h"
33 #include "unicode/timezone.h"
34 #include "ErrorCode.h"
35 #include <cutils/log.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <time.h>
39 #include <sys/time.h>
40
41 jclass string_class;
42
43 static UBool icuError(JNIEnv *env, UErrorCode errorcode)
44 {
45   const char   *emsg      = u_errorName(errorcode);
46         jclass  exception;
47
48   if (U_FAILURE(errorcode)) {
49     switch (errorcode) {
50       case U_ILLEGAL_ARGUMENT_ERROR :
51         exception = env->FindClass("java/lang/IllegalArgumentException");
52         break;
53       case U_INDEX_OUTOFBOUNDS_ERROR :
54       case U_BUFFER_OVERFLOW_ERROR :
55         exception = env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
56         break;
57       case U_UNSUPPORTED_ERROR :
58         exception = env->FindClass("java/lang/UnsupportedOperationException");
59         break;
60       default :
61         exception = env->FindClass("java/lang/RuntimeException");
62     }
63
64     return (env->ThrowNew(exception, emsg) != 0);
65   }
66   return 0;
67 }
68
69 static Locale getLocale(JNIEnv *env, jstring locale) {
70     const char *name = env->GetStringUTFChars(locale, NULL);
71     Locale result = Locale::createFromName(name);
72     env->ReleaseStringUTFChars(locale, name);
73     return result;
74 }
75
76 static jstring getJStringFromUnicodeString(JNIEnv *env, UnicodeString string) {
77     
78     UErrorCode status = U_ZERO_ERROR;
79
80     int stringLength = string.length();
81     jchar *res = (jchar *) malloc(sizeof(jchar) * (stringLength + 1));
82     string.extract(res, stringLength+1, status);
83     if(U_FAILURE(status)) {
84         free(res);
85         LOGI("Error getting string for getJStringFromUnicodeString");
86         status = U_ZERO_ERROR;
87         return NULL;
88     }
89     jstring result = env->NewString(res, stringLength);
90     free(res);
91     return result;
92 }
93
94 static void addObject(JNIEnv *env, jobjectArray result, const char *keyStr, jobject elem, int index) {
95     jclass objArray_class = env->FindClass("java/lang/Object");
96     jobjectArray element = env->NewObjectArray(2, objArray_class, NULL);
97     jstring key = env->NewStringUTF(keyStr);
98     env->SetObjectArrayElement(element, 0, key);
99     env->SetObjectArrayElement(element, 1, elem);
100     env->SetObjectArrayElement(result, index, element);
101     env->DeleteLocalRef(key);
102     env->DeleteLocalRef(element);
103
104
105 static jint getFractionDigitsNative(JNIEnv* env, jclass clazz, 
106         jstring currencyCode) {
107     // LOGI("ENTER getFractionDigitsNative");
108     
109     UErrorCode status = U_ZERO_ERROR;
110     
111     NumberFormat *fmt = NumberFormat::createCurrencyInstance(status);
112     if(U_FAILURE(status)) {
113         return -1;
114     }
115
116     const jchar *cCode = env->GetStringChars(currencyCode, NULL);
117     fmt->setCurrency(cCode, status);
118     env->ReleaseStringChars(currencyCode, cCode);
119     if(U_FAILURE(status)) {
120         return -1;
121     }
122     
123     // for CurrencyFormats the minimum and maximum fraction digits are the same.
124     int result = fmt->getMinimumFractionDigits(); 
125     delete(fmt);
126     return result;
127 }
128
129 static jstring getCurrencyCodeNative(JNIEnv* env, jclass clazz, 
130         jstring key) {
131     // LOGI("ENTER getCurrencyCodeNative");
132
133     UErrorCode status = U_ZERO_ERROR;
134
135     UResourceBundle *supplData = ures_openDirect(NULL, "supplementalData", &status);
136     if(U_FAILURE(status)) {
137         return NULL;
138     }
139
140     UResourceBundle *currencyMap = ures_getByKey(supplData, "CurrencyMap", NULL, &status);
141     if(U_FAILURE(status)) {
142         ures_close(supplData);
143         return NULL;
144     }
145
146     const char *keyChars = env->GetStringUTFChars(key, NULL);
147     UResourceBundle *currency = ures_getByKey(currencyMap, keyChars, NULL, &status);
148     env->ReleaseStringUTFChars(key, keyChars);
149     if(U_FAILURE(status)) {
150         ures_close(currencyMap);
151         ures_close(supplData);
152         return NULL;
153     }
154
155     UResourceBundle *currencyElem = ures_getByIndex(currency, 0, NULL, &status);
156     if(U_FAILURE(status)) {
157         ures_close(currency);
158         ures_close(currencyMap);
159         ures_close(supplData);
160         return env->NewStringUTF("None");
161     }
162
163     // check if there is a to date. If there is, the currency isn't used anymore.
164     UResourceBundle *currencyTo = ures_getByKey(currencyElem, "to", NULL, &status);
165     if(!U_FAILURE(status)) {
166         // return and let the ResourceBundle throw an exception
167         ures_close(currencyElem);
168         ures_close(currency);
169         ures_close(currencyMap);
170         ures_close(supplData);
171         return NULL;
172     }
173     status = U_ZERO_ERROR;
174     ures_close(currencyTo);
175
176     UResourceBundle *currencyId = ures_getByKey(currencyElem, "id", NULL, &status);
177     if(U_FAILURE(status)) {
178         // No id defined for this country
179         ures_close(currencyElem);
180         ures_close(currency);
181         ures_close(currencyMap);
182         ures_close(supplData);
183         return env->NewStringUTF("None");
184     }
185
186     int length;
187     const jchar *id = ures_getString(currencyId, &length, &status);
188     if(U_FAILURE(status)) {
189         ures_close(currencyId);
190         ures_close(currencyElem);
191         ures_close(currency);
192         ures_close(currencyMap);
193         ures_close(supplData);
194         return env->NewStringUTF("None");
195     }
196
197     ures_close(currencyId);
198     ures_close(currencyElem);
199     ures_close(currency);
200     ures_close(currencyMap);
201     ures_close(supplData);
202
203     if(length == 0) {
204         return env->NewStringUTF("None");
205     }
206     return env->NewString(id, length);
207 }
208
209 static jstring getCurrencySymbolNative(JNIEnv* env, jclass clazz, 
210         jstring locale, jstring currencyCode) {
211     // LOGI("ENTER getCurrencySymbolNative");
212
213     UErrorCode status = U_ZERO_ERROR;
214
215     const char *locName = env->GetStringUTFChars(locale, NULL);
216     UResourceBundle *root = ures_open(NULL, locName, &status);
217     env->ReleaseStringUTFChars(locale, locName);
218     if(U_FAILURE(status)) {
219         return NULL;
220     }
221
222     UResourceBundle *rootElems = ures_getByKey(root, "Currencies", NULL, &status);
223     if(U_FAILURE(status)) {
224         ures_close(root);
225         return NULL;
226     }
227
228     const char *currName = env->GetStringUTFChars(currencyCode, NULL);
229     UResourceBundle *currencyElems = ures_getByKey(rootElems, currName, NULL, &status);
230     env->ReleaseStringUTFChars(currencyCode, currName);
231     if(U_FAILURE(status)) {
232         ures_close(rootElems);
233         ures_close(root);
234         return NULL;
235     }
236
237     int currSymbL;
238     const jchar *currSymbU = ures_getStringByIndex(currencyElems, 0, &currSymbL, &status);
239     if(U_FAILURE(status)) {
240         ures_close(currencyElems);
241         ures_close(rootElems);
242         ures_close(root);
243         return NULL;
244     }
245
246     ures_close(currencyElems);
247     ures_close(rootElems);
248     ures_close(root);
249
250     if(currSymbL == 0) {
251         return NULL;
252     }
253     return env->NewString(currSymbU, currSymbL);
254 }
255
256 static jstring getDisplayCountryNative(JNIEnv* env, jclass clazz, 
257         jstring targetLocale, jstring locale) {
258     // LOGI("ENTER getDisplayCountryNative");
259     
260     UErrorCode status = U_ZERO_ERROR;
261
262     Locale loc = getLocale(env, locale);
263     Locale targetLoc = getLocale(env, targetLocale);
264     
265     UnicodeString string;
266     targetLoc.getDisplayCountry(loc, string);
267
268     jstring result = getJStringFromUnicodeString(env, string);
269
270     return result;
271 }
272
273 static jstring getDisplayLanguageNative(JNIEnv* env, jclass clazz, 
274         jstring targetLocale, jstring locale) {
275     // LOGI("ENTER getDisplayLanguageNative");
276
277     Locale loc = getLocale(env, locale);
278     Locale targetLoc = getLocale(env, targetLocale);
279
280     UnicodeString string;
281     targetLoc.getDisplayLanguage(loc, string);
282     
283     jstring result = getJStringFromUnicodeString(env, string);
284     
285     return result;
286 }
287
288 static jstring getDisplayVariantNative(JNIEnv* env, jclass clazz, 
289         jstring targetLocale, jstring locale) {
290     // LOGI("ENTER getDisplayVariantNative");
291
292     Locale loc = getLocale(env, locale);
293     Locale targetLoc = getLocale(env, targetLocale);
294     
295     UnicodeString string;
296     targetLoc.getDisplayVariant(loc, string);
297     
298     jstring result = getJStringFromUnicodeString(env, string);
299     
300     return result;
301 }
302
303 static jstring getISO3CountryNative(JNIEnv* env, jclass clazz, jstring locale) {
304     // LOGI("ENTER getISO3CountryNative");
305
306     Locale loc = getLocale(env, locale);
307     
308     const char *string = loc.getISO3Country();
309     
310     jstring result = env->NewStringUTF(string);
311     
312     return result;
313 }
314
315 static jstring getISO3LanguageNative(JNIEnv* env, jclass clazz, jstring locale) {
316     // LOGI("ENTER getISO3LanguageNative");
317
318     Locale loc = getLocale(env, locale);
319     
320     const char *string = loc.getISO3Language();
321     
322     jstring result = env->NewStringUTF(string);
323     
324     return result;
325 }
326
327 static jobjectArray getISOCountriesNative(JNIEnv* env, jclass clazz) {
328     // LOGI("ENTER getISOCountriesNative");
329
330     const char* const* strings = Locale::getISOCountries();
331     
332     int count = 0;
333     while(strings[count] != NULL) {
334         count++;
335     }
336   
337     jobjectArray result = env->NewObjectArray(count, string_class, NULL);
338
339     jstring res;
340     for(int i = 0; i < count; i++) {
341         res = env->NewStringUTF(strings[i]);
342         env->SetObjectArrayElement(result, i, res);
343         env->DeleteLocalRef(res);
344     }
345     return result;
346 }
347
348 static jobjectArray getISOLanguagesNative(JNIEnv* env, jclass clazz) {
349     // LOGI("ENTER getISOLanguagesNative");
350     
351     const char* const* strings = Locale::getISOLanguages();
352     
353     const char *string = strings[0];
354     
355     int count = 0;
356     while(strings[count] != NULL) {
357         count++;
358     }
359     
360     jobjectArray result = env->NewObjectArray(count, string_class, NULL);
361
362     jstring res;
363     for(int i = 0; i < count; i++) {
364         res = env->NewStringUTF(strings[i]);
365         env->SetObjectArrayElement(result, i, res);
366         env->DeleteLocalRef(res);
367     }
368     return result;
369 }
370
371 static jobjectArray getAvailableLocalesNative(JNIEnv* env, jclass clazz) {
372     // LOGI("ENTER getAvailableLocalesNative");
373     
374     int count = uloc_countAvailable();
375     
376     jobjectArray result = env->NewObjectArray(count, string_class, NULL);
377
378     jstring res;
379     const char * string;    
380     for(int i = 0; i < count; i++) {
381         string = uloc_getAvailable(i);
382         res = env->NewStringUTF(string);
383         env->SetObjectArrayElement(result, i, res);
384         env->DeleteLocalRef(res);
385     }
386
387     return result;
388 }
389
390 static void getTimeZonesNative(JNIEnv* env, jclass clazz,
391         jobjectArray outerArray, jstring locale) {
392     // LOGI("ENTER getTimeZonesNative");
393     
394     UErrorCode status = U_ZERO_ERROR;
395
396     jobjectArray zoneIdArray;
397     jobjectArray longStdTimeArray;
398     jobjectArray shortStdTimeArray;
399     jobjectArray longDlTimeArray;
400     jobjectArray shortDlTimeArray;
401
402     jstring content;
403     jstring strObj;
404     const jchar *res;
405     UnicodeString resU;
406     jint length;
407     const UnicodeString *zoneID;
408     DateFormat *df;
409
410     UnicodeString longPattern("zzzz","");
411     UnicodeString shortPattern("z","");
412       
413     Locale loc = getLocale(env, locale);
414
415     SimpleDateFormat longFormat(longPattern, loc, status);
416     SimpleDateFormat shortFormat(shortPattern, loc, status);
417
418
419     zoneIdArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 0);
420     longStdTimeArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 1);
421     shortStdTimeArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 2);
422     longDlTimeArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 3);
423     shortDlTimeArray = (jobjectArray) env->GetObjectArrayElement(outerArray, 4);
424
425     int count = env->GetArrayLength(zoneIdArray);
426
427     TimeZone* zones[count];
428     
429     // get all timezone objects
430     for(int i = 0; i < count; i++) {
431         strObj = (jstring) env->GetObjectArrayElement(zoneIdArray, i);
432         length = env->GetStringLength(strObj);
433         res = env->GetStringChars(strObj, NULL);
434         const UnicodeString zoneID((UChar *)res, length);
435         env->ReleaseStringChars(strObj, res);
436         zones[i] = TimeZone::createTimeZone(zoneID);
437         env->DeleteLocalRef(strObj);
438     }
439
440     // 15th January 2008
441     UDate date1 = 1203105600000.0;
442     // 15th July 2008
443     UDate date2 = 1218826800000.0;
444
445     for (int i = 0; i < count; i++) {
446            TimeZone *tz = zones[i];
447            longFormat.setTimeZone(*tz);
448            shortFormat.setTimeZone(*tz);
449            
450            int32_t daylightOffset;
451            int32_t rawOffset;
452            UDate standardDate;
453            UDate daylightSavingDate;
454            tz->getOffset(date1, false, rawOffset, daylightOffset, status);
455            if (daylightOffset != 0) {
456                // The Timezone is reporting that we are in daylight time
457                // for the winter date.  The dates are for the wrong hemisphere,
458                // swap them.
459                standardDate = date2;
460                daylightSavingDate = date1;
461            } else {
462                standardDate = date1;
463                daylightSavingDate = date2;
464            }
465                      
466            UnicodeString shortDayLight;
467            UnicodeString longDayLight;
468            UnicodeString shortStandard;
469            UnicodeString longStandard;
470            
471            shortFormat.format(daylightSavingDate, shortDayLight);
472            content = getJStringFromUnicodeString(env, shortDayLight);
473            env->SetObjectArrayElement(shortDlTimeArray, i, content);
474            env->DeleteLocalRef(content);
475
476            shortFormat.format(standardDate, shortStandard);
477            content = getJStringFromUnicodeString(env, shortStandard);
478            env->SetObjectArrayElement(shortStdTimeArray, i, content);
479            env->DeleteLocalRef(content);
480
481            longFormat.format (daylightSavingDate, longDayLight);
482            content = getJStringFromUnicodeString(env, longDayLight);
483            env->SetObjectArrayElement(longDlTimeArray, i, content);
484            env->DeleteLocalRef(content);
485
486            longFormat.format (standardDate, longStandard);
487            content = getJStringFromUnicodeString(env, longStandard);
488            env->SetObjectArrayElement(longStdTimeArray, i, content);
489            env->DeleteLocalRef(content);
490            delete(tz);
491     }
492 }
493
494
495
496
497 static jstring getDisplayTimeZoneNative(JNIEnv* env, jclass clazz,
498         jstring zoneID, jboolean isDST, jint style, jstring localeID) {
499
500     // Build TimeZone object
501     const jchar* idChars = env->GetStringChars(zoneID, NULL);
502     jint idLength = env->GetStringLength(zoneID);
503     UnicodeString idString((UChar*)idChars, idLength);
504     TimeZone* zone = TimeZone::createTimeZone(idString);
505     env->ReleaseStringChars(zoneID, idChars);
506
507     // Build Locale object (can we rely on zero termination of JNI result?)
508     const char* localeChars = env->GetStringUTFChars(localeID, NULL);
509     jint localeLength = env->GetStringLength(localeID);
510     Locale locale = Locale::createFromName(localeChars);
511
512     // Try to get the display name of the TimeZone according to the Locale
513     UnicodeString buffer;
514     zone->getDisplayName((UBool)isDST, (style == 0 ? TimeZone::SHORT : TimeZone::LONG), locale, buffer);
515     const UChar* tempChars = buffer.getBuffer();
516     int tempLength = buffer.length();
517     jstring result = env->NewString((jchar*)tempChars, tempLength);
518     env->ReleaseStringUTFChars(localeID, localeChars);
519
520     // Clean up everything
521     delete(zone);
522     
523     return result;
524 }
525
526 static void getDayInitVector(JNIEnv *env, UResourceBundle *gregorian, int *values) {
527
528     UErrorCode status = U_ZERO_ERROR;
529
530     // get the First day of week and the minimal days in first week numbers
531     UResourceBundle *gregorianElems = ures_getByKey(gregorian, "DateTimeElements", NULL, &status);
532     if(U_FAILURE(status)) {
533         return;
534     }
535
536     int intVectSize;
537     const int *result;
538     result = ures_getIntVector(gregorianElems, &intVectSize, &status);
539     if(U_FAILURE(status)) {
540         ures_close(gregorianElems);
541         return;
542     }
543
544     if(intVectSize == 2) {
545         values[0] = result[0];
546         values[1] = result[1];
547     }
548
549     ures_close(gregorianElems);
550
551 }
552
553 static jobjectArray getAmPmMarkers(JNIEnv *env, UResourceBundle *gregorian) {
554     
555     jobjectArray amPmMarkers;
556     jstring pmU, amU;
557
558     UErrorCode status = U_ZERO_ERROR;
559
560     UResourceBundle *gregorianElems;
561
562     gregorianElems = ures_getByKey(gregorian, "AmPmMarkers", NULL, &status);
563     if(U_FAILURE(status)) {
564         return NULL;
565     }
566
567     int lengthAm, lengthPm;
568
569     ures_resetIterator(gregorianElems);
570
571     const jchar* am = ures_getStringByIndex(gregorianElems, 0, &lengthAm, &status);
572     const jchar* pm = ures_getStringByIndex(gregorianElems, 1, &lengthPm, &status);
573
574     if(U_FAILURE(status)) {
575         ures_close(gregorianElems);
576         return NULL;
577     }
578     
579     amPmMarkers = env->NewObjectArray(2, string_class, NULL);
580     amU = env->NewString(am, lengthAm);
581     env->SetObjectArrayElement(amPmMarkers, 0, amU);
582     env->DeleteLocalRef(amU);
583     pmU = env->NewString(pm, lengthPm);
584     env->SetObjectArrayElement(amPmMarkers, 1, pmU);
585     env->DeleteLocalRef(pmU);
586     ures_close(gregorianElems);
587
588     return amPmMarkers;
589 }
590
591 static jobjectArray getEras(JNIEnv* env, UResourceBundle *gregorian) {
592     
593     jobjectArray eras;
594     jstring eraU;
595     const jchar* era;
596
597     UErrorCode status = U_ZERO_ERROR;
598
599     UResourceBundle *gregorianElems;
600     UResourceBundle *eraElems;
601
602     gregorianElems = ures_getByKey(gregorian, "eras", NULL, &status);
603     if(U_FAILURE(status)) {
604         return NULL;
605     }
606
607     eraElems = ures_getByKey(gregorianElems, "abbreviated", NULL, &status);
608     if(U_FAILURE(status)) {
609         ures_close(gregorianElems);
610         return NULL;
611     }
612
613     int eraLength;
614
615     int eraCount = ures_getSize(eraElems);
616     eras = env->NewObjectArray(eraCount, string_class, NULL);
617
618     ures_resetIterator(eraElems);
619     for(int i = 0; i < eraCount; i++) {
620         era = ures_getStringByIndex(eraElems, i, &eraLength, &status);
621         if(U_FAILURE(status)) {
622             ures_close(gregorianElems);
623             ures_close(eraElems);
624             return NULL;
625         }
626         eraU = env->NewString(era, eraLength);
627         env->SetObjectArrayElement(eras, i, eraU);
628         env->DeleteLocalRef(eraU);
629     }
630     ures_close(eraElems);
631     ures_close(gregorianElems);
632
633     return eras;
634 }
635
636 static jobjectArray getMonthNames(JNIEnv *env, UResourceBundle *gregorian) {
637     
638     UErrorCode status = U_ZERO_ERROR;
639
640     const jchar* month;
641     jstring monthU;
642
643     UResourceBundle *gregorianElems = ures_getByKey(gregorian, "monthNames", NULL, &status);
644     if(U_FAILURE(status)) {
645         return NULL;
646     }
647
648     UResourceBundle *monthNameElems = ures_getByKey(gregorianElems, "format", NULL, &status);
649     if(U_FAILURE(status)) {
650         ures_close(gregorianElems);
651         return NULL;
652     }
653
654     UResourceBundle *monthNameElemsFormat = ures_getByKey(monthNameElems, "wide", NULL, &status);
655     if(U_FAILURE(status)) {
656         ures_close(monthNameElems);
657         ures_close(gregorianElems);
658         return NULL;
659     }
660
661     int monthNameLength;
662     ures_resetIterator(monthNameElemsFormat);
663     int monthCount = ures_getSize(monthNameElemsFormat);
664     jobjectArray months = env->NewObjectArray(monthCount + 1, string_class, NULL);
665     for(int i = 0; i < monthCount; i++) {
666         month = ures_getStringByIndex(monthNameElemsFormat, i, &monthNameLength, &status);
667         if(U_FAILURE(status)) {
668             ures_close(monthNameElemsFormat);
669             ures_close(monthNameElems);
670             ures_close(gregorianElems);
671             return NULL;
672         }
673         monthU = env->NewString(month, monthNameLength);
674         env->SetObjectArrayElement(months, i, monthU);
675         env->DeleteLocalRef(monthU);
676     }
677
678     monthU = env->NewStringUTF("");
679     env->SetObjectArrayElement(months, monthCount, monthU);
680     env->DeleteLocalRef(monthU);
681
682     ures_close(monthNameElemsFormat);
683     ures_close(monthNameElems);
684     ures_close(gregorianElems);
685     return months;
686 }
687
688 static jobjectArray getShortMonthNames(JNIEnv *env, UResourceBundle *gregorian) {
689     
690     UErrorCode status = U_ZERO_ERROR;
691
692     const jchar* shortMonth;
693     jstring shortMonthU;
694
695     UResourceBundle *gregorianElems = ures_getByKey(gregorian, "monthNames", NULL, &status);
696     if(U_FAILURE(status)) {
697         return NULL;
698     }
699
700     UResourceBundle *monthNameElems = ures_getByKey(gregorianElems, "format", NULL, &status);
701     if(U_FAILURE(status)) {
702         ures_close(gregorianElems);
703         return NULL;
704     }
705
706     UResourceBundle *monthNameElemsFormat = ures_getByKey(monthNameElems, "abbreviated", NULL, &status);
707     if(U_FAILURE(status)) {
708         ures_close(monthNameElems);
709         ures_close(gregorianElems);
710         return NULL;
711     }
712
713     int shortMonthNameLength;
714     ures_resetIterator(monthNameElemsFormat);
715     int shortMonthCount = ures_getSize(monthNameElemsFormat);
716     // the array length is +1 because the harmony locales had an empty string at the end of their month name array
717     jobjectArray shortMonths = env->NewObjectArray(shortMonthCount + 1, string_class, NULL);
718     for(int i = 0; i < shortMonthCount; i++) {
719         shortMonth = ures_getStringByIndex(monthNameElemsFormat, i, &shortMonthNameLength, &status);
720         if(U_FAILURE(status)) {
721             ures_close(monthNameElemsFormat);
722             ures_close(monthNameElems);
723             ures_close(gregorianElems);
724             return NULL;
725         }
726         shortMonthU = env->NewString(shortMonth, shortMonthNameLength);
727         env->SetObjectArrayElement(shortMonths, i, shortMonthU);
728         env->DeleteLocalRef(shortMonthU);
729     }
730
731     shortMonthU = env->NewStringUTF("");
732     env->SetObjectArrayElement(shortMonths, shortMonthCount, shortMonthU);
733     env->DeleteLocalRef(shortMonthU);
734
735     ures_close(monthNameElemsFormat);
736     ures_close(monthNameElems);
737     ures_close(gregorianElems);
738     return shortMonths;
739 }
740
741 static jobjectArray getWeekdayNames(JNIEnv *env, UResourceBundle *gregorian) {
742     
743     UErrorCode status = U_ZERO_ERROR;
744
745     const jchar* day;
746     jstring dayU;
747
748     UResourceBundle *gregorianElems = ures_getByKey(gregorian, "dayNames", NULL, &status);
749     if(U_FAILURE(status)) {
750         return NULL;
751     }
752
753     UResourceBundle *dayNameElems = ures_getByKey(gregorianElems, "format", NULL, &status);
754     if(U_FAILURE(status)) {
755         ures_close(gregorianElems);
756         return NULL;
757     }
758
759     UResourceBundle *dayNameElemsFormat = ures_getByKey(dayNameElems, "wide", NULL, &status);
760     if(U_FAILURE(status)) {
761         ures_close(dayNameElems);
762         ures_close(gregorianElems);
763         return NULL;
764     }
765
766     int dayNameLength;
767     ures_resetIterator(dayNameElemsFormat);
768     int dayCount = ures_getSize(dayNameElemsFormat);
769     jobjectArray weekdays = env->NewObjectArray(dayCount + 1, string_class, NULL);
770     // first entry in the weekdays array is an empty string
771     env->SetObjectArrayElement(weekdays, 0, env->NewStringUTF(""));
772     for(int i = 0; i < dayCount; i++) {
773         day = ures_getStringByIndex(dayNameElemsFormat, i, &dayNameLength, &status);
774         if(U_FAILURE(status)) {
775             ures_close(dayNameElemsFormat);
776             ures_close(dayNameElems);
777             ures_close(gregorianElems);
778             return NULL;
779         }
780         dayU = env->NewString(day, dayNameLength);
781         env->SetObjectArrayElement(weekdays, i + 1, dayU);
782         env->DeleteLocalRef(dayU);
783     }
784     
785     ures_close(dayNameElemsFormat);
786     ures_close(dayNameElems);
787     ures_close(gregorianElems);
788     return weekdays;
789
790 }
791
792 static jobjectArray getShortWeekdayNames(JNIEnv *env, UResourceBundle *gregorian) {
793     
794     UErrorCode status = U_ZERO_ERROR;
795
796     const jchar* shortDay;
797     jstring shortDayU;
798
799     UResourceBundle *gregorianElems = ures_getByKey(gregorian, "dayNames", NULL, &status);
800     if(U_FAILURE(status)) {
801         return NULL;
802     }
803
804     UResourceBundle *dayNameElems = ures_getByKey(gregorianElems, "format", NULL, &status);
805     if(U_FAILURE(status)) {
806         ures_close(gregorianElems);
807         return NULL;
808     }
809
810     UResourceBundle *dayNameElemsFormat = ures_getByKey(dayNameElems, "abbreviated", NULL, &status);
811     if(U_FAILURE(status)) {
812         ures_close(dayNameElems);
813         ures_close(gregorianElems);
814         return NULL;
815     }
816
817     int shortDayNameLength;
818     ures_resetIterator(dayNameElemsFormat);
819     int shortDayCount = ures_getSize(dayNameElemsFormat);
820     jobjectArray shortWeekdays = env->NewObjectArray(shortDayCount + 1, string_class, NULL);
821     env->SetObjectArrayElement(shortWeekdays, 0, env->NewStringUTF(""));
822     for(int i = 0; i < shortDayCount; i++) {
823         shortDay = ures_getStringByIndex(dayNameElemsFormat, i, &shortDayNameLength, &status);
824         if(U_FAILURE(status)) {
825             ures_close(dayNameElemsFormat);
826             ures_close(dayNameElems);
827             ures_close(gregorianElems);
828             return NULL;
829         }
830         shortDayU = env->NewString(shortDay, shortDayNameLength);
831         env->SetObjectArrayElement(shortWeekdays, i + 1, shortDayU);
832         env->DeleteLocalRef(shortDayU);
833     }
834
835     ures_close(dayNameElemsFormat);
836     ures_close(dayNameElems);
837     ures_close(gregorianElems);
838     return shortWeekdays;
839 }
840
841 static jstring getDecimalPatternChars(JNIEnv *env, UResourceBundle *rootElems) {
842     
843     UErrorCode status = U_ZERO_ERROR;
844
845     int zeroL, digitL, decSepL, groupL, listL, percentL, permillL, expL, currSepL, minusL;
846     int patternLength;
847
848     jchar *patternChars;
849
850     const jchar* zero = ures_getStringByIndex(rootElems, 4, &zeroL, &status);
851
852     const jchar* digit = ures_getStringByIndex(rootElems, 5, &digitL, &status);
853
854     const jchar* decSep = ures_getStringByIndex(rootElems, 0, &decSepL, &status);
855
856     const jchar* group = ures_getStringByIndex(rootElems, 1, &groupL, &status);
857
858     const jchar* list = ures_getStringByIndex(rootElems, 2, &listL, &status);
859
860     const jchar* percent = ures_getStringByIndex(rootElems, 3, &percentL, &status);
861
862     const jchar* permill = ures_getStringByIndex(rootElems, 8, &permillL, &status);
863
864     const jchar* exp = ures_getStringByIndex(rootElems, 7, &expL, &status);
865
866     const jchar* currSep = ures_getStringByIndex(rootElems, 0, &currSepL, &status);
867
868     const jchar* minus = ures_getStringByIndex(rootElems, 6, &minusL, &status);
869
870     if(U_FAILURE(status)) {
871         return NULL;
872     }
873
874
875     patternChars = (jchar *) malloc(11 * sizeof(jchar));
876
877     patternChars[0] = 0;
878
879     u_strncat(patternChars, zero, 1);
880     u_strncat(patternChars, digit, 1);
881     u_strncat(patternChars, decSep, 1);
882     u_strncat(patternChars, group, 1);
883     u_strncat(patternChars, list, 1);
884     u_strncat(patternChars, percent, 1);
885     u_strncat(patternChars, permill, 1);
886     u_strncat(patternChars, exp, 1);
887     u_strncat(patternChars, currSep, 1);
888     u_strncat(patternChars, minus, 1);
889
890     jstring decimalPatternChars = env->NewString(patternChars, 10);
891
892     free(patternChars);
893
894     return decimalPatternChars;
895 }
896
897 static jstring getIntCurrencyCode(JNIEnv *env, jclass clazz, jstring locale) {
898
899     const char *locStr = env->GetStringUTFChars(locale, NULL);
900     char country[3] = {0,0,0};
901
902     // getting the 2 character country name
903     if(strlen(locStr) < 5) {
904         env->ReleaseStringUTFChars(locale, locStr);
905         return NULL;
906     }
907     if(locStr[3] < 'A' || locStr[3] > 'Z' || locStr[4] < 'A' || locStr[4] > 'Z') {
908         env->ReleaseStringUTFChars(locale, locStr);
909         return NULL;
910     }
911     country[0] = locStr[3];
912     country[1] = locStr[4];
913
914     env->ReleaseStringUTFChars(locale, locStr);
915
916     return getCurrencyCodeNative(env, clazz, env->NewStringUTF(country));
917 }
918
919 static jstring getCurrencySymbol(JNIEnv *env, jclass clazz, jstring locale, jstring intCurrencySymbol) {
920
921     jstring result = getCurrencySymbolNative(env, clazz, locale, intCurrencySymbol);
922     if(result == intCurrencySymbol) {
923         return NULL;
924     }
925     return result;
926
927 }
928
929 static jobjectArray getContentImpl(JNIEnv* env, jclass clazz, 
930         jstring locale, jboolean needsTZ) {
931     
932     UErrorCode status = U_ZERO_ERROR;
933
934     const char *loc = env->GetStringUTFChars(locale, NULL);
935     UResourceBundle *root = ures_openU(NULL, loc, &status);
936
937     env->ReleaseStringUTFChars(locale, loc);
938     if(U_FAILURE(status)) {
939         LOGI("Error getting resources");
940         status = U_ZERO_ERROR;
941         return NULL;
942     }
943
944
945
946     jclass obj_class = env->FindClass("java/lang/Object");
947     jclass integer_class = env->FindClass("java/lang/Integer");
948     jmethodID integerInit = env->GetMethodID(integer_class, "<init>", "(I)V");
949     jobjectArray result;
950
951     jobject firstDayOfWeek = NULL;
952     jobject minimalDaysInFirstWeek = NULL;
953     jobjectArray amPmMarkers = NULL;
954     jobjectArray eras = NULL;
955     jstring localPatternChars = NULL;
956     jobjectArray weekdays = NULL;
957     jobjectArray shortWeekdays = NULL;
958     jobjectArray months = NULL;
959     jobjectArray shortMonths = NULL;
960     jstring time_SHORT = NULL;
961     jstring time_MEDIUM = NULL;
962     jstring time_LONG = NULL;
963     jstring time_FULL = NULL;
964     jstring date_SHORT = NULL;
965     jstring date_MEDIUM = NULL;
966     jstring date_LONG = NULL;
967     jstring date_FULL = NULL;
968     jstring decimalPatternChars = NULL;
969     jstring naN = NULL;
970     jstring infinity = NULL;
971     jstring currencySymbol = NULL;
972     jstring intCurrencySymbol = NULL;
973     jstring numberPattern = NULL;
974     jstring integerPattern = NULL;
975     jstring currencyPattern = NULL;
976     jstring percentPattern = NULL;
977     jobjectArray zones = NULL;
978
979     int counter = 0;
980
981     int firstDayVals[2] = {-1, -1};
982
983     const jchar* nan = (const jchar *)NULL;
984     const jchar* inf = (const jchar *)NULL;
985     int nanL, infL;
986
987
988     UResourceBundle *gregorian;
989     UResourceBundle *gregorianElems;
990     UResourceBundle *rootElems;
991
992
993
994
995     // get the resources needed
996     rootElems = ures_getByKey(root, "calendar", NULL, &status);
997     if(U_FAILURE(status)) {
998         return NULL;
999     }
1000
1001     gregorian = ures_getByKey(rootElems, "gregorian", NULL, &status);
1002     if(U_FAILURE(status)) {
1003         ures_close(rootElems);
1004         return NULL;
1005     }
1006
1007
1008
1009     // adding the first day of week and minimal days in first week values
1010     getDayInitVector(env, gregorian, firstDayVals);
1011     if((firstDayVals[0] != -1) && (firstDayVals[1] != -1)) {
1012         firstDayOfWeek = env->NewObject(integer_class, integerInit, firstDayVals[0]);
1013         minimalDaysInFirstWeek = env->NewObject(integer_class, integerInit, firstDayVals[1]);
1014         // adding First_Day and Minimal_Days integer to the result
1015         counter += 2;
1016     }
1017
1018
1019     // adding ampm string array to the result");
1020     amPmMarkers = getAmPmMarkers(env, gregorian);
1021     if(amPmMarkers != NULL) {
1022         counter++;
1023     }
1024
1025
1026     // adding eras string array to the result
1027     eras = getEras(env, gregorian);
1028     if(eras != NULL) {
1029         counter++;
1030     }
1031
1032
1033     // local pattern chars are initially always the same
1034     localPatternChars = env->NewStringUTF("GyMdkHmsSEDFwWahKzZ");
1035     // adding local pattern chars string to the result
1036     counter++;
1037
1038
1039     // adding month names string array to the result
1040     months = getMonthNames(env, gregorian);
1041     if(months != NULL) {
1042         counter++;
1043     }
1044
1045
1046     // adding short month names string array to the result
1047     shortMonths = getShortMonthNames(env, gregorian);
1048     if(shortMonths != NULL) {
1049         counter++;
1050     }
1051
1052
1053     // adding day names string array to the result
1054     weekdays = getWeekdayNames(env, gregorian);
1055     if(weekdays != NULL) {
1056         counter++;
1057     }
1058
1059
1060     // adding short day names string array to the result
1061     shortWeekdays = getShortWeekdayNames(env, gregorian);
1062     if(shortWeekdays != NULL) {
1063         counter++;
1064     }
1065
1066     const UChar *pattern;
1067     jchar check[2] = {0, 0};
1068     u_uastrcpy(check, "v");
1069     jchar replacement[2] = {0, 0};
1070     u_uastrcpy(replacement, "z");
1071     jchar *pos;
1072     jchar *patternCopy;
1073     int patternLength;
1074
1075     // adding date and time format patterns to the result
1076     gregorianElems = ures_getByKey(gregorian, "DateTimePatterns", NULL, &status);
1077     if(U_FAILURE(status)) {
1078         status = U_ZERO_ERROR;
1079         goto endOfCalendar;
1080     }
1081
1082     pattern = ures_getStringByIndex(gregorianElems, 0, &patternLength, &status);
1083     // there are some patterns in icu that use the pattern character 'v'
1084     // java doesn't accept this, so it gets replaced by 'z' which has
1085     // about the same result as 'v', the timezone name. 
1086     // 'v' -> "PT", 'z' -> "PST", v is the generic timezone and z the standard tz
1087     // "vvvv" -> "Pacific Time", "zzzz" -> "Pacific Standard Time"
1088     patternCopy = (jchar *) malloc((patternLength + 1) * sizeof(jchar));
1089     u_strcpy(patternCopy, pattern);
1090     if(U_FAILURE(status)) {
1091         free(patternCopy);
1092         status = U_ZERO_ERROR;
1093         goto endOfCalendar;
1094     }
1095     while((pos = u_strchr(patternCopy, check[0])) != NULL) {
1096         u_memset(pos, replacement[0], 1);
1097     }
1098     time_FULL = env->NewString(patternCopy, patternLength);
1099     free(patternCopy);
1100     counter++;
1101
1102     pattern = ures_getStringByIndex(gregorianElems, 1, &patternLength, &status);
1103     if(U_FAILURE(status)) {
1104         status = U_ZERO_ERROR;
1105         goto endOfCalendar;
1106     }
1107     time_LONG = env->NewString(pattern, patternLength);
1108     counter++;
1109
1110     pattern = ures_getStringByIndex(gregorianElems, 2, &patternLength, &status);
1111     if(U_FAILURE(status)) {
1112         status = U_ZERO_ERROR;
1113         goto endOfCalendar;
1114     }
1115     time_MEDIUM = env->NewString(pattern, patternLength);
1116     counter++;
1117
1118     pattern = ures_getStringByIndex(gregorianElems, 3, &patternLength, &status);
1119     if(U_FAILURE(status)) {
1120         status = U_ZERO_ERROR;
1121         goto endOfCalendar;
1122     }
1123     time_SHORT = env->NewString(pattern, patternLength);
1124     counter++;
1125
1126     pattern = ures_getStringByIndex(gregorianElems, 4, &patternLength, &status);
1127     if(U_FAILURE(status)) {
1128         status = U_ZERO_ERROR;
1129         goto endOfCalendar;
1130     }
1131     date_FULL = env->NewString(pattern, patternLength);
1132     counter++;
1133
1134     pattern = ures_getStringByIndex(gregorianElems, 5, &patternLength, &status);
1135     if(U_FAILURE(status)) {
1136         status = U_ZERO_ERROR;
1137         goto endOfCalendar;
1138     }
1139     date_LONG = env->NewString(pattern, patternLength);
1140     counter++;
1141
1142     pattern = ures_getStringByIndex(gregorianElems, 6, &patternLength, &status);
1143     if(U_FAILURE(status)) {
1144         status = U_ZERO_ERROR;
1145         goto endOfCalendar;
1146     }
1147     date_MEDIUM = env->NewString(pattern, patternLength);
1148     counter++;
1149
1150     pattern = ures_getStringByIndex(gregorianElems, 7, &patternLength, &status);
1151     if(U_FAILURE(status)) {
1152         status = U_ZERO_ERROR;
1153         goto endOfCalendar;
1154     }
1155     date_SHORT = env->NewString(pattern, patternLength);
1156     counter++;
1157
1158
1159 endOfCalendar:
1160
1161     if(gregorianElems != NULL) {
1162         ures_close(gregorianElems);
1163     }
1164     ures_close(gregorian);
1165     ures_close(rootElems);
1166
1167
1168     rootElems = ures_getByKey(root, "NumberElements", NULL, &status);
1169     if(U_FAILURE(status)) {
1170         status = U_ZERO_ERROR;
1171     }
1172
1173     if(ures_getSize(rootElems) >= 11) {
1174
1175         // adding decimal pattern chars to the result
1176         decimalPatternChars = getDecimalPatternChars(env, rootElems);
1177         if(decimalPatternChars != NULL) {
1178             counter++;
1179         }
1180
1181         // adding NaN pattern char to the result
1182         nan = ures_getStringByIndex(rootElems, 10, &nanL, &status);
1183         if(U_SUCCESS(status)) {
1184             naN = env->NewString(nan, nanL);
1185             counter++;
1186         }
1187         status = U_ZERO_ERROR;
1188
1189         // adding infinity pattern char to the result
1190         inf = ures_getStringByIndex(rootElems, 9, &infL, &status);
1191         if(U_SUCCESS(status)) {
1192             infinity = env->NewString(inf, infL);
1193             counter++;
1194         }
1195         status = U_ZERO_ERROR;
1196     }
1197
1198     ures_close(rootElems);
1199
1200
1201     // adding intl currency code to result
1202     intCurrencySymbol = getIntCurrencyCode(env, clazz, locale);
1203     if(intCurrencySymbol != NULL) {
1204         // adding currency symbol to result
1205         currencySymbol = getCurrencySymbol(env, clazz, locale, intCurrencySymbol);
1206     } else {
1207         intCurrencySymbol = env->NewStringUTF("XXX");
1208     }
1209     if(currencySymbol == NULL) {
1210         currencySymbol = env->NewStringUTF("\u00a4");
1211     }
1212     counter += 2;
1213
1214
1215     // adding number format patterns to the result
1216     int numOfEntries;
1217     int decSepOffset;
1218     NumberFormat *nf;
1219     jchar *tmpPattern;
1220
1221     rootElems = ures_getByKey(root, "NumberPatterns", NULL, &status);
1222     if(U_FAILURE(status)) {
1223         status = U_ZERO_ERROR;
1224         goto zones;
1225     }
1226
1227     numOfEntries = ures_getSize(rootElems);
1228     if(numOfEntries < 3) {
1229         ures_close(rootElems);
1230         goto zones;
1231     }
1232
1233     // number pattern
1234     pattern = ures_getStringByIndex(rootElems, 0, &patternLength, &status);
1235     if(U_FAILURE(status)) {
1236         status = U_ZERO_ERROR;
1237         ures_close(rootElems);
1238         goto zones;
1239     }
1240     numberPattern = env->NewString(pattern, patternLength);
1241     counter++;
1242
1243     // integer pattern derived from number pattern
1244     // We need to convert a C string literal to a UChar string for u_strcspn.
1245     static const char c_decSep[] = ".";
1246     UChar decSep[sizeof(c_decSep)];
1247     u_charsToUChars(c_decSep, decSep, sizeof(c_decSep));
1248     decSepOffset = u_strcspn(pattern, decSep);
1249     tmpPattern =  (jchar *) malloc((decSepOffset + 1) * sizeof(jchar));
1250     u_strncpy(tmpPattern, pattern, decSepOffset);
1251     integerPattern = env->NewString(tmpPattern, decSepOffset);
1252     free(tmpPattern);
1253     counter++;
1254
1255     // currency pattern
1256     pattern = ures_getStringByIndex(rootElems, 1, &patternLength, &status);
1257     if(U_FAILURE(status)) {
1258         status = U_ZERO_ERROR;
1259         ures_close(rootElems);
1260         goto zones;
1261     }
1262     currencyPattern = env->NewString(pattern, patternLength);
1263     counter++;
1264
1265     // percent pattern
1266     pattern = ures_getStringByIndex(rootElems, 2, &patternLength, &status);
1267     if(U_FAILURE(status)) {
1268         status = U_ZERO_ERROR;
1269         ures_close(rootElems);
1270         goto zones;
1271     }
1272     percentPattern = env->NewString(pattern, patternLength);
1273     counter++;
1274
1275     ures_close(rootElems);
1276
1277 zones:
1278
1279     ures_close(root);
1280
1281
1282     if(needsTZ == JNI_TRUE) {
1283         counter++; //add empty timezone
1284     }
1285
1286
1287
1288     // collect all content and put it into an array
1289     result = env->NewObjectArray(counter, obj_class, NULL);
1290
1291     int index = 0;
1292     
1293     if(needsTZ == JNI_TRUE) {
1294         addObject(env, result, "timezones", NULL, index++);
1295     }
1296     if(firstDayOfWeek != NULL && index < counter) {
1297         addObject(env, result, "First_Day", firstDayOfWeek, index++);
1298     }
1299     if(minimalDaysInFirstWeek != NULL && index < counter) {
1300         addObject(env, result, "Minimal_Days", minimalDaysInFirstWeek, index++);
1301     }
1302     if(amPmMarkers != NULL && index < counter) {
1303         addObject(env, result, "ampm", amPmMarkers, index++);
1304     }
1305     if(eras != NULL && index < counter) {
1306         addObject(env, result, "eras", eras, index++);
1307     }
1308     if(localPatternChars != NULL && index < counter) {
1309         addObject(env, result, "LocalPatternChars", localPatternChars, index++);
1310     }
1311     if(weekdays != NULL && index < counter) {
1312         addObject(env, result, "weekdays", weekdays, index++);
1313     }
1314     if(shortWeekdays != NULL && index < counter) {
1315         addObject(env, result, "shortWeekdays", shortWeekdays, index++);
1316     }
1317     if(months != NULL && index < counter) {
1318         addObject(env, result, "months", months, index++);
1319     }
1320     if(shortMonths != NULL && index < counter) {
1321         addObject(env, result, "shortMonths", shortMonths, index++);
1322     }
1323     if(time_SHORT != NULL && index < counter) {
1324         addObject(env, result, "Time_SHORT", time_SHORT, index++);
1325     }
1326     if(time_MEDIUM != NULL && index < counter) {
1327         addObject(env, result, "Time_MEDIUM", time_MEDIUM, index++);
1328     }
1329     if(time_LONG != NULL && index < counter) {
1330         addObject(env, result, "Time_LONG", time_LONG, index++);
1331     }
1332     if(time_FULL != NULL && index < counter) {
1333         addObject(env, result, "Time_FULL", time_FULL, index++);
1334     }
1335     if(date_SHORT != NULL && index < counter) {
1336         addObject(env, result, "Date_SHORT", date_SHORT, index++);
1337     }
1338     if(date_MEDIUM != NULL && index < counter) {
1339         addObject(env, result, "Date_MEDIUM", date_MEDIUM, index++);
1340     }
1341     if(date_LONG != NULL && index < counter) {
1342         addObject(env, result, "Date_LONG", date_LONG, index++);
1343     }
1344     if(date_FULL != NULL && index < counter) {
1345         addObject(env, result, "Date_FULL", date_FULL, index++);
1346     }
1347     if(decimalPatternChars != NULL && index < counter) {
1348         addObject(env, result, "DecimalPatternChars", decimalPatternChars, index++);
1349     }
1350     if(naN != NULL && index < counter) {
1351         addObject(env, result, "NaN", naN, index++);
1352     }
1353     if(infinity != NULL && index < counter) {
1354         addObject(env, result, "Infinity", infinity, index++);
1355     }
1356     if(currencySymbol != NULL && index < counter) {
1357         addObject(env, result, "CurrencySymbol", currencySymbol, index++);
1358     }
1359     if(intCurrencySymbol != NULL && index < counter) {
1360         addObject(env, result, "IntCurrencySymbol", intCurrencySymbol, index++);
1361     }
1362     if(numberPattern != NULL && index < counter) {
1363         addObject(env, result, "Number", numberPattern, index++);
1364     }
1365     if(integerPattern != NULL && index < counter) {
1366         addObject(env, result, "Integer", integerPattern, index++);
1367     }
1368     if(currencyPattern != NULL && index < counter) {
1369         addObject(env, result, "Currency", currencyPattern, index++);
1370     }
1371     if(percentPattern != NULL && index < counter) {
1372         addObject(env, result, "Percent", percentPattern, index++);
1373     }
1374
1375     return result;
1376
1377 }
1378
1379 static JNINativeMethod gMethods[] = {
1380     /* name, signature, funcPtr */
1381     {"getFractionDigitsNative", "(Ljava/lang/String;)I",                   
1382             (void*) getFractionDigitsNative},
1383     {"getCurrencyCodeNative", "(Ljava/lang/String;)Ljava/lang/String;",
1384             (void*) getCurrencyCodeNative},
1385     {"getCurrencySymbolNative", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
1386             (void*) getCurrencySymbolNative},
1387     {"getDisplayCountryNative", 
1388             "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
1389             (void*) getDisplayCountryNative},
1390     {"getDisplayLanguageNative", 
1391             "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
1392             (void*) getDisplayLanguageNative},
1393     {"getDisplayVariantNative",
1394             "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
1395             (void*) getDisplayVariantNative},
1396     {"getISO3CountryNative",
1397             "(Ljava/lang/String;)Ljava/lang/String;",
1398             (void*) getISO3CountryNative},
1399     {"getISO3LanguageNative",
1400             "(Ljava/lang/String;)Ljava/lang/String;",
1401             (void*) getISO3LanguageNative},
1402     {"getISOCountriesNative", "()[Ljava/lang/String;",
1403             (void*) getISOCountriesNative},
1404     {"getISOLanguagesNative", "()[Ljava/lang/String;",
1405             (void*) getISOLanguagesNative},
1406     {"getAvailableLocalesNative", "()[Ljava/lang/String;",
1407             (void*) getAvailableLocalesNative},
1408     {"getTimeZonesNative", 
1409             "([[Ljava/lang/String;Ljava/lang/String;)V",
1410             (void*) getTimeZonesNative},
1411     {"getDisplayTimeZoneNative", 
1412             "(Ljava/lang/String;ZILjava/lang/String;)Ljava/lang/String;",
1413             (void*) getDisplayTimeZoneNative},
1414     {"getContentImpl", 
1415             "(Ljava/lang/String;Z)[[Ljava/lang/Object;",
1416             (void*) getContentImpl},
1417 };
1418
1419 int register_com_ibm_icu4jni_util_Resources(JNIEnv* env) {
1420     
1421     // initializing String
1422
1423     jclass stringclass = env->FindClass("java/lang/String");
1424
1425     if(stringclass == NULL) {
1426         LOGE("Can't find java/lang/String");
1427         jniThrowException(env, "java/lang/ClassNotFoundException", "java.lang.String");
1428         return -1;
1429     }
1430     
1431     string_class = (jclass) env->NewGlobalRef(stringclass);
1432     
1433     return jniRegisterNativeMethods(env, 
1434             "com/ibm/icu4jni/util/Resources", gMethods, 
1435             NELEM(gMethods));
1436 }