Project

Profile

Help

Download (13.9 KB) Statistics
| Branch: | Revision:

he / src / main / c / Saxon.C.API / PEC / SaxonCGlue.c @ af4371f2

1 72bf04c6 Norman Walsh
#include "SaxonCGlue.h"
2
3
jobject cpp;
4
char * dllname;
5
char * resources_dir;
6
int jvmCreated = 0;
7
char * tempDllname =
8
#if defined (__linux__)
9
"/libsaxonpec.so";
10
#elif  defined (__APPLE__) && defined(__MACH__)
11
"/libsaxonpec.dylib";
12
#else
13
"\\libsaxonpec.dll";
14
#endif
15
16
17
char * tempResources_dir =
18
#ifdef __linux__
19
"/saxon-data";
20
#elif  defined (__APPLE__) && defined(__MACH__)
21
"/saxon-data";
22
#else
23
"\\saxon-data";
24
#endif
25
26
char * dllPath =
27
#if defined (__linux__)
28
"/usr/lib";
29
#elif  defined (__APPLE__) && defined(__MACH__)
30
"/usr/local/lib";
31
#else
32
"C:\\Program Files\\Saxonica\\SaxonPEC1.2.1";
33
#endif
34
35
/*
36
* Set Dll name. Also set the saxon resources directory.
37
* If the SAXONC_HOME sxnc_environmental variable is set then use that as base.
38
*/
39
void setDllname() {
40
        size_t name_len = strlen(tempDllname);
41
        size_t rDir_len = strlen(tempResources_dir);
42
        char * env = getenv("SAXONC_HOME");
43
        size_t env_len;
44
        if (env != NULL) {
45
46
47
                env_len = strlen(env);
48
                int bufSize = name_len + env_len + 1;
49
                int rbufSize = rDir_len + env_len + 1;
50
                dllname = malloc(sizeof(char)*bufSize);
51
                resources_dir = malloc(sizeof(char)*rbufSize);
52
                snprintf(dllname, bufSize, "%s%s", env, tempDllname);
53
                snprintf(resources_dir, rbufSize, "%s%s", env, tempResources_dir);
54
55
#ifdef DEBUG        
56
57
                printf("envDir: %s\n", env);
58
59
60
#endif
61
62
        }
63
        else {
64
                env_len = strlen(dllPath);
65
                int bufSize = name_len + env_len + 1;
66
                int rbufSize = rDir_len + env_len + 1;
67
                dllname = malloc(sizeof(char)*bufSize);
68
                resources_dir = malloc(sizeof(char)*rbufSize);
69
70
#ifdef DEBUG
71
                if (dllname == NULL || resources_dir == NULL)
72
                {
73
                        // error
74
                        printf("Error in allocation of Dllname\n");
75
                }
76
#endif
77
                if (snprintf(dllname, bufSize, "%s%s", dllPath, tempDllname) >= bufSize) {
78
                        bufSize *= 2;
79
                        free(dllname);
80
                        dllname = malloc(sizeof(char)*bufSize);
81
                        if (snprintf(dllname, bufSize, "%s%s", dllPath, tempDllname) >= bufSize) {
82
                                printf("Saxon/C Error: Unable to allocate space for dllname and path");
83
                                exit(1);
84
                        }
85
                }
86
                if (snprintf(resources_dir, rbufSize, "%s%s", dllPath, tempResources_dir) >= rbufSize) {
87
                        printf("Saxon/C warning: Unable to allocate space for resources directory");
88
89
                }
90
        }
91
92
93
#ifdef DEBUG
94
95
        printf("Library length: %i\n", name_len);
96
        printf("Env length: %i\n", env_len);
97
        printf("size of dllname %i\n", strlen(dllname));
98
        printf("dllName: %s\n", dllname);
99
        printf("resources_dir: %s\n", resources_dir);
100
        printf("size of resources dir %i\n", strlen(resources_dir));
101
#endif
102
103
}
104
105
char * getDllname() {
106
        return dllname;
107
}
108
109
char * getResourceDirectory() {
110
        return resources_dir;
111
}
112
113
char * _getResourceDirectory() {
114
        return resources_dir;
115
}
116
117
/*
118
 * Load dll using the default setting in Saxon/C
119
 * Recommended method to use to load library
120
 */
