1 /* 2 * Copyright (c) 1997, 2015, 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 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 /* 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 = (int)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 jclass strClazz = NULL; 630 631 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 632 return; 633 634 strClazz = JNU_ClassString(env); 635 CHECK_NULL(strClazz); 636 637 propname = (*env)->NewStringUTF(env, "sun.jnu.encoding"); 638 if (propname) { 639 jboolean exc; 640 enc = JNU_CallStaticMethodByName 641 (env, 642 &exc, 643 "java/lang/System", 644 "getProperty", 645 "(Ljava/lang/String;)Ljava/lang/String;", 646 propname).l; 647 if (!exc) { 648 if (enc) { 649 const char* encname = (*env)->GetStringUTFChars(env, enc, 0); 650 if (encname) { 651 /* 652 * On Solaris with nl_langinfo() called in GetJavaProperties(): 653 * 654 * locale undefined -> NULL -> hardcoded default 655 * "C" locale -> "" -> hardcoded default (on 2.6) 656 * "C" locale -> "ISO646-US" (on Sol 7/8) 657 * "en_US" locale -> "ISO8859-1" 658 * "en_GB" locale -> "ISO8859-1" (on Sol 7/8) 659 * "en_UK" locale -> "ISO8859-1" (on 2.6) 660 */ 661 if ((strcmp(encname, "8859_1") == 0) || 662 (strcmp(encname, "ISO8859-1") == 0) || 663 (strcmp(encname, "ISO8859_1") == 0)) 664 fastEncoding = FAST_8859_1; 665 else if (strcmp(encname, "ISO646-US") == 0) 666 fastEncoding = FAST_646_US; 667 else if (strcmp(encname, "Cp1252") == 0 || 668 /* This is a temporary fix until we move */ 669 /* to wide character versions of all Windows */ 670 /* calls. */ 671 strcmp(encname, "utf-16le") == 0) 672 fastEncoding = FAST_CP1252; 673 else { 674 fastEncoding = NO_FAST_ENCODING; 675 jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc); 676 } 677 (*env)->ReleaseStringUTFChars(env, enc, encname); 678 } 679 } 680 } else { 681 (*env)->ExceptionClear(env); 682 } 683 } else { 684 (*env)->ExceptionClear(env); 685 } 686 (*env)->DeleteLocalRef(env, propname); 687 (*env)->DeleteLocalRef(env, enc); 688 689 /* Initialize method-id cache */ 690 String_getBytes_ID = (*env)->GetMethodID(env, strClazz, 691 "getBytes", "(Ljava/lang/String;)[B"); 692 CHECK_NULL(String_getBytes_ID); 693 String_init_ID = (*env)->GetMethodID(env, strClazz, 694 "<init>", "([BLjava/lang/String;)V"); 695 } 696 697 static jboolean isJNUEncodingSupported = JNI_FALSE; 698 static jboolean jnuEncodingSupported(JNIEnv *env) { 699 jboolean exe; 700 if (isJNUEncodingSupported == JNI_TRUE) { 701 return JNI_TRUE; 702 } 703 isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName ( 704 env, &exe, 705 "java/nio/charset/Charset", 706 "isSupported", 707 "(Ljava/lang/String;)Z", 708 jnuEncoding).z; 709 return isJNUEncodingSupported; 710 } 711 712 static jboolean _warnUnsupportedEncoding = JNI_TRUE; 713 static void warnUnsupportedEncoding(JNIEnv *env) { 714 if (_warnUnsupportedEncoding) { 715 _warnUnsupportedEncoding = JNI_FALSE; 716 jio_fprintf(stderr, 717 "Warning: encoding '%s' not supported - falling back to default encoding.\n", 718 (*env)->GetStringUTFChars(env, jnuEncoding, 0)); 719 } 720 } 721 722 JNIEXPORT jstring 723 NewStringPlatform(JNIEnv *env, const char *str) 724 { 725 return JNU_NewStringPlatform(env, str); 726 } 727 728 JNIEXPORT jstring JNICALL 729 JNU_NewStringPlatform(JNIEnv *env, const char *str) 730 { 731 jstring result = NULL; 732 jbyteArray hab = 0; 733 int len; 734 735 if (fastEncoding == NO_ENCODING_YET) { 736 initializeEncoding(env); 737 JNU_CHECK_EXCEPTION_RETURN(env, NULL); 738 } 739 740 if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET)) 741 return newString8859_1(env, str); 742 if (fastEncoding == FAST_646_US) 743 return newString646_US(env, str); 744 if (fastEncoding == FAST_CP1252) 745 return newStringCp1252(env, str); 746 747 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 748 return NULL; 749 750 len = (int)strlen(str); 751 hab = (*env)->NewByteArray(env, len); 752 if (hab != 0) { 753 jclass strClazz = JNU_ClassString(env); 754 CHECK_NULL_RETURN(strClazz, 0); 755 (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str); 756 if (jnuEncodingSupported(env)) { 757 result = (*env)->NewObject(env, strClazz, 758 String_init_ID, hab, jnuEncoding); 759 } else { 760 warnUnsupportedEncoding(env); 761 /*If the encoding specified in sun.jnu.encoding is not endorsed 762 by "Charset.isSupported" we have to fall back to use String(byte[]) 763 explicitly here without specifying the encoding name, in which the 764 StringCoding class will pickup the iso-8859-1 as the fallback 765 converter for us. 766 */ 767 jmethodID mid = (*env)->GetMethodID(env, strClazz, 768 "<init>", "([B)V"); 769 if (mid != NULL) { 770 result = (*env)->NewObject(env, strClazz, mid, hab); 771 } 772 } 773 (*env)->DeleteLocalRef(env, hab); 774 return result; 775 } 776 return NULL; 777 } 778 779 JNIEXPORT const char * 780 GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) 781 { 782 return JNU_GetStringPlatformChars(env, jstr, isCopy); 783 } 784 785 JNIEXPORT const char * JNICALL 786 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) 787 { 788 char *result = NULL; 789 jbyteArray hab = 0; 790 791 if (isCopy) 792 *isCopy = JNI_TRUE; 793 794 if (fastEncoding == NO_ENCODING_YET) { 795 initializeEncoding(env); 796 JNU_CHECK_EXCEPTION_RETURN(env, 0); 797 } 798 799 if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET)) 800 return getString8859_1Chars(env, jstr); 801 if (fastEncoding == FAST_646_US) 802 return getString646_USChars(env, jstr); 803 if (fastEncoding == FAST_CP1252) 804 return getStringCp1252Chars(env, jstr); 805 806 if ((*env)->EnsureLocalCapacity(env, 2) < 0) 807 return 0; 808 809 if (jnuEncodingSupported(env)) { 810 hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding); 811 } else { 812 warnUnsupportedEncoding(env); 813 jmethodID mid; 814 jclass strClazz = JNU_ClassString(env); 815 CHECK_NULL_RETURN(strClazz, 0); 816 mid = (*env)->GetMethodID(env, strClazz, 817 "getBytes", "()[B"); 818 if (mid != NULL) { 819 hab = (*env)->CallObjectMethod(env, jstr, mid); 820 } 821 } 822 823 if (!(*env)->ExceptionCheck(env)) { 824 jint len = (*env)->GetArrayLength(env, hab); 825 result = MALLOC_MIN4(len); 826 if (result == 0) { 827 JNU_ThrowOutOfMemoryError(env, 0); 828 (*env)->DeleteLocalRef(env, hab); 829 return 0; 830 } 831 (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result); 832 result[len] = 0; /* NULL-terminate */ 833 } 834 835 (*env)->DeleteLocalRef(env, hab); 836 return result; 837 } 838 839 JNIEXPORT void JNICALL 840 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str) 841 { 842 free((void *)str); 843 } 844 845 /* 846 * Export the platform dependent path canonicalization so that 847 * VM can find it when loading system classes. 848 * This function is also used by the instrumentation agent. 849 */ 850 extern int canonicalize(char *path, const char *out, int len); 851 852 JNIEXPORT int 853 Canonicalize(JNIEnv *unused, char *orig, char *out, int len) 854 { 855 /* canonicalize an already natived path */ 856 return canonicalize(orig, out, len); 857 } 858 859 JNIEXPORT jclass JNICALL 860 JNU_ClassString(JNIEnv *env) 861 { 862 static jclass cls = 0; 863 if (cls == 0) { 864 jclass c; 865 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 866 return 0; 867 c = (*env)->FindClass(env, "java/lang/String"); 868 CHECK_NULL_RETURN(c, NULL); 869 cls = (*env)->NewGlobalRef(env, c); 870 (*env)->DeleteLocalRef(env, c); 871 } 872 return cls; 873 } 874 875 JNIEXPORT jclass JNICALL 876 JNU_ClassClass(JNIEnv *env) 877 { 878 static jclass cls = 0; 879 if (cls == 0) { 880 jclass c; 881 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 882 return 0; 883 c = (*env)->FindClass(env, "java/lang/Class"); 884 CHECK_NULL_RETURN(c, NULL); 885 cls = (*env)->NewGlobalRef(env, c); 886 (*env)->DeleteLocalRef(env, c); 887 } 888 return cls; 889 } 890 891 JNIEXPORT jclass JNICALL 892 JNU_ClassObject(JNIEnv *env) 893 { 894 static jclass cls = 0; 895 if (cls == 0) { 896 jclass c; 897 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 898 return 0; 899 c = (*env)->FindClass(env, "java/lang/Object"); 900 CHECK_NULL_RETURN(c, NULL); 901 cls = (*env)->NewGlobalRef(env, c); 902 (*env)->DeleteLocalRef(env, c); 903 } 904 return cls; 905 } 906 907 JNIEXPORT jclass JNICALL 908 JNU_ClassThrowable(JNIEnv *env) 909 { 910 static jclass cls = 0; 911 if (cls == 0) { 912 jclass c; 913 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 914 return 0; 915 c = (*env)->FindClass(env, "java/lang/Throwable"); 916 CHECK_NULL_RETURN(c, NULL); 917 cls = (*env)->NewGlobalRef(env, c); 918 (*env)->DeleteLocalRef(env, c); 919 } 920 return cls; 921 } 922 923 JNIEXPORT jint JNICALL 924 JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src, 925 jint count) 926 { 927 int i; 928 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 929 return -1; 930 for (i=0; i<count; i++) { 931 jstring p = (*env)->GetObjectArrayElement(env, src, i); 932 (*env)->SetObjectArrayElement(env, dst, i, p); 933 (*env)->DeleteLocalRef(env, p); 934 } 935 return 0; 936 } 937 938 JNIEXPORT void * JNICALL 939 JNU_GetEnv(JavaVM *vm, jint version) 940 { 941 void *env; 942 (*vm)->GetEnv(vm, &env, version); 943 return env; 944 } 945 946 JNIEXPORT jint JNICALL 947 JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char* classname) 948 { 949 jclass cls; 950 if ((*env)->EnsureLocalCapacity(env, 1) < 0) 951 return JNI_ERR; 952 cls = (*env)->FindClass(env, classname); 953 if (cls != NULL) { 954 jint result = (*env)->IsInstanceOf(env, object, cls); 955 (*env)->DeleteLocalRef(env, cls); 956 return result; 957 } 958 return JNI_ERR; 959 } 960 961 JNIEXPORT jboolean JNICALL 962 JNU_Equals(JNIEnv *env, jobject object1, jobject object2) 963 { 964 static jmethodID mid = NULL; 965 if (mid == NULL) { 966 jclass objClazz = JNU_ClassObject(env); 967 CHECK_NULL_RETURN(objClazz, JNI_FALSE); 968 mid = (*env)->GetMethodID(env, objClazz, "equals", 969 "(Ljava/lang/Object;)Z"); 970 CHECK_NULL_RETURN(mid, JNI_FALSE); 971 } 972 return (*env)->CallBooleanMethod(env, object1, mid, object2); 973 } 974 975 976 /************************************************************************ 977 * Thread calls 978 */ 979 980 static jmethodID Object_waitMID; 981 static jmethodID Object_notifyMID; 982 static jmethodID Object_notifyAllMID; 983 984 JNIEXPORT void JNICALL 985 JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout) 986 { 987 if (object == NULL) { 988 JNU_ThrowNullPointerException(env, "JNU_MonitorWait argument"); 989 return; 990 } 991 if (Object_waitMID == NULL) { 992 jclass cls = JNU_ClassObject(env); 993 if (cls == NULL) { 994 return; 995 } 996 Object_waitMID = (*env)->GetMethodID(env, cls, "wait", "(J)V"); 997 if (Object_waitMID == NULL) { 998 return; 999 } 1000 } 1001 (*env)->CallVoidMethod(env, object, Object_waitMID, timeout); 1002 } 1003 1004 JNIEXPORT void JNICALL 1005 JNU_Notify(JNIEnv *env, jobject object) 1006 { 1007 if (object == NULL) { 1008 JNU_ThrowNullPointerException(env, "JNU_Notify argument"); 1009 return; 1010 } 1011 if (Object_notifyMID == NULL) { 1012 jclass cls = JNU_ClassObject(env); 1013 if (cls == NULL) { 1014 return; 1015 } 1016 Object_notifyMID = (*env)->GetMethodID(env, cls, "notify", "()V"); 1017 if (Object_notifyMID == NULL) { 1018 return; 1019 } 1020 } 1021 (*env)->CallVoidMethod(env, object, Object_notifyMID); 1022 } 1023 1024 JNIEXPORT void JNICALL 1025 JNU_NotifyAll(JNIEnv *env, jobject object) 1026 { 1027 if (object == NULL) { 1028 JNU_ThrowNullPointerException(env, "JNU_NotifyAll argument"); 1029 return; 1030 } 1031 if (Object_notifyAllMID == NULL) { 1032 jclass cls = JNU_ClassObject(env); 1033 if (cls == NULL) { 1034 return; 1035 } 1036 Object_notifyAllMID = (*env)->GetMethodID(env, cls,"notifyAll", "()V"); 1037 if (Object_notifyAllMID == NULL) { 1038 return; 1039 } 1040 } 1041 (*env)->CallVoidMethod(env, object, Object_notifyAllMID); 1042 } 1043 1044 1045 /************************************************************************ 1046 * Debugging utilities 1047 */ 1048 1049 JNIEXPORT void JNICALL 1050 JNU_PrintString(JNIEnv *env, char *hdr, jstring string) 1051 { 1052 if (string == NULL) { 1053 fprintf(stderr, "%s: is NULL\n", hdr); 1054 } else { 1055 const char *stringPtr = JNU_GetStringPlatformChars(env, string, 0); 1056 if (stringPtr == 0) 1057 return; 1058 fprintf(stderr, "%s: %s\n", hdr, stringPtr); 1059 JNU_ReleaseStringPlatformChars(env, string, stringPtr); 1060 } 1061 } 1062 1063 JNIEXPORT void JNICALL 1064 JNU_PrintClass(JNIEnv *env, char* hdr, jobject object) 1065 { 1066 if (object == NULL) { 1067 fprintf(stderr, "%s: object is NULL\n", hdr); 1068 return; 1069 } else { 1070 jclass cls = (*env)->GetObjectClass(env, object); 1071 jstring clsName = JNU_ToString(env, cls); 1072 if (clsName == NULL) { 1073 JNU_PrintString(env, hdr, clsName); 1074 } 1075 (*env)->DeleteLocalRef(env, cls); 1076 (*env)->DeleteLocalRef(env, clsName); 1077 } 1078 } 1079 1080 JNIEXPORT jstring JNICALL 1081 JNU_ToString(JNIEnv *env, jobject object) 1082 { 1083 if (object == NULL) { 1084 return (*env)->NewStringUTF(env, "NULL"); 1085 } else { 1086 return (jstring)JNU_CallMethodByName(env, 1087 NULL, 1088 object, 1089 "toString", 1090 "()Ljava/lang/String;").l; 1091 } 1092 } 1093 1094 JNIEXPORT jvalue JNICALL 1095 JNU_GetFieldByName(JNIEnv *env, 1096 jboolean *hasException, 1097 jobject obj, 1098 const char *name, 1099 const char *signature) 1100 { 1101 jclass cls; 1102 jfieldID fid; 1103 jvalue result; 1104 1105 result.i = 0; 1106 1107 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1108 goto done2; 1109 1110 cls = (*env)->GetObjectClass(env, obj); 1111 fid = (*env)->GetFieldID(env, cls, name, signature); 1112 if (fid == 0) 1113 goto done1; 1114 1115 switch (*signature) { 1116 case '[': 1117 case 'L': 1118 result.l = (*env)->GetObjectField(env, obj, fid); 1119 break; 1120 case 'Z': 1121 result.z = (*env)->GetBooleanField(env, obj, fid); 1122 break; 1123 case 'B': 1124 result.b = (*env)->GetByteField(env, obj, fid); 1125 break; 1126 case 'C': 1127 result.c = (*env)->GetCharField(env, obj, fid); 1128 break; 1129 case 'S': 1130 result.s = (*env)->GetShortField(env, obj, fid); 1131 break; 1132 case 'I': 1133 result.i = (*env)->GetIntField(env, obj, fid); 1134 break; 1135 case 'J': 1136 result.j = (*env)->GetLongField(env, obj, fid); 1137 break; 1138 case 'F': 1139 result.f = (*env)->GetFloatField(env, obj, fid); 1140 break; 1141 case 'D': 1142 result.d = (*env)->GetDoubleField(env, obj, fid); 1143 break; 1144 1145 default: 1146 (*env)->FatalError(env, "JNU_GetFieldByName: illegal signature"); 1147 } 1148 1149 done1: 1150 (*env)->DeleteLocalRef(env, cls); 1151 done2: 1152 if (hasException) { 1153 *hasException = (*env)->ExceptionCheck(env); 1154 } 1155 return result; 1156 } 1157 1158 JNIEXPORT void JNICALL 1159 JNU_SetFieldByName(JNIEnv *env, 1160 jboolean *hasException, 1161 jobject obj, 1162 const char *name, 1163 const char *signature, 1164 ...) 1165 { 1166 jclass cls; 1167 jfieldID fid; 1168 va_list args; 1169 1170 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1171 goto done2; 1172 1173 cls = (*env)->GetObjectClass(env, obj); 1174 fid = (*env)->GetFieldID(env, cls, name, signature); 1175 if (fid == 0) 1176 goto done1; 1177 1178 va_start(args, signature); 1179 switch (*signature) { 1180 case '[': 1181 case 'L': 1182 (*env)->SetObjectField(env, obj, fid, va_arg(args, jobject)); 1183 break; 1184 case 'Z': 1185 (*env)->SetBooleanField(env, obj, fid, (jboolean)va_arg(args, int)); 1186 break; 1187 case 'B': 1188 (*env)->SetByteField(env, obj, fid, (jbyte)va_arg(args, int)); 1189 break; 1190 case 'C': 1191 (*env)->SetCharField(env, obj, fid, (jchar)va_arg(args, int)); 1192 break; 1193 case 'S': 1194 (*env)->SetShortField(env, obj, fid, (jshort)va_arg(args, int)); 1195 break; 1196 case 'I': 1197 (*env)->SetIntField(env, obj, fid, va_arg(args, jint)); 1198 break; 1199 case 'J': 1200 (*env)->SetLongField(env, obj, fid, va_arg(args, jlong)); 1201 break; 1202 case 'F': 1203 (*env)->SetFloatField(env, obj, fid, (jfloat)va_arg(args, jdouble)); 1204 break; 1205 case 'D': 1206 (*env)->SetDoubleField(env, obj, fid, va_arg(args, jdouble)); 1207 break; 1208 1209 default: 1210 (*env)->FatalError(env, "JNU_SetFieldByName: illegal signature"); 1211 } 1212 va_end(args); 1213 1214 done1: 1215 (*env)->DeleteLocalRef(env, cls); 1216 done2: 1217 if (hasException) { 1218 *hasException = (*env)->ExceptionCheck(env); 1219 } 1220 } 1221 1222 JNIEXPORT jvalue JNICALL 1223 JNU_GetStaticFieldByName(JNIEnv *env, 1224 jboolean *hasException, 1225 const char *classname, 1226 const char *name, 1227 const char *signature) 1228 { 1229 jclass cls; 1230 jfieldID fid; 1231 jvalue result; 1232 1233 result.i = 0; 1234 1235 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1236 goto done2; 1237 1238 cls = (*env)->FindClass(env, classname); 1239 if (cls == 0) 1240 goto done2; 1241 1242 fid = (*env)->GetStaticFieldID(env, cls, name, signature); 1243 if (fid == 0) 1244 goto done1; 1245 1246 switch (*signature) { 1247 case '[': 1248 case 'L': 1249 result.l = (*env)->GetStaticObjectField(env, cls, fid); 1250 break; 1251 case 'Z': 1252 result.z = (*env)->GetStaticBooleanField(env, cls, fid); 1253 break; 1254 case 'B': 1255 result.b = (*env)->GetStaticByteField(env, cls, fid); 1256 break; 1257 case 'C': 1258 result.c = (*env)->GetStaticCharField(env, cls, fid); 1259 break; 1260 case 'S': 1261 result.s = (*env)->GetStaticShortField(env, cls, fid); 1262 break; 1263 case 'I': 1264 result.i = (*env)->GetStaticIntField(env, cls, fid); 1265 break; 1266 case 'J': 1267 result.j = (*env)->GetStaticLongField(env, cls, fid); 1268 break; 1269 case 'F': 1270 result.f = (*env)->GetStaticFloatField(env, cls, fid); 1271 break; 1272 case 'D': 1273 result.d = (*env)->GetStaticDoubleField(env, cls, fid); 1274 break; 1275 1276 default: 1277 (*env)->FatalError(env, "JNU_GetStaticFieldByName: illegal signature"); 1278 } 1279 1280 done1: 1281 (*env)->DeleteLocalRef(env, cls); 1282 done2: 1283 if (hasException) { 1284 *hasException = (*env)->ExceptionCheck(env); 1285 } 1286 return result; 1287 } 1288 1289 JNIEXPORT void JNICALL 1290 JNU_SetStaticFieldByName(JNIEnv *env, 1291 jboolean *hasException, 1292 const char *classname, 1293 const char *name, 1294 const char *signature, 1295 ...) 1296 { 1297 jclass cls; 1298 jfieldID fid; 1299 va_list args; 1300 1301 if ((*env)->EnsureLocalCapacity(env, 3) < 0) 1302 goto done2; 1303 1304 cls = (*env)->FindClass(env, classname); 1305 if (cls == 0) 1306 goto done2; 1307 1308 fid = (*env)->GetStaticFieldID(env, cls, name, signature); 1309 if (fid == 0) 1310 goto done1; 1311 1312 va_start(args, signature); 1313 switch (*signature) { 1314 case '[': 1315 case 'L': 1316 (*env)->SetStaticObjectField(env, cls, fid, va_arg(args, jobject)); 1317 break; 1318 case 'Z': 1319 (*env)->SetStaticBooleanField(env, cls, fid, (jboolean)va_arg(args, int)); 1320 break; 1321 case 'B': 1322 (*env)->SetStaticByteField(env, cls, fid, (jbyte)va_arg(args, int)); 1323 break; 1324 case 'C': 1325 (*env)->SetStaticCharField(env, cls, fid, (jchar)va_arg(args, int)); 1326 break; 1327 case 'S': 1328 (*env)->SetStaticShortField(env, cls, fid, (jshort)va_arg(args, int)); 1329 break; 1330 case 'I': 1331 (*env)->SetStaticIntField(env, cls, fid, va_arg(args, jint)); 1332 break; 1333 case 'J': 1334 (*env)->SetStaticLongField(env, cls, fid, va_arg(args, jlong)); 1335 break; 1336 case 'F': 1337 (*env)->SetStaticFloatField(env, cls, fid, (jfloat)va_arg(args, jdouble)); 1338 break; 1339 case 'D': 1340 (*env)->SetStaticDoubleField(env, cls, fid, va_arg(args, jdouble)); 1341 break; 1342 1343 default: 1344 (*env)->FatalError(env, "JNU_SetStaticFieldByName: illegal signature"); 1345 } 1346 va_end(args); 1347 1348 done1: 1349 (*env)->DeleteLocalRef(env, cls); 1350 done2: 1351 if (hasException) { 1352 *hasException = (*env)->ExceptionCheck(env); 1353 } 1354 }