]> git.saurik.com Git - apple/javascriptcore.git/blame - bindings/jni/jni_utility.cpp
JavaScriptCore-466.1.tar.gz
[apple/javascriptcore.git] / bindings / jni / jni_utility.cpp
CommitLineData
b37bf2e1
A
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
38namespace KJS {
39
40namespace Bindings {
41
42static 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
58static 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.
64void setJavaVM(JavaVM *javaVM)
65{
66 jvm = javaVM;
67}
68
69JavaVM *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
90JNIEnv* 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
106static 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
173static 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
232static 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
280static 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
311jmethodID 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
350void callJNIVoidMethod (jobject obj, const char *name, const char *sig, ... )
351{
352 CALL_JNI_METHOD (void_type, obj, name, sig);
353}
354
355jobject 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
361jboolean 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
367jboolean 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
373jbyte 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
379jchar 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
385jshort 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
391jint 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
397jlong 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
403jfloat 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
409jdouble 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
415void callJNIVoidMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
416{
417 jvalue result = callJNIMethodA (void_type, obj, name, sig, args);
418}
419
420jobject 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
426jbyte 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
432jchar 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
438jshort 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
444jint 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
450jlong 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
456jfloat 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
462jdouble 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
468jboolean 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
474void callJNIVoidMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
475{
476 jvalue result = callJNIMethodIDA (void_type, obj, methodID, args);
477}
478
479jobject callJNIObjectMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
480{
481 jvalue result = callJNIMethodIDA (object_type, obj, methodID, args);
482 return result.l;
483}
484
485jbyte callJNIByteMethodIDA ( jobject obj, jmethodID methodID, jvalue *args)
486{
487 jvalue result = callJNIMethodIDA (byte_type, obj, methodID, args);
488 return result.b;
489}
490
491jchar callJNICharMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
492{
493 jvalue result = callJNIMethodIDA (char_type, obj, methodID, args);
494 return result.c;
495}
496
497jshort callJNIShortMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
498{
499 jvalue result = callJNIMethodIDA (short_type, obj, methodID, args);
500 return result.s;
501}
502
503jint callJNIIntMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
504{
505 jvalue result = callJNIMethodIDA (int_type, obj, methodID, args);
506 return result.i;
507}
508
509jlong callJNILongMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
510{
511 jvalue result = callJNIMethodIDA (long_type, obj, methodID, args);
512 return result.j;
513}
514
515jfloat callJNIFloatMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
516{
517 jvalue result = callJNIMethodIDA (float_type, obj, methodID, args);
518 return result.f;
519}
520
521jdouble callJNIDoubleMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
522{
523 jvalue result = callJNIMethodIDA (double_type, obj, methodID, args);
524 return result.d;
525}
526
527jboolean callJNIBooleanMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
528{
529 jvalue result = callJNIMethodIDA (boolean_type, obj, methodID, args);
530 return result.z;
531}
532
533const char *getCharactersFromJString (jstring aJString)
534{
535 return getCharactersFromJStringInEnv (getJNIEnv(), aJString);
536}
537
538void releaseCharactersForJString (jstring aJString, const char *s)
539{
540 releaseCharactersForJStringInEnv (getJNIEnv(), aJString, s);
541}
542
543const 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
555void releaseCharactersForJStringInEnv (JNIEnv *env, jstring aJString, const char *s)
556{
557 env->ReleaseStringUTFChars (aJString, s);
558}
559
560const 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
572void releaseUCharactersForJStringInEnv (JNIEnv *env, jstring aJString, const jchar *s)
573{
574 env->ReleaseStringChars (aJString, s);
575}
576
577JNIType 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
607const 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
650JNIType 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
692jvalue 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
755static 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
879jvalue 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)