121
HANDLE loadDefaultDll() {
122
        return loadDll(NULL);
123
}
124
125
126
/*
127
 * Load dll.
128
 */
129
HANDLE loadDll(char* name)
130
{
131
        if (name == NULL) {
132
                setDllname();
133
                name = getDllname();
134
                //perror("Error1: ");
135
        }
136
137
#if !(defined (__linux__) || (defined (__APPLE__) && defined(__MACH__)))
138
        HANDLE hDll = LoadLibrary(name); // Used for windows only
139
#else
140
        HANDLE hDll = LoadLibrary(name);
141
#endif
142
        if (!hDll) {
143
                fprintf(stderr, "Unable to load %s\n", name);
144
                perror("Error: ");
145
                exit(1);
146
        }
147
#ifdef DEBUG
148
        fprintf(stderr, "%s loaded\n", name);
149
#endif
150
151
        return hDll;
152
}
153
154
155
156
jint(JNICALL * JNI_GetDefaultJavaVMInitArgs_func) (void *args);
157
jint(JNICALL * JNI_CreateJavaVM_func) (JavaVM **pvm, void **penv, void *args);
158
159
160
161
void initDefaultJavaRT(sxnc_environment *env) {
162
        sxnc_environment *environi = env;
163
        initJavaRT((environi->myDllHandle), &(environi->jvm), &(environi->env));
164
}
165
166
/*
167
 * Initialize JET run-time.
168
 */
169
void initJavaRT(HANDLE myDllHandle, JavaVM** pjvm, JNIEnv** penv)
170
{
171
        if (jvmCreated == 0) {
172
                jvmCreated = 1;
173
#ifdef DEBUG
174
                perror("initJavaRT - load Saxon/C library\n");
175
#endif
176
                int result;
177
                JavaVMInitArgs args;
178
                JNI_GetDefaultJavaVMInitArgs_func =
179
                        (jint(JNICALL *) (void *args))
180
#if !(defined (__linux__) || (defined (__APPLE__) && defined(__MACH__)))
181
                        GetProcAddress((HMODULE)myDllHandle, "JNI_GetDefaultJavaVMInitArgs");
182
#else
183
                        GetProcAddress(myDllHandle, "JNI_GetDefaultJavaVMInitArgs");
184
#endif
185
186
187
                JNI_CreateJavaVM_func =
188
                        (jint(JNICALL *) (JavaVM **pvm, void **penv, void *args))
189
190
#if !(defined (__linux__) || (defined (__APPLE__) && defined(__MACH__)))
191
                        GetProcAddress((HMODULE)myDllHandle, "JNI_CreateJavaVM");
192
#else
193
                        GetProcAddress(myDllHandle, "JNI_CreateJavaVM");
194
195
#endif
196
197
198
                if (!JNI_GetDefaultJavaVMInitArgs_func) {
199
                        fprintf(stderr, "%s doesn't contain public JNI_GetDefaultJavaVMInitArgs\n", getDllname());
200
                        exit(1);
201
                }
202
203
                if (!JNI_CreateJavaVM_func) {
204
                        fprintf(stderr, "%s doesn't contain public JNI_CreateJavaVM\n", getDllname());
205
                        exit(1);
206
                }
207
208
                memset(&args, 0, sizeof(args));
209
210
                args.version = JNI_VERSION_1_2;
211
                result = JNI_GetDefaultJavaVMInitArgs_func(&args);
212
                if (result != JNI_OK) {
213
                        fprintf(stderr, "JNI_GetDefaultJavaVMInitArgs() failed with result\n");
214
                        exit(1);
215
                }
216
217
                /*
218
                 * NOTE: no JVM is actually created
219
                 * this call to JNI_CreateJavaVM is intended for JET RT initialization
220
                 */
221
                result = JNI_CreateJavaVM_func(pjvm, (void **)penv, &args);
222
                if (result != JNI_OK) {
223
                        fprintf(stderr, "JNI_CreateJavaVM() failed with result: %i\n", result);
224
                        exit(1);
225
                }
226
227
228
                fflush(stdout);
229
        }
230
        else {
231
#ifdef DEBUG
232
                perror("initJavaRT - Saxon/C library loaded already\n");
233
#endif
234
        }
235
}
236
237
238
/*
239
 * Look for class.
240
 */
