Interface margins and axes bounds properties.
[scilab.git] / scilab / modules / jvm / src / c / JniUtils.c
1 /*------------------------------------------------------------------------*/
2 /* file: JniUtils.cpp                                                     */
3 /* Copyright INRIA 2007                                                   */
4 /* Authors : Jean-Baptiste Silvy                                          */
5 /* desc : Set of functions to simplify the use of JNI. These              */
6 /*        functions are used to call Java from C code                     */
7 /*------------------------------------------------------------------------*/
8
9 #include <string.h>
10
11 #include "JniUtils.h"
12 #include "MALLOC.h"
13 #include "Scierror.h"
14
15 /*------------------------------------------------------------------------------------------*/
16 /** Static variable containing the jvm. */
17 static JavaVM * sciJVM  = NULL ;
18 /** Static variable containing the current java environment. */
19 static JNIEnv * sciJEnv = NULL ;
20
21 /*------------------------------------------------------------------------------------------*/
22 jniCallMethodCache * jniCreateCallMethodCache( void )
23 {
24   jniCallMethodCache * newCache = MALLOC(sizeof(jniCallMethodCache)) ;
25   if ( newCache == NULL ) { return NULL ; }
26
27   newCache->methodId      = NULL ;
28   newCache->instanceClass = NULL ;
29
30   return newCache;
31 }
32 /*------------------------------------------------------------------------------------------*/
33 void jniDestroyCallMethodCache( jniCallMethodCache * cache )
34 {
35   if ( cache != NULL )
36   {
37      cache->methodId = NULL ;
38      if ( cache->instanceClass != NULL )
39      {
40        (*sciJEnv)->DeleteGlobalRef(sciJEnv, cache->instanceClass) ;
41      }
42      FREE(cache) ;
43   }
44 }
45 /*------------------------------------------------------------------------------------------*/
46 void jniInitializeCallMethodCache( jniCallMethodCache * cache, jclass instanceClass, jmethodID methodId )
47 {
48   cache->methodId = methodId ;
49
50   cache->instanceClass = (*sciJEnv)->NewGlobalRef(sciJEnv, instanceClass) ;
51 }
52 /*------------------------------------------------------------------------------------------*/
53 BOOL jniIsCallMethodCacheInitialized( jniCallMethodCache * cache )
54 {
55   return ( cache != NULL && cache->instanceClass != NULL ) ;
56 }
57 /*------------------------------------------------------------------------------------------*/
58 void jniInitUtils( JavaVM * jvm )
59 {
60   sciJVM = jvm ;
61   jniUpdateCurrentEnv() ;
62 }
63 /*------------------------------------------------------------------------------------------*/
64 void jniCloseUtils( void )
65 {
66   sciJEnv = NULL ;
67   sciJVM  = NULL ;
68 }
69 /*------------------------------------------------------------------------------------------*/
70 void jniSetCurrentEnv( JNIEnv * env )
71 {
72   sciJEnv = env ;
73 }
74 /*------------------------------------------------------------------------------------------*/
75 JNIEnv * jniUpdateCurrentEnv( void )
76 {
77   /* tips from sun, use AttachCurrentThread to always get the right environment */ 
78   (*sciJVM)->AttachCurrentThread( sciJVM, (void **) &sciJEnv, NULL ) ;
79   //(*sciJVM)->GetEnv( sciJVM, (void **) &sciJEnv, JNI_VERSION_1_6 ) ;
80   /* clear all previous exceptions pending on the thread */
81   (*sciJEnv)->ExceptionClear( sciJEnv ) ;
82   return sciJEnv;
83 }
84 /*------------------------------------------------------------------------------------------*/
85 JNIEnv * jniGetCurrentJavaEnv( void )
86 {
87   return sciJEnv ;
88 }
89 /*------------------------------------------------------------------------------------------*/
90 jdoubleArray jniCreateDoubleArrayCopy( const jdouble * cArray, int nbElements )
91 {
92   jdoubleArray res = (*sciJEnv)->NewDoubleArray( sciJEnv, nbElements ) ;
93   (*sciJEnv)->SetDoubleArrayRegion( sciJEnv, res, 0, nbElements, cArray ) ;
94   if ( !jniCheckLastCall(FALSE) )
95   {
96     return NULL ;
97   }
98   return res ;
99 }
100 /*------------------------------------------------------------------------------------------*/
101 jintArray jniCreateIntArrayCopy( const jint * cArray, int nbElements )
102 {
103   jintArray res = (*sciJEnv)->NewIntArray( sciJEnv, nbElements ) ;
104   (*sciJEnv)->SetIntArrayRegion( sciJEnv, res, 0, nbElements, cArray ) ;
105   if ( !jniCheckLastCall(FALSE) )
106   {
107     return NULL ;
108   }
109   return res ;
110 }
111 /*------------------------------------------------------------------------------------------*/
112 void jniCopyJavaDoubleArray( const jdoubleArray javaArray, jdouble * cArray )
113 {
114   int arrayLength = (*sciJEnv)->GetArrayLength( sciJEnv, javaArray ) ;
115   (*sciJEnv)->GetDoubleArrayRegion( sciJEnv, javaArray, 0, arrayLength, cArray ) ;
116 }
117 /*------------------------------------------------------------------------------------------*/
118 void jniCopyJavaIntArray( const jintArray javaArray, jint * cArray )
119 {
120   int arrayLength = (*sciJEnv)->GetArrayLength( sciJEnv, javaArray ) ;
121   (*sciJEnv)->GetIntArrayRegion( sciJEnv, javaArray, 0, arrayLength, cArray ) ;
122 }
123 /*------------------------------------------------------------------------------------------*/
124 jstring jniCreateStringCopy( const char * cString )
125 {
126   jstring res = (*sciJEnv)->NewStringUTF( sciJEnv, cString ) ;
127   if ( !jniCheckLastCall(FALSE) )
128   {
129     return NULL ;
130   }
131   return res ;
132 }
133 /*------------------------------------------------------------------------------------------*/
134 void jniDeleteLocalEntity( jobject entity )
135 {
136   if ( entity != NULL )
137   {
138     (*sciJEnv)->DeleteLocalRef( sciJEnv, entity ) ;
139   }
140 }
141 /*------------------------------------------------------------------------------------------*/
142 void jniDeleteGlobalEntity( jobject entity )
143 {
144   if ( entity != NULL )
145   {
146     (*sciJEnv)->DeleteGlobalRef( sciJEnv, entity ) ;
147   }
148 }
149 /*------------------------------------------------------------------------------------------*/
150 BOOL jniCreateDefaultInstance( const char * className, jclass * instanceClass, jobject * instance )
151 {
152   jmethodID constructObject = NULL ;
153   jobject localInstance ;
154   jclass  localClass ;
155   
156   localClass = (*sciJEnv)->FindClass( sciJEnv, className ) ;
157   if ( !jniCheckLastCall(TRUE) )
158   {
159     Scierror( 999, "Unable to find class %s.\r\n", className ) ;
160     *instanceClass = NULL ;
161     *instance      = NULL ;
162     return FALSE ;
163   }
164
165   *instanceClass = (*sciJEnv)->NewGlobalRef(sciJEnv, localClass) ;
166
167   /* "()V" for no parameters and return void */
168   /* "<init>" for constructor */
169   constructObject = (*sciJEnv)->GetMethodID( sciJEnv, *instanceClass, "<init>", "()V" ) ;
170
171   localInstance = (*sciJEnv)->NewObject( sciJEnv, *instanceClass, constructObject ) ;
172   if ( !jniCheckLastCall(TRUE) )
173   {
174     Scierror( 999, "Unable to create an instance of class %s.\r\n", className ) ;
175     (*sciJEnv)->DeleteGlobalRef(sciJEnv, *instanceClass) ;
176     *instanceClass = NULL ;
177     *instance      = NULL ;
178     return FALSE ;
179   }
180   
181   *instance = (*sciJEnv)->NewGlobalRef(sciJEnv, localInstance) ;
182
183   return TRUE ;
184 }
185 /*------------------------------------------------------------------------------------------*/
186 BOOL jniCreateDefaultInstanceSafe( const char * className, jclass * instanceClass, jobject * instance )
187 {
188   if ( instanceClass == NULL || instance == NULL ) { return FALSE ; }
189   jniUpdateCurrentEnv() ;
190   return jniCreateDefaultInstance( className, instanceClass, instance ) ;
191 }
192 /*------------------------------------------------------------------------------------------*/
193 jvalue jniCallMemberFunction( jobject instance, jniCallMethodCache * cache, const char * functionName, const char * descriptor, ... )
194 {
195   va_list args ;
196   jvalue res;
197
198   /* Call the function with the optionals parameters */
199   va_start( args, descriptor ) ;
200   res = jniCallMemberFunctionV( instance, cache, functionName, descriptor, args ) ;
201   va_end(args);
202   return res ;
203 }
204 /*------------------------------------------------------------------------------------------*/
205 jvalue jniCallMemberFunctionSafe( jobject instance, jniCallMethodCache * cache, const char * functionName, const char * descriptor, ... )
206 {
207   va_list args ;
208   jvalue res;
209
210   jniInitJValue(&res) ;
211
212   if ( instance == NULL ) { return res ; }
213
214   jniUpdateCurrentEnv() ;
215
216   /* Call the function with the optionals parameters */
217   va_start( args, descriptor ) ;
218   res = jniCallMemberFunctionV( instance, cache, functionName, descriptor, args ) ;
219   va_end(args);
220   return res ;
221 }
222 /*------------------------------------------------------------------------------------------*/
223 jvalue jniCallMemberFunctionV( jobject instance, jniCallMethodCache * cache, const char * functionName, const char * descriptor, va_list args )
224 {
225   jclass instanceClass = NULL;
226   jmethodID methodId = NULL;
227   jvalue res;
228   int returnTypeIndex = 0 ;
229   
230   jniInitJValue(&res) ;
231   
232   if ((*sciJEnv)->EnsureLocalCapacity(sciJEnv, 2) == JNI_OK)
233   {
234     if ( !jniIsCallMethodCacheInitialized(cache) )
235     {
236       // Need to intialize cache
237       instanceClass = (*sciJEnv)->GetObjectClass(sciJEnv, instance) ;
238       methodId = (*sciJEnv)->GetMethodID(sciJEnv, instanceClass, functionName, descriptor ) ;
239       if ( cache != NULL )
240       {
241         jniInitializeCallMethodCache(cache, instanceClass, methodId) ;
242       }
243     }
244     else
245     {
246       // cache already initialized
247       instanceClass = cache->instanceClass ;
248       methodId = cache->methodId ;
249     }
250
251     if ( methodId == NULL )
252     {
253       Scierror( 999, "Error when calling function %s.\r\n", functionName ) ;
254       return res;
255     }
256
257     /* parse the descriptor to find return type */
258     while( descriptor[returnTypeIndex] != ')' )
259     {
260       returnTypeIndex++ ;
261     }
262     returnTypeIndex++;
263
264     switch( descriptor[returnTypeIndex] )
265     {
266     case 'V':
267       (*sciJEnv)->CallVoidMethodV(sciJEnv, instance, methodId, args) ;
268       break;
269     case 'Z':
270       res.z = (*sciJEnv)->CallBooleanMethodV(sciJEnv, instance, methodId, args) ;
271       break;
272     case 'B':
273       res.b = (*sciJEnv)->CallByteMethodV(sciJEnv, instance, methodId, args) ;
274       break;
275     case 'C':
276       res.c = (*sciJEnv)->CallCharMethodV(sciJEnv, instance, methodId, args) ;
277       break;
278     case 'S':
279       res.s = (*sciJEnv)->CallShortMethodV(sciJEnv, instance, methodId, args) ;
280       break;
281     case 'I':
282       res.i = (*sciJEnv)->CallIntMethodV(sciJEnv, instance, methodId, args) ;
283       break;
284     case 'J':
285       res.j = (*sciJEnv)->CallLongMethodV(sciJEnv, instance, methodId, args) ;
286       break;
287     case 'F':
288       res.f = (*sciJEnv)->CallFloatMethodV(sciJEnv, instance, methodId, args) ;
289       break;
290     case 'D':
291       res.d = (*sciJEnv)->CallDoubleMethodV(sciJEnv, instance, methodId, args) ;
292       break;
293     case '[':
294     case'L':
295       res.l = (*sciJEnv)->CallObjectMethodV(sciJEnv, instance, methodId, args) ;
296       break;
297     default:
298       Scierror( 999, "Error when calling function %s.\r\n", functionName ) ;
299       break;
300     }
301
302     if ( !jniCheckLastCall(TRUE) )
303     {
304       Scierror( 999, "Error when calling function %s.\r\n", functionName ) ;
305       return res ;
306     }
307
308   }
309   return res;
310
311 }
312 /*------------------------------------------------------------------------------------------*/
313 void jniInitJValue( jvalue * value )
314 {
315   value->b = 0 ;
316   value->c = 0 ;
317   value->d = 0.0 ;
318   value->f = 0.0 ;
319   value->i = 0 ;
320   value->j = 0 ;
321   value->l = NULL ;
322   value->s = 0 ;
323   value->z = 0 ;
324 }
325 /*------------------------------------------------------------------------------------------*/
326 double jniGetDoubleValue( jvalue value )
327 {
328   return value.d ;
329 }
330 /*------------------------------------------------------------------------------------------*/
331 int jniGetIntValue( jvalue value )
332 {
333   return value.i ;
334 }
335 /*------------------------------------------------------------------------------------------*/
336 BOOL jniCheckLastCall( BOOL dumpStack )
337 {
338   jniUpdateCurrentEnv() ;
339   if ( !sciJEnv ) { return FALSE ; }
340
341   if ( (*sciJEnv)->ExceptionOccurred(sciJEnv) )
342   {
343     if ( dumpStack )
344     {
345       (*sciJEnv)->ExceptionDescribe(sciJEnv) ;
346     }
347     return FALSE ;
348   }
349   return TRUE ;
350 }
351 /*------------------------------------------------------------------------------------------*/