Project

Profile

Help

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

he / src / main / c / Saxon.C.API / SaxonCGlue.c @ 55b80284

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 != 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
                printf("Error: SaxoncDll.%s <init>() not found\n", name);
276
                return;
277
        }
278

    
279
        obj = (*penv)->NewObject(penv, myClassInDll, MID_init);
280
        if (!obj) {
281
                printf("Error: failed to allocate an object - please check if an exception was thrown\n");
282
                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
                printf("Error: SaxoncDll.<init>() not found\n");
325
                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
                printf("Error: SaxoncDll.<init>() not found\n");
344
                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
                printf("Error: failed to allocate an object - please check if an exception was thrown\n");
357
                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
                printf("Error: SaxoncDll.<init>() not found\n");
375
                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
                printf("Error: failed to allocate an object - please check if an exception was thrown\n");
388
                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) {
400
        if ((*(environii->env))->ExceptionCheck(environii->env)) {
401

    
402
                jthrowable exc = (*(environii->env))->ExceptionOccurred(environii->env);
403
#ifdef DEBUG
404
                (*(environii->env))->ExceptionDescribe(environii->env);
405
#endif
406
                if (exc) {
407
                        printf("Exception Occurred!");
408
                }
409
                jclass exccls = (jclass)(*(environii->env))->GetObjectClass(environii->env, exc);
410

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

    
413
                jmethodID getName = (jmethodID)(*(environii->env))->GetMethodID(environii->env, clscls, "getName", "()Ljava/lang/String;");
414
                jstring name = (jstring)((*(environii->env))->CallObjectMethod(environii->env, exccls, getName));
415
                char const* utfName = (*(environii->env))->GetStringUTFChars(environii->env, name, NULL);
416

    
417
                //if(callingObject != NULL && strcmp(utfName, "net.sf.saxon.s9api.SaxonApiException") == 0){
418

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

    
421
                if (getMessage) {
422

    
423
                        jstring message = (jstring)((*(environii->env))->CallObjectMethod(environii->env, exc, getMessage));
424

    
425
                        if (!message) {
426

    
427
                                (*(environii->env))->ExceptionClear(environii->env);
428
                                return 0;
429
                        }
430
                        char const* utfMessage = (*(environii->env))->GetStringUTFChars(environii->env, message, NULL);
431

    
432
                        if (utfMessage != NULL) {
433
                                (*(environii->env))->ReleaseStringUTFChars(environii->env, name, utfName);
434
                        }
435

    
436
                        (*(environii->env))->ExceptionClear(environii->env);
437
                        return utfMessage;
438
                }
439
                // }
440
                (*(environii->env))->ReleaseStringUTFChars(environii->env, name, utfName);
441
        }
442

    
443
        return 0;
444
}
445

    
446

    
447
/*
448
 * Clean up and destroy Java VM to release memory used.
449
 */
450
void finalizeJavaRT(JavaVM* jvm)
451
{
452

    
453
        if (jvmCreated != 0) {
454
                (*jvm)->DestroyJavaVM(jvm);
455
                jvmCreated = 0;
456
        }
457
}
458

    
459

    
460
/*
461
 * Get a parameter from list
462
 */
463
jobject getParameter(sxnc_parameter *parameters, int parLen, const char* namespacei, const char * name) {
464
        int i = 0;
465
        namespacei = NULL; // variable not used yet
466
        if (namespacei == NULL) {} // avoiding warning. In next release fix this
467
        for (i = 0; i < parLen; i++) {
468
                if (strcmp(parameters[i].name, name) == 0)
469
                        return (jobject)parameters[i].value;
470
        }
471
        return NULL;
472
}
473

    
474

    
475
/*
476
 * Get a property from list
477
 */
478
char* getProperty(sxnc_property * properties, int propLen, const char* namespacei, const char * name) {
479
        int i = 0;
480
        namespacei = NULL; // variable not used yet
481
        if (namespacei == NULL) {} // avoiding warning. In next release fix this
482
        for (i = 0; i < propLen; i++) {
483
                if (strcmp(properties[i].name, name) == 0)
484
                        return properties[i].value;
485
        }
486
        return 0;
487
}
488

    
489

    
490
/*
491
 * set a parameter
492
 */
493
void setParameter(sxnc_parameter **parameters, int * parLen, int * parCap, const char * namespacei, const char * name, jobject value) {
494

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

    
521

    
522
/*
523
 * set a property
524
 */
525
void setProperty(sxnc_property ** properties, int *propLen, int *propCap, const char* name, const char* value) {
526
        if (getProperty(*properties, (*propLen), "", name) != 0) {
527
                return;
528
        }
529

    
530
        if (((*propLen) + 1) >= (*propCap)) {
531
                (*propCap) *= 2;
532
                sxnc_property* temp = (sxnc_property*)malloc(sizeof(sxnc_property)*  (*propCap));
533
                int i = 0;
534
                for (i = 0; i < (*propLen) - 1; i++) {
535
                        temp[i] = (*properties)[i];
536
                }
537
                free(properties);
538
                properties = &temp;
539

    
540
        }
541
        int nameLen = strlen(name) + 1;
542
        char *newName = (char*)malloc(sizeof(char)*nameLen);
543
        snprintf(newName, nameLen, "%s", name);
544
        char *newValue = (char*)malloc(sizeof(char)*strlen(value) + 1);
545
        snprintf(newValue, strlen(value) + 1, "%s", value);
546
        (*properties)[(*propLen)].name = (char*)newName;
547
        (*properties)[(*propLen)].value = (char*)newValue;
548
        (*propLen)++;
549
}
550

    
551
/*
552
 * clear parameter
553
 */
554
void clearSettings(sxnc_parameter **parameters, int *parLen, sxnc_property ** properties, int *propLen) {
555
        free(*parameters);
556
        free(*parameters);
557

    
558

    
559
        *parameters = (sxnc_parameter *)calloc(10, sizeof(sxnc_parameter));
560
        *properties = (sxnc_property *)calloc(10, sizeof(sxnc_property));
561
        (*parLen) = 0;
562
        (*propLen) = 0;
563
}
564

    
565

    
566
const char * stringValue(sxnc_environment *environi, jobject value) {
567
        jclass  objClass = lookForClass(environi->env, "java/lang/Object");
568
        static jmethodID strMID = NULL;
569
        if (!strMID) {
570
                strMID = (jmethodID)(*(environi->env))->GetMethodID(environi->env, objClass, "toString", "()Ljava/lang/String;");
571
                if (!strMID) {
572
                        printf("\nError: Object %s() not found\n", "toString");
573
                        fflush(stdout);
574
                        return NULL;
575
                }
576
        }
577
        jstring result = (jstring)((*(environi->env))->CallObjectMethod(environi->env, value, strMID));
578
        if (result) {
579
                const char * str = (*(environi->env))->GetStringUTFChars(environi->env, result, NULL);
580
                return str;
581
        }
582

    
583
        //checkForException(environ, cpp);
584
        return 0;
585

    
586
}
587

    
588

    
589

    
590

    
(7-7/56)