1 /* 2 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <stdlib.h> 27 #include <string.h> 28 29 #include "jvm.h" 30 #include "jni.h" 31 #include "jni_util.h" 32 33 /* Due to a bug in the win32 C runtime library strings 34 * such as "z:" need to be appended with a "." so we 35 * must allocate at least 4 bytes to allow room for 36 * this expansion. See 4235353 for details. 37 */ 38 #define MALLOC_MIN4(len) ((char *)malloc((len) + 1 < 4 ? 4 : (len) + 1)) 39 40 /** 41 * Throw a Java exception by name. Similar to SignalError. 42 */ 43 JNIEXPORT void JNICALL 44 JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg) 45 { 46 jclass cls = (*env)->FindClass(env, name); 47 48 if (cls != 0) /* Otherwise an exception has already been thrown */ 49 (*env)->ThrowNew(env, cls, msg); 50 } 51 52 /* JNU_Throw common exceptions */ 53 54 JNIEXPORT void JNICALL 55 JNU_ThrowNullPointerException(JNIEnv *env, const char *msg) 56 { 57 JNU_ThrowByName(env, "java/lang/NullPointerException", msg); 58 } 59 60 JNIEXPORT void JNICALL 61 JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv *env, const char *msg) 62 { 63 JNU_ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", msg); 64 } 65 66 JNIEXPORT void JNICALL 67 JNU_ThrowOutOfMemoryError(JNIEnv *env, const char *msg) 68 { 69 JNU_ThrowByName(env, "java/lang/OutOfMemoryError", msg); 70 } 71 72 JNIEXPORT void JNICALL 73 JNU_ThrowIllegalArgumentException(JNIEnv *env, const char *msg) 74 { 75 JNU_ThrowByName(env, "java/lang/IllegalArgumentException", msg); 76 } 77 78 JNIEXPORT void JNICALL 79 JNU_ThrowIllegalAccessError(JNIEnv *env, const char *msg) 80 { 81 JNU_ThrowByName(env, "java/lang/IllegalAccessError", msg); 82 } 83 84 JNIEXPORT void JNICALL 85 JNU_ThrowIllegalAccessException(JNIEnv *env, const char *msg) 86 { 87 JNU_ThrowByName(env, "java/lang/IllegalAccessException", msg); 88 } 89 90 JNIEXPORT void JNICALL 91 JNU_ThrowInternalError(JNIEnv *env, const char *msg) 92 { 93 JNU_ThrowByName(env, "java/lang/InternalError", msg); 94 } 95 96 JNIEXPORT void JNICALL 97 JNU_ThrowNoSuchFieldException(JNIEnv *env, const char *msg) 98 { 99 JNU_ThrowByName(env, "java/lang/NoSuchFieldException", msg); 100 } 101 102 JNIEXPORT void JNICALL 103 JNU_ThrowNoSuchMethodException(JNIEnv *env, const char *msg) 104 { 105 JNU_ThrowByName(env, "java/lang/NoSuchMethodException", msg); 106 } 107 108 JNIEXPORT void JNICALL 109 JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg) 110 { 111 JNU_ThrowByName(env, "java/lang/ClassNotFoundException", msg); 112 } 113 114 JNIEXPORT void JNICALL 115 JNU_ThrowNumberFormatException(JNIEnv *env, const char *msg) 116 { 117 JNU_ThrowByName(env, "java/lang/NumberFormatException", msg); 118 } 119 120 JNIEXPORT void JNICALL 121 JNU_ThrowIOException(JNIEnv *env, const char *msg) 122 { 123 JNU_ThrowByName(env, "java/io/IOException", msg); 124 } 125 126 JNIEXPORT void JNICALL 127 JNU_ThrowNoSuchFieldError(JNIEnv *env, const char *msg) 128 { 129 JNU_ThrowByName(env, "java/lang/NoSuchFieldError", msg); 130 } 131 132 JNIEXPORT void JNICALL 133 JNU_ThrowNoSuchMethodError(JNIEnv *env, const char *msg) 134 { 135 JNU_ThrowByName(env, "java/lang/NoSuchMethodError", msg); 136 } 137 138 JNIEXPORT void JNICALL 139 JNU_ThrowStringIndexOutOfBoundsException(JNIEnv *env, const char *msg) 140 { 141 JNU_ThrowByName(env, "java/lang/StringIndexOutOfBoundsException", msg); 142 } 143 144 JNIEXPORT void JNICALL 145 JNU_ThrowInstantiationException(JNIEnv *env, const char *msg) 146 { 147 JNU_ThrowByName(env, "java/lang/InstantiationException", msg); 148 } 149 150 151 /* Throw an exception by name, using the string returned by 152 * JVM_LastErrorString for the detail string. If the last-error 153 * string is NULL, use the given default detail string. 154 */ 155 JNIEXPORT void JNICALL 156 JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name, 157 const char *defaultDetail) 158 { 159 char buf[256]; 160 int n = JVM_GetLastErrorString(buf, sizeof(buf)); 161 162 if (n > 0) { 163 jstring s = JNU_NewStringPlatform(env, buf); 164 if (s != NULL) { 165 jobject x = JNU_NewObjectByName(env, name, 166 "(Ljava/lang/String;)V", s); 167 if (x != NULL) { 168 (*env)->Throw(env, x); 169 } 170 } 171 } 172 if (!(*env)->ExceptionOccurred(env)) { 173 JNU_ThrowByName(env, name, defaultDetail); 174 } 175 } 176 177 /* Throw an IOException, using the last-error string for the detail 178 * string. If the last-error string is NULL, use the given default 179 * detail string. 180 */ 181 JNIEXPORT void JNICALL 182 JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail) 183 { 184 JNU_ThrowByNameWithLastError(env, "java/io/IOException", defaultDetail); 185 } 186 187 188 JNIEXPORT jvalue JNICALL 189 JNU_CallStaticMethodByName(JNIEnv *env, 190 jboolean *hasException, 191 const char *class_name, 192 const char *name, 193 const char *signature, 194 ...) 195 { 196 jclass clazz; 197 jmethodID mid; 198 va_list args; 199 jvalue result; 200 const char *p = signature; 201 202 /* find out the return type */ 203 while (*p && *p != ')') 204 p++; 205 p++; 206 207 result.i = 0; 208 209 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 210 goto done2; 211 212 clazz = (*env)->FindClass(env, class_name); 213 if (clazz == 0) 214 goto done2; 215 mid = (*env)->GetStaticMethodID(env, clazz, name, signature); 216 if (mid == 0) 217 goto done1; 218 va_start(args, signature); 219 switch (*p) { 220 case 'V': 221 (*env)->CallStaticVoidMethodV(env, clazz, mid, args); 222 break; 223 case '[': 224 case 'L': 225 result.l = (*env)->CallStaticObjectMethodV(env, clazz, mid, args); 226 break; 227 case 'Z': 228 result.z = (*env)->CallStaticBooleanMethodV(env, clazz, mid, args); 229 break; 230 case 'B': 231 result.b = (*env)->CallStaticByteMethodV(env, clazz, mid, args); 232 break; 233 case 'C': 234 result.c = (*env)->CallStaticCharMethodV(env, clazz, mid, args); 235 break; 236 case 'S': 237 result.s = (*env)->CallStaticShortMethodV(env, clazz, mid, args); 238 break; 239 case 'I': 240 result.i = (*env)->CallStaticIntMethodV(env, clazz, mid, args); 241 break; 242 case 'J': 243 result.j = (*env)->CallStaticLongMethodV(env, clazz, mid, args); 244 break; 245 case 'F': 246 result.f = (*env)->CallStaticFloatMethodV(env, clazz, mid, args); 247 break; 248 case 'D': 249 result.d = (*env)->CallStaticDoubleMethodV(env, clazz, mid, args); 250 break; 251 default: 252 (*env)->FatalError(env, "JNU_CallStaticMethodByName: illegal signature"); 253 } 254 va_end(args); 255 256 done1: 257 (*env)->DeleteLocalRef(env, clazz); 258 done2: 259 if (hasException) { 260 *hasException = (*env)->ExceptionCheck(env); 261 } 262 return result; 263 } 264 265 JNIEXPORT jvalue JNICALL 266 JNU_CallMethodByName(JNIEnv *env, 267 jboolean *hasException, 268 jobject obj, 269 const char *name, 270 const char *signature, 271 ...) 272 { 273 jvalue result; 274 va_list args; 275 276 va_start(args, signature); 277 result = JNU_CallMethodByNameV(env, hasException, obj, name, signature, 278 args); 279 va_end(args); 280 281 return result; 282 } 283 284 285 JNIEXPORT jvalue JNICALL 286 JNU_CallMethodByNameV(JNIEnv *env, 287 jboolean *hasException, 288 jobject obj, 289 const char *name, 290 const char *signature, 291 va_list args) 292 { 293 jclass clazz; 294 jmethodID mid; 295 jvalue result; 296 const char *p = signature; 297 298 /* find out the return type */ 299 while (*p && *p != ')') 300 p++; 301 p++; 302 303 result.i = 0; 304 305 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 306 goto done2; 307 308 clazz = (*env)->GetObjectClass(env, obj); 309 mid = (*env)->GetMethodID(env, clazz, name, signature); 310 if (mid == 0) 311 goto done1; 312 313 switch (*p) { 314 case 'V': 315 (*env)->CallVoidMethodV(env, obj, mid, args); 316 break; 317 case '[': 318 case 'L': 319 result.l = (*env)->CallObjectMethodV(env, obj, mid, args); 320 break; 321 case 'Z': 322 result.z = (*env)->CallBooleanMethodV(env, obj, mid, args); 323 break; 324 case 'B': 325 result.b = (*env)->CallByteMethodV(env, obj, mid, args); 326 break; 327 case 'C': 328 result.c = (*env)->CallCharMethodV(env, obj, mid, args); 329 break; 330 case 'S': 331 result.s = (*env)->CallShortMethodV(env, obj, mid, args); 332 break; 333 case 'I': 334 result.i = (*env)->CallIntMethodV(env, obj, mid, args); 335 break; 336 case 'J': 337 result.j = (*env)->CallLongMethodV(env, obj, mid, args); 338 break; 339 case 'F': 340 result.f = (*env)->CallFloatMethodV(env, obj, mid, args); 341 break; 342 case 'D': 343 result.d = (*env)->CallDoubleMethodV(env, obj, mid, args); 344 break; 345 default: 346 (*env)->FatalError(env, "JNU_CallMethodByNameV: illegal signature"); 347 } 348 done1: 349 (*env)->DeleteLocalRef(env, clazz); 350 done2: 351 if (hasException) { 352 *hasException = (*env)->ExceptionCheck(env); 353 } 354 return result; 355 } 356 357 JNIEXPORT jobject JNICALL 358 JNU_NewObjectByName(JNIEnv *env, const char *class_name, 359 const char *constructor_sig, ...) 360 { 361 jobject obj = NULL; 362 363 jclass cls = 0; 364 jmethodID cls_initMID; 365 va_list args; 366 367 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 368 goto done; 369 370 cls = (*env)->FindClass(env, class_name); 371 if (cls == 0) { 372 goto done; 373 } 374 cls_initMID = (*env)->GetMethodID(env, cls, 375 "<init>", constructor_sig); 376 if (cls_initMID == NULL) { 377 goto done; 378 } 379 va_start(args, constructor_sig); 380 obj = (*env)->NewObjectV(env, cls, cls_initMID, args); 381 va_end(args); 382 383 done: 384 (*env)->DeleteLocalRef(env, cls); 385 return obj; 386 } 387 388 /* Optimized for char set ISO_8559_1 */ 389 static jstring 390 newString8859_1(JNIEnv *env, const char *str) 391 { 392 int len = (int)strlen(str); 393 jchar buf[512]; 394 jchar *str1; 395 jstring result; 396 int i; 397 398 if (len > 512) { 399 str1 = (jchar *)malloc(len * sizeof(jchar)); 400 if (str1 == 0) { 401 JNU_ThrowOutOfMemoryError(env, 0); 402 return 0; 403 } 404 } else 405 str1 = buf; 406 407 for (i=0;i<len;i++) 408 str1[i] = (unsigned char)str[i]; 409 result = (*env)->NewString(env, str1, len); 410 if (str1 != buf) 411 free(str1); 412 return result; 413 } 414 415 static const char* 416 getString8859_1Chars(JNIEnv *env, jstring jstr) 417 { 418 int i; 419 char *result; 420 jint len = (*env)->GetStringLength(env, jstr); 421 const jchar *str = (*env)->GetStringCritical(env, jstr, 0); 422 if (str == 0) { 423 return 0; 424 } 425 426 result = MALLOC_MIN4(len); 427 if (result == 0) { 428 (*env)->ReleaseStringCritical(env, jstr, str); 429 JNU_ThrowOutOfMemoryError(env, 0); 430 return 0; 431 } 432 433 for (i=0; i<len; i++) { 434 jchar unicode = str[i]; 435 if (unicode <= 0x00ff) 436 result[i] = (char)unicode; 437 else 438 result[i] = '?'; 439 } 440 441 result[len] = 0; 442 (*env)->ReleaseStringCritical(env, jstr, str); 443 return result; 444 } 445 446 447 /* Optimized for char set ISO646-US (us-ascii) */ 448 static jstring 449 newString646_US(JNIEnv *env, const char *str) 450 { 451 int len = strlen(str); 452 jchar buf[512]; 453 jchar *str1; 454 jstring result; 455 int i; 456 457 if (len > 512) { 458 str1 = (jchar *)malloc(len * sizeof(jchar)); 459 if (str1 == 0) { 460 JNU_ThrowOutOfMemoryError(env, 0); 461 return 0; 462 } 463 } else 464 str1 = buf; 465 466 for (i=0; i<len; i++) { 467 unsigned char c = (unsigned char)str[i]; 468 if (c <= 0x7f) 469 str1[i] = c; 470 else 471 str1[i] = '?'; 472 } 473 474 result = (*env)->NewString(env, str1, len); 475 if (str1 != buf) 476 free(str1); 477 return result; 478 } 479 480 static const char* 481 getString646_USChars(JNIEnv *env, jstring jstr) 482 { 483 int i; 484 char *result; 485 jint len = (*env)->GetStringLength(env, jstr); 486 const jchar *str = (*env)->GetStringCritical(env, jstr, 0); 487 if (str == 0) { 488 return 0; 489 } 490 491 result = MALLOC_MIN4(len); 492 if (result == 0) { 493 (*env)->ReleaseStringCritical(env, jstr, str); 494 JNU_ThrowOutOfMemoryError(env, 0); 495 return 0; 496 } 497 498 for (i=0; i<len; i++) { 499 jchar unicode = str[i]; 500 if (unicode <= 0x007f ) 501 result[i] = (char)unicode; 502 else 503 result[i] = '?'; 504 } 505 506 result[len] = 0; 507 (*env)->ReleaseStringCritical(env, jstr, str); 508 return result; 509 } 510 511 /* enumeration of c1 row from Cp1252 */ 512 static int cp1252c1chars[32] = { 513 0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021, 514 0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD, 515 0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014, 516 0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178 517 }; 518 519 /* Optimized for char set Cp1252 */ 520 static jstring 521 newStringCp1252(JNIEnv *env, const char *str) 522 { 523 int len = (int) strlen(str); 524 jchar buf[512]; 525 jchar *str1; 526 jstring result; 527 int i; 528 if (len > 512) { 529 str1 = (jchar *)malloc(len * sizeof(jchar)); 530 if (str1 == 0) { 531 JNU_ThrowOutOfMemoryError(env, 0); 532 return 0; 533 } 534 } else 535 str1 = buf; 536 537 for (i=0; i<len; i++) { 538 unsigned char c = (unsigned char)str[i]; 539 if ((c >= 0x80) && (c <= 0x9f)) 540 str1[i] = cp1252c1chars[c-128]; 541 else 542 str1[i] = c; 543 } 544 545 result = (*env)->NewString(env, str1, len); 546 if (str1 != buf) 547 free(str1); 548 return result; 549 } 550 551 static const char* 552 getStringCp1252Chars(JNIEnv *env, jstring jstr) 553 { 554 int i; 555 char *result; 556 jint len = (*env)->GetStringLength(env, jstr); 557 const jchar *str = (*env)->GetStringCritical(env, jstr, 0); 558 if (str == 0) { 559 return 0; 560 } 561 562 result = MALLOC_MIN4(len); 563 if (result == 0) { 564 (*env)->ReleaseStringCritical(env, jstr, str); 565 JNU_ThrowOutOfMemoryError(env, 0); 566 return 0; 567 } 568 569 for (i=0; i<len; i++) { 570 jchar c = str[i]; 571 if (c < 256) 572 result[i] = (char)c; 573 else switch(c) { 574 case 0x20AC: result[i] = (char)0x80; break; 575 case 0x201A: result[i] = (char)0x82; break; 576 case 0x0192: result[i] = (char)0x83; break; 577 case 0x201E: result[i] = (char)0x84; break; 578 case 0x2026: result[i] = (char)0x85; break; 579 case 0x2020: result[i] = (char)0x86; break; 580 case 0x2021: result[i] = (char)0x87; break; 581 case 0x02C6: result[i] = (char)0x88; break; 582 case 0x2030: result[i] = (char)0x89; break; 583 case 0x0160: result[i] = (char)0x8A; break; 584 case 0x2039: result[i] = (char)0x8B; break; 585 case 0x0152: result[i] = (char)0x8C; break; 586 case 0x017D: result[i] = (char)0x8E; break; 587 case 0x2018: result[i] = (char)0x91; break; 588 case 0x2019: result[i] = (char)0x92; break; 589 case 0x201C: result[i] = (char)0x93; break; 590 case 0x201D: result[i] = (char)0x94; break; 591 case 0x2022: result[i] = (char)0x95; break; 592 case 0x2013: result[i] = (char)0x96; break; 593 case 0x2014: result[i] = (char)0x97; break; 594 case 0x02DC: result[i] = (char)0x98; break; 595 case 0x2122: result[i] = (char)0x99; break; 596 case 0x0161: result[i] = (char)0x9A; break; 597 case 0x203A: result[i] = (char)0x9B; break; 598 case 0x0153: result[i] = (char)0x9C; break; 599 case 0x017E: result[i] = (char)0x9E; break; 600 case 0x0178: result[i] = (char)0x9F; break; 601 default: result[i] = '?'; break; 602 } 603 } 604 605 result[len] = 0; 606 (*env)->ReleaseStringCritical(env, jstr, str); 607 return result; 608 } 609 610 static int fastEncoding = NO_ENCODING_YET; 611 static jstring jnuEncoding = NULL; 612 613 /* Cached method IDs */ 614 static jmethodID String_init_ID; /* String(byte[], enc) */ 615 static jmethodID String_getBytes_ID; /* String.getBytes(enc) */ 616 617 int getFastEncoding() { 618 return fastEncoding; 619 } 620 621 /* Initialize the fast encoding. If the "sun.jnu.encoding" property 622 * has not yet been set, we leave fastEncoding == NO_ENCODING_YET. 623 */ 624 void 625 initializeEncoding(JNIEnv *env) 626 { 627 jstring propname = 0; 628 jstring enc = 0; 629 630 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 631 return; 632 633 propname = (*env)->NewStringUTF(env, "sun.jnu.encoding"); 634 if (propname) { 635 jboolean exc; 636 enc = JNU_CallStaticMethodByName 637 (env, 638 &exc, 639 "java/lang/System", 640 "getProperty", 641 "(Ljava/lang/String;)Ljava/lang/String;", 642 propname).l; 643 if (!exc) { 644 if (enc) { 645 const char* encname = (*env)->GetStringUTFChars(env, enc, 0); 646 if (encname) { 647 /* 648 * On Solaris with nl_langinfo() called in GetJavaProperties(): 649 * 650 * locale undefined -> NULL -> hardcoded default 651 * "C" locale -> "" -> hardcoded default (on 2.6) 652 * "C" locale -> "ISO646-US" (on Sol 7/8) 653 * "en_US" locale -> "ISO8859-1" 654 * "en_GB" locale -> "ISO8859-1" (on Sol 7/8) 655 * "en_UK" locale -> "ISO8859-1" (on 2.6) 656 */ 657 if ((strcmp(encname, "8859_1") == 0) || 658 (strcmp(encname, "ISO8859-1") == 0) || 659 (strcmp(encname, "ISO8859_1") == 0)) 660 fastEncoding = FAST_8859_1; 661 else if (strcmp(encname, "ISO646-US") == 0) 662 fastEncoding = FAST_646_US; 663 else if (strcmp(encname, "Cp1252") == 0 || 664 /* This is a temporary fix until we move */ 665 /* to wide character versions of all Windows */ 666 /* calls. */ 667 strcmp(encname, "utf-16le") == 0) 668 fastEncoding = FAST_CP1252; 669 else { 670 fastEncoding = NO_FAST_ENCODING; 671 jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc); 672 } 673 (*env)->ReleaseStringUTFChars(env, enc, encname); 674 } 675 } 676 } else { 677 (*env)->ExceptionClear(env); 678 } 679 } else { 680 (*env)->ExceptionClear(env); 681 } 682 (*env)->DeleteLocalRef(env, propname); 683 (*env)->DeleteLocalRef(env, enc); 684 685 /* Initialize method-id cache */ 686 String_getBytes_ID = (*env)->GetMethodID(env, JNU_ClassString(env), 687 "getBytes", "(Ljava/lang/String;)[B"); 688 String_init_ID = (*env)->GetMethodID(env, JNU_ClassString(env), 689 "<init>", "([BLjava/lang/String;)V"); 690 } 691 692 static jboolean isJNUEncodingSupported = JNI_FALSE; 693 static jboolean jnuEncodingSupported(JNIEnv *env) { 694 jboolean exe; 695 if (isJNUEncodingSupported == JNI_TRUE) { 696 return JNI_TRUE; 697 } 698 isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName ( 699 env, &exe, 700 "java/nio/charset/Charset", 701 "isSupported", 702 "(Ljava/lang/String;)Z", 703 jnuEncoding).z; 704 return isJNUEncodingSupported; 705 } 706 707 708 JNIEXPORT jstring 709 NewStringPlatform(JNIEnv *env, const char *str) 710 { 711 return JNU_NewStringPlatform(env, str); 712 } 713 714 JNIEXPORT jstring JNICALL 715 JNU_NewStringPlatform(JNIEnv *env, const char *str) 716 { 717 jstring result; 718 result = nativeNewStringPlatform(env, str); 719 if (result == NULL) { 720 jbyteArray hab = 0; 721 int len; 722 723 if (fastEncoding == NO_ENCODING_YET) 724 initializeEncoding(env); 725 726 if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET)) 727 return newString8859_1(env, str); 728 if (fastEncoding == FAST_646_US) 729 return newString646_US(env, str); 730 if (fastEncoding == FAST_CP1252) 731 return newStringCp1252(env, str); 732 733 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 734 return NULL; 735 736 len = (int)strlen(str); 737 hab = (*env)->NewByteArray(env, len); 738 if (hab != 0) { 739 (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str); 740 if (jnuEncodingSupported(env)) { 741 result = (*env)->NewObject(env, JNU_ClassString(env), 742 String_init_ID, hab, jnuEncoding); 743 } else { 744 /*If the encoding specified in sun.jnu.encoding is not endorsed 745 by "Charset.isSupported" we have to fall back to use String(byte[]) 746 explicitly here without specifying the encoding name, in which the 747 StringCoding class will pickup the iso-8859-1 as the fallback 748 converter for us. 749 */ 750 jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env), 751 "<init>", "([B)V"); 752 result = (*env)->NewObject(env, JNU_ClassString(env), mid, hab); 753 } 754 (*env)->DeleteLocalRef(env, hab); 755 return result; 756 } 757 } 758 return NULL; 759 } 760 761 JNIEXPORT const char * 762 GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) 763 { 764 return JNU_GetStringPlatformChars(env, jstr, isCopy); 765 } 766 767 JNIEXPORT const char * JNICALL 768 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) 769 { 770 char *result = nativeGetStringPlatformChars(env, jstr, isCopy); 771 if (result == NULL) { 772 773 jbyteArray hab = 0; 774 775 if (isCopy) 776 *isCopy = JNI_TRUE; 777 778 if (fastEncoding == NO_ENCODING_YET) 779 initializeEncoding(env); 780 781 if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET)) 782 return getString8859_1Chars(env, jstr); 783 if (fastEncoding == FAST_646_US) 784 return getString646_USChars(env, jstr); 785 if (fastEncoding == FAST_CP1252) 786 return getStringCp1252Chars(env, jstr); 787 788 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 789 return 0; 790 791 if (jnuEncodingSupported(env)) { 792 hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding); 793 } else { 794 jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env), 795 "getBytes", "()[B"); 796 hab = (*env)->CallObjectMethod(env, jstr, mid); 797 } 798 799 if (!(*env)->ExceptionCheck(env)) { 800 jint len = (*env)->GetArrayLength(env, hab); 801 result = MALLOC_MIN4(len); 802 if (result == 0) { 803 JNU_ThrowOutOfMemoryError(env, 0); 804 (*env)->DeleteLocalRef(env, hab); 805 return 0; 806 } 807 (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result); 808 result[len] = 0; /* NULL-terminate */ 809 } 810 811 (*env)->DeleteLocalRef(env, hab); 812 } 813 return result; 814 } 815 816 JNIEXPORT void JNICALL 817 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str) 818 { 819 free((void *)str); 820 } 821 822 /* 823 * Export the platform dependent path canonicalization so that 824 * VM can find it when loading system classes. 825 * 826 */ 827 extern int canonicalize(char *path, const char *out, int len); 828 829 JNIEXPORT int 830 Canonicalize(JNIEnv *env, char *orig, char *out, int len) 831 { 832 /* canonicalize an already natived path */ 833 return canonicalize(orig, out, len); 834 } 835 836 JNIEXPORT jclass JNICALL 837 JNU_ClassString(JNIEnv *env) 838 { 839 static jclass cls = 0; 840 if (cls == 0) { 841 jclass c; 842 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 843 return 0; 844 c = (*env)->FindClass(env, "java/lang/String"); 845 cls = (*env)->NewGlobalRef(env, c); 846 (*env)->DeleteLocalRef(env, c); 847 } 848 return cls; 849 } 850 851 JNIEXPORT jclass JNICALL 852 JNU_ClassClass(JNIEnv *env) 853 { 854 static jclass cls = 0; 855 if (cls == 0) { 856 jclass c; 857 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 858 return 0; 859 c = (*env)->FindClass(env, "java/lang/Class"); 860 cls = (*env)->NewGlobalRef(env, c); 861 (*env)->DeleteLocalRef(env, c); 862 } 863 return cls; 864 } 865 866 JNIEXPORT jclass JNICALL 867 JNU_ClassObject(JNIEnv *env) 868 { 869 static jclass cls = 0; 870 if (cls == 0) { 871 jclass c; 872 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 873 return 0; 874 c = (*env)->FindClass(env, "java/lang/Object"); 875 cls = (*env)->NewGlobalRef(env, c); 876 (*env)->DeleteLocalRef(env, c); 877 } 878 return cls; 879 } 880 881 JNIEXPORT jclass JNICALL 882 JNU_ClassThrowable(JNIEnv *env) 883 { 884 static jclass cls = 0; 885 if (cls == 0) { 886 jclass c; 887 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 888 return 0; 889 c = (*env)->FindClass(env, "java/lang/Throwable"); 890 cls = (*env)->NewGlobalRef(env, c); 891 (*env)->DeleteLocalRef(env, c); 892 } 893 return cls; 894 } 895 896 JNIEXPORT jint JNICALL 897 JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src, 898 jint count) 899 { 900 int i; 901 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 902 return -1; 903 for (i=0; i<count; i++) { 904 jstring p = (*env)->GetObjectArrayElement(env, src, i); 905 (*env)->SetObjectArrayElement(env, dst, i, p); 906 (*env)->DeleteLocalRef(env, p); 907 } 908 return 0; 909 } 910 911 JNIEXPORT void * JNICALL 912 JNU_GetEnv(JavaVM *vm, jint version) 913 { 914 void *env; 915 (*vm)->GetEnv(vm, &env, version); 916 return env; 917 } 918 919 JNIEXPORT jint JNICALL 920 JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char* classname) 921 { 922 jclass cls; 923 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 924 return JNI_ERR; 925 cls = (*env)->FindClass(env, classname); 926 if (cls != NULL) { 927 jint result = (*env)->IsInstanceOf(env, object, cls); 928 (*env)->DeleteLocalRef(env, cls); 929 return result; 930 } 931 return JNI_ERR; 932 } 933 934 JNIEXPORT jboolean JNICALL 935 JNU_Equals(JNIEnv *env, jobject object1, jobject object2) 936 { 937 static jmethodID mid = NULL; 938 if (mid == NULL) { 939 mid = (*env)->GetMethodID(env, JNU_ClassObject(env), "equals", 940 "(Ljava/lang/Object;)Z"); 941 } 942 return (*env)->CallBooleanMethod(env, object1, mid, object2); 943 } 944 945 946 /************************************************************************ 947 * Thread calls 948 */ 949 950 static jmethodID Object_waitMID; 951 static jmethodID Object_notifyMID; 952 static jmethodID Object_notifyAllMID; 953 954 JNIEXPORT void JNICALL 955 JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout) 956 { 957 if (object == NULL) { 958 JNU_ThrowNullPointerException(env, "JNU_MonitorWait argument"); 959 return; 960 } 961 if (Object_waitMID == NULL) { 962 jclass cls = JNU_ClassObject(env); 963 if (cls == NULL) { 964 return; 965 } 966 Object_waitMID = (*env)->GetMethodID(env, cls, "wait", "(J)V"); 967 if (Object_waitMID == NULL) { 968 return; 969 } 970 } 971 (*env)->CallVoidMethod(env, object, Object_waitMID, timeout); 972 } 973 974 JNIEXPORT void JNICALL 975 JNU_Notify(JNIEnv *env, jobject object) 976 { 977 if (object == NULL) { 978 JNU_ThrowNullPointerException(env, "JNU_Notify argument"); 979 return; 980 } 981 if (Object_notifyMID == NULL) { 982 jclass cls = JNU_ClassObject(env); 983 if (cls == NULL) { 984 return; 985 } 986 Object_notifyMID = (*env)->GetMethodID(env, cls, "notify", "()V"); 987 if (Object_notifyMID == NULL) { 988 return; 989 } 990 } 991 (*env)->CallVoidMethod(env, object, Object_notifyMID); 992 } 993 994 JNIEXPORT void JNICALL 995 JNU_NotifyAll(JNIEnv *env, jobject object) 996 { 997 if (object == NULL) { 998 JNU_ThrowNullPointerException(env, "JNU_NotifyAll argument"); 999 return; 1000 } 1001 if (Object_notifyAllMID == NULL) { 1002 jclass cls = JNU_ClassObject(env); 1003 if (cls == NULL) { 1004 return; 1005 } 1006 Object_notifyAllMID = (*env)->GetMethodID(env, cls,"notifyAll", "()V"); 1007 if (Object_notifyAllMID == NULL) { 1008 return; 1009 } 1010 } 1011 (*env)->CallVoidMethod(env, object, Object_notifyAllMID); 1012 } 1013 1014 1015 /************************************************************************ 1016 * Debugging utilities 1017 */ 1018 1019 JNIEXPORT void JNICALL 1020 JNU_PrintString(JNIEnv *env, char *hdr, jstring string) 1021 { 1022 if (string == NULL) { 1023 fprintf(stderr, "%s: is NULL\n", hdr); 1024 } else { 1025 const char *stringPtr = JNU_GetStringPlatformChars(env, string, 0); 1026 if (stringPtr == 0) 1027 return; 1028 fprintf(stderr, "%s: %s\n", hdr, stringPtr); 1029 JNU_ReleaseStringPlatformChars(env, string, stringPtr); 1030 } 1031 } 1032 1033 JNIEXPORT void JNICALL 1034 JNU_PrintClass(JNIEnv *env, char* hdr, jobject object) 1035 { 1036 if (object == NULL) { 1037 fprintf(stderr, "%s: object is NULL\n", hdr); 1038 return; 1039 } else { 1040 jclass cls = (*env)->GetObjectClass(env, object); 1041 jstring clsName = JNU_ToString(env, cls); 1042 JNU_PrintString(env, hdr, clsName); 1043 (*env)->DeleteLocalRef(env, cls); 1044 (*env)->DeleteLocalRef(env, clsName); 1045 } 1046 } 1047 1048 JNIEXPORT jstring JNICALL 1049 JNU_ToString(JNIEnv *env, jobject object) 1050 { 1051 if (object == NULL) { 1052 return (*env)->NewStringUTF(env, "NULL"); 1053 } else { 1054 return (jstring)JNU_CallMethodByName(env, 1055 NULL, 1056 object, 1057 "toString", 1058 "()Ljava/lang/String;").l; 1059 } 1060 } 1061 1062 JNIEXPORT jvalue JNICALL 1063 JNU_GetFieldByName(JNIEnv *env, 1064 jboolean *hasException, 1065 jobject obj, 1066 const char *name, 1067 const char *signature) 1068 { 1069 jclass cls; 1070 jfieldID fid; 1071 jvalue result; 1072 1073 result.i = 0; 1074 1075 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1076 goto done2; 1077 1078 cls = (*env)->GetObjectClass(env, obj); 1079 fid = (*env)->GetFieldID(env, cls, name, signature); 1080 if (fid == 0) 1081 goto done1; 1082 1083 switch (*signature) { 1084 case '[': 1085 case 'L': 1086 result.l = (*env)->GetObjectField(env, obj, fid); 1087 break; 1088 case 'Z': 1089 result.z = (*env)->GetBooleanField(env, obj, fid); 1090 break; 1091 case 'B': 1092 result.b = (*env)->GetByteField(env, obj, fid); 1093 break; 1094 case 'C': 1095 result.c = (*env)->GetCharField(env, obj, fid); 1096 break; 1097 case 'S': 1098 result.s = (*env)->GetShortField(env, obj, fid); 1099 break; 1100 case 'I': 1101 result.i = (*env)->GetIntField(env, obj, fid); 1102 break; 1103 case 'J': 1104 result.j = (*env)->GetLongField(env, obj, fid); 1105 break; 1106 case 'F': 1107 result.f = (*env)->GetFloatField(env, obj, fid); 1108 break; 1109 case 'D': 1110 result.d = (*env)->GetDoubleField(env, obj, fid); 1111 break; 1112 1113 default: 1114 (*env)->FatalError(env, "JNU_GetFieldByName: illegal signature"); 1115 } 1116 1117 done1: 1118 (*env)->DeleteLocalRef(env, cls); 1119 done2: 1120 if (hasException) { 1121 *hasException = (*env)->ExceptionCheck(env); 1122 } 1123 return result; 1124 } 1125 1126 JNIEXPORT void JNICALL 1127 JNU_SetFieldByName(JNIEnv *env, 1128 jboolean *hasException, 1129 jobject obj, 1130 const char *name, 1131 const char *signature, 1132 ...) 1133 { 1134 jclass cls; 1135 jfieldID fid; 1136 va_list args; 1137 1138 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1139 goto done2; 1140 1141 cls = (*env)->GetObjectClass(env, obj); 1142 fid = (*env)->GetFieldID(env, cls, name, signature); 1143 if (fid == 0) 1144 goto done1; 1145 1146 va_start(args, signature); 1147 switch (*signature) { 1148 case '[': 1149 case 'L': 1150 (*env)->SetObjectField(env, obj, fid, va_arg(args, jobject)); 1151 break; 1152 case 'Z': 1153 (*env)->SetBooleanField(env, obj, fid, (jboolean)va_arg(args, int)); 1154 break; 1155 case 'B': 1156 (*env)->SetByteField(env, obj, fid, (jbyte)va_arg(args, int)); 1157 break; 1158 case 'C': 1159 (*env)->SetCharField(env, obj, fid, (jchar)va_arg(args, int)); 1160 break; 1161 case 'S': 1162 (*env)->SetShortField(env, obj, fid, (jshort)va_arg(args, int)); 1163 break; 1164 case 'I': 1165 (*env)->SetIntField(env, obj, fid, va_arg(args, jint)); 1166 break; 1167 case 'J': 1168 (*env)->SetLongField(env, obj, fid, va_arg(args, jlong)); 1169 break; 1170 case 'F': 1171 (*env)->SetFloatField(env, obj, fid, (jfloat)va_arg(args, jdouble)); 1172 break; 1173 case 'D': 1174 (*env)->SetDoubleField(env, obj, fid, va_arg(args, jdouble)); 1175 break; 1176 1177 default: 1178 (*env)->FatalError(env, "JNU_SetFieldByName: illegal signature"); 1179 } 1180 va_end(args); 1181 1182 done1: 1183 (*env)->DeleteLocalRef(env, cls); 1184 done2: 1185 if (hasException) { 1186 *hasException = (*env)->ExceptionCheck(env); 1187 } 1188 } 1189 1190 JNIEXPORT jvalue JNICALL 1191 JNU_GetStaticFieldByName(JNIEnv *env, 1192 jboolean *hasException, 1193 const char *classname, 1194 const char *name, 1195 const char *signature) 1196 { 1197 jclass cls; 1198 jfieldID fid; 1199 jvalue result; 1200 1201 result.i = 0; 1202 1203 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1204 goto done2; 1205 1206 cls = (*env)->FindClass(env, classname); 1207 if (cls == 0) 1208 goto done2; 1209 1210 fid = (*env)->GetStaticFieldID(env, cls, name, signature); 1211 if (fid == 0) 1212 goto done1; 1213 1214 switch (*signature) { 1215 case '[': 1216 case 'L': 1217 result.l = (*env)->GetStaticObjectField(env, cls, fid); 1218 break; 1219 case 'Z': 1220 result.z = (*env)->GetStaticBooleanField(env, cls, fid); 1221 break; 1222 case 'B': 1223 result.b = (*env)->GetStaticByteField(env, cls, fid); 1224 break; 1225 case 'C': 1226 result.c = (*env)->GetStaticCharField(env, cls, fid); 1227 break; 1228 case 'S': 1229 result.s = (*env)->GetStaticShortField(env, cls, fid); 1230 break; 1231 case 'I': 1232 result.i = (*env)->GetStaticIntField(env, cls, fid); 1233 break; 1234 case 'J': 1235 result.j = (*env)->GetStaticLongField(env, cls, fid); 1236 break; 1237 case 'F': 1238 result.f = (*env)->GetStaticFloatField(env, cls, fid); 1239 break; 1240 case 'D': 1241 result.d = (*env)->GetStaticDoubleField(env, cls, fid); 1242 break; 1243 1244 default: 1245 (*env)->FatalError(env, "JNU_GetStaticFieldByName: illegal signature"); 1246 } 1247 1248 done1: 1249 (*env)->DeleteLocalRef(env, cls); 1250 done2: 1251 if (hasException) { 1252 *hasException = (*env)->ExceptionCheck(env); 1253 } 1254 return result; 1255 } 1256 1257 JNIEXPORT void JNICALL 1258 JNU_SetStaticFieldByName(JNIEnv *env, 1259 jboolean *hasException, 1260 const char *classname, 1261 const char *name, 1262 const char *signature, 1263 ...) 1264 { 1265 jclass cls; 1266 jfieldID fid; 1267 va_list args; 1268 1269 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1270 goto done2; 1271 1272 cls = (*env)->FindClass(env, classname); 1273 if (cls == 0) 1274 goto done2; 1275 1276 fid = (*env)->GetStaticFieldID(env, cls, name, signature); 1277 if (fid == 0) 1278 goto done1; 1279 1280 va_start(args, signature); 1281 switch (*signature) { 1282 case '[': 1283 case 'L': 1284 (*env)->SetStaticObjectField(env, cls, fid, va_arg(args, jobject)); 1285 break; 1286 case 'Z': 1287 (*env)->SetStaticBooleanField(env, cls, fid, (jboolean)va_arg(args, int)); 1288 break; 1289 case 'B': 1290 (*env)->SetStaticByteField(env, cls, fid, (jbyte)va_arg(args, int)); 1291 break; 1292 case 'C': 1293 (*env)->SetStaticCharField(env, cls, fid, (jchar)va_arg(args, int)); 1294 break; 1295 case 'S': 1296 (*env)->SetStaticShortField(env, cls, fid, (jshort)va_arg(args, int)); 1297 break; 1298 case 'I': 1299 (*env)->SetStaticIntField(env, cls, fid, va_arg(args, jint)); 1300 break; 1301 case 'J': 1302 (*env)->SetStaticLongField(env, cls, fid, va_arg(args, jlong)); 1303 break; 1304 case 'F': 1305 (*env)->SetStaticFloatField(env, cls, fid, (jfloat)va_arg(args, jdouble)); 1306 break; 1307 case 'D': 1308 (*env)->SetStaticDoubleField(env, cls, fid, va_arg(args, jdouble)); 1309 break; 1310 1311 default: 1312 (*env)->FatalError(env, "JNU_SetStaticFieldByName: illegal signature"); 1313 } 1314 va_end(args); 1315 1316 done1: 1317 (*env)->DeleteLocalRef(env, cls); 1318 done2: 1319 if (hasException) { 1320 *hasException = (*env)->ExceptionCheck(env); 1321 } 1322 }