241
jclass lookForClass(JNIEnv* penv, const char* name)
242
{
243
        jclass clazz = (*penv)->FindClass(penv, name);
244
245
        if (!clazz) {
246
                printf("Unable to find class %s\n", name);
247
                return NULL;
248
        }
249
#ifdef DEBUG
250
        printf("Class %s found\n", name);
251
        fflush(stdout);
252
#endif
253
254
        return clazz;
255
}
256
257
258
/*
259
 * Create an object and invoke the instance method
260
 */
261
void invokeInstanceMethod(JNIEnv* penv, jclass myClassInDll, char * name, char * arguments)
262
{
263
        jmethodID MID_init, MID_name;
264
        jobject obj;
265
266
        MID_init = (*penv)->GetMethodID(penv, myClassInDll, "<init>", "()V");
267
        if (!MID_init) {
268
                printf("Error: MyClassInDll.<init>() not found\n");
269
                return;
270
        }
271
272
        obj = (*penv)->NewObject(penv, myClassInDll, MID_init);
273
        if (!obj) {
274
                printf("Error: failed to allocate an object\n");
275
                return;
276
        }
277
278
        MID_name = (*penv)->GetMethodID(penv, myClassInDll, name, arguments);
279
280
        if (!MID_name) {
281
                printf("Error: %s not found\n", name);
282
                return;
283
        }
284
285
        (*(penv))->CallVoidMethod(penv, obj, MID_name);
286
}
287
288
289
290
291
/*
292
 * Invoke the static method
293
 */
294
void invokeStaticMethod(JNIEnv* penv, jclass myClassInDll, char* name, char* arguments)
295
{
296
        jmethodID MID_name;
297
298
        MID_name = (*penv)->GetStaticMethodID(penv, myClassInDll, name, arguments);
299
        if (!MID_name) {
300
                printf("\nError: method %s not found\n", name);
301
                return;
302
        }
303
304
        (*penv)->CallStaticVoidMethod(penv, myClassInDll, MID_name);
305
}
306
307
308
/*
309
 * Find a constructor with a set arguments
310
 */
311
jmethodID findConstructor(JNIEnv* penv, jclass myClassInDll, char* arguments)
312
{
313
        jmethodID MID_initj;
314
315
        MID_initj = (jmethodID)(*penv)->GetMethodID(penv, myClassInDll, "<init>", arguments);
316
        if (!MID_initj) {
317
                printf("Error: MyClassInDll.<init>() not found\n");
318
                fflush(stdout);
319
                return 0;
320
        }
321
322
        return MID_initj;
323
}
324
325
/*
326
 * Create the Java SaxonProcessor
327
 */
328
jobject createSaxonProcessor(JNIEnv* penv, jclass myClassInDll, const char * arguments, jobject argument1, jboolean license)
329
{
330
        jmethodID MID_initi;
331
332
        jobject obj;
333
334
        MID_initi = (jmethodID)(*(penv))->GetMethodID(penv, myClassInDll, "<init>", arguments);
335
        if (!MID_initi) {
336
                printf("Error: MyClassInDll.<init>() not found\n");
337
                return NULL;
338
        }
339
340
        if (argument1) {
341
342
                obj = (jobject)(*(penv))->NewObject(penv, myClassInDll, MID_initi, argument1, license);
343
        }
344
        else {
345
346
                obj = (jobject)(*(penv))->NewObject(penv, myClassInDll, MID_initi, license);
347
        }
348
        if (!obj) {
349
                printf("Error: failed to allocate an object\n");
350
                return NULL;
351
        }
352
        return obj;
353
}
354
355
356
/*
357
 * Create the Java SaxonProcessor without boolean license argument
358
 */
