Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 473
Functions: 0.0% 0 / 0 / 43
Branches: 0.0% 0 / 0 / 312

OMCompiler/SimulationRuntime/c/meta/java_interface.c
Line Branch Exec Source
1 /*
2 * This file belongs to the OpenModelica Run-Time System
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC), c/o Linköpings
5 * universitet, Department of Computer and Information Science, SE-58183 Linköping, Sweden. All rights
6 * reserved.
7 *
8 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF THE BSD NEW LICENSE OR THE
9 * AGPL VERSION 3 LICENSE OR THE OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. ANY
10 * USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S
11 * ACCEPTANCE OF THE BSD NEW LICENSE OR THE OSMC PUBLIC LICENSE OR THE AGPL
12 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
13 *
14 * The OpenModelica software and the OSMC (Open Source Modelica Consortium) Public License
15 * (OSMC-PL) are obtained from OSMC, either from the above address, from the URLs:
16 * http://www.openmodelica.org or https://github.com/OpenModelica/ or
17 * http://www.ida.liu.se/projects/OpenModelica, and in the OpenModelica distribution. GNU
18 * AGPL version 3 is obtained from: https://www.gnu.org/licenses/licenses.html#GPL. The BSD NEW
19 * License is obtained from: http://www.opensource.org/licenses/BSD-3-Clause.
20 *
21 * This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY
23 * SET FORTH IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF
24 * OSMC-PL.
25 *
26 */
27
28 #include "meta_modelica_string.h"
29
30 #if defined(__MINGW32__) || defined(_MSC_VER) /* Windows/MinGW */
31
32 #include <windows.h>
33 #define MAXPATHLEN 1024
34 #include <winreg.h>
35 #include <winerror.h>
36
37 #include <stdlib.h>
38 #include <string.h>
39 #include <stdarg.h>
40 #include "java_interface.h"
41
42 typedef jint (__stdcall * GetCreatedJavaVMsFunc)(JavaVM **, jsize, jsize *);
43 typedef jint (__stdcall * CreateJavaVMFunc)(JavaVM**,void**,void*);
44
45 #else /* UNIX */
46
47 #include <unistd.h>
48 #include <dlfcn.h>
49
50 #include <stdlib.h>
51 #include <string.h>
52 #include <stdarg.h>
53 #include "java_interface.h"
54
55 typedef jint (*GetCreatedJavaVMsFunc)(JavaVM **, jsize, jsize *);
56 typedef jint (*CreateJavaVMFunc)(JavaVM**,void**,void*);
57
58 #endif
59
60 static const char* JAVA_MODELICA_ARRAY = "org/openmodelica/ModelicaArray";
61 static const char* JAVA_MODELICA_INTEGER = "org/openmodelica/ModelicaInteger";
62 static const char* JAVA_MODELICA_REAL = "org/openmodelica/ModelicaReal";
63 static const char* JAVA_MODELICA_BOOLEAN = "org/openmodelica/ModelicaBoolean";
64 static const char* JAVA_MODELICA_STRING = "org/openmodelica/ModelicaString";
65 static const char* JAVA_MODELICA_RECORD = "org/openmodelica/ModelicaRecord";
66 static const char* JAVA_MODELICA_OMCRECORD = "org/openmodelica/OMCModelicaRecord";
67 static const char* JAVA_MODELICA_TUPLE = "org/openmodelica/ModelicaTuple";
68 static const char* JAVA_MODELICA_OPTION = "org/openmodelica/ModelicaOption";
69 static char* classPath;
70
71 static int inside_exception = 0;
72
73 static GetCreatedJavaVMsFunc OMC_GetCreatedJavaVMs = NULL;
74 static CreateJavaVMFunc OMC_CreateJavaVM = NULL;
75
76
77 #if defined(__MINGW32__) || defined(_MSC_VER) /* Windows/MinGW */
78 /* Windows Dynamic Loading - NOT TESTED IF IT EVEN COMPILES */
79
80 int GetStringFromWindowsRegistry(HKEY key, const char *name, char *buf, int buf_length)
81 {
82 DWORD type, size;
83 if(RegQueryValueEx(key, name, 0, &type, 0, &size) == ERROR_SUCCESS) {
84 if(type == REG_SZ && (size < (unsigned int)buf_length)) {
85 /* The key is a string with ok length */
86 if(RegQueryValueEx(key, name, 0, 0, (unsigned char*)buf, &size) == 0) {
87 return 0;
88 }
89 }
90 }
91 return 1;
92 }
93
94 int GetRegistryJavaHome(char *java_home, int java_home_length)
95 {
96 HKEY key, curver_key;
97 char version[MAXPATHLEN];
98
99 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\JavaSoft\\Java Runtime Environment", 0, KEY_READ, &key) != 0) {
100 return 1;
101 }
102
103 if(GetStringFromWindowsRegistry(key, "CurrentVersion", version, sizeof(version))) {
104 RegCloseKey(key);
105 return 1;
106 }
107
108 if(RegOpenKeyEx(key, version, 0, KEY_READ, &curver_key) != 0) {
109 RegCloseKey(key);
110 return 1;
111 }
112
113 if(GetStringFromWindowsRegistry(curver_key, "JavaHome", java_home, java_home_length)) {
114 RegCloseKey(key);
115 RegCloseKey(curver_key);
116 return 1;
117 }
118
119 RegCloseKey(key);
120 RegCloseKey(curver_key);
121 return 0;
122 }
123
124 HINSTANCE
125 tryToLoadJavaHome(const char* java_home) {
126 char* vmlibpath;
127 int i, java_home_length;
128 HINSTANCE libVM = NULL;
129 #define NUM_PATHS 2
130 const char* possiblePaths[NUM_PATHS] = {
131 "%s\\bin\\client\\jvm.dll",
132 "%s\\bin\\server\\jvm.dll"
133 };
134 if(java_home == NULL)
135 return NULL;
136 java_home_length = strlen(java_home);
137 vmlibpath = malloc(java_home_length+500);
138 for(i=0; i<NUM_PATHS && libVM == NULL; i++) {
139 sprintf(vmlibpath, possiblePaths[i], java_home);
140 libVM = LoadLibrary(vmlibpath);
141 /* fprintf(stderr, "Tried to load %s: %s\n", vmlibpath, libVM == NULL ? "fail" : "success"); */
142 }
143 free(vmlibpath);
144 return libVM;
145 }
146
147 void loadJNI(void)
148 {
149 HINSTANCE libVM = NULL;
150 char java_home_registry[MAXPATHLEN];
151 char* java_home_env;
152 static int java_init = 0;
153 java_home_registry[0] = '\0';
154
155 if(java_init == 0) {
156 java_init = 1;
157 java_home_env = getenv("JAVA_HOME");
158
159 libVM = tryToLoadJavaHome(java_home_env);
160 if(libVM == NULL && 0 == GetRegistryJavaHome(java_home_registry, MAXPATHLEN)) {
161 libVM = tryToLoadJavaHome(java_home_registry);
162 }
163
164 if(libVM == NULL) {
165 fprintf(stderr, "Failed to dynamically load JVM\nEnvironment JAVA_HOME = '%s'\nWindows Registry JAVA_HOME = '%s'\n", java_home_env, java_home_registry);
166 EXIT(EXIT_CODE_JAVA_ERROR);
167 }
168
169 OMC_GetCreatedJavaVMs = (GetCreatedJavaVMsFunc) GetProcAddress(libVM, "JNI_GetCreatedJavaVMs");
170 if(OMC_GetCreatedJavaVMs == NULL) {
171 fprintf(stderr, "GetProcAddress(JNI_GetCreatedJavaVMs) failed\n");
172 EXIT(EXIT_CODE_JAVA_ERROR);
173 }
174
175 OMC_CreateJavaVM = (CreateJavaVMFunc) GetProcAddress(libVM, "JNI_CreateJavaVM");
176 if(OMC_CreateJavaVM == NULL) {
177 fprintf(stderr, "GetProcAddress(JNI_CreateJavaVM) failed\n");
178 EXIT(EXIT_CODE_JAVA_ERROR);
179 }
180 }
181 }
182
183 #else /* UNIX dynamic loading */
184
185 void*
186 ✗ tryToLoadJavaHome(const char* java_home) {
187 char* vmlibpath;
188 int i, java_home_length;
189 void *libVM = NULL;
190 #define NUM_PATHS 6
191 ✗ const char* possiblePaths[NUM_PATHS] = {
192 "%s/jre/lib/i386/client/libjvm.so",
193 "%s/jre/lib/i386/server/libjvm.so",
194 "%s/jre/lib/amd64/client/libjvm.so",
195 "%s/jre/lib/amd64/server/libjvm.so",
196 "%s/jre/lib/ppc/client/libjvm.so",
197 "%s/jre/lib/ppc/server/libjvm.so"
198 };
199 ✗ if(java_home == NULL)
200 return NULL;
201 ✗ java_home_length = strlen(java_home);
202 ✗ vmlibpath = malloc(java_home_length+500);
203 ✗ for(i=0; i<NUM_PATHS && libVM == NULL; i++) {
204 ✗ sprintf(vmlibpath, possiblePaths[i], java_home);
205 ✗ libVM = dlopen(vmlibpath, RTLD_LAZY);
206 }
207 ✗ free(vmlibpath);
208 ✗ return libVM;
209 }
210
211 ✗ void loadJNI(void)
212 {
213 void *libVM = NULL;
214 static int java_init = 0;
215 char* java_home;
216 const char* default_java_home = "/usr/lib/jvm/default-java/";
217
218 ✗ if(java_init == 0) {
219 ✗ java_init = 1;
220 ✗ java_home = getenv("JAVA_HOME");
221 ✗ libVM = tryToLoadJavaHome(java_home);
222 ✗ libVM = libVM != NULL ? libVM : tryToLoadJavaHome(default_java_home);
223
224 ✗ if(libVM == NULL) {
225 ✗ fprintf(stderr, "Failed to dynamically load JVM\nEnvironment JAVA_HOME = '%s'\nDefault JAVA_HOME '%s'\n", java_home, default_java_home);
226 ✗ EXIT(EXIT_CODE_JAVA_ERROR);
227 }
228
229 /*
230 * Will produce compiler warnings because data pointers are not function pointers:
231 * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html
232 */
233 if(libVM == NULL) {
234 fprintf(stderr, "dlopen failed: %s\n", dlerror());
235 EXIT(EXIT_CODE_JAVA_ERROR);
236 }
237 ✗ *(void **) (&OMC_CreateJavaVM) = dlsym(libVM, "JNI_CreateJavaVM");
238 ✗ if(OMC_CreateJavaVM == NULL) {
239 ✗ fprintf(stderr, "dlsym(JNI_CreateJavaVM) failed: %s\n", dlerror());
240 ✗ EXIT(EXIT_CODE_JAVA_ERROR);
241 }
242 ✗ *(void **) (&OMC_GetCreatedJavaVMs) = dlsym(libVM, "JNI_GetCreatedJavaVMs");
243 ✗ if(OMC_GetCreatedJavaVMs == NULL) {
244 ✗ fprintf(stderr, "dlsym(JNI_GetCreatedJavaVMs) failed: %s\n", dlerror());
245 ✗ EXIT(EXIT_CODE_JAVA_ERROR);
246 }
247 }
248 ✗ }
249 #endif
250
251
252
253 /* Should work for multi-threaded applications */
254 ✗ JNIEnv* getJavaEnv(void)
255 {
256 jint res;
257 ✗ JavaVM *jvm = NULL;
258 ✗ JNIEnv *env = NULL;
259 ✗ jsize nVMs = 0;
260 #if defined(__MINGW32__) || defined(_MSC_VER) /* Windows/MinGW */
261 const char* classpathFormatString = "-Djava.class.path=%s\\share\\omc\\java\\modelica_java.jar;%s\\share\\omc\\java\\antlr-3.1.3.jar;%s";
262 #else
263 const char* classpathFormatString = "-Djava.class.path=%s/share/omc/java/modelica_java.jar:%s/share/omc/java/antlr-3.1.3.jar:%s";
264 #endif
265 const char* openmodelicahome;
266 char* classpathEnv;
267 JavaVMInitArgs vm_args;
268 JavaVMOption options[3];
269 long classPathIx = 0;
270 long classPathLen;
271
272 ✗ loadJNI();
273
274 ✗ if(OMC_GetCreatedJavaVMs(&jvm, 1, &nVMs)) {
275 ✗ fprintf(stderr, "JNI_GetCreatedJavaVMs returned error\n");
276 ✗ EXIT(EXIT_CODE_JAVA_ERROR);
277 }
278
279 ✗ if(nVMs == 1) {
280 ✗ if((*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL)) {
281 ✗ fprintf(stderr, "jvm->AttachCurrentThread returned error\n");
282 ✗ return NULL;
283 }
284 ✗ return env;
285 }
286
287 ✗ openmodelicahome = getenv("OPENMODELICAHOME");
288 ✗ if(openmodelicahome == NULL) {
289 ✗ fprintf(stderr, "getenv(OPENMODELICAHOME) failed - Java subsystem can't find the Java runtime...\n");
290 ✗ EXIT(EXIT_CODE_JAVA_ERROR);
291 }
292 ✗ openmodelicahome = GC_strdup(openmodelicahome);
293
294 ✗ classpathEnv = getenv("CLASSPATH");
295 ✗ if(classpathEnv == NULL)
296 classpathEnv = "";
297
298 ✗ classPathLen = strlen(classpathFormatString) + 2*strlen(openmodelicahome) + strlen(classpathEnv) + 100;
299 ✗ classPath = malloc(classPathLen);
300 ✗ if(classPath == NULL) {
301 ✗ fprintf(stderr, "%s:%d malloc failed\n", __FILE__, __LINE__);
302 ✗ EXIT(EXIT_CODE_JAVA_ERROR);
303 }
304
305 classPathIx = sprintf(classPath, classpathFormatString, openmodelicahome, openmodelicahome, classpathEnv);
306 ✗ classPath[classPathIx] = '\0';
307
308 #if 1
309 ✗ options[0].optionString = classPath;
310 ✗ vm_args.nOptions = 1;
311 #else
312 /* For debugging */
313 options[0].optionString = classPath;
314 options[1].optionString = "-verbose:jni";
315 options[2].optionString = "-Xcheck:jni";
316 vm_args.nOptions = 3;
317 fprintf(stderr, "options[0] %s\noptions[1] %s\noptions[2] %s\n",
318 options[0].optionString,
319 options[1].optionString,
320 options[2].optionString);
321 #endif
322
323 ✗ vm_args.version = JNI_VERSION_1_4;
324 ✗ vm_args.options = options;
325 ✗ vm_args.ignoreUnrecognized = JNI_TRUE;
326 /* Create the Java VM */
327 ✗ res = OMC_CreateJavaVM(&jvm, (void**)&env, &vm_args);
328
329 ✗ if(res < 0) {
330 ✗ jvm = NULL;
331 ✗ env = NULL;
332
333 ✗ fprintf(stderr, "%s:%d JNI_CreateJavaVM failed\n", __FILE__, __LINE__);
334 ✗ EXIT(EXIT_CODE_JAVA_ERROR);
335 }
336
337 /* Check that the system works */
338 ✗ (*env)->FindClass(env, "java/lang/String");
339 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
340 ✗ (*env)->FindClass(env, JAVA_MODELICA_STRING);
341 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
342
343 ✗ return env;
344 }
345
346 ✗ jobject NewJavaArray(JNIEnv* env) {
347 jobject res;
348 jmethodID cid;
349 ✗ const char* className = JAVA_MODELICA_ARRAY;
350 const char* sig = "()V";
351 ✗ jclass cls = (*env)->FindClass(env, className);
352
353 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
354
355 ✗ cid = (*env)->GetMethodID(env, cls, "<init>", sig);
356 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
357 ✗ res = (*env)->NewObject(env, cls, cid);
358 ✗ (*env)->DeleteLocalRef(env, cls);
359
360 ✗ return res;
361 }
362
363 ✗ void JavaArrayAdd(JNIEnv* env, jobject arr, jobject obj) {
364 const char* methodName = "add";
365 const char* sig = "(Ljava/lang/Object;)Z";
366 ✗ jclass cls = (*env)->GetObjectClass(env,arr);
367 ✗ jmethodID mid = (*env)->GetMethodID(env, cls, methodName, sig);
368 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
369 ✗ (*env)->CallBooleanMethod(env, arr, mid, obj);
370 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
371 ✗ (*env)->DeleteLocalRef(env, cls);
372 ✗ }
373
374 ✗ jobject JavaArrayGet(JNIEnv* env, jobject arr, jint ix) {
375 jobject res;
376 const char* methodName = "get";
377 const char* sig = "(I)Ljava/lang/Object;";
378 ✗ jclass cls = (*env)->GetObjectClass(env,arr);
379 ✗ jmethodID mid = (*env)->GetMethodID(env, cls, methodName, sig);
380 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
381 ✗ res = (*env)->CallObjectMethod(env, arr, mid, ix);
382 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
383 ✗ (*env)->DeleteLocalRef(env, cls);
384 ✗ return res;
385 }
386
387 ✗ void MakeJavaMultiDimArray(JNIEnv* env, jobject jarr, int numDim, jint firstDim, ...) {
388 ✗ jint *dims = malloc(numDim*sizeof(jint));
389 int i;
390 va_list va;
391 jobject jdims;
392 jmethodID mid;
393 ✗ const char* className = JAVA_MODELICA_ARRAY;
394 const char* methodName = "setDims";
395 const char* sig = "(I[I)V";
396
397 ✗ jclass cls = (*env)->FindClass(env, className);
398
399 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
400
401 ✗ mid = (*env)->GetMethodID(env, cls, methodName, sig);
402 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
403
404 ✗ va_start(va, firstDim);
405 ✗ for(i=0; i<numDim-1; i++) {
406 ✗ dims[i] = va_arg(va, jint);
407 }
408 ✗ va_end(va);
409
410 ✗ jdims = (*env)->NewIntArray(env, numDim-1);
411 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
412 ✗ (*env)->SetIntArrayRegion(env, jdims, 0, numDim-1, dims);
413 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
414
415 ✗ (*env)->CallVoidMethod(env, jarr, mid, firstDim, jdims);
416
417 ✗ (*env)->DeleteLocalRef(env, jdims);
418 ✗ (*env)->DeleteLocalRef(env, cls);
419 ✗ free(dims);
420 ✗ }
421
422 ✗ void FlattenJavaMultiDimArray(JNIEnv* env, jobject jarr) {
423 const char* methodName = "flattenModelicaArray";
424 const char* sig = "()V";
425 ✗ jclass cls = (*env)->GetObjectClass(env,jarr);
426 ✗ jmethodID mid = (*env)->GetMethodID(env, cls, methodName, sig);
427 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
428 ✗ (*env)->CallVoidMethod(env, jarr, mid);
429 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
430 ✗ (*env)->DeleteLocalRef(env, cls);
431 ✗ }
432
433 ✗ jobject NewFlatJavaIntegerArray(JNIEnv* env, modelica_integer* base, int num)
434 {
435 ✗ jobject jarr = NewJavaArray(env);
436 int i;
437 ✗ for(i=0; i<num; i++) {
438 ✗ jobject o = NewJavaInteger(env, base[i]);
439 ✗ JavaArrayAdd(env, jarr, o);
440 ✗ (*env)->DeleteLocalRef(env, o);
441 }
442 ✗ return jarr;
443 }
444
445 ✗ jobject NewFlatJavaDoubleArray(JNIEnv* env, modelica_real* base, int num)
446 {
447 ✗ jobject jarr = NewJavaArray(env);
448 int i;
449 ✗ for(i=0; i<num; i++) {
450 ✗ jobject o = NewJavaDouble(env, base[i]);
451 ✗ JavaArrayAdd(env, jarr, o);
452 ✗ (*env)->DeleteLocalRef(env, o);
453 }
454 ✗ return jarr;
455 }
456
457 ✗ jobject NewFlatJavaStringArray(JNIEnv* env, metamodelica_string* base, int num)
458 {
459 ✗ jobject jarr = NewJavaArray(env);
460 int i;
461 ✗ for(i=0; i<num; i++) {
462 /* base[i] is a tagged MetaModelica string; NewJavaString wants the bytes. */
463 ✗ jobject o = NewJavaString(env, MMC_STRINGDATA(base[i]));
464 ✗ JavaArrayAdd(env, jarr, o);
465 ✗ (*env)->DeleteLocalRef(env, o);
466 }
467 ✗ return jarr;
468 }
469
470 ✗ jobject NewFlatJavaBooleanArray(JNIEnv* env, modelica_boolean* base, int num)
471 {
472 ✗ jobject jarr = NewJavaArray(env);
473 int i;
474 ✗ for(i=0; i<num; i++) {
475 ✗ jobject o = NewJavaBoolean(env, base[i]);
476 ✗ JavaArrayAdd(env, jarr, o);
477 ✗ (*env)->DeleteLocalRef(env, o);
478 }
479 ✗ return jarr;
480 }
481
482 ✗ void GetFlatJavaIntegerArray(JNIEnv* env, jobject jarr, modelica_integer* base, int num)
483 {
484 int i;
485 ✗ for(i=0; i<num; i++) {
486 ✗ base[i] = GetJavaInteger(env, JavaArrayGet(env,jarr,i));
487 }
488 ✗ }
489
490 ✗ void GetFlatJavaDoubleArray(JNIEnv* env, jobject jarr, modelica_real* base, int num)
491 {
492 int i;
493 ✗ for(i=0; i<num; i++) {
494 ✗ base[i] = GetJavaDouble(env, JavaArrayGet(env,jarr,i));
495 }
496 ✗ }
497
498 ✗ void GetFlatJavaBooleanArray(JNIEnv* env, jobject jarr, modelica_boolean* base, int num)
499 {
500 int i;
501 ✗ for(i=0; i<num; i++) {
502 ✗ base[i] = GetJavaBoolean(env, JavaArrayGet(env,jarr,i));
503 }
504 ✗ }
505
506 ✗ void GetFlatJavaStringArray(JNIEnv* env, jobject jarr, metamodelica_string* base, int num)
507 {
508 int i;
509 ✗ for(i=0; i<num; i++) {
510 ✗ base[i] = omc_string_new(GetJavaString(env, JavaArrayGet(env,jarr,i)));
511 }
512 ✗ }
513
514 ✗ jobject NewJavaRecord(JNIEnv* env, const char* recordName, int ctor_index, jobject map)
515 {
516 jobject res, tmp;
517 jmethodID cid;
518 ✗ const char* className = JAVA_MODELICA_OMCRECORD;
519 const char* sig = "(ILjava/lang/String;Ljava/util/Map;)V";
520 ✗ jclass cls = (*env)->FindClass(env, className);
521
522 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
523
524 ✗ cid = (*env)->GetMethodID(env, cls, "<init>", sig);
525 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
526 ✗ tmp = (*env)->NewStringUTF(env,recordName);
527 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
528 ✗ res = (*env)->NewObject(env, cls, cid, ctor_index, tmp, map);
529 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
530 ✗ (*env)->DeleteLocalRef(env, cls);
531 ✗ (*env)->DeleteLocalRef(env, tmp);
532
533 ✗ return res;
534 }
535
536 ✗ jobject NewJavaTuple(JNIEnv* env, jobject arr)
537 {
538 jobject res;
539 jmethodID cid;
540 ✗ const char* className = JAVA_MODELICA_TUPLE;
541 const char* sig = "(Ljava/util/List;)V";
542 ✗ jclass cls = (*env)->FindClass(env, className);
543
544 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
545
546 ✗ cid = (*env)->GetMethodID(env, cls, "<init>", sig);
547 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
548 ✗ res = (*env)->NewObject(env, cls, cid, arr);
549 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
550 ✗ (*env)->DeleteLocalRef(env, cls);
551
552 ✗ return res;
553 }
554
555 ✗ jobject NewJavaMap(JNIEnv* env)
556 {
557 jobject res;
558 jmethodID cid;
559 const char* className = "java/util/LinkedHashMap";
560
561 ✗ jclass cls = (*env)->FindClass(env, className);
562 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
563
564 ✗ cid = (*env)->GetMethodID(env, cls, "<init>", "()V");
565 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
566
567 ✗ res = (*env)->NewObject(env, cls, cid);
568 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
569 ✗ (*env)->DeleteLocalRef(env, cls);
570
571 ✗ return res;
572 }
573
574 ✗ jobject NewJavaInteger(JNIEnv* env, jint value)
575 {
576 ✗ const char* className = JAVA_MODELICA_INTEGER;
577 const char* sig = "(I)V";
578 jobject res;
579 jmethodID cid;
580
581 ✗ jclass cls = (*env)->FindClass(env, className);
582 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
583
584 ✗ cid = (*env)->GetMethodID(env, cls, "<init>", sig);
585 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
586
587 ✗ res = (*env)->NewObject(env, cls, cid, value);
588 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
589 ✗ (*env)->DeleteLocalRef(env, cls);
590
591 ✗ return res;
592 }
593
594 ✗ jobject NewJavaDouble(JNIEnv* env, jdouble value)
595 {
596 ✗ const char* className = JAVA_MODELICA_REAL;
597 const char* sig = "(D)V";
598 jobject res;
599 jmethodID cid;
600
601 ✗ jclass cls = (*env)->FindClass(env, className);
602 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
603
604 ✗ cid = (*env)->GetMethodID(env, cls, "<init>", sig);
605 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
606
607 ✗ res = (*env)->NewObject(env, cls, cid, value);
608 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
609 ✗ (*env)->DeleteLocalRef(env, cls);
610
611 ✗ return res;
612 }
613
614 ✗ jobject NewJavaBoolean(JNIEnv* env, jboolean value)
615 {
616 ✗ const char* className = JAVA_MODELICA_BOOLEAN;
617 const char* sig = "(Z)V";
618 jobject res;
619 jmethodID cid;
620
621 ✗ jclass cls = (*env)->FindClass(env, className);
622 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
623
624 ✗ cid = (*env)->GetMethodID(env, cls, "<init>", sig);
625 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
626
627 ✗ res = (*env)->NewObject(env, cls, cid, value);
628 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
629 ✗ (*env)->DeleteLocalRef(env, cls);
630
631 ✗ return res;
632 }
633
634 ✗ jobject NewJavaString(JNIEnv* env, const char* value)
635 {
636 ✗ const char* className = JAVA_MODELICA_STRING;
637 const char* sig = "(Ljava/lang/String;Z)V";
638 jobject res, tmp;
639 jmethodID cid;
640 ✗ jclass cls = (*env)->FindClass(env, className);
641
642 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
643
644 ✗ cid = (*env)->GetMethodID(env, cls, "<init>", sig);
645 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
646
647 ✗ tmp = value == NULL ? NULL : (*env)->NewStringUTF(env,value);
648 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
649 ✗ res = (*env)->NewObject(env, cls, cid, tmp, JNI_TRUE);
650 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
651 ✗ (*env)->DeleteLocalRef(env, cls);
652
653 ✗ return res;
654 }
655
656 ✗ jobject NewJavaOption(JNIEnv* env, jobject value)
657 {
658 ✗ const char* className = JAVA_MODELICA_OPTION;
659 const char* sig = "(Lorg/openmodelica/ModelicaObject;)V";
660 jobject res;
661 jmethodID cid;
662
663 ✗ jclass cls = (*env)->FindClass(env, className);
664 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
665
666 ✗ cid = (*env)->GetMethodID(env, cls, "<init>", sig);
667 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
668
669 ✗ res = (*env)->NewObject(env, cls, cid, value);
670 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
671 ✗ (*env)->DeleteLocalRef(env, cls);
672
673 ✗ return res;
674 }
675
676 ✗ jobject mmc_to_jobject(JNIEnv* env, void* mmc)
677 {
678 mmc_uint_t hdr;
679 int numslots;
680 unsigned ctor;
681 int i;
682
683 ✗ if(0 == ((mmc_sint_t)mmc & 1)) /* INTEGER */
684 ✗ return NewJavaInteger(env,MMC_UNTAGFIXNUM(mmc));
685 ✗ hdr = MMC_GETHDR(mmc);
686 ✗ if(hdr == MMC_REALHDR) /* REAL */
687 ✗ return NewJavaDouble(env,mmc_prim_get_real(mmc));
688 ✗ if(MMC_HDRISSTRING(hdr)) /* STRING */
689 ✗ return NewJavaString(env,omc_string_data(mmc));
690 ✗ if(hdr == MMC_NILHDR) /* Empty list; Tested, but not in OMC. */ {
691 ✗ return NewJavaArray(env);
692 }
693
694 ✗ numslots = MMC_HDRSLOTS(hdr);
695 ✗ ctor = 255 & (hdr >> 2);
696
697 ✗ if(numslots>0 && ctor > 1) { /* RECORD */
698 jobject rec_map;
699 ✗ struct record_description* desc = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(mmc),1));
700 ✗ rec_map = NewJavaMap(env);
701 ✗ if(numslots == 1 && desc == NULL) {
702 ✗ return NewJavaRecord(env, "***output record***", -2, rec_map);
703 }
704
705 ✗ for(i=1; i<numslots; i++) {
706 ✗ jobject o = mmc_to_jobject(env, MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(mmc),i+1)));
707 ✗ AddObjectToJavaMap(env, rec_map, desc->fieldNames[i-1], o);
708 }
709
710 ✗ return NewJavaRecord(env, desc->name, ctor-3, rec_map);
711 }
712
713 ✗ if(numslots>0 && ctor == 0) { /* TUPLE; Tested, but not in OMC. */
714 ✗ jobject arr = NewJavaArray(env);
715 ✗ for(i=1; i<=numslots; i++) {
716 ✗ jobject o = mmc_to_jobject(env, MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(mmc),i)));
717 ✗ JavaArrayAdd(env, arr, o);
718 }
719 ✗ return NewJavaTuple(env, arr);
720 }
721
722 ✗ if(numslots==0 && ctor==1) /* NONE(); Tested, but not in OMC. */ {
723 ✗ return NewJavaOption(env, NULL);
724 }
725
726 ✗ if(numslots==1 && ctor==1) /* SOME(x); Tested, but not in OMC. */ {
727 ✗ return NewJavaOption(env, mmc_to_jobject(env, MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(mmc),1))));
728 }
729
730 ✗ if(numslots==2 && ctor==1) { /* CONS-PAIR; Tested, but not in OMC. */
731 ✗ jobject arr = NewJavaArray(env);
732 ✗ while(!MMC_NILTEST(mmc)) {
733 ✗ JavaArrayAdd(env, arr, mmc_to_jobject(env, MMC_CAR(mmc)));
734 ✗ mmc = MMC_CDR(mmc);
735 }
736 return arr;
737 }
738
739 ✗ fprintf(stderr, "%s:%s: %d slots; ctor %d - FAILED to detect the type\n",
740 __FILE__, __func__, numslots, ctor);
741 ✗ EXIT(EXIT_CODE_JAVA_ERROR);
742 }
743
744 ✗ const char* jobjectToString(JNIEnv* env, jobject obj)
745 {
746 jmethodID mid;
747 jobject jstr;
748 jclass cls;
749 ✗ cls = (*env)->GetObjectClass(env, obj);
750 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
751 ✗ mid = (*env)->GetMethodID(env, cls, "toString", "()Ljava/lang/String;");
752 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
753 ✗ jstr = (*env)->CallObjectMethod(env, obj, mid);
754 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
755 ✗ return copyJstring(env, jstr);
756 }
757
758 ✗ const char* copyJstring(JNIEnv* env, jobject jstr)
759 {
760 const char* str_tmp;
761 const char* str;
762 ✗ if(jstr == NULL) {
763 ✗ fprintf(stderr, "%s: Java String was NULL\n", __func__);
764 ✗ EXIT(EXIT_CODE_JAVA_ERROR);
765 }
766 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
767 ✗ str_tmp = (*env)->GetStringUTFChars(env, jstr, NULL);
768 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
769 ✗ if(str_tmp == NULL) {
770 ✗ fprintf(stderr, "%s: GetStringUTFChars failed\n", __func__);
771 ✗ EXIT(EXIT_CODE_JAVA_ERROR);
772 }
773
774 ✗ str = GC_strdup(str_tmp);
775 ✗ (*env)->ReleaseStringUTFChars(env, jstr, str_tmp);
776 ✗ return str;
777 }
778
779
780 ✗ void* jobject_to_mmc_record(JNIEnv* env, jobject record)
781 {
782 jmethodID midGetKeys,midToArray,midGetIndex,midRecPath;
783 jfieldID fidRecName;
784 jclass clsObj;
785 jclass clsKeySet;
786 jobject keySet, jarrKeys, recordName, recordPath;
787 jsize length;
788 jint i, ctor_index;
789 void** values;
790 void* res;
791 static jint jobject_to_mmc_record_warning_shown = 0;
792
793 ✗ struct record_description *rec_desc = malloc(sizeof(struct record_description));
794
795 ✗ clsObj = (*env)->GetObjectClass(env, record);
796 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
797 /* Copy record names to C strings */
798 ✗ fidRecName = (*env)->GetFieldID(env, clsObj, "recordName", "Ljava/lang/String;");
799 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
800 ✗ recordName = (*env)->GetObjectField(env, record, fidRecName);
801 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
802 ✗ midRecPath = (*env)->GetMethodID(env, clsObj, "getRecordPath", "()Ljava/lang/String;");
803 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
804 ✗ recordPath = (*env)->CallObjectMethod(env, record, midRecPath);
805 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
806 ✗ rec_desc->path=copyJstring(env, recordPath);
807 ✗ rec_desc->name=copyJstring(env, recordName);
808 /* Get the ctor_index */
809 ✗ midGetIndex = (*env)->GetMethodID(env, clsObj, "get_ctor_index", "()I");
810 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
811 ✗ ctor_index = (*env)->CallIntMethod(env, record, midGetIndex);
812 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
813 /* Get the key set */
814 ✗ midGetKeys = (*env)->GetMethodID(env, clsObj, "keySet", "()Ljava/util/Set;");
815 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
816 ✗ keySet = (*env)->CallObjectMethod(env, record, midGetKeys);
817 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
818 ✗ clsKeySet = (*env)->GetObjectClass(env, keySet);
819 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
820 ✗ midToArray = (*env)->GetMethodID(env, clsKeySet, "toArray", "()[Ljava/lang/Object;");
821 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
822 ✗ jarrKeys = (*env)->CallObjectMethod(env, keySet, midToArray);
823 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
824 ✗ length = (*env)->GetArrayLength(env, jarrKeys);
825 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
826 /* Alloc and fill data/fieldnames */
827 ✗ rec_desc->fieldNames = malloc(length*sizeof(char*));
828 ✗ values = malloc((length+1)*sizeof(void*));
829 ✗ values[0] = rec_desc;
830 ✗ for(i=0; i<length; i++) {
831 ✗ jobject jstr = (*env)->GetObjectArrayElement(env, jarrKeys, i);
832 jobject fieldValue;
833 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
834 ✗ rec_desc->fieldNames[i] = copyJstring(env, jstr);
835 ✗ fieldValue = GetObjectFromJavaMap(env, record, rec_desc->fieldNames[i]);
836 ✗ values[i+1] = jobject_to_mmc(env, fieldValue);
837 }
838
839 ✗ if(ctor_index == -2 && 0 == jobject_to_mmc_record_warning_shown) {
840 ✗ const char* recStr = jobjectToString(env, record);
841 ✗ jobject_to_mmc_record_warning_shown = 1;
842 printf("Warning: %s:%s:%d\n*** %s\n", __FILE__, __func__, __LINE__, recStr);
843 printf("*** The record sent from Java does not carry a valid ctor_index value\n");
844 printf("*** The field names may not be valid in OMC, but you can still view the structure in the Interactive interface.\n");
845 printf("*** The returned record was probably created using new ModelicaRecord(...)\n");
846 printf("*** Using the automatically generated interface (org.openmodelica.corba.parser.DefinitionsParser) is preferred.\n");
847 printf("*** If you want to remove this warning, inherit from ModelicaRecord and override int get_ctor_index().\n");
848 printf("*** Make it return -1 for regular records or >=0 for uniontypes.\n");
849 printf("*** The correct value to use for uniontypes can be seen if you run getDefinitions() in the Interactive interface.\n");
850 printf("*** This message will only be shown once per object file.\n");
851 }
852 ✗ res = mmc_mk_box_arr(length+1, (ctor_index != -2 ? ctor_index+3 : 2), values);
853 ✗ free(values);
854 ✗ return res;
855 }
856
857 ✗ void* jobject_to_mmc_int(JNIEnv* env, jobject obj)
858 {
859 ✗ return mmc_mk_icon(GetJavaInteger(env, obj));
860 }
861
862 ✗ void* jobject_to_mmc_real(JNIEnv* env, jobject obj)
863 {
864 ✗ return mmc_mk_rcon(GetJavaDouble(env, obj));
865 }
866
867 ✗ void* jobject_to_mmc_bool(JNIEnv* env, jobject obj)
868 {
869 ✗ return mmc_mk_icon(GetJavaBoolean(env, obj) != JNI_FALSE ? 1 : 0);
870 }
871
872 ✗ void* jobject_to_mmc_string(JNIEnv* env, jobject obj)
873 {
874 ✗ return omc_string_new(GetJavaString(env, obj));
875 }
876
877 ✗ void* jobject_to_mmc_tuple(JNIEnv* env, jobject obj)
878 {
879 jobject jarr;
880 jmethodID mid;
881 jclass cls;
882 int i, length;
883 void** values;
884 void* res;
885
886 ✗ cls = (*env)->GetObjectClass(env, obj);
887 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
888 ✗ mid = (*env)->GetMethodID(env, cls, "toArray", "()[Ljava/lang/Object;");
889 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
890 ✗ jarr = (*env)->CallObjectMethod(env, obj, mid);
891 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
892 ✗ length = (*env)->GetArrayLength(env, jarr);
893
894 ✗ values = malloc((length)*sizeof(void*));
895 ✗ for(i=0; i<length; i++) {
896 ✗ jobject fieldValue = (*env)->GetObjectArrayElement(env, jarr, i);
897 ✗ values[i] = jobject_to_mmc(env, fieldValue);
898 }
899 ✗ res = mmc_mk_box_arr(length, 0 /* tuple: ctor=0 */, values);
900 ✗ free(values);
901 ✗ return res;
902 }
903
904 ✗ void* jobject_to_mmc_list(JNIEnv* env, jobject obj)
905 {
906 jobject jarr;
907 jmethodID mid;
908 jclass cls;
909 int i, length;
910 void* res;
911
912 ✗ cls = (*env)->GetObjectClass(env, obj);
913 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
914 ✗ mid = (*env)->GetMethodID(env, cls, "toArray", "()[Ljava/lang/Object;");
915 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
916 ✗ jarr = (*env)->CallObjectMethod(env, obj, mid);
917 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
918 ✗ length = (*env)->GetArrayLength(env, jarr);
919
920 res = mmc_mk_nil();
921 ✗ for(i=0; i<length; i++) {
922 /* Copy in reverse order */
923 ✗ jobject fieldValue = (*env)->GetObjectArrayElement(env, jarr, length-i-1);
924 ✗ res = mmc_mk_cons(jobject_to_mmc(env, fieldValue), res);
925 }
926 ✗ return res;
927 }
928
929 ✗ void* jobject_to_mmc_option(JNIEnv* env, jobject obj)
930 {
931 jobject option;
932 jfieldID fid;
933 jclass cls;
934
935 ✗ cls = (*env)->GetObjectClass(env, obj);
936 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
937 ✗ fid = (*env)->GetFieldID(env, cls, "o", "Lorg/openmodelica/ModelicaObject;");
938 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
939 ✗ option = (*env)->GetObjectField(env, obj, fid);
940 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
941 ✗ if(option == NULL)
942 return mmc_mk_none();
943 ✗ return mmc_mk_some(jobject_to_mmc(env, option));
944 }
945
946 #define CALL_IF_INSTANCEOF(env,fn,o,c) { \
947 jobject cls = (*env)->FindClass(env, c); \
948 CHECK_FOR_JAVA_EXCEPTION(env); \
949 if((*env)->IsInstanceOf(env,o,cls)) \
950 return fn(env, o); \
951 CHECK_FOR_JAVA_EXCEPTION(env);\
952 };
953
954 ✗ void* jobject_to_mmc(JNIEnv* env, jobject o)
955 {
956 ✗ CALL_IF_INSTANCEOF(env,jobject_to_mmc_record, o, JAVA_MODELICA_RECORD);
957 ✗ CALL_IF_INSTANCEOF(env,jobject_to_mmc_int, o, JAVA_MODELICA_INTEGER);
958 ✗ CALL_IF_INSTANCEOF(env,jobject_to_mmc_real, o, JAVA_MODELICA_REAL);
959 ✗ CALL_IF_INSTANCEOF(env,jobject_to_mmc_bool, o, JAVA_MODELICA_BOOLEAN);
960 ✗ CALL_IF_INSTANCEOF(env,jobject_to_mmc_string, o, JAVA_MODELICA_STRING);
961 ✗ CALL_IF_INSTANCEOF(env,jobject_to_mmc_tuple, o, JAVA_MODELICA_TUPLE);
962 ✗ CALL_IF_INSTANCEOF(env,jobject_to_mmc_option, o, JAVA_MODELICA_OPTION);
963 ✗ CALL_IF_INSTANCEOF(env,jobject_to_mmc_list, o, JAVA_MODELICA_ARRAY); /* LIST */
964
965 ✗ fprintf(stderr, "%s:%s: Failed to parse object: %s\n",
966 __FILE__, __func__, jobjectToString(env, o));
967 ✗ EXIT(EXIT_CODE_JAVA_ERROR);
968 }
969
970 ✗ jint GetJavaInteger(JNIEnv* env, jobject obj) {
971 jfieldID fid;
972 ✗ jclass cls = (*env)->GetObjectClass(env, obj);
973 jint res;
974
975 ✗ fid = (*env)->GetFieldID(env, cls, "i", "I");
976 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
977
978 ✗ res = (*env)->GetIntField(env, obj, fid);
979 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
980 ✗ return res;
981 }
982
983
984 ✗ jdouble GetJavaDouble(JNIEnv* env, jobject obj) {
985 jfieldID fid;
986 ✗ jclass cls = (*env)->GetObjectClass(env, obj);
987 jdouble res;
988
989 ✗ fid = (*env)->GetFieldID(env, cls, "r", "D");
990 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
991
992 ✗ res = (*env)->GetDoubleField(env, obj, fid);
993 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
994 ✗ return res;
995 }
996
997 ✗ jboolean GetJavaBoolean(JNIEnv* env, jobject obj) {
998 jfieldID fid;
999 ✗ jclass cls = (*env)->GetObjectClass(env, obj);
1000 jboolean res;
1001
1002 ✗ fid = (*env)->GetFieldID(env, cls, "b", "Z");
1003 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1004
1005 ✗ res = (*env)->GetBooleanField(env, obj, fid);
1006 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1007 ✗ return res;
1008 }
1009
1010 ✗ const char* GetJavaString(JNIEnv* env, jobject obj) {
1011 jobject jstr;
1012 jmethodID mid;
1013
1014 ✗ jclass cls = (*env)->GetObjectClass(env, obj);
1015
1016 ✗ mid = (*env)->GetMethodID(env, cls, "toEscapedString", "()Ljava/lang/String;");
1017 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1018
1019 ✗ jstr = (*env)->CallObjectMethod(env, obj, mid);
1020 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1021 ✗ return copyJstring(env, jstr);
1022 }
1023
1024 ✗ void AddObjectToJavaMap(JNIEnv* env, jobject map, const char* key, jobject value)
1025 {
1026 const char* sig = "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;";
1027 const char* methodName = "put";
1028 jmethodID mid;
1029 jclass cls;
1030 jobject keyString;
1031
1032 ✗ cls = (*env)->GetObjectClass(env, map);
1033
1034 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1035
1036 ✗ mid = (*env)->GetMethodID(env, cls, methodName, sig);
1037 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1038
1039 ✗ keyString = (*env)->NewStringUTF(env,key);
1040 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1041 ✗ (*env)->CallObjectMethod(env, map, mid, keyString, value);
1042 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1043
1044 ✗ (*env)->DeleteLocalRef(env, cls);
1045 ✗ (*env)->DeleteLocalRef(env, keyString);
1046 ✗ (*env)->DeleteLocalRef(env, value);
1047 ✗ return;
1048 }
1049
1050 ✗ jobject GetObjectFromJavaMap(JNIEnv* env, jobject map, const char* key) {
1051 const char* sig = "(Ljava/lang/Object;)Ljava/lang/Object;";
1052 const char* methodName = "get";
1053 jmethodID mid;
1054 jclass cls;
1055 jobject keyString, res;
1056
1057 ✗ cls = (*env)->GetObjectClass(env, map);
1058 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1059 ✗ mid = (*env)->GetMethodID(env, cls, methodName, sig);
1060 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1061
1062 ✗ keyString = (*env)->NewStringUTF(env,key);
1063 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1064 ✗ res = (*env)->CallObjectMethod(env, map, mid, keyString);
1065 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1066
1067 ✗ (*env)->DeleteLocalRef(env, cls);
1068 ✗ (*env)->DeleteLocalRef(env, keyString);
1069 ✗ return res;
1070 }
1071
1072 ✗ metamodelica_string GetStackTrace(JNIEnv* env, jobject t)
1073 {
1074 jmethodID mid;
1075 jclass cls;
1076 jstring msg;
1077 metamodelica_string res;
1078
1079 ✗ cls = (*env)->FindClass(env, "org/openmodelica/ModelicaHelper");
1080 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1081 ✗ mid = (*env)->GetStaticMethodID(env, cls, "getStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;");
1082 ✗ CHECK_FOR_JAVA_EXCEPTION(env);
1083 ✗ msg = (*env)->CallStaticObjectMethod(env, cls, mid, t);
1084 ✗ res = omc_string_new(copyJstring(env, msg));
1085
1086 ✗ (*env)->DeleteLocalRef(env, msg);
1087 ✗ (*env)->DeleteLocalRef(env, cls);
1088 ✗ return res;
1089 }
1090
1091 const char* __CheckForJavaException(JNIEnv* env)
1092 {
1093 jthrowable exc;
1094 char* res;
1095 static int inside_exception = 0;
1096
1097 exc = (*env)->ExceptionOccurred(env);
1098 if(exc) {
1099 (*env)->ExceptionClear(env);
1100
1101 if(inside_exception) {
1102 return "The exception handler triggered an exception.\nMake sure the java runtime is installed in $OPENMODELICAHOME/share/java/modelica_java.jar\n";
1103 }
1104 inside_exception = 1;
1105 res = (char*)GetStackTrace(env, exc);
1106 inside_exception = 0;
1107
1108 (*env)->DeleteLocalRef(env, exc);
1109 return res;
1110 } else {
1111 return NULL;
1112 }
1113 }
1114