Project

Profile

Help

How to connect?
Download (14 KB) Statistics
| Branch: | Tag: | Revision:

he / latest10 / hec / Saxon.C.API / EEC / SaxonCGlue.c @ 6304fb8b

1
#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 != nullptr) {
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 == nullptr || resources_dir == nullptr)
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: %i\n", name_len);
95
        printf("Env length: %i\n", env_len);
96
        printf("size of dllname %i\n", strlen(dllname));
97
        printf("dllName: %s\n", dllname);
98
        printf("resources_dir: %s\n", resources_dir);
99
        printf("size of resources dir %i\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(nullptr);
122
}
123

    
124

    
125
/*
126
 * Load dll.
127
 */
128
HANDLE loadDll(char* name)
129
{
130
        if (name == nullptr) {
131
                setDllname();
132
                name = getDllname();
133
                //perror("Error1: ");
134
        }
135

    
136
#if !(defined (__linux__) || (defined (__APPLE__) && defined(__MACH__)))
137
        HANDLE hDll = LoadLibrary(name); // Used for windows only
138
#else
139
        HANDLE hDll = LoadLibrary(name);
140
#endif
141
        if (!hDll) {
142
                fprintf(stderr, "Unable to load %s\n", name);
143
                perror("Error: ");
144
                exit(1);
145
        }
146
#ifdef DEBUG
147
        fprintf(stderr, "%s loaded\n", name);
148
#endif
149

    
150
        return hDll;
151
}
152

    
153

    
154

    
155
jint(JNICALL * JNI_GetDefaultJavaVMInitArgs_func) (void *args);
156
jint(JNICALL * JNI_CreateJavaVM_func) (JavaVM **pvm, void **penv, void *args);
157

    
158

    
159

    
160
void initDefaultJavaRT(sxnc_environment *env) {
161
        sxnc_environment *environi = env;
162
        initJavaRT((environi->myDllHandle), &(environi->jvm), &(environi->env));
163
}
164

    
165
/*
166
 * Initialize JET run-time.
167
 */
168
void initJavaRT(HANDLE myDllHandle, JavaVM** pjvm, JNIEnv** penv)
169
{
170
        if (jvmCreated == 0) {
171
                jvmCreated = 1;
172
#ifdef DEBUG
173
                perror("initJavaRT - load Saxon/C library\n");
174
#endif
175
                int result;
176
                JavaVMInitArgs args;
177
                JNI_GetDefaultJavaVMInitArgs_func =
178
                        (jint(JNICALL *) (void *args))
179
#if !(defined (__linux__) || (defined (__APPLE__) && defined(__MACH__)))
180
                        GetProcAddress((HMODULE)myDllHandle, "JNI_GetDefaultJavaVMInitArgs");
181
#else
182
                        GetProcAddress(myDllHandle, "JNI_GetDefaultJavaVMInitArgs");
183
#endif
184

    
185

    
186
                JNI_CreateJavaVM_func =
187
                        (jint(JNICALL *) (JavaVM **pvm, void **penv, void *args))
188

    
189
#if !(defined (__linux__) || (defined (__APPLE__) && defined(__MACH__)))
190
                        GetProcAddress((HMODULE)myDllHandle, "JNI_CreateJavaVM");
191
#else
192
                        GetProcAddress(myDllHandle, "JNI_CreateJavaVM");
193

    
194
#endif
195

    
196

    
197
                if (!JNI_GetDefaultJavaVMInitArgs_func) {
198
                        fprintf(stderr, "%s doesn't contain public JNI_GetDefaultJavaVMInitArgs\n", getDllname());
199
                        exit(1);
200
                }
201

    
202
                if (!JNI_CreateJavaVM_func) {
203
                        fprintf(stderr, "%s doesn't contain public JNI_CreateJavaVM\n", getDllname());
204
                        exit(1);
205
                }
206

    
207
                memset(&args, 0, sizeof(args));
208

    
209
                args.version = JNI_VERSION_1_2;
210
                result = JNI_GetDefaultJavaVMInitArgs_func(&args);
211
                if (result != JNI_OK) {
212
                        fprintf(stderr, "JNI_GetDefaultJavaVMInitArgs() failed with result\n");
213
                        exit(1);
214
                }
215

    
216
                /*
217
                 * NOTE: no JVM is actually created
218
                 * this call to JNI_CreateJavaVM is intended for JET RT initialization
219
                 */
220
                result = JNI_CreateJavaVM_func(pjvm, (void **)penv, &args);
221
                if (result != JNI_OK) {
222
                        fprintf(stderr, "JNI_CreateJavaVM() failed with result: %i\n", result);
223
                        exit(1);
224
                }
225

    
226

    
227
                fflush(stdout);
228
        }
229
        else {
230
#ifdef DEBUG
231
                perror("initJavaRT - Saxon/C library loaded already\n");
232
#endif
233
        }
234
}
235

    
236

    
237
/*
238
 * Look for class.
239
 */
