]> git.saurik.com Git - apple/javascriptcore.git/blob - bindings/jni/jni_utility.cpp
JavaScriptCore-466.1.6.tar.gz
[apple/javascriptcore.git] / bindings / jni / jni_utility.cpp
1 /*
2 * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27
28 #if ENABLE(JAVA_BINDINGS)
29
30 #include "jni_utility.h"
31
32 #include "list.h"
33 #include "jni_runtime.h"
34 #include "runtime_array.h"
35 #include "runtime_object.h"
36 #include <dlfcn.h>
37
38 namespace KJS {
39
40 namespace Bindings {
41
42 static jint KJS_GetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs)
43 {
44 static void* javaVMFramework = 0;
45 if (!javaVMFramework)
46 javaVMFramework = dlopen("/System/Library/Frameworks/JavaVM.framework/JavaVM", RTLD_LAZY);
47 if (!javaVMFramework)
48 return JNI_ERR;
49
50 static jint(*functionPointer)(JavaVM**, jsize, jsize *) = 0;
51 if (!functionPointer)
52 functionPointer = (jint(*)(JavaVM**, jsize, jsize *))dlsym(javaVMFramework, "JNI_GetCreatedJavaVMs");
53 if (!functionPointer)
54 return JNI_ERR;
55 return functionPointer(vmBuf, bufLen, nVMs);
56 }
57
58 static JavaVM *jvm = 0;
59
60 // Provide the ability for an outside component to specify the JavaVM to use
61 // If the jvm value is set, the getJavaVM function below will just return.
62 // In getJNIEnv(), if AttachCurrentThread is called to a VM that is already
63 // attached, the result is a no-op.
64 void setJavaVM(JavaVM *javaVM)
65 {
66 jvm = javaVM;
67 }
68
69 JavaVM *getJavaVM()
70 {
71 if (jvm)
72 return jvm;
73
74 JavaVM *jvmArray[1];
75 jsize bufLen = 1;
76 jsize nJVMs = 0;
77 jint jniError = 0;
78
79 // Assumes JVM is already running ..., one per process
80 jniError = KJS_GetCreatedJavaVMs(jvmArray, bufLen, &nJVMs);
81 if ( jniError == JNI_OK && nJVMs > 0 ) {
82 jvm = jvmArray[0];
83 }
84 else
85 fprintf(stderr, "%s: JNI_GetCreatedJavaVMs failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError);
86
87 return jvm;
88 }
89
90 JNIEnv* getJNIEnv()
91 {
92 union {
93 JNIEnv* env;
94 void* dummy;
95 } u;
96 jint jniError = 0;
97
98 jniError = (getJavaVM())->AttachCurrentThread(&u.dummy, NULL);
99 if (jniError == JNI_OK)
100 return u.env;
101 else
102 fprintf(stderr, "%s: AttachCurrentThread failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError);
103 return NULL;
104 }
105
106 static jvalue callJNIMethod (JNIType type, jobject obj, const char *name, const char *sig, va_list args)
107 {
108 JavaVM *jvm = getJavaVM();
109 JNIEnv *env = getJNIEnv();
110 jvalue result;
111
112 bzero (&result, sizeof(jvalue));
113 if ( obj != NULL && jvm != NULL && env != NULL) {
114 jclass cls = env->GetObjectClass(obj);
115 if ( cls != NULL ) {
116 jmethodID mid = env->GetMethodID(cls, name, sig);
117 if ( mid != NULL )
118 {
119 switch (type) {
120 case void_type:
121 env->functions->CallVoidMethodV(env, obj, mid, args);
122 break;
123 case array_type:
124 case object_type:
125 result.l = env->functions->CallObjectMethodV(env, obj, mid, args);
126 break;
127 case boolean_type:
128 result.z = env->functions->CallBooleanMethodV(env, obj, mid, args);
129 break;
130 case byte_type:
131 result.b = env->functions->CallByteMethodV(env, obj, mid, args);
132 break;
133 case char_type:
134 result.c = env->functions->CallCharMethodV(env, obj, mid, args);
135 break;
136 case short_type:
137 result.s = env->functions->CallShortMethodV(env, obj, mid, args);
138 break;
139 case int_type:
140 result.i = env->functions->CallIntMethodV(env, obj, mid, args);
141 break;
142 case long_type:
143 result.j = env->functions->CallLongMethodV(env, obj, mid, args);
144 break;
145 case float_type:
146 result.f = env->functions->CallFloatMethodV(env, obj, mid, args);
147 break;
148 case double_type:
149 result.d = env->functions->CallDoubleMethodV(env, obj, mid, args);
150 break;
151 default:
152 fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type);
153 }
154 }
155 else
156 {
157 fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, name, obj);
158 env->ExceptionDescribe();
159 env->ExceptionClear();
160 fprintf (stderr, "\n");
161 }
162
163 env->DeleteLocalRef(cls);
164 }
165 else {
166 fprintf(stderr, "%s: Could not find class for %p\n", __PRETTY_FUNCTION__, obj);
167 }
168 }
169
170 return result;
171 }
172
173 static jvalue callJNIStaticMethod (JNIType type, jclass cls, const char *name, const char *sig, va_list args)
174 {
175 JavaVM *jvm = getJavaVM();
176 JNIEnv *env = getJNIEnv();
177 jvalue result;
178
179 bzero (&result, sizeof(jvalue));
180 if ( cls != NULL && jvm != NULL && env != NULL) {
181 jmethodID mid = env->GetStaticMethodID(cls, name, sig);
182 if ( mid != NULL )
183 {
184 switch (type) {
185 case void_type:
186 env->functions->CallStaticVoidMethodV(env, cls, mid, args);
187 break;
188 case array_type:
189 case object_type:
190 result.l = env->functions->CallStaticObjectMethodV(env, cls, mid, args);
191 break;
192 case boolean_type:
193 result.z = env->functions->CallStaticBooleanMethodV(env, cls, mid, args);
194 break;
195 case byte_type:
196 result.b = env->functions->CallStaticByteMethodV(env, cls, mid, args);
197 break;
198 case char_type:
199 result.c = env->functions->CallStaticCharMethodV(env, cls, mid, args);
200 break;
201 case short_type:
202 result.s = env->functions->CallStaticShortMethodV(env, cls, mid, args);
203 break;
204 case int_type:
205 result.i = env->functions->CallStaticIntMethodV(env, cls, mid, args);
206 break;
207 case long_type:
208 result.j = env->functions->CallStaticLongMethodV(env, cls, mid, args);
209 break;
210 case float_type:
211 result.f = env->functions->CallStaticFloatMethodV(env, cls, mid, args);
212 break;
213 case double_type:
214 result.d = env->functions->CallStaticDoubleMethodV(env, cls, mid, args);
215 break;
216 default:
217 fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type);
218 }
219 }
220 else
221 {
222 fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, name, cls);
223 env->ExceptionDescribe();
224 env->ExceptionClear();
225 fprintf (stderr, "\n");
226 }
227 }
228
229 return result;
230 }
231
232 static jvalue callJNIMethodIDA (JNIType type, jobject obj, jmethodID mid, jvalue *args)
233 {
234 JNIEnv *env = getJNIEnv();
235 jvalue result;
236
237 bzero (&result, sizeof(jvalue));
238 if ( obj != NULL && mid != NULL )
239 {
240 switch (type) {
241 case void_type:
242 env->functions->CallVoidMethodA(env, obj, mid, args);
243 break;
244 case array_type:
245 case object_type:
246 result.l = env->functions->CallObjectMethodA(env, obj, mid, args);
247 break;
248 case boolean_type:
249 result.z = env->functions->CallBooleanMethodA(env, obj, mid, args);
250 break;
251 case byte_type:
252 result.b = env->functions->CallByteMethodA(env, obj, mid, args);
253 break;
254 case char_type:
255 result.c = env->functions->CallCharMethodA(env, obj, mid, args);
256 break;
257 case short_type:
258 result.s = env->functions->CallShortMethodA(env, obj, mid, args);
259 break;
260 case int_type:
261 result.i = env->functions->CallIntMethodA(env, obj, mid, args);
262 break;
263 case long_type:
264 result.j = env->functions->CallLongMethodA(env, obj, mid, args);
265 break;
266 case float_type:
267 result.f = env->functions->CallFloatMethodA(env, obj, mid, args);
268 break;
269 case double_type:
270 result.d = env->functions->CallDoubleMethodA(env, obj, mid, args);
271 break;
272 default:
273 fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type);
274 }
275 }
276
277 return result;
278 }
279
280 static jvalue callJNIMethodA (JNIType type, jobject obj, const char *name, const char *sig, jvalue *args)
281 {
282 JavaVM *jvm = getJavaVM();
283 JNIEnv *env = getJNIEnv();
284 jvalue result;
285
286 bzero (&result, sizeof(jvalue));
287 if ( obj != NULL && jvm != NULL && env != NULL) {
288 jclass cls = env->GetObjectClass(obj);
289 if ( cls != NULL ) {
290 jmethodID mid = env->GetMethodID(cls, name, sig);
291 if ( mid != NULL ) {
292 result = callJNIMethodIDA (type, obj, mid, args);
293 }
294 else {
295 fprintf(stderr, "%s: Could not find method: %s\n", __PRETTY_FUNCTION__, name);
296 env->ExceptionDescribe();
297 env->ExceptionClear();
298 fprintf (stderr, "\n");
299 }
300
301 env->DeleteLocalRef(cls);
302 }
303 else {
304 fprintf(stderr, "%s: Could not find class for object\n", __PRETTY_FUNCTION__);
305 }
306 }
307
308 return result;
309 }
310
311 jmethodID getMethodID (jobject obj, const char *name, const char *sig)
312 {
313 JNIEnv *env = getJNIEnv();
314 jmethodID mid = 0;
315
316 if ( env != NULL) {
317 jclass cls = env->GetObjectClass(obj);
318 if ( cls != NULL ) {
319 mid = env->GetMethodID(cls, name, sig);
320 if (!mid) {
321 env->ExceptionClear();
322 mid = env->GetStaticMethodID(cls, name, sig);
323 if (!mid) {
324 env->ExceptionClear();
325 }
326 }
327 }
328 env->DeleteLocalRef(cls);
329 }
330 return mid;
331 }
332
333
334 #define CALL_JNI_METHOD(function_type,obj,name,sig) \
335 va_list args;\
336 va_start (args, sig);\
337 \
338 jvalue result = callJNIMethod(function_type, obj, name, sig, args);\
339 \
340 va_end (args);
341
342 #define CALL_JNI_STATIC_METHOD(function_type,cls,name,sig) \
343 va_list args;\
344 va_start (args, sig);\
345 \
346 jvalue result = callJNIStaticMethod(function_type, cls, name, sig, args);\
347 \
348 va_end (args);
349
350 void callJNIVoidMethod (jobject obj, const char *name, const char *sig, ... )
351 {
352 CALL_JNI_METHOD (void_type, obj, name, sig);
353 }
354
355 jobject callJNIObjectMethod (jobject obj, const char *name, const char *sig, ... )
356 {
357 CALL_JNI_METHOD (object_type, obj, name, sig);
358 return result.l;
359 }
360
361 jboolean callJNIBooleanMethod( jobject obj, const char *name, const char *sig, ... )
362 {
363 CALL_JNI_METHOD (boolean_type, obj, name, sig);
364 return result.z;
365 }
366
367 jboolean callJNIStaticBooleanMethod (jclass cls, const char *name, const char *sig, ... )
368 {
369 CALL_JNI_STATIC_METHOD (boolean_type, cls, name, sig);
370 return result.z;
371 }
372
373 jbyte callJNIByteMethod( jobject obj, const char *name, const char *sig, ... )
374 {
375 CALL_JNI_METHOD (byte_type, obj, name, sig);
376 return result.b;
377 }
378
379 jchar callJNICharMethod (jobject obj, const char *name, const char *sig, ... )
380 {
381 CALL_JNI_METHOD (char_type, obj, name, sig);
382 return result.c;
383 }
384
385 jshort callJNIShortMethod (jobject obj, const char *name, const char *sig, ... )
386 {
387 CALL_JNI_METHOD (short_type, obj, name, sig);
388 return result.s;
389 }
390
391 jint callJNIIntMethod (jobject obj, const char *name, const char *sig, ... )
392 {
393 CALL_JNI_METHOD (int_type, obj, name, sig);
394 return result.i;
395 }
396
397 jlong callJNILongMethod (jobject obj, const char *name, const char *sig, ... )
398 {
399 CALL_JNI_METHOD (long_type, obj, name, sig);
400 return result.j;
401 }
402
403 jfloat callJNIFloatMethod (jobject obj, const char *name, const char *sig, ... )
404 {
405 CALL_JNI_METHOD (float_type, obj, name, sig);
406 return result.f;
407 }
408
409 jdouble callJNIDoubleMethod (jobject obj, const char *name, const char *sig, ... )
410 {
411 CALL_JNI_METHOD (double_type, obj, name, sig);
412 return result.d;
413 }
414
415 void callJNIVoidMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
416 {
417 jvalue result = callJNIMethodA (void_type, obj, name, sig, args);
418 }
419
420 jobject callJNIObjectMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
421 {
422 jvalue result = callJNIMethodA (object_type, obj, name, sig, args);
423 return result.l;
424 }
425
426 jbyte callJNIByteMethodA ( jobject obj, const char *name, const char *sig, jvalue *args)
427 {
428 jvalue result = callJNIMethodA (byte_type, obj, name, sig, args);
429 return result.b;
430 }
431
432 jchar callJNICharMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
433 {
434 jvalue result = callJNIMethodA (char_type, obj, name, sig, args);
435 return result.c;
436 }
437
438 jshort callJNIShortMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
439 {
440 jvalue result = callJNIMethodA (short_type, obj, name, sig, args);
441 return result.s;
442 }
443
444 jint callJNIIntMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
445 {
446 jvalue result = callJNIMethodA (int_type, obj, name, sig, args);
447 return result.i;
448 }
449
450 jlong callJNILongMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
451 {
452 jvalue result = callJNIMethodA (long_type, obj, name, sig, args);
453 return result.j;
454 }
455
456 jfloat callJNIFloatMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
457 {
458 jvalue result = callJNIMethodA (float_type, obj, name, sig, args);
459 return result.f;
460 }
461
462 jdouble callJNIDoubleMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
463 {
464 jvalue result = callJNIMethodA (double_type, obj, name, sig, args);
465 return result.d;
466 }
467
468 jboolean callJNIBooleanMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
469 {
470 jvalue result = callJNIMethodA (boolean_type, obj, name, sig, args);
471 return result.z;
472 }
473
474 void callJNIVoidMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
475 {
476 jvalue result = callJNIMethodIDA (void_type, obj, methodID, args);
477 }
478
479 jobject callJNIObjectMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
480 {
481 jvalue result = callJNIMethodIDA (object_type, obj, methodID, args);
482 return result.l;
483 }
484
485 jbyte callJNIByteMethodIDA ( jobject obj, jmethodID methodID, jvalue *args)
486 {
487 jvalue result = callJNIMethodIDA (byte_type, obj, methodID, args);
488 return result.b;
489 }
490
491 jchar callJNICharMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
492 {
493 jvalue result = callJNIMethodIDA (char_type, obj, methodID, args);
494 return result.c;
495 }
496
497 jshort callJNIShortMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
498 {
499 jvalue result = callJNIMethodIDA (short_type, obj, methodID, args);
500 return result.s;
501 }
502
503 jint callJNIIntMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
504 {
505 jvalue result = callJNIMethodIDA (int_type, obj, methodID, args);
506 return result.i;
507 }
508
509 jlong callJNILongMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
510 {
511 jvalue result = callJNIMethodIDA (long_type, obj, methodID, args);
512 return result.j;
513 }
514
515 jfloat callJNIFloatMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
516 {
517 jvalue result = callJNIMethodIDA (float_type, obj, methodID, args);
518 return result.f;
519 }
520
521 jdouble callJNIDoubleMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
522 {
523 jvalue result = callJNIMethodIDA (double_type, obj, methodID, args);
524 return result.d;
525 }
526
527 jboolean callJNIBooleanMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
528 {
529 jvalue result = callJNIMethodIDA (boolean_type, obj, methodID, args);
530 return result.z;
531 }
532
533 const char *getCharactersFromJString (jstring aJString)
534 {
535 return getCharactersFromJStringInEnv (getJNIEnv(), aJString);
536 }
537
538 void releaseCharactersForJString (jstring aJString, const char *s)
539 {
540 releaseCharactersForJStringInEnv (getJNIEnv(), aJString, s);
541 }
542
543 const char *getCharactersFromJStringInEnv (JNIEnv *env, jstring aJString)
544 {
545 jboolean isCopy;
546 const char *s = env->GetStringUTFChars((jstring)aJString, &isCopy);
547 if (!s) {
548 env->ExceptionDescribe();
549 env->ExceptionClear();
550 fprintf (stderr, "\n");
551 }
552 return s;
553 }
554
555 void releaseCharactersForJStringInEnv (JNIEnv *env, jstring aJString, const char *s)
556 {
557 env->ReleaseStringUTFChars (aJString, s);
558 }
559
560 const jchar *getUCharactersFromJStringInEnv (JNIEnv *env, jstring aJString)
561 {
562 jboolean isCopy;
563 const jchar *s = env->GetStringChars((jstring)aJString, &isCopy);
564 if (!s) {
565 env->ExceptionDescribe();
566 env->ExceptionClear();
567 fprintf (stderr, "\n");
568 }
569 return s;
570 }
571
572 void releaseUCharactersForJStringInEnv (JNIEnv *env, jstring aJString, const jchar *s)
573 {
574 env->ReleaseStringChars (aJString, s);
575 }
576
577 JNIType JNITypeFromClassName(const char *name)
578 {
579 JNIType type;
580
581 if (strcmp("byte",name) == 0)
582 type = byte_type;
583 else if (strcmp("short",name) == 0)
584 type = short_type;
585 else if (strcmp("int",name) == 0)
586 type = int_type;
587 else if (strcmp("long",name) == 0)
588 type = long_type;
589 else if (strcmp("float",name) == 0)
590 type = float_type;
591 else if (strcmp("double",name) == 0)
592 type = double_type;
593 else if (strcmp("char",name) == 0)
594 type = char_type;
595 else if (strcmp("boolean",name) == 0)
596 type = boolean_type;
597 else if (strcmp("void",name) == 0)
598 type = void_type;
599 else if ('[' == name[0])
600 type = array_type;
601 else
602 type = object_type;
603
604 return type;
605 }
606
607 const char *signatureFromPrimitiveType(JNIType type)
608 {
609 switch (type){
610 case void_type:
611 return "V";
612
613 case array_type:
614 return "[";
615
616 case object_type:
617 return "L";
618
619 case boolean_type:
620 return "Z";
621
622 case byte_type:
623 return "B";
624
625 case char_type:
626 return "C";
627
628 case short_type:
629 return "S";
630
631 case int_type:
632 return "I";
633
634 case long_type:
635 return "J";
636
637 case float_type:
638 return "F";
639
640 case double_type:
641 return "D";
642
643 case invalid_type:
644 default:
645 break;
646 }
647 return "";
648 }
649
650 JNIType JNITypeFromPrimitiveType(char type)
651 {
652 switch (type){
653 case 'V':
654 return void_type;
655
656 case 'L':
657 return object_type;
658
659 case '[':
660 return array_type;
661
662 case 'Z':
663 return boolean_type;
664
665 case 'B':
666 return byte_type;
667
668 case 'C':
669 return char_type;
670
671 case 'S':
672 return short_type;
673
674 case 'I':
675 return int_type;
676
677 case 'J':
678 return long_type;
679
680 case 'F':
681 return float_type;
682
683 case 'D':
684 return double_type;
685
686 default:
687 break;
688 }
689 return invalid_type;
690 }
691
692 jvalue getJNIField( jobject obj, JNIType type, const char *name, const char *signature)
693 {
694 JavaVM *jvm = getJavaVM();
695 JNIEnv *env = getJNIEnv();
696 jvalue result;
697
698 bzero (&result, sizeof(jvalue));
699 if ( obj != NULL && jvm != NULL && env != NULL) {
700 jclass cls = env->GetObjectClass(obj);
701 if ( cls != NULL ) {
702 jfieldID field = env->GetFieldID(cls, name, signature);
703 if ( field != NULL ) {
704 switch (type) {
705 case array_type:
706 case object_type:
707 result.l = env->functions->GetObjectField(env, obj, field);
708 break;
709 case boolean_type:
710 result.z = env->functions->GetBooleanField(env, obj, field);
711 break;
712 case byte_type:
713 result.b = env->functions->GetByteField(env, obj, field);
714 break;
715 case char_type:
716 result.c = env->functions->GetCharField(env, obj, field);
717 break;
718 case short_type:
719 result.s = env->functions->GetShortField(env, obj, field);
720 break;
721 case int_type:
722 result.i = env->functions->GetIntField(env, obj, field);
723 break;
724 case long_type:
725 result.j = env->functions->GetLongField(env, obj, field);
726 break;
727 case float_type:
728 result.f = env->functions->GetFloatField(env, obj, field);
729 break;
730 case double_type:
731 result.d = env->functions->GetDoubleField(env, obj, field);
732 break;
733 default:
734 fprintf(stderr, "%s: invalid field type (%d)\n", __PRETTY_FUNCTION__, (int)type);
735 }
736 }
737 else
738 {
739 fprintf(stderr, "%s: Could not find field: %s\n", __PRETTY_FUNCTION__, name);
740 env->ExceptionDescribe();
741 env->ExceptionClear();
742 fprintf (stderr, "\n");
743 }
744
745 env->DeleteLocalRef(cls);
746 }
747 else {
748 fprintf(stderr, "%s: Could not find class for object\n", __PRETTY_FUNCTION__);
749 }
750 }
751
752 return result;
753 }
754
755 static jobject convertArrayInstanceToJavaArray(ExecState *exec, JSValue *value, const char *javaClassName) {
756
757 ASSERT(JSLock::lockCount() > 0);
758
759 JNIEnv *env = getJNIEnv();
760 // As JS Arrays can contain a mixture of objects, assume we can convert to
761 // the requested Java Array type requested, unless the array type is some object array
762 // other than a string.
763 ArrayInstance *jsArray = static_cast<ArrayInstance *>(value);
764 unsigned length = jsArray->getLength();
765 jobjectArray jarray = 0;
766
767 // Build the correct array type
768 switch (JNITypeFromPrimitiveType(javaClassName[1])) {
769 case object_type: {
770 // Only support string object types
771 if (0 == strcmp("[Ljava.lang.String;", javaClassName)) {
772 jarray = (jobjectArray)env->NewObjectArray(length,
773 env->FindClass("java/lang/String"),
774 env->NewStringUTF(""));
775 for(unsigned i = 0; i < length; i++) {
776 JSValue* item = jsArray->getItem(i);
777 UString stringValue = item->toString(exec);
778 env->SetObjectArrayElement(jarray,i,
779 env->functions->NewString(env, (const jchar *)stringValue.data(), stringValue.size()));
780 }
781 }
782 break;
783 }
784
785 case boolean_type: {
786 jarray = (jobjectArray)env->NewBooleanArray(length);
787 for(unsigned i = 0; i < length; i++) {
788 JSValue* item = jsArray->getItem(i);
789 jboolean value = (jboolean)item->toNumber(exec);
790 env->SetBooleanArrayRegion((jbooleanArray)jarray, (jsize)i, (jsize)1, &value);
791 }
792 break;
793 }
794
795 case byte_type: {
796 jarray = (jobjectArray)env->NewByteArray(length);
797 for(unsigned i = 0; i < length; i++) {
798 JSValue* item = jsArray->getItem(i);
799 jbyte value = (jbyte)item->toNumber(exec);
800 env->SetByteArrayRegion((jbyteArray)jarray, (jsize)i, (jsize)1, &value);
801 }
802 break;
803 }
804
805 case char_type: {
806 jarray = (jobjectArray)env->NewCharArray(length);
807 for(unsigned i = 0; i < length; i++) {
808 JSValue* item = jsArray->getItem(i);
809 UString stringValue = item->toString(exec);
810 jchar value = 0;
811 if (stringValue.size() > 0)
812 value = ((const jchar*)stringValue.data())[0];
813 env->SetCharArrayRegion((jcharArray)jarray, (jsize)i, (jsize)1, &value);
814 }
815 break;
816 }
817
818 case short_type: {
819 jarray = (jobjectArray)env->NewShortArray(length);
820 for(unsigned i = 0; i < length; i++) {
821 JSValue* item = jsArray->getItem(i);
822 jshort value = (jshort)item->toNumber(exec);
823 env->SetShortArrayRegion((jshortArray)jarray, (jsize)i, (jsize)1, &value);
824 }
825 break;
826 }
827
828 case int_type: {
829 jarray = (jobjectArray)env->NewIntArray(length);
830 for(unsigned i = 0; i < length; i++) {
831 JSValue* item = jsArray->getItem(i);
832 jint value = (jint)item->toNumber(exec);
833 env->SetIntArrayRegion((jintArray)jarray, (jsize)i, (jsize)1, &value);
834 }
835 break;
836 }
837
838 case long_type: {
839 jarray = (jobjectArray)env->NewLongArray(length);
840 for(unsigned i = 0; i < length; i++) {
841 JSValue* item = jsArray->getItem(i);
842 jlong value = (jlong)item->toNumber(exec);
843 env->SetLongArrayRegion((jlongArray)jarray, (jsize)i, (jsize)1, &value);
844 }
845 break;
846 }
847
848 case float_type: {
849 jarray = (jobjectArray)env->NewFloatArray(length);
850 for(unsigned i = 0; i < length; i++) {
851 JSValue* item = jsArray->getItem(i);
852 jfloat value = (jfloat)item->toNumber(exec);
853 env->SetFloatArrayRegion((jfloatArray)jarray, (jsize)i, (jsize)1, &value);
854 }
855 break;
856 }
857
858 case double_type: {
859 jarray = (jobjectArray)env->NewDoubleArray(length);
860 for(unsigned i = 0; i < length; i++) {
861 JSValue* item = jsArray->getItem(i);
862 jdouble value = (jdouble)item->toNumber(exec);
863 env->SetDoubleArrayRegion((jdoubleArray)jarray, (jsize)i, (jsize)1, &value);
864 }
865 break;
866 }
867
868 case array_type: // don't handle embedded arrays
869 case void_type: // Don't expect arrays of void objects
870 case invalid_type: // Array of unknown objects
871 break;
872 }
873
874 // if it was not one of the cases handled, then null is returned
875 return jarray;
876 }
877
878
879 jvalue convertValueToJValue (ExecState *exec, JSValue *value, JNIType _JNIType, const char *javaClassName)
880 {
881 JSLock lock;
882
883 jvalue result;
884
885 switch (_JNIType){
886 case array_type:
887 case object_type: {
888 result.l = (jobject)0;
889
890 // First see if we have a Java instance.
891 if (value->isObject()){
892 JSObject *objectImp = static_cast<JSObject*>(value);
893 if (objectImp->classInfo() == &RuntimeObjectImp::info) {
894 RuntimeObjectImp *imp = static_cast<RuntimeObjectImp *>(value);
895 JavaInstance *instance = static_cast<JavaInstance*>(imp->getInternalInstance());
896 if (instance)
897 result.l = instance->javaInstance();
898 }
899 else if (objectImp->classInfo() == &RuntimeArray::info) {
900 // Input is a JavaScript Array that was originally created from a Java Array
901 RuntimeArray *imp = static_cast<RuntimeArray *>(value);
902 JavaArray *array = static_cast<JavaArray*>(imp->getConcreteArray());
903 result.l = array->javaArray();
904 }
905 else if (objectImp->classInfo() == &ArrayInstance::info) {
906 // Input is a Javascript Array. We need to create it to a Java Array.
907 result.l = convertArrayInstanceToJavaArray(exec, value, javaClassName);
908 }
909 }
910
911 // Now convert value to a string if the target type is a java.lang.string, and we're not
912 // converting from a Null.
913 if (result.l == 0 && strcmp(javaClassName, "java.lang.String") == 0) {
914 #ifdef CONVERT_NULL_TO_EMPTY_STRING
915 if (value->isNull()) {
916 JNIEnv *env = getJNIEnv();
917 jchar buf[2];
918 jobject javaString = env->functions->NewString (env, buf, 0);
919 result.l = javaString;
920 }
921 else
922 #else
923 if (!value->isNull())
924 #endif
925 {
926 UString stringValue = value->toString(exec);
927 JNIEnv *env = getJNIEnv();
928 jobject javaString = env->functions->NewString (env, (const jchar *)stringValue.data(), stringValue.size());
929 result.l = javaString;
930 }
931 } else if (result.l == 0)
932 bzero (&result, sizeof(jvalue)); // Handle it the same as a void case
933 }
934 break;
935
936 case boolean_type: {
937 result.z = (jboolean)value->toNumber(exec);
938 }
939 break;
940
941 case byte_type: {
942 result.b = (jbyte)value->toNumber(exec);
943 }
944 break;
945
946 case char_type: {
947 result.c = (jchar)value->toNumber(exec);
948 }
949 break;
950
951 case short_type: {
952 result.s = (jshort)value->toNumber(exec);
953 }
954 break;
955
956 case int_type: {
957 result.i = (jint)value->toNumber(exec);
958 }
959 break;
960
961 case long_type: {
962 result.j = (jlong)value->toNumber(exec);
963 }
964 break;
965
966 case float_type: {
967 result.f = (jfloat)value->toNumber(exec);
968 }
969 break;
970
971 case double_type: {
972 result.d = (jdouble)value->toNumber(exec);
973 }
974 break;
975
976 break;
977
978 case invalid_type:
979 default:
980 case void_type: {
981 bzero (&result, sizeof(jvalue));
982 }
983 break;
984 }
985 return result;
986 }
987
988 } // end of namespace Bindings
989
990 } // end of namespace KJS
991
992 #endif // ENABLE(JAVA_BINDINGS)