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