240
jclass lookForClass(JNIEnv* penv, const char* name)
241
{
242
        jclass clazz = (*penv)->FindClass(penv, name);
243

    
244
        if (!clazz) {
245
                printf("Unable to find class %s\n", name);
246
                return nullptr;
247
        }
248
#ifdef DEBUG
249
        printf("Class %s found\n", name);
250
        fflush(stdout);
251
#endif
252

    
253
        return clazz;
254
}
255

    
256

    
257
/*
258
 * Create an object and invoke the instance method
259
 */
260
void invokeInstanceMethod(JNIEnv* penv, jclass myClassInDll, char * name, char * arguments)
261
{
262
        jmethodID MID_init, MID_name;
263
        jobject obj;
264

    
265
        MID_init = (*penv)->GetMethodID(penv, myClassInDll, "<init>", "()V");
266
        if (!MID_init) {
267
                printf("Error: MyClassInDll.<init>() not found\n");
268
                return;
269
        }
270

    
271
        obj = (*penv)->NewObject(penv, myClassInDll, MID_init);
272
        if (!obj) {
273
                printf("Error: failed to allocate an object\n");
274
                return;
275
        }
276

    
277
        MID_name = (*penv)->GetMethodID(penv, myClassInDll, name, arguments);
278

    
279
        if (!MID_name) {
280
                printf("Error: %s not found\n", name);
281
                return;
282
        }
283

    
284
        (*(penv))->CallVoidMethod(penv, obj, MID_name);
285
}
286

    
287

    
288

    
289

    
290
/*
291
 * Invoke the static method
292
 */
293
void invokeStaticMethod(JNIEnv* penv, jclass myClassInDll, char* name, char* arguments)
294
{
295
        jmethodID MID_name;
296

    
297
        MID_name = (*penv)->GetStaticMethodID(penv, myClassInDll, name, arguments);
298
        if (!MID_name) {
299
                printf("\nError: method %s not found\n", name);
300
                return;
301
        }
302

    
303
        (*penv)->CallStaticVoidMethod(penv, myClassInDll, MID_name);
304
}
305

    
306

    
307
/*
308
 * Find a constructor with a set arguments
309
 */
310
jmethodID findConstructor(JNIEnv* penv, jclass myClassInDll, char* arguments)
311
{
312
        jmethodID MID_initj;
313

    
314
        MID_initj = (jmethodID)(*penv)->GetMethodID(penv, myClassInDll, "<init>", arguments);
315
        if (!MID_initj) {
316
                printf("Error: MyClassInDll.<init>() not found\n");
317
                fflush(stdout);
318
                return 0;
319
        }
320

    
321
        return MID_initj;
322
}
323

    
324
/*
325
 * Create the Java SaxonProcessor
326
 */
327
jobject createSaxonProcessor(JNIEnv* penv, jclass myClassInDll, const char * arguments, jobject argument1, jboolean license)
328
{
329
        jmethodID MID_initi;
330

    
331
        jobject obj;
332

    
333
        MID_initi = (jmethodID)(*(penv))->GetMethodID(penv, myClassInDll, "<init>", arguments);
334
        if (!MID_initi) {
335
                printf("Error: MyClassInDll.<init>() not found\n");
336
                return nullptr;
337
        }
338

    
339
        if (argument1) {
340

    
341
                obj = (jobject)(*(penv))->NewObject(penv, myClassInDll, MID_initi, argument1, license);
342
        }
343
        else {
344

    
345
                obj = (jobject)(*(penv))->NewObject(penv, myClassInDll, MID_initi, license);
346
        }
347
        if (!obj) {
348
                printf("Error: failed to allocate an object\n");
349
                return nullptr;
350
        }
351
        return obj;
352
}
353

    
354

    
355
/*
356
 * Create the Java SaxonProcessor without boolean license argument
357
 */
