• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 Apple 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 #include "JNIUtility.h"
28 
29 #if ENABLE(MAC_JAVA_BRIDGE)
30 
31 #include <dlfcn.h>
32 
33 namespace JSC {
34 
35 namespace Bindings {
36 
KJSGetCreatedJavaVMs(JavaVM ** vmBuf,jsize bufLen,jsize * nVMs)37 static jint KJSGetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs)
38 {
39     static void* javaVMFramework = 0;
40     if (!javaVMFramework)
41         javaVMFramework = dlopen("/System/Library/Frameworks/JavaVM.framework/JavaVM", RTLD_LAZY);
42     if (!javaVMFramework)
43         return JNI_ERR;
44 
45     typedef jint(*FunctionPointerType)(JavaVM**, jsize, jsize*);
46     static FunctionPointerType functionPointer = 0;
47     if (!functionPointer)
48         functionPointer = reinterpret_cast<FunctionPointerType>(dlsym(javaVMFramework, "JNI_GetCreatedJavaVMs"));
49     if (!functionPointer)
50         return JNI_ERR;
51     return functionPointer(vmBuf, bufLen, nVMs);
52 }
53 
54 static JavaVM* jvm = 0;
55 
56 // Provide the ability for an outside component to specify the JavaVM to use
57 // If the jvm value is set, the getJavaVM function below will just return.
58 // In getJNIEnv(), if AttachCurrentThread is called to a VM that is already
59 // attached, the result is a no-op.
setJavaVM(JavaVM * javaVM)60 void setJavaVM(JavaVM* javaVM)
61 {
62     jvm = javaVM;
63 }
64 
getJavaVM()65 JavaVM* getJavaVM()
66 {
67     if (jvm)
68         return jvm;
69 
70     JavaVM* jvmArray[1];
71     jsize bufLen = 1;
72     jsize nJVMs = 0;
73     jint jniError = 0;
74 
75     // Assumes JVM is already running ..., one per process
76     jniError = KJSGetCreatedJavaVMs(jvmArray, bufLen, &nJVMs);
77     if (jniError == JNI_OK && nJVMs > 0)
78         jvm = jvmArray[0];
79     else
80         fprintf(stderr, "%s: JNI_GetCreatedJavaVMs failed, returned %ld\n", __PRETTY_FUNCTION__, static_cast<long>(jniError));
81 
82     return jvm;
83 }
84 
getJNIEnv()85 JNIEnv* getJNIEnv()
86 {
87     union {
88         JNIEnv* env;
89         void* dummy;
90     } u;
91     jint jniError = 0;
92 
93     jniError = getJavaVM()->AttachCurrentThread(&u.dummy, 0);
94     if (jniError == JNI_OK)
95         return u.env;
96     fprintf(stderr, "%s: AttachCurrentThread failed, returned %ld\n", __PRETTY_FUNCTION__, static_cast<long>(jniError));
97     return 0;
98 }
99 
getMethodID(jobject obj,const char * name,const char * sig)100 jmethodID getMethodID(jobject obj, const char* name, const char* sig)
101 {
102     JNIEnv* env = getJNIEnv();
103     jmethodID mid = 0;
104 
105     if (env) {
106         jclass cls = env->GetObjectClass(obj);
107         if (cls) {
108             mid = env->GetMethodID(cls, name, sig);
109             if (!mid) {
110                 env->ExceptionClear();
111                 mid = env->GetStaticMethodID(cls, name, sig);
112                 if (!mid)
113                     env->ExceptionClear();
114             }
115         }
116         env->DeleteLocalRef(cls);
117     }
118     return mid;
119 }
120 
getCharactersFromJString(jstring aJString)121 const char* getCharactersFromJString(jstring aJString)
122 {
123     return getCharactersFromJStringInEnv(getJNIEnv(), aJString);
124 }
125 
releaseCharactersForJString(jstring aJString,const char * s)126 void releaseCharactersForJString(jstring aJString, const char* s)
127 {
128     releaseCharactersForJStringInEnv(getJNIEnv(), aJString, s);
129 }
130 
getCharactersFromJStringInEnv(JNIEnv * env,jstring aJString)131 const char* getCharactersFromJStringInEnv(JNIEnv* env, jstring aJString)
132 {
133     jboolean isCopy;
134     const char* s = env->GetStringUTFChars(aJString, &isCopy);
135     if (!s) {
136         env->ExceptionDescribe();
137         env->ExceptionClear();
138         fprintf(stderr, "\n");
139     }
140     return s;
141 }
142 
releaseCharactersForJStringInEnv(JNIEnv * env,jstring aJString,const char * s)143 void releaseCharactersForJStringInEnv(JNIEnv* env, jstring aJString, const char* s)
144 {
145     env->ReleaseStringUTFChars(aJString, s);
146 }
147 
getUCharactersFromJStringInEnv(JNIEnv * env,jstring aJString)148 const jchar* getUCharactersFromJStringInEnv(JNIEnv* env, jstring aJString)
149 {
150     jboolean isCopy;
151     const jchar* s = env->GetStringChars(aJString, &isCopy);
152     if (!s) {
153         env->ExceptionDescribe();
154         env->ExceptionClear();
155         fprintf(stderr, "\n");
156     }
157     return s;
158 }
159 
releaseUCharactersForJStringInEnv(JNIEnv * env,jstring aJString,const jchar * s)160 void releaseUCharactersForJStringInEnv(JNIEnv* env, jstring aJString, const jchar* s)
161 {
162     env->ReleaseStringChars(aJString, s);
163 }
164 
JNITypeFromClassName(const char * name)165 JNIType JNITypeFromClassName(const char* name)
166 {
167     JNIType type;
168 
169     if (!strcmp("byte", name))
170         type = byte_type;
171     else if (!strcmp("short", name))
172         type = short_type;
173     else if (!strcmp("int", name))
174         type = int_type;
175     else if (!strcmp("long", name))
176         type = long_type;
177     else if (!strcmp("float", name))
178         type = float_type;
179     else if (!strcmp("double", name))
180         type = double_type;
181     else if (!strcmp("char", name))
182         type = char_type;
183     else if (!strcmp("boolean", name))
184         type = boolean_type;
185     else if (!strcmp("void", name))
186         type = void_type;
187     else if ('[' == name[0])
188         type = array_type;
189     else
190         type = object_type;
191 
192     return type;
193 }
194 
signatureFromPrimitiveType(JNIType type)195 const char* signatureFromPrimitiveType(JNIType type)
196 {
197     switch (type) {
198     case void_type:
199         return "V";
200 
201     case array_type:
202         return "[";
203 
204     case object_type:
205         return "L";
206 
207     case boolean_type:
208         return "Z";
209 
210     case byte_type:
211         return "B";
212 
213     case char_type:
214         return "C";
215 
216     case short_type:
217         return "S";
218 
219     case int_type:
220         return "I";
221 
222     case long_type:
223         return "J";
224 
225     case float_type:
226         return "F";
227 
228     case double_type:
229         return "D";
230 
231     case invalid_type:
232     default:
233         break;
234     }
235     return "";
236 }
237 
JNITypeFromPrimitiveType(char type)238 JNIType JNITypeFromPrimitiveType(char type)
239 {
240     switch (type) {
241     case 'V':
242         return void_type;
243 
244     case 'L':
245         return object_type;
246 
247     case '[':
248         return array_type;
249 
250     case 'Z':
251         return boolean_type;
252 
253     case 'B':
254         return byte_type;
255 
256     case 'C':
257         return char_type;
258 
259     case 'S':
260         return short_type;
261 
262     case 'I':
263         return int_type;
264 
265     case 'J':
266         return long_type;
267 
268     case 'F':
269         return float_type;
270 
271     case 'D':
272         return double_type;
273 
274     default:
275         break;
276     }
277     return invalid_type;
278 }
279 
getJNIField(jobject obj,JNIType type,const char * name,const char * signature)280 jvalue getJNIField(jobject obj, JNIType type, const char* name, const char* signature)
281 {
282     JavaVM* jvm = getJavaVM();
283     JNIEnv* env = getJNIEnv();
284     jvalue result;
285 
286     memset(&result, 0, sizeof(jvalue));
287     if (obj && jvm && env) {
288         jclass cls = env->GetObjectClass(obj);
289         if (cls) {
290             jfieldID field = env->GetFieldID(cls, name, signature);
291             if (field) {
292                 switch (type) {
293                 case array_type:
294                 case object_type:
295                     result.l = env->functions->GetObjectField(env, obj, field);
296                     break;
297                 case boolean_type:
298                     result.z = env->functions->GetBooleanField(env, obj, field);
299                     break;
300                 case byte_type:
301                     result.b = env->functions->GetByteField(env, obj, field);
302                     break;
303                 case char_type:
304                     result.c = env->functions->GetCharField(env, obj, field);
305                     break;
306                 case short_type:
307                     result.s = env->functions->GetShortField(env, obj, field);
308                     break;
309                 case int_type:
310                     result.i = env->functions->GetIntField(env, obj, field);
311                     break;
312                 case long_type:
313                     result.j = env->functions->GetLongField(env, obj, field);
314                     break;
315                 case float_type:
316                     result.f = env->functions->GetFloatField(env, obj, field);
317                     break;
318                 case double_type:
319                     result.d = env->functions->GetDoubleField(env, obj, field);
320                     break;
321                 default:
322                     fprintf(stderr, "%s: invalid field type (%d)\n", __PRETTY_FUNCTION__, static_cast<int>(type));
323                 }
324             } else {
325                 fprintf(stderr, "%s: Could not find field: %s\n", __PRETTY_FUNCTION__, name);
326                 env->ExceptionDescribe();
327                 env->ExceptionClear();
328                 fprintf(stderr, "\n");
329             }
330 
331             env->DeleteLocalRef(cls);
332         } else
333             fprintf(stderr, "%s: Could not find class for object\n", __PRETTY_FUNCTION__);
334     }
335 
336     return result;
337 }
338 
339 } // namespace Bindings
340 
341 } // namespace JSC
342 
343 #endif // ENABLE(MAC_JAVA_BRIDGE)
344