359
jobject createSaxonProcessor2(JNIEnv* penv, jclass myClassInDll, const char * arguments, jobject argument1)
360
{
361
        jmethodID MID_initi;
362
363
        jobject obj;
364
365
        MID_initi = (jmethodID)(*(penv))->GetMethodID(penv, myClassInDll, "<init>", arguments);
366
        if (!MID_initi) {
367
                printf("Error: MyClassInDll.<init>() not found\n");
368
                return NULL;
369
        }
370
371
        if (argument1) {
372
373
                obj = (jobject)(*(penv))->NewObject(penv, myClassInDll, MID_initi, argument1);
374
        }
375
        else {
376
377
                obj = (jobject)(*(penv))->NewObject(penv, myClassInDll, MID_initi);
378
        }
379
        if (!obj) {
380
                printf("Error: failed to allocate an object\n");
381
                return NULL;
382
        }
383
        return obj;
384
}
385
386
387
388
389
/*
390
 * Callback to check for exceptions. When called it returns the exception as a string
391
 */
392
const char * checkForException(sxnc_environment *environii, jobject callingObject) {
393
        if (callingObject) {} // TODO: Remove the callingObject variable
394
        if ((*(environii->env))->ExceptionCheck(environii->env)) {
395
396
                jthrowable exc = (*(environii->env))->ExceptionOccurred(environii->env);
397
#ifdef DEBUG
398
                (*(environii->env))->ExceptionDescribe(environii->env);
399
#endif
400
                if (exc) {
401
                        printf("Exception Occurred!");
402
                }
403
                jclass exccls = (jclass)(*(environii->env))->GetObjectClass(environii->env, exc);
404
405
                jclass clscls = (jclass)(*(environii->env))->FindClass(environii->env, "java/lang/Class");
406
407
                jmethodID getName = (jmethodID)(*(environii->env))->GetMethodID(environii->env, clscls, "getName", "()Ljava/lang/String;");
408
                jstring name = (jstring)((*(environii->env))->CallObjectMethod(environii->env, exccls, getName));
409
                char const* utfName = (*(environii->env))->GetStringUTFChars(environii->env, name, NULL);
410
411
                //if(callingObject != NULL && strcmp(utfName, "net.sf.saxon.s9api.SaxonApiException") == 0){
412
413
                jmethodID  getMessage = (jmethodID)(*(environii->env))->GetMethodID(environii->env, exccls, "getMessage", "()Ljava/lang/String;");
414
415
                if (getMessage) {
416
417
                        jstring message = (jstring)((*(environii->env))->CallObjectMethod(environii->env, exc, getMessage));
418
419
                        if (!message) {
420
421
                                (*(environii->env))->ExceptionClear(environii->env);
422
                                return 0;
423
                        }
424
                        char const* utfMessage = (*(environii->env))->GetStringUTFChars(environii->env, message, NULL);
425
426
                        if (utfMessage != NULL) {
427
                                (*(environii->env))->ReleaseStringUTFChars(environii->env, name, utfName);
428
                        }
429
430
                        (*(environii->env))->ExceptionClear(environii->env);
431
                        return utfMessage;
432
                }
433
                // }
434
                (*(environii->env))->ReleaseStringUTFChars(environii->env, name, utfName);
435
        }
436
        //(*(environii->env))->ExceptionClear(environii->env);
437
        return 0;
438
}
439
440
441
/*
442
 * Clean up and destroy Java VM to release memory used.
443
 */
444
void finalizeJavaRT(JavaVM* jvm)
445
{
446
447
        if (jvmCreated != 0) {
448
                (*jvm)->DestroyJavaVM(jvm);
449
                jvmCreated = 0;
450
        }
451
}
452
453
454
/*
455
 * Get a parameter from list
456
 */
457
jobject getParameter(sxnc_parameter *parameters, int parLen, const char* namespacei, const char * name) {
458
        int i = 0;
459
        namespacei = NULL; // variable not used yet
460
        if (namespacei == NULL) {} // avoiding warning. In next release fix this
461
        for (i = 0; i < parLen; i++) {
462
                if (strcmp(parameters[i].name, name) == 0)
463
                        return (jobject)parameters[i].value;
464
        }
465
        return NULL;
466
}
467
468
469
/*
470
 * Get a property from list
471
 */
472
char* getProperty(sxnc_property * properties, int propLen, const char* namespacei, const char * name) {
473
        int i = 0;
474
        namespacei = NULL; // variable not used yet
475
        if (namespacei == NULL) {} // avoiding warning. In next release fix this
476
        for (i = 0; i < propLen; i++) {
477
                if (strcmp(properties[i].name, name) == 0)
478
                        return properties[i].value;
479
        }
480
        return 0;
481
}
482
483
484
/*
485
 * set a parameter
486
 */
