Project

Profile

Help

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

he / src / main / c / Saxon.C.API / SaxonCGlue.c @ 03fcd3f9

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