1 /* 2 * Copyright (c) 1997, 2016, 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 * getLastErrorString 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 size_t n = 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 /* 178 * Throw an exception by name, using a given message and the string 179 * returned by getLastErrorString to construct the detail string. 180 */ 181 JNIEXPORT void JNICALL 182 JNU_ThrowByNameWithMessageAndLastError 183 (JNIEnv *env, const char *name, const char *message) 184 { 185 char buf[256]; 186 size_t n = getLastErrorString(buf, sizeof(buf)); 187 size_t messagelen = message == NULL ? 0 : strlen(message); 188 189 if (n > 0) { 190 jstring s = JNU_NewStringPlatform(env, buf); 191 if (s != NULL) { 192 jobject x = NULL; 193 if (messagelen) { 194 jstring s2 = NULL; 195 size_t messageextlen = messagelen + 4; 196 char *str1 = (char *)malloc((messageextlen) * sizeof(char)); 197 if (str1 == 0) { 198 JNU_ThrowOutOfMemoryError(env, 0); 199 return; 200 } 201 jio_snprintf(str1, messageextlen, " (%s)", message); 202 s2 = (*env)->NewStringUTF(env, str1); 203 free(str1); 204 JNU_CHECK_EXCEPTION(env); 205 if (s2 != NULL) { 206 jstring s3 = JNU_CallMethodByName( 207 env, NULL, s, "concat", 208 "(Ljava/lang/String;)Ljava/lang/String;", 209 s2).l; 210 (*env)->DeleteLocalRef(env, s2); 211 JNU_CHECK_EXCEPTION(env); 212 if (s3 != NULL) { 213 (*env)->DeleteLocalRef(env, s); 214 s = s3; 215 } 216 } 217 } 218 x = JNU_NewObjectByName(env, name, "(Ljava/lang/String;)V", s); 219 if (x != NULL) { 220 (*env)->Throw(env, x); 221 } 222 } 223 } 224 225 if (!(*env)->ExceptionOccurred(env)) { 226 if (messagelen) { 227 JNU_ThrowByName(env, name, message); 228 } else { 229 JNU_ThrowByName(env, name, "no further information"); 230 } 231 } 232 } 233 234 /* 235 * Convenience method. 236 * Call JNU_ThrowByNameWithLastError for java.io.IOException. 237 */ 238 JNIEXPORT void JNICALL 239 JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail) 240 { 241 JNU_ThrowByNameWithLastError(env, "java/io/IOException", defaultDetail); 242 } 243 244 245 JNIEXPORT jvalue JNICALL 246 JNU_CallStaticMethodByName(JNIEnv *env, 247 jboolean *hasException, 248 const char *class_name, 249 const char *name, 250 const char *signature, 251 ...) 252 { 253 jclass clazz; 254 jmethodID mid; 255 va_list args; 256 jvalue result; 257 const char *p = signature; 258 259 /* find out the return type */ 260 while (*p && *p != ')') 261 p++; 262 p++; 263 264 result.i = 0; 265 266 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 267 goto done2; 268 269 clazz = (*env)->FindClass(env, class_name); 270 if (clazz == 0) 271 goto done2; 272 mid = (*env)->GetStaticMethodID(env, clazz, name, signature); 273 if (mid == 0) 274 goto done1; 275 va_start(args, signature); 276 switch (*p) { 277 case 'V': 278 (*env)->CallStaticVoidMethodV(env, clazz, mid, args); 279 break; 280 case '[': 281 case 'L': 282 result.l = (*env)->CallStaticObjectMethodV(env, clazz, mid, args); 283 break; 284 case 'Z': 285 result.z = (*env)->CallStaticBooleanMethodV(env, clazz, mid, args); 286 break; 287 case 'B': 288 result.b = (*env)->CallStaticByteMethodV(env, clazz, mid, args); 289 break; 290 case 'C': 291 result.c = (*env)->CallStaticCharMethodV(env, clazz, mid, args); 292 break; 293 case 'S': 294 result.s = (*env)->CallStaticShortMethodV(env, clazz, mid, args); 295 break; 296 case 'I': 297 result.i = (*env)->CallStaticIntMethodV(env, clazz, mid, args); 298 break; 299 case 'J': 300 result.j = (*env)->CallStaticLongMethodV(env, clazz, mid, args); 301 break; 302 case 'F': 303 result.f = (*env)->CallStaticFloatMethodV(env, clazz, mid, args); 304 break; 305 case 'D': 306 result.d = (*env)->CallStaticDoubleMethodV(env, clazz, mid, args); 307 break; 308 default: 309 (*env)->FatalError(env, "JNU_CallStaticMethodByName: illegal signature"); 310 } 311 va_end(args); 312 313 done1: 314 (*env)->DeleteLocalRef(env, clazz); 315 done2: 316 if (hasException) { 317 *hasException = (*env)->ExceptionCheck(env); 318 } 319 return result; 320 } 321 322 JNIEXPORT jvalue JNICALL 323 JNU_CallMethodByName(JNIEnv *env, 324 jboolean *hasException, 325 jobject obj, 326 const char *name, 327 const char *signature, 328 ...) 329 { 330 jvalue result; 331 va_list args; 332 333 va_start(args, signature); 334 result = JNU_CallMethodByNameV(env, hasException, obj, name, signature, 335 args); 336 va_end(args); 337 338 return result; 339 } 340 341 342 JNIEXPORT jvalue JNICALL 343 JNU_CallMethodByNameV(JNIEnv *env, 344 jboolean *hasException, 345 jobject obj, 346 const char *name, 347 const char *signature, 348 va_list args) 349 { 350 jclass clazz; 351 jmethodID mid; 352 jvalue result; 353 const char *p = signature; 354 355 /* find out the return type */ 356 while (*p && *p != ')') 357 p++; 358 p++; 359 360 result.i = 0; 361 362 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 363 goto done2; 364 365 clazz = (*env)->GetObjectClass(env, obj); 366 mid = (*env)->GetMethodID(env, clazz, name, signature); 367 if (mid == 0) 368 goto done1; 369 370 switch (*p) { 371 case 'V': 372 (*env)->CallVoidMethodV(env, obj, mid, args); 373 break; 374 case '[': 375 case 'L': 376 result.l = (*env)->CallObjectMethodV(env, obj, mid, args); 377 break; 378 case 'Z': 379 result.z = (*env)->CallBooleanMethodV(env, obj, mid, args); 380 break; 381 case 'B': 382 result.b = (*env)->CallByteMethodV(env, obj, mid, args); 383 break; 384 case 'C': 385 result.c = (*env)->CallCharMethodV(env, obj, mid, args); 386 break; 387 case 'S': 388 result.s = (*env)->CallShortMethodV(env, obj, mid, args); 389 break; 390 case 'I': 391 result.i = (*env)->CallIntMethodV(env, obj, mid, args); 392 break; 393 case 'J': 394 result.j = (*env)->CallLongMethodV(env, obj, mid, args); 395 break; 396 case 'F': 397 result.f = (*env)->CallFloatMethodV(env, obj, mid, args); 398 break; 399 case 'D': 400 result.d = (*env)->CallDoubleMethodV(env, obj, mid, args); 401 break; 402 default: 403 (*env)->FatalError(env, "JNU_CallMethodByNameV: illegal signature"); 404 } 405 done1: 406 (*env)->DeleteLocalRef(env, clazz); 407 done2: 408 if (hasException) { 409 *hasException = (*env)->ExceptionCheck(env); 410 } 411 return result; 412 } 413 414 JNIEXPORT jobject JNICALL 415 JNU_NewObjectByName(JNIEnv *env, const char *class_name, 416 const char *constructor_sig, ...) 417 { 418 jobject obj = NULL; 419 420 jclass cls = 0; 421 jmethodID cls_initMID; 422 va_list args; 423 424 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 425 goto done; 426 427 cls = (*env)->FindClass(env, class_name); 428 if (cls == 0) { 429 goto done; 430 } 431 cls_initMID = (*env)->GetMethodID(env, cls, 432 "<init>", constructor_sig); 433 if (cls_initMID == NULL) { 434 goto done; 435 } 436 va_start(args, constructor_sig); 437 obj = (*env)->NewObjectV(env, cls, cls_initMID, args); 438 va_end(args); 439 440 done: 441 (*env)->DeleteLocalRef(env, cls); 442 return obj; 443 } 444 445 /* Optimized for char set ISO_8559_1 */ 446 static jstring 447 newString8859_1(JNIEnv *env, const char *str) 448 { 449 int len = (int)strlen(str); 450 jchar buf[512]; 451 jchar *str1; 452 jstring result; 453 int i; 454 455 if (len > 512) { 456 str1 = (jchar *)malloc(len * sizeof(jchar)); 457 if (str1 == 0) { 458 JNU_ThrowOutOfMemoryError(env, 0); 459 return 0; 460 } 461 } else 462 str1 = buf; 463 464 for (i=0;i<len;i++) 465 str1[i] = (unsigned char)str[i]; 466 result = (*env)->NewString(env, str1, len); 467 if (str1 != buf) 468 free(str1); 469 return result; 470 } 471 472 static const char* 473 getString8859_1Chars(JNIEnv *env, jstring jstr) 474 { 475 int i; 476 char *result; 477 jint len = (*env)->GetStringLength(env, jstr); 478 const jchar *str = (*env)->GetStringCritical(env, jstr, 0); 479 if (str == 0) { 480 return 0; 481 } 482 483 result = MALLOC_MIN4(len); 484 if (result == 0) { 485 (*env)->ReleaseStringCritical(env, jstr, str); 486 JNU_ThrowOutOfMemoryError(env, 0); 487 return 0; 488 } 489 490 for (i=0; i<len; i++) { 491 jchar unicode = str[i]; 492 if (unicode <= 0x00ff) 493 result[i] = (char)unicode; 494 else 495 result[i] = '?'; 496 } 497 498 result[len] = 0; 499 (*env)->ReleaseStringCritical(env, jstr, str); 500 return result; 501 } 502 503 static const char* 504 getStringUTF8(JNIEnv *env, jstring jstr) 505 { 506 jsize len; 507 jsize unicode_len; 508 char *result; 509 len = (*env)->GetStringUTFLength(env, jstr); 510 unicode_len = (*env)->GetStringLength(env, jstr); 511 result = malloc(len + 1); 512 if (result == NULL) { 513 JNU_ThrowOutOfMemoryError(env, NULL); 514 return NULL; 515 } 516 (*env)->GetStringUTFRegion(env, jstr, 0, unicode_len, result); 517 518 return result; 519 } 520 521 522 /* Optimized for char set ISO646-US (us-ascii) */ 523 static jstring 524 newString646_US(JNIEnv *env, const char *str) 525 { 526 int len = (int)strlen(str); 527 jchar buf[512]; 528 jchar *str1; 529 jstring result; 530 int i; 531 532 if (len > 512) { 533 str1 = (jchar *)malloc(len * sizeof(jchar)); 534 if (str1 == 0) { 535 JNU_ThrowOutOfMemoryError(env, 0); 536 return 0; 537 } 538 } else 539 str1 = buf; 540 541 for (i=0; i<len; i++) { 542 unsigned char c = (unsigned char)str[i]; 543 if (c <= 0x7f) 544 str1[i] = c; 545 else 546 str1[i] = '?'; 547 } 548 549 result = (*env)->NewString(env, str1, len); 550 if (str1 != buf) 551 free(str1); 552 return result; 553 } 554 555 static const char* 556 getString646_USChars(JNIEnv *env, jstring jstr) 557 { 558 int i; 559 char *result; 560 jint len = (*env)->GetStringLength(env, jstr); 561 const jchar *str = (*env)->GetStringCritical(env, jstr, 0); 562 if (str == 0) { 563 return 0; 564 } 565 566 result = MALLOC_MIN4(len); 567 if (result == 0) { 568 (*env)->ReleaseStringCritical(env, jstr, str); 569 JNU_ThrowOutOfMemoryError(env, 0); 570 return 0; 571 } 572 573 for (i=0; i<len; i++) { 574 jchar unicode = str[i]; 575 if (unicode <= 0x007f ) 576 result[i] = (char)unicode; 577 else 578 result[i] = '?'; 579 } 580 581 result[len] = 0; 582 (*env)->ReleaseStringCritical(env, jstr, str); 583 return result; 584 } 585 586 /* enumeration of c1 row from Cp1252 */ 587 static int cp1252c1chars[32] = { 588 0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021, 589 0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD, 590 0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014, 591 0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178 592 }; 593 594 /* Optimized for char set Cp1252 */ 595 static jstring 596 newStringCp1252(JNIEnv *env, const char *str) 597 { 598 int len = (int) strlen(str); 599 jchar buf[512]; 600 jchar *str1; 601 jstring result; 602 int i; 603 if (len > 512) { 604 str1 = (jchar *)malloc(len * sizeof(jchar)); 605 if (str1 == 0) { 606 JNU_ThrowOutOfMemoryError(env, 0); 607 return 0; 608 } 609 } else 610 str1 = buf; 611 612 for (i=0; i<len; i++) { 613 unsigned char c = (unsigned char)str[i]; 614 if ((c >= 0x80) && (c <= 0x9f)) 615 str1[i] = cp1252c1chars[c-128]; 616 else 617 str1[i] = c; 618 } 619 620 result = (*env)->NewString(env, str1, len); 621 if (str1 != buf) 622 free(str1); 623 return result; 624 } 625 626 static const char* 627 getStringCp1252Chars(JNIEnv *env, jstring jstr) 628 { 629 int i; 630 char *result; 631 jint len = (*env)->GetStringLength(env, jstr); 632 const jchar *str = (*env)->GetStringCritical(env, jstr, 0); 633 if (str == 0) { 634 return 0; 635 } 636 637 result = MALLOC_MIN4(len); 638 if (result == 0) { 639 (*env)->ReleaseStringCritical(env, jstr, str); 640 JNU_ThrowOutOfMemoryError(env, 0); 641 return 0; 642 } 643 644 for (i=0; i<len; i++) { 645 jchar c = str[i]; 646 if (c < 256) 647 result[i] = (char)c; 648 else switch(c) { 649 case 0x20AC: result[i] = (char)0x80; break; 650 case 0x201A: result[i] = (char)0x82; break; 651 case 0x0192: result[i] = (char)0x83; break; 652 case 0x201E: result[i] = (char)0x84; break; 653 case 0x2026: result[i] = (char)0x85; break; 654 case 0x2020: result[i] = (char)0x86; break; 655 case 0x2021: result[i] = (char)0x87; break; 656 case 0x02C6: result[i] = (char)0x88; break; 657 case 0x2030: result[i] = (char)0x89; break; 658 case 0x0160: result[i] = (char)0x8A; break; 659 case 0x2039: result[i] = (char)0x8B; break; 660 case 0x0152: result[i] = (char)0x8C; break; 661 case 0x017D: result[i] = (char)0x8E; break; 662 case 0x2018: result[i] = (char)0x91; break; 663 case 0x2019: result[i] = (char)0x92; break; 664 case 0x201C: result[i] = (char)0x93; break; 665 case 0x201D: result[i] = (char)0x94; break; 666 case 0x2022: result[i] = (char)0x95; break; 667 case 0x2013: result[i] = (char)0x96; break; 668 case 0x2014: result[i] = (char)0x97; break; 669 case 0x02DC: result[i] = (char)0x98; break; 670 case 0x2122: result[i] = (char)0x99; break; 671 case 0x0161: result[i] = (char)0x9A; break; 672 case 0x203A: result[i] = (char)0x9B; break; 673 case 0x0153: result[i] = (char)0x9C; break; 674 case 0x017E: result[i] = (char)0x9E; break; 675 case 0x0178: result[i] = (char)0x9F; break; 676 default: result[i] = '?'; break; 677 } 678 } 679 680 result[len] = 0; 681 (*env)->ReleaseStringCritical(env, jstr, str); 682 return result; 683 } 684 685 static int fastEncoding = NO_ENCODING_YET; 686 static jstring jnuEncoding = NULL; 687 688 /* Cached method IDs */ 689 static jmethodID String_init_ID; /* String(byte[], enc) */ 690 static jmethodID String_getBytes_ID; /* String.getBytes(enc) */ 691 692 int getFastEncoding() { 693 return fastEncoding; 694 } 695 696 /* Initialize the fast encoding. If the "sun.jnu.encoding" property 697 * has not yet been set, we leave fastEncoding == NO_ENCODING_YET. 698 */ 699 void 700 initializeEncoding(JNIEnv *env) 701 { 702 jstring propname = 0; 703 jstring enc = 0; 704 jclass strClazz = NULL; 705 706 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 707 return; 708 709 strClazz = JNU_ClassString(env); 710 CHECK_NULL(strClazz); 711 712 propname = (*env)->NewStringUTF(env, "sun.jnu.encoding"); 713 if (propname) { 714 jboolean exc; 715 enc = JNU_CallStaticMethodByName 716 (env, 717 &exc, 718 "java/lang/System", 719 "getProperty", 720 "(Ljava/lang/String;)Ljava/lang/String;", 721 propname).l; 722 if (!exc) { 723 if (enc) { 724 const char* encname = (*env)->GetStringUTFChars(env, enc, 0); 725 if (encname) { 726 /* 727 * On Solaris with nl_langinfo() called in GetJavaProperties(): 728 * 729 * locale undefined -> NULL -> hardcoded default 730 * "C" locale -> "" -> hardcoded default (on 2.6) 731 * "C" locale -> "ISO646-US" (on Sol 7/8) 732 * "en_US" locale -> "ISO8859-1" 733 * "en_GB" locale -> "ISO8859-1" (on Sol 7/8) 734 * "en_UK" locale -> "ISO8859-1" (on 2.6) 735 */ 736 if ((strcmp(encname, "8859_1") == 0) || 737 (strcmp(encname, "ISO8859-1") == 0) || 738 (strcmp(encname, "ISO8859_1") == 0) || 739 (strcmp(encname, "ISO-8859-1") == 0)) 740 fastEncoding = FAST_8859_1; 741 else if (strcmp(encname, "UTF-8") == 0) 742 fastEncoding = FAST_UTF_8; 743 else if (strcmp(encname, "ISO646-US") == 0) 744 fastEncoding = FAST_646_US; 745 else if (strcmp(encname, "Cp1252") == 0 || 746 /* This is a temporary fix until we move */ 747 /* to wide character versions of all Windows */ 748 /* calls. */ 749 strcmp(encname, "utf-16le") == 0) 750 fastEncoding = FAST_CP1252; 751 else { 752 fastEncoding = NO_FAST_ENCODING; 753 jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc); 754 } 755 (*env)->ReleaseStringUTFChars(env, enc, encname); 756 } 757 } 758 } else { 759 (*env)->ExceptionClear(env); 760 } 761 } else { 762 (*env)->ExceptionClear(env); 763 } 764 (*env)->DeleteLocalRef(env, propname); 765 (*env)->DeleteLocalRef(env, enc); 766 767 /* Initialize method-id cache */ 768 String_getBytes_ID = (*env)->GetMethodID(env, strClazz, 769 "getBytes", "(Ljava/lang/String;)[B"); 770 CHECK_NULL(String_getBytes_ID); 771 String_init_ID = (*env)->GetMethodID(env, strClazz, 772 "<init>", "([BLjava/lang/String;)V"); 773 } 774 775 static jboolean isJNUEncodingSupported = JNI_FALSE; 776 static jboolean jnuEncodingSupported(JNIEnv *env) { 777 jboolean exe; 778 if (isJNUEncodingSupported == JNI_TRUE) { 779 return JNI_TRUE; 780 } 781 isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName ( 782 env, &exe, 783 "java/nio/charset/Charset", 784 "isSupported", 785 "(Ljava/lang/String;)Z", 786 jnuEncoding).z; 787 return isJNUEncodingSupported; 788 } 789 790 791 JNIEXPORT jstring 792 NewStringPlatform(JNIEnv *env, const char *str) 793 { 794 return JNU_NewStringPlatform(env, str); 795 } 796 797 JNIEXPORT jstring JNICALL 798 JNU_NewStringPlatform(JNIEnv *env, const char *str) 799 { 800 jstring result = NULL; 801 jbyteArray hab = 0; 802 int len; 803 804 if (fastEncoding == NO_ENCODING_YET) { 805 initializeEncoding(env); 806 JNU_CHECK_EXCEPTION_RETURN(env, NULL); 807 } 808 809 if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET)) 810 return newString8859_1(env, str); 811 if (fastEncoding == FAST_646_US) 812 return newString646_US(env, str); 813 if (fastEncoding == FAST_CP1252) 814 return newStringCp1252(env, str); 815 if (fastEncoding == FAST_UTF_8) 816 return (*env)->NewStringUTF(env, str); 817 818 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 819 return NULL; 820 821 len = (int)strlen(str); 822 hab = (*env)->NewByteArray(env, len); 823 if (hab != 0) { 824 jclass strClazz = JNU_ClassString(env); 825 CHECK_NULL_RETURN(strClazz, 0); 826 (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str); 827 if (jnuEncodingSupported(env)) { 828 result = (*env)->NewObject(env, strClazz, 829 String_init_ID, hab, jnuEncoding); 830 } else { 831 /*If the encoding specified in sun.jnu.encoding is not endorsed 832 by "Charset.isSupported" we have to fall back to use String(byte[]) 833 explicitly here without specifying the encoding name, in which the 834 StringCoding class will pickup the iso-8859-1 as the fallback 835 converter for us. 836 */ 837 jmethodID mid = (*env)->GetMethodID(env, strClazz, 838 "<init>", "([B)V"); 839 if (mid != NULL) { 840 result = (*env)->NewObject(env, strClazz, mid, hab); 841 } 842 } 843 (*env)->DeleteLocalRef(env, hab); 844 return result; 845 } 846 return NULL; 847 } 848 849 JNIEXPORT const char * 850 GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) 851 { 852 return JNU_GetStringPlatformChars(env, jstr, isCopy); 853 } 854 855 JNIEXPORT const char * JNICALL 856 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) 857 { 858 char *result = NULL; 859 jbyteArray hab = 0; 860 861 if (isCopy) 862 *isCopy = JNI_TRUE; 863 864 if (fastEncoding == NO_ENCODING_YET) { 865 initializeEncoding(env); 866 JNU_CHECK_EXCEPTION_RETURN(env, 0); 867 } 868 869 if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET)) 870 return getString8859_1Chars(env, jstr); 871 if (fastEncoding == FAST_646_US) 872 return getString646_USChars(env, jstr); 873 if (fastEncoding == FAST_CP1252) 874 return getStringCp1252Chars(env, jstr); 875 if (fastEncoding == FAST_UTF_8) 876 return getStringUTF8(env, jstr); 877 878 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 879 return 0; 880 881 if (jnuEncodingSupported(env)) { 882 hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding); 883 } else { 884 jmethodID mid; 885 jclass strClazz = JNU_ClassString(env); 886 CHECK_NULL_RETURN(strClazz, 0); 887 mid = (*env)->GetMethodID(env, strClazz, 888 "getBytes", "()[B"); 889 if (mid != NULL) { 890 hab = (*env)->CallObjectMethod(env, jstr, mid); 891 } 892 } 893 894 if (!(*env)->ExceptionCheck(env)) { 895 jint len = (*env)->GetArrayLength(env, hab); 896 result = MALLOC_MIN4(len); 897 if (result == 0) { 898 JNU_ThrowOutOfMemoryError(env, 0); 899 (*env)->DeleteLocalRef(env, hab); 900 return 0; 901 } 902 (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result); 903 result[len] = 0; /* NULL-terminate */ 904 } 905 906 (*env)->DeleteLocalRef(env, hab); 907 return result; 908 } 909 910 JNIEXPORT void JNICALL 911 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str) 912 { 913 free((void *)str); 914 } 915 916 /* 917 * Export the platform dependent path canonicalization so that 918 * VM can find it when loading system classes. 919 * This function is also used by the instrumentation agent. 920 */ 921 extern int canonicalize(char *path, const char *out, int len); 922 923 JNIEXPORT int 924 Canonicalize(JNIEnv *unused, char *orig, char *out, int len) 925 { 926 /* canonicalize an already natived path */ 927 return canonicalize(orig, out, len); 928 } 929 930 JNIEXPORT jclass JNICALL 931 JNU_ClassString(JNIEnv *env) 932 { 933 static jclass cls = 0; 934 if (cls == 0) { 935 jclass c; 936 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 937 return 0; 938 c = (*env)->FindClass(env, "java/lang/String"); 939 CHECK_NULL_RETURN(c, NULL); 940 cls = (*env)->NewGlobalRef(env, c); 941 (*env)->DeleteLocalRef(env, c); 942 } 943 return cls; 944 } 945 946 JNIEXPORT jclass JNICALL 947 JNU_ClassClass(JNIEnv *env) 948 { 949 static jclass cls = 0; 950 if (cls == 0) { 951 jclass c; 952 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 953 return 0; 954 c = (*env)->FindClass(env, "java/lang/Class"); 955 CHECK_NULL_RETURN(c, NULL); 956 cls = (*env)->NewGlobalRef(env, c); 957 (*env)->DeleteLocalRef(env, c); 958 } 959 return cls; 960 } 961 962 JNIEXPORT jclass JNICALL 963 JNU_ClassObject(JNIEnv *env) 964 { 965 static jclass cls = 0; 966 if (cls == 0) { 967 jclass c; 968 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 969 return 0; 970 c = (*env)->FindClass(env, "java/lang/Object"); 971 CHECK_NULL_RETURN(c, NULL); 972 cls = (*env)->NewGlobalRef(env, c); 973 (*env)->DeleteLocalRef(env, c); 974 } 975 return cls; 976 } 977 978 JNIEXPORT jclass JNICALL 979 JNU_ClassThrowable(JNIEnv *env) 980 { 981 static jclass cls = 0; 982 if (cls == 0) { 983 jclass c; 984 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 985 return 0; 986 c = (*env)->FindClass(env, "java/lang/Throwable"); 987 CHECK_NULL_RETURN(c, NULL); 988 cls = (*env)->NewGlobalRef(env, c); 989 (*env)->DeleteLocalRef(env, c); 990 } 991 return cls; 992 } 993 994 JNIEXPORT jint JNICALL 995 JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src, 996 jint count) 997 { 998 int i; 999 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 1000 return -1; 1001 for (i=0; i<count; i++) { 1002 jstring p = (*env)->GetObjectArrayElement(env, src, i); 1003 (*env)->SetObjectArrayElement(env, dst, i, p); 1004 (*env)->DeleteLocalRef(env, p); 1005 } 1006 return 0; 1007 } 1008 1009 JNIEXPORT void * JNICALL 1010 JNU_GetEnv(JavaVM *vm, jint version) 1011 { 1012 void *env; 1013 (*vm)->GetEnv(vm, &env, version); 1014 return env; 1015 } 1016 1017 JNIEXPORT jint JNICALL 1018 JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char* classname) 1019 { 1020 jclass cls; 1021 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 1022 return JNI_ERR; 1023 cls = (*env)->FindClass(env, classname); 1024 if (cls != NULL) { 1025 jint result = (*env)->IsInstanceOf(env, object, cls); 1026 (*env)->DeleteLocalRef(env, cls); 1027 return result; 1028 } 1029 return JNI_ERR; 1030 } 1031 1032 JNIEXPORT jboolean JNICALL 1033 JNU_Equals(JNIEnv *env, jobject object1, jobject object2) 1034 { 1035 static jmethodID mid = NULL; 1036 if (mid == NULL) { 1037 jclass objClazz = JNU_ClassObject(env); 1038 CHECK_NULL_RETURN(objClazz, JNI_FALSE); 1039 mid = (*env)->GetMethodID(env, objClazz, "equals", 1040 "(Ljava/lang/Object;)Z"); 1041 CHECK_NULL_RETURN(mid, JNI_FALSE); 1042 } 1043 return (*env)->CallBooleanMethod(env, object1, mid, object2); 1044 } 1045 1046 1047 /************************************************************************ 1048 * Thread calls 1049 */ 1050 1051 static jmethodID Object_waitMID; 1052 static jmethodID Object_notifyMID; 1053 static jmethodID Object_notifyAllMID; 1054 1055 JNIEXPORT void JNICALL 1056 JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout) 1057 { 1058 if (object == NULL) { 1059 JNU_ThrowNullPointerException(env, "JNU_MonitorWait argument"); 1060 return; 1061 } 1062 if (Object_waitMID == NULL) { 1063 jclass cls = JNU_ClassObject(env); 1064 if (cls == NULL) { 1065 return; 1066 } 1067 Object_waitMID = (*env)->GetMethodID(env, cls, "wait", "(J)V"); 1068 if (Object_waitMID == NULL) { 1069 return; 1070 } 1071 } 1072 (*env)->CallVoidMethod(env, object, Object_waitMID, timeout); 1073 } 1074 1075 JNIEXPORT void JNICALL 1076 JNU_Notify(JNIEnv *env, jobject object) 1077 { 1078 if (object == NULL) { 1079 JNU_ThrowNullPointerException(env, "JNU_Notify argument"); 1080 return; 1081 } 1082 if (Object_notifyMID == NULL) { 1083 jclass cls = JNU_ClassObject(env); 1084 if (cls == NULL) { 1085 return; 1086 } 1087 Object_notifyMID = (*env)->GetMethodID(env, cls, "notify", "()V"); 1088 if (Object_notifyMID == NULL) { 1089 return; 1090 } 1091 } 1092 (*env)->CallVoidMethod(env, object, Object_notifyMID); 1093 } 1094 1095 JNIEXPORT void JNICALL 1096 JNU_NotifyAll(JNIEnv *env, jobject object) 1097 { 1098 if (object == NULL) { 1099 JNU_ThrowNullPointerException(env, "JNU_NotifyAll argument"); 1100 return; 1101 } 1102 if (Object_notifyAllMID == NULL) { 1103 jclass cls = JNU_ClassObject(env); 1104 if (cls == NULL) { 1105 return; 1106 } 1107 Object_notifyAllMID = (*env)->GetMethodID(env, cls,"notifyAll", "()V"); 1108 if (Object_notifyAllMID == NULL) { 1109 return; 1110 } 1111 } 1112 (*env)->CallVoidMethod(env, object, Object_notifyAllMID); 1113 } 1114 1115 1116 /************************************************************************ 1117 * Debugging utilities 1118 */ 1119 1120 JNIEXPORT void JNICALL 1121 JNU_PrintString(JNIEnv *env, char *hdr, jstring string) 1122 { 1123 if (string == NULL) { 1124 fprintf(stderr, "%s: is NULL\n", hdr); 1125 } else { 1126 const char *stringPtr = JNU_GetStringPlatformChars(env, string, 0); 1127 if (stringPtr == 0) 1128 return; 1129 fprintf(stderr, "%s: %s\n", hdr, stringPtr); 1130 JNU_ReleaseStringPlatformChars(env, string, stringPtr); 1131 } 1132 } 1133 1134 JNIEXPORT void JNICALL 1135 JNU_PrintClass(JNIEnv *env, char* hdr, jobject object) 1136 { 1137 if (object == NULL) { 1138 fprintf(stderr, "%s: object is NULL\n", hdr); 1139 return; 1140 } else { 1141 jclass cls = (*env)->GetObjectClass(env, object); 1142 jstring clsName = JNU_ToString(env, cls); 1143 if (clsName == NULL) { 1144 JNU_PrintString(env, hdr, clsName); 1145 } 1146 (*env)->DeleteLocalRef(env, cls); 1147 (*env)->DeleteLocalRef(env, clsName); 1148 } 1149 } 1150 1151 JNIEXPORT jstring JNICALL 1152 JNU_ToString(JNIEnv *env, jobject object) 1153 { 1154 if (object == NULL) { 1155 return (*env)->NewStringUTF(env, "NULL"); 1156 } else { 1157 return (jstring)JNU_CallMethodByName(env, 1158 NULL, 1159 object, 1160 "toString", 1161 "()Ljava/lang/String;").l; 1162 } 1163 } 1164 1165 JNIEXPORT jvalue JNICALL 1166 JNU_GetFieldByName(JNIEnv *env, 1167 jboolean *hasException, 1168 jobject obj, 1169 const char *name, 1170 const char *signature) 1171 { 1172 jclass cls; 1173 jfieldID fid; 1174 jvalue result; 1175 1176 result.i = 0; 1177 1178 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1179 goto done2; 1180 1181 cls = (*env)->GetObjectClass(env, obj); 1182 fid = (*env)->GetFieldID(env, cls, name, signature); 1183 if (fid == 0) 1184 goto done1; 1185 1186 switch (*signature) { 1187 case '[': 1188 case 'L': 1189 result.l = (*env)->GetObjectField(env, obj, fid); 1190 break; 1191 case 'Z': 1192 result.z = (*env)->GetBooleanField(env, obj, fid); 1193 break; 1194 case 'B': 1195 result.b = (*env)->GetByteField(env, obj, fid); 1196 break; 1197 case 'C': 1198 result.c = (*env)->GetCharField(env, obj, fid); 1199 break; 1200 case 'S': 1201 result.s = (*env)->GetShortField(env, obj, fid); 1202 break; 1203 case 'I': 1204 result.i = (*env)->GetIntField(env, obj, fid); 1205 break; 1206 case 'J': 1207 result.j = (*env)->GetLongField(env, obj, fid); 1208 break; 1209 case 'F': 1210 result.f = (*env)->GetFloatField(env, obj, fid); 1211 break; 1212 case 'D': 1213 result.d = (*env)->GetDoubleField(env, obj, fid); 1214 break; 1215 1216 default: 1217 (*env)->FatalError(env, "JNU_GetFieldByName: illegal signature"); 1218 } 1219 1220 done1: 1221 (*env)->DeleteLocalRef(env, cls); 1222 done2: 1223 if (hasException) { 1224 *hasException = (*env)->ExceptionCheck(env); 1225 } 1226 return result; 1227 } 1228 1229 JNIEXPORT void JNICALL 1230 JNU_SetFieldByName(JNIEnv *env, 1231 jboolean *hasException, 1232 jobject obj, 1233 const char *name, 1234 const char *signature, 1235 ...) 1236 { 1237 jclass cls; 1238 jfieldID fid; 1239 va_list args; 1240 1241 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1242 goto done2; 1243 1244 cls = (*env)->GetObjectClass(env, obj); 1245 fid = (*env)->GetFieldID(env, cls, name, signature); 1246 if (fid == 0) 1247 goto done1; 1248 1249 va_start(args, signature); 1250 switch (*signature) { 1251 case '[': 1252 case 'L': 1253 (*env)->SetObjectField(env, obj, fid, va_arg(args, jobject)); 1254 break; 1255 case 'Z': 1256 (*env)->SetBooleanField(env, obj, fid, (jboolean)va_arg(args, int)); 1257 break; 1258 case 'B': 1259 (*env)->SetByteField(env, obj, fid, (jbyte)va_arg(args, int)); 1260 break; 1261 case 'C': 1262 (*env)->SetCharField(env, obj, fid, (jchar)va_arg(args, int)); 1263 break; 1264 case 'S': 1265 (*env)->SetShortField(env, obj, fid, (jshort)va_arg(args, int)); 1266 break; 1267 case 'I': 1268 (*env)->SetIntField(env, obj, fid, va_arg(args, jint)); 1269 break; 1270 case 'J': 1271 (*env)->SetLongField(env, obj, fid, va_arg(args, jlong)); 1272 break; 1273 case 'F': 1274 (*env)->SetFloatField(env, obj, fid, (jfloat)va_arg(args, jdouble)); 1275 break; 1276 case 'D': 1277 (*env)->SetDoubleField(env, obj, fid, va_arg(args, jdouble)); 1278 break; 1279 1280 default: 1281 (*env)->FatalError(env, "JNU_SetFieldByName: illegal signature"); 1282 } 1283 va_end(args); 1284 1285 done1: 1286 (*env)->DeleteLocalRef(env, cls); 1287 done2: 1288 if (hasException) { 1289 *hasException = (*env)->ExceptionCheck(env); 1290 } 1291 } 1292 1293 JNIEXPORT jvalue JNICALL 1294 JNU_GetStaticFieldByName(JNIEnv *env, 1295 jboolean *hasException, 1296 const char *classname, 1297 const char *name, 1298 const char *signature) 1299 { 1300 jclass cls; 1301 jfieldID fid; 1302 jvalue result; 1303 1304 result.i = 0; 1305 1306 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1307 goto done2; 1308 1309 cls = (*env)->FindClass(env, classname); 1310 if (cls == 0) 1311 goto done2; 1312 1313 fid = (*env)->GetStaticFieldID(env, cls, name, signature); 1314 if (fid == 0) 1315 goto done1; 1316 1317 switch (*signature) { 1318 case '[': 1319 case 'L': 1320 result.l = (*env)->GetStaticObjectField(env, cls, fid); 1321 break; 1322 case 'Z': 1323 result.z = (*env)->GetStaticBooleanField(env, cls, fid); 1324 break; 1325 case 'B': 1326 result.b = (*env)->GetStaticByteField(env, cls, fid); 1327 break; 1328 case 'C': 1329 result.c = (*env)->GetStaticCharField(env, cls, fid); 1330 break; 1331 case 'S': 1332 result.s = (*env)->GetStaticShortField(env, cls, fid); 1333 break; 1334 case 'I': 1335 result.i = (*env)->GetStaticIntField(env, cls, fid); 1336 break; 1337 case 'J': 1338 result.j = (*env)->GetStaticLongField(env, cls, fid); 1339 break; 1340 case 'F': 1341 result.f = (*env)->GetStaticFloatField(env, cls, fid); 1342 break; 1343 case 'D': 1344 result.d = (*env)->GetStaticDoubleField(env, cls, fid); 1345 break; 1346 1347 default: 1348 (*env)->FatalError(env, "JNU_GetStaticFieldByName: illegal signature"); 1349 } 1350 1351 done1: 1352 (*env)->DeleteLocalRef(env, cls); 1353 done2: 1354 if (hasException) { 1355 *hasException = (*env)->ExceptionCheck(env); 1356 } 1357 return result; 1358 } 1359 1360 JNIEXPORT void JNICALL 1361 JNU_SetStaticFieldByName(JNIEnv *env, 1362 jboolean *hasException, 1363 const char *classname, 1364 const char *name, 1365 const char *signature, 1366 ...) 1367 { 1368 jclass cls; 1369 jfieldID fid; 1370 va_list args; 1371 1372 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1373 goto done2; 1374 1375 cls = (*env)->FindClass(env, classname); 1376 if (cls == 0) 1377 goto done2; 1378 1379 fid = (*env)->GetStaticFieldID(env, cls, name, signature); 1380 if (fid == 0) 1381 goto done1; 1382 1383 va_start(args, signature); 1384 switch (*signature) { 1385 case '[': 1386 case 'L': 1387 (*env)->SetStaticObjectField(env, cls, fid, va_arg(args, jobject)); 1388 break; 1389 case 'Z': 1390 (*env)->SetStaticBooleanField(env, cls, fid, (jboolean)va_arg(args, int)); 1391 break; 1392 case 'B': 1393 (*env)->SetStaticByteField(env, cls, fid, (jbyte)va_arg(args, int)); 1394 break; 1395 case 'C': 1396 (*env)->SetStaticCharField(env, cls, fid, (jchar)va_arg(args, int)); 1397 break; 1398 case 'S': 1399 (*env)->SetStaticShortField(env, cls, fid, (jshort)va_arg(args, int)); 1400 break; 1401 case 'I': 1402 (*env)->SetStaticIntField(env, cls, fid, va_arg(args, jint)); 1403 break; 1404 case 'J': 1405 (*env)->SetStaticLongField(env, cls, fid, va_arg(args, jlong)); 1406 break; 1407 case 'F': 1408 (*env)->SetStaticFloatField(env, cls, fid, (jfloat)va_arg(args, jdouble)); 1409 break; 1410 case 'D': 1411 (*env)->SetStaticDoubleField(env, cls, fid, va_arg(args, jdouble)); 1412 break; 1413 1414 default: 1415 (*env)->FatalError(env, "JNU_SetStaticFieldByName: illegal signature"); 1416 } 1417 va_end(args); 1418 1419 done1: 1420 (*env)->DeleteLocalRef(env, cls); 1421 done2: 1422 if (hasException) { 1423 *hasException = (*env)->ExceptionCheck(env); 1424 } 1425 }