487
void setParameter(sxnc_parameter **parameters, int * parLen, int * parCap, const char * namespacei, const char * name, jobject value) {
488
489
        namespacei = NULL;
490
        if (getParameter(*parameters, (*parLen), "", name) != 0) {
491
                return;
492
        }
493
        (*parLen)++;
494
        if ((*parLen) >= (*parCap)) {
495
                (*parCap) *= 2;
496
                sxnc_parameter* temp = (sxnc_parameter*)malloc(sizeof(sxnc_parameter)*(*parCap));
497
                int i = 0;
498
                for (i = 0; i < (*parLen) - 1; i++) {
499
                        temp[i] = (*parameters)[i];
500
                }
501
                free(parameters);
502
                parameters = &temp;
503
        }
504
        int nameLen = strlen(name) + 7;
505
        char *newName = malloc(sizeof(char)*nameLen);
506
        int namespaceLen = strlen(namespacei);
507
        char *newNamespace = malloc(sizeof(char)*namespaceLen);
508
        snprintf(newName, nameLen, "%s%s", "param:", name);
509
        snprintf(newNamespace, namespaceLen, "%s", name);
510
        (*parameters)[(*parLen) - 1].name = (char*)newName;
511
        (*parameters)[(*parLen) - 1].namespacei = (char*)newNamespace;
512
        (*parameters)[(*parLen) - 1].value = (jobject)value;
513
}
514
515
516
/*
517
 * set a property
518
 */
519
void setProperty(sxnc_property ** properties, int *propLen, int *propCap, const char* name, const char* value) {
520
        if (getProperty(*properties, (*propLen), "", name) != 0) {
521
                return;
522
        }
523
524
        if (((*propLen) + 1) >= (*propCap)) {
525
                (*propCap) *= 2;
526
                sxnc_property* temp = (sxnc_property*)malloc(sizeof(sxnc_property)*  (*propCap));
527
                int i = 0;
528
                for (i = 0; i < (*propLen) - 1; i++) {
529
                        temp[i] = (*properties)[i];
530
                }
531
                free(properties);
532
                properties = &temp;
533
534
        }
535
        int nameLen = strlen(name) + 1;
536
        char *newName = (char*)malloc(sizeof(char)*nameLen);
537
        snprintf(newName, nameLen, "%s", name);
538
        char *newValue = (char*)malloc(sizeof(char)*strlen(value) + 1);
539
        snprintf(newValue, strlen(value) + 1, "%s", value);
540
        (*properties)[(*propLen)].name = (char*)newName;
541
        (*properties)[(*propLen)].value = (char*)newValue;
542
        (*propLen)++;
543
}
544
545
/*
546
 * clear parameter
547
 */
548
void clearSettings(sxnc_parameter **parameters, int *parLen, sxnc_property ** properties, int *propLen) {
549
        free(*parameters);
550
        free(*parameters);
551
552
553
        *parameters = (sxnc_parameter *)calloc(10, sizeof(sxnc_parameter));
554
        *properties = (sxnc_property *)calloc(10, sizeof(sxnc_property));
555
        (*parLen) = 0;
556
        (*propLen) = 0;
557
}
558
559
560
const char * stringValue(sxnc_environment *environi, jobject value) {
561
        jclass  objClass = lookForClass(environi->env, "java/lang/Object");
562
        static jmethodID strMID = NULL;
563
        if (!strMID) {
564
                strMID = (jmethodID)(*(environi->env))->GetMethodID(environi->env, objClass, "toString", "()Ljava/lang/String;");
565
                if (!strMID) {
566
                        printf("\nError: Object %s() not found\n", "toString");
567
                        fflush(stdout);
568
                        return NULL;
569
                }
570
        }
571
        jstring result = (jstring)((*(environi->env))->CallObjectMethod(environi->env, value, strMID));
572
        if (result) {
573
                const char * str = (*(environi->env))->GetStringUTFChars(environi->env, result, NULL);
574
                return str;
575
        }
576
577
        //checkForException(environ, cpp);
578
        return 0;
579
580
}
581
582
583