358
jobject createSaxonProcessor2(JNIEnv* penv, jclass myClassInDll, const char * arguments, jobject argument1)
359
{
360
        jmethodID MID_initi;
361

    
362
        jobject obj;
363

    
364
        MID_initi = (jmethodID)(*(penv))->GetMethodID(penv, myClassInDll, "<init>", arguments);
365
        if (!MID_initi) {
366
                printf("Error: MyClassInDll.<init>() not found\n");
367
                return nullptr;
368
        }
369

    
370
        if (argument1) {
371

    
372
                obj = (jobject)(*(penv))->NewObject(penv, myClassInDll, MID_initi, argument1);
373
        }
374
        else {
375

    
376
                obj = (jobject)(*(penv))->NewObject(penv, myClassInDll, MID_initi);
377
        }
378
        if (!obj) {
379
                printf("Error: failed to allocate an object\n");
380
                return nullptr;
381
        }
382
        return obj;
383
}
384

    
385

    
386

    
387

    
388
/*
389
 * Callback to check for exceptions. When called it returns the exception as a string
390
 */
391
const char * checkForException(sxnc_environment *environii, jobject callingObject) {
392
        if (callingObject) {} // TODO: Remove the callingObject variable
393
        if ((*(environii->env))->ExceptionCheck(environii->env)) {
394

    
395
                jthrowable exc = (*(environii->env))->ExceptionOccurred(environii->env);
396
#ifdef DEBUG
397
                (*(environii->env))->ExceptionDescribe(environii->env);
398
#endif
399
                if (exc) {
400
                        printf("Exception Occurred!");
401
                }
402
                jclass exccls = (jclass)(*(environii->env))->GetObjectClass(environii->env, exc);
403

    
404
                jclass clscls = (jclass)(*(environii->env))->FindClass(environii->env, "java/lang/Class");
405

    
406
                jmethodID getName = (jmethodID)(*(environii->env))->GetMethodID(environii->env, clscls, "getName", "()Ljava/lang/String;");
407
                jstring name = (jstring)((*(environii->env))->CallObjectMethod(environii->env, exccls, getName));
408
                char const* utfName = (*(environii->env))->GetStringUTFChars(environii->env, name, nullptr);
409

    
410
                //if(callingObject != nullptr && strcmp(utfName, "net.sf.saxon.s9api.SaxonApiException") == 0){
411

    
412
                jmethodID  getMessage = (jmethodID)(*(environii->env))->GetMethodID(environii->env, exccls, "getMessage", "()Ljava/lang/String;");
413

    
414
                if (getMessage) {
415

    
416
                        jstring message = (jstring)((*(environii->env))->CallObjectMethod(environii->env, exc, getMessage));
417

    
418
                        if (!message) {
419

    
420
                                (*(environii->env))->ExceptionClear(environii->env);
421
                                return 0;
422
                        }
423
                        char const* utfMessage = (*(environii->env))->GetStringUTFChars(environii->env, message, nullptr);
424

    
425
                        if (utfMessage != nullptr) {
426
                                (*(environii->env))->ReleaseStringUTFChars(environii->env, name, utfName);
427
                        }
428

    
429
                        (*(environii->env))->ExceptionClear(environii->env);
430
                        return utfMessage;
431
                }
432
                // }
433
                (*(environii->env))->ReleaseStringUTFChars(environii->env, name, utfName);
434
        }
435
        //(*(environii->env))->ExceptionClear(environii->env);
436
        return 0;
437
}
438

    
439

    
440
/*
441
 * Clean up and destroy Java VM to release memory used.
442
 */
443
void finalizeJavaRT(JavaVM* jvm)
444
{
445

    
446
        if (jvmCreated != 0) {
447
                (*jvm)->DestroyJavaVM(jvm);
448
                jvmCreated = 0;
449
        }
450
}
451

    
452

    
453
/*
454
 * Get a parameter from list
455
 */
456
jobject getParameter(sxnc_parameter *parameters, int parLen, const char* namespacei, const char * name) {
457
        int i = 0;
458
        namespacei = nullptr; // variable not used yet
459
        if (namespacei == nullptr) {} // avoiding warning. In next release fix this
460
        for (i = 0; i < parLen; i++) {
461
                if (strcmp(parameters[i].name, name) == 0)
462
                        return (jobject)parameters[i].value;
463
        }
464
        return nullptr;
465
}
466

    
467

    
468
/*
469
 * Get a property from list
470
 */
471
char* getProperty(sxnc_property * properties, int propLen, const char* namespacei, const char * name) {
472
        int i = 0;
473
        namespacei = nullptr; // variable not used yet
474
        if (namespacei == nullptr) {} // avoiding warning. In next release fix this
475
        for (i = 0; i < propLen; i++) {
476
                if (strcmp(properties[i].name, name) == 0)
477
                        return properties[i].value;
478
        }
479
        return 0;
480
}
481

    
482

    
483
/*
484
 * set a parameter
485
 */
486
void setParameter(sxnc_parameter **parameters, int * parLen, int * parCap, const char * namespacei, const char * name, jobject value) {
487

    
488
        namespacei = nullptr;
489
        if (getParameter(*parameters, (*parLen), "", name) != 0) {
490
                return;
491
        }
492
        (*parLen)++;
493
        if ((*parLen) >= (*parCap)) {
494
                (*parCap) *= 2;
495
                sxnc_parameter* temp = (sxnc_parameter*)malloc(sizeof(sxnc_parameter)*(*parCap));
496
                int i = 0;
497
                for (i = 0; i < (*parLen) - 1; i++) {
498
                        temp[i] = (*parameters)[i];
499
                }
500
                free(parameters);
501
                parameters = &temp;
502
        }
503
        int nameLen = strlen(name) + 7;
504
        char *newName = malloc(sizeof(char)*nameLen);
505
        int namespaceLen = strlen(namespacei);
506
        char *newNamespace = malloc(sizeof(char)*namespaceLen);
507
        snprintf(newName, nameLen, "%s%s", "param:", name);
508
        snprintf(newNamespace, namespaceLen, "%s", name);
509
        (*parameters)[(*parLen) - 1].name = (char*)newName;
510
        (*parameters)[(*parLen) - 1].namespacei = (char*)newNamespace;
511
        (*parameters)[(*parLen) - 1].value = (jobject)value;
512
}
513

    
514

    
515
/*
516
 * set a property
517
 */
518
void setProperty(sxnc_property ** properties, int *propLen, int *propCap, const char* name, const char* value) {
519
        if (getProperty(*properties, (*propLen), "", name) != 0) {
520
                return;
521
        }
522

    
523
        if (((*propLen) + 1) >= (*propCap)) {
524
                (*propCap) *= 2;
525
                sxnc_property* temp = (sxnc_property*)malloc(sizeof(sxnc_property)*  (*propCap));
526
                int i = 0;
527
                for (i = 0; i < (*propLen) - 1; i++) {
528
                        temp[i] = (*properties)[i];
529
                }
530
                free(properties);
531
                properties = &temp;
532

    
533
        }
534
        int nameLen = strlen(name) + 1;
535
        char *newName = (char*)malloc(sizeof(char)*nameLen);
536
        snprintf(newName, nameLen, "%s", name);
537
        char *newValue = (char*)malloc(sizeof(char)*strlen(value) + 1);
538
        snprintf(newValue, strlen(value) + 1, "%s", value);
539
        (*properties)[(*propLen)].name = (char*)newName;
540
        (*properties)[(*propLen)].value = (char*)newValue;
541
        (*propLen)++;
542
}
543

    
544
/*
545
 * clear parameter
546
 */
547
void clearSettings(sxnc_parameter **parameters, int *parLen, sxnc_property ** properties, int *propLen) {
548
        free(*parameters);
549
        free(*parameters);
550

    
551

    
552
        *parameters = (sxnc_parameter *)calloc(10, sizeof(sxnc_parameter));
553
        *properties = (sxnc_property *)calloc(10, sizeof(sxnc_property));
554
        (*parLen) = 0;
555
        (*propLen) = 0;
556
}
557

    
558

    
559
const char * stringValue(sxnc_environment *environi, jobject value) {
560
        jclass  objClass = lookForClass(environi->env, "java/lang/Object");
561
        static jmethodID strMID = nullptr;
562
        if (!strMID) {
563
                strMID = (jmethodID)(*(environi->env))->GetMethodID(environi->env, objClass, "toString", "()Ljava/lang/String;");
564
                if (!strMID) {
565
                        printf("\nError: Object %s() not found\n", "toString");
566
                        fflush(stdout);
567
                        return nullptr;
568
                }
569
        }
570
        jstring result = (jstring)((*(environi->env))->CallObjectMethod(environi->env, value, strMID));
571
        if (result) {
572
                const char * str = (*(environi->env))->GetStringUTFChars(environi->env, result, nullptr);
573
                return str;
574
        }
575

    
576
        //checkForException(environ, cpp);
577
        return 0;
578

    
579
}
580

    
581

    
582

    
583

    
    (1-1/1)