Project

Profile

Help

Bug #4595 » Query.c

O'Neil Delpratt, 2020-06-16 11:47

 
1
#include <jni.h>
2

    
3
#if defined __linux__ || defined __APPLE__
4
    #include <stdlib.h>
5
    #include <string.h>
6
    #include <dlfcn.h>
7
    #include <stdio.h>  
8
    #define HANDLE void*
9
    #define LoadLibrary(x) dlopen(x, RTLD_LAZY)
10
//    #define FreeLibrary(x) dlclose(x, RTLD_LAZY)
11
    #define GetProcAddress(x,y) dlsym(x,y)
12
#else
13
    #include <windows.h>
14
#endif
15

    
16
#ifndef __cplusplus
17
    #ifndef _BOOL
18
        #include <stdbool.h>
19
        //typedef int bool;
20
        #define true 1
21
        #define false 0
22
    #else
23
        #define true 1
24
        #define false 0
25
    #endif
26
#endif
27

    
28

    
29
char * dllname;
30
char * resources_dir;
31
int jvmCreated = 0;
32
char * tempDllname =
33
#if defined (__linux__)
34
    #ifdef EEC
35
            "/libsaxoneec.so";
36
    #elif defined PEC
37
            "/libsaxonpec.so";
38
    #else
39
            "/libsaxonhec.so";
40
    #endif
41
#elif  defined (__APPLE__) && defined(__MACH__)
42
    #ifdef EEC
43
        "/libsaxoneec.dylib";
44
    #elif defined PEC
45
            "/libsaxonpec.dylib";
46
    #else
47
            "/libsaxonhec.dylib";
48
    #endif
49
#else
50
    #ifdef EEC
51
        "\\libsaxoneec.dll";
52
    #elif defined PEC
53
            "\\libsaxonpec.dll";
54
    #else
55
            "\\libsaxonhec.dll";
56
    #endif
57
#endif
58

    
59
char * tempResources_dir =
60
#ifdef __linux__
61
"/saxon-data";
62
#elif  defined (__APPLE__) && defined(__MACH__)
63
"/saxon-data";
64
#else
65
"\\saxon-data";
66
#endif
67

    
68
char * dllPath =
69
#if defined (__linux__)
70
"/usr/lib";
71
#elif  defined (__APPLE__) && defined(__MACH__)
72
"/usr/local/lib";
73
#else
74
    #ifdef EEC
75
        "C:\\Program Files\\Saxonica\\SaxonEEC1.2.1";
76
    #elif defined PEC
77
            "C:\\Program Files\\Saxonica\\SaxonPEC1.2.1";
78
    #else
79
            "C:\\Program Files\\Saxonica\\SaxonHEC1.2.1";
80
    #endif
81
#endif
82

    
83

    
84
//===============================================================================================//
85
/*! <code>sxnc_environment</code>. This struct captures the jni, JVM and handler to the cross compiled Saxon/C library.
86
 * <p/>
87
 */
88
typedef struct {
89
                JNIEnv *env;
90
                HANDLE myDllHandle;
91
                JavaVM *jvm;
92
        } sxnc_environment;
93

    
94

    
95
//===============================================================================================//
96

    
97
/*! <code>MyParameter</code>. This struct captures details of paramaters used for the transformation as (string, value) pairs.
98
 * <p/>
99
 */
100
typedef struct {
101
                char* name;
102
                jobject value;
103
        } MyParameter;
104

    
105
//===============================================================================================//
106

    
107
/*! <code>MyProperty</code>. This struct captures details of properties used for the transformation as (string, string) pairs.
108
 * <p/>
109
 */
110
typedef struct {
111
                char * name;
112
                char * value;
113
        } MyProperty;
114

    
115
jobject cpp;
116

    
117

    
118

    
119
const char * failure;
120

    
121
/*
122
* Set Dll name. Also set the saxon resources directory.
123
* If the SAXONC_HOME sxnc_environmental variable is set then use that as base.
124
*/
125
void setDllname() {
126
        size_t name_len = strlen(tempDllname);
127
        size_t rDir_len = strlen(tempResources_dir);
128
        char * env = getenv("SAXONC_HOME");
129
        size_t env_len;
130
        if (env != NULL) {
131

    
132

    
133
                env_len = strlen(env);
134
                int bufSize = name_len + env_len + 1;
135
                int rbufSize = rDir_len + env_len + 1;
136
                dllname = malloc(sizeof(char)*bufSize);
137
                resources_dir = malloc(sizeof(char)*rbufSize);
138
                snprintf(dllname, bufSize, "%s%s", env, tempDllname);
139
                snprintf(resources_dir, rbufSize, "%s%s", env, tempResources_dir);
140

    
141
#ifdef DEBUG
142

    
143
                printf("envDir: %s\n", env);
144

    
145

    
146
#endif
147

    
148
        }
149
        else {
150
                env_len = strlen(dllPath);
151
                int bufSize = name_len + env_len + 1;
152
                int rbufSize = rDir_len + env_len + 1;
153
                dllname = malloc(sizeof(char)*bufSize);
154
                resources_dir = malloc(sizeof(char)*rbufSize);
155

    
156
#ifdef DEBUG
157
                if (dllname == NULL || resources_dir == NULL)
158
                {
159
                        // error
160
                        printf("Error in allocation of Dllname\n");
161
                }
162
#endif
163
                if (snprintf(dllname, bufSize, "%s%s", dllPath, tempDllname) >= bufSize) {
164
                        bufSize *= 2;
165
                        free(dllname);
166
                        dllname = malloc(sizeof(char)*bufSize);
167
                        if (snprintf(dllname, bufSize, "%s%s", dllPath, tempDllname) >= bufSize) {
168
                                printf("Saxon/C Error: Unable to allocate space for dllname and path");
169
                                exit(1);
170
                        }
171
                }
172
                if (snprintf(resources_dir, rbufSize, "%s%s", dllPath, tempResources_dir) >= rbufSize) {
173
                        printf("Saxon/C warning: Unable to allocate space for resources directory");
174

    
175
                }
176
        }
177

    
178

    
179
#ifdef DEBUG
180

    
181
        printf("Library length: %zu\n", name_len);
182
        printf("Env length: %zu\n", env_len);
183
        printf("size of dllname %zu\n", strlen(dllname));
184
        printf("dllName: %s\n", dllname);
185
        printf("resources_dir: %s\n", resources_dir);
186
        printf("size of resources dir %zu\n", strlen(resources_dir));
187
#endif
188

    
189
}
190

    
191
/*
192
 * Load dll.
193
 */
194
HANDLE loadDll(char* name)
195
{
196
    HANDLE hDll = LoadLibrary (name);
197

    
198
    if (!hDll) {
199
        printf ("Unable to load %s\n", name);
200
        exit(1);
201
    }
202
#ifdef DEBUG
203
    printf ("%s loaded\n", name);
204
#endif
205
    return hDll;
206
}
207

    
208

    
209
jint (JNICALL * JNI_GetDefaultJavaVMInitArgs_func) (void *args);
210
jint (JNICALL * JNI_CreateJavaVM_func) (JavaVM **pvm, void **penv, void *args);
211

    
212
/*
213
 * Initialize JET run-time.
214
 */
215
void initJavaRT(HANDLE myDllHandle, JavaVM** pjvm, JNIEnv** penv)
216
{
217
    int            result;
218
    JavaVMInitArgs args;
219

    
220
    JNI_GetDefaultJavaVMInitArgs_func = 
221
             (jint (JNICALL *) (void *args))
222
             GetProcAddress (myDllHandle, "JNI_GetDefaultJavaVMInitArgs");
223

    
224
    JNI_CreateJavaVM_func =
225
             (jint (JNICALL *) (JavaVM **pvm, void **penv, void *args))
226
             GetProcAddress (myDllHandle, "JNI_CreateJavaVM");
227

    
228
    if(!JNI_GetDefaultJavaVMInitArgs_func) {
229
        printf ("%s doesn't contain public JNI_GetDefaultJavaVMInitArgs\n", dllname);
230
        exit (1);
231
    }
232

    
233
    if(!JNI_CreateJavaVM_func) {
234
        printf ("%s doesn't contain public JNI_CreateJavaVM\n", dllname);
235
        exit (1);
236
    }
237

    
238
    memset (&args, 0, sizeof(args));
239

    
240
    args.version = JNI_VERSION_1_2;
241
    result = JNI_GetDefaultJavaVMInitArgs_func(&args);
242
    if (result != JNI_OK) {
243
        printf ("JNI_GetDefaultJavaVMInitArgs() failed with result %d\n", result);
244
        exit(1);
245
    }
246
  
247
    /*
248
     * NOTE: no JVM is actually created
249
     * this call to JNI_CreateJavaVM is intended for JET RT initialization
250
     */
251
    result = JNI_CreateJavaVM_func (pjvm, (void **)penv, &args);
252
    if (result != JNI_OK) {
253
        printf ("JNI_CreateJavaVM() failed with result %d\n", result);
254
        exit(1);
255
    }
256
#ifdef DEBUG
257
    printf ("JET RT initialized\n");
258
    fflush (stdout);
259
#endif
260
}
261

    
262

    
263
/*
264
 * Look for class.
265
 */
266
jclass lookForClass (JNIEnv* penv, char* name)
267
{
268
    jclass clazz = (*penv)->FindClass (penv, name);
269

    
270
    if (!clazz) {
271
        printf("Unable to find class %s\n", name);
272
        return NULL;
273
    }
274
#ifdef DEBUG
275
    printf ("Class %s found\n", name);
276
    fflush (stdout);
277
#endif
278

    
279
    return clazz;
280
}
281

    
282

    
283
jmethodID findConstructor (JNIEnv* penv, jclass myClassInDll, char* arguments)
284
{
285
    jmethodID MID_init, mID;
286
    jobject obj;
287

    
288
    MID_init = (jmethodID)(*penv)->GetMethodID (penv, myClassInDll, "<init>", arguments);
289
    if (!MID_init) {
290
        printf("Error: MyClassInDll.<init>() not found\n");
291
        fflush (stdout);
292
        return 0;
293
    }
294

    
295
  return MID_init;
296
}
297

    
298
jobject createObject (JNIEnv* penv, jclass myClassInDll, const char * arguments)
299
{
300
    jmethodID MID_init, mID;
301
    jobject obj;
302

    
303
    MID_init = (jmethodID)(*(penv))->GetMethodID (penv, myClassInDll, "<init>", arguments);
304
    if (!MID_init) {
305
        printf("Error: MyClassInDll.<init>() not found\n");
306
        return NULL;
307
    }
308

    
309
      obj = (jobject)(*(penv))->NewObject(penv, myClassInDll, MID_init, (jboolean)true);
310
      if (!obj) {
311
        printf("Error: failed to allocate an object\n");
312
        return NULL;
313
      }
314
    return obj;
315
}
316

    
317
void checkForException(sxnc_environment environi, jclass callingClass,  jobject callingObject){
318

    
319
    if ((*(environi.env))->ExceptionCheck(environi.env)) {
320
        char *  result1;
321
        const char * errorCode = NULL;
322
        jthrowable exc = (*(environi.env))->ExceptionOccurred(environi.env);
323
        (*(environi.env))->ExceptionDescribe(environi.env); //comment code
324
         jclass exccls = (jclass)(*(environi.env))->GetObjectClass(environi.env, exc);
325
        jclass clscls = (jclass)(*(environi.env))->FindClass(environi.env, "java/lang/Class");
326

    
327
        jmethodID getName = (jmethodID)(*(environi.env))->GetMethodID(environi.env, clscls, "getName", "()Ljava/lang/String;");
328
        jstring name =(jstring)((*(environi.env))->CallObjectMethod(environi.env, exccls, getName));
329
        char const* utfName = (char const*)(*(environi.env))->GetStringUTFChars(environi.env, name, 0);
330
        printf(utfName);
331

    
332
         jmethodID  getMessage = (jmethodID)(*(environi.env))->GetMethodID(environi.env, exccls, "getMessage", "()Ljava/lang/String;");
333
        if(getMessage) {
334

    
335
                jstring message = (jstring)((*(environi.env))->CallObjectMethod(environi.env, exc, getMessage));
336
                if(message) {                
337
                        char const* utfMessage = (char const*)(*(environi.env))->GetStringUTFChars(environi.env, message, 0);
338
                }
339
        
340
        }
341

    
342
     }
343
        //return NULL;
344

    
345
}
346

    
347

    
348
void finalizeJavaRT (JavaVM* jvm)
349
{
350
    (*jvm)->DestroyJavaVM (jvm);
351
}
352

    
353

    
354

    
355

    
356

    
357
int query(sxnc_environment environi, int argc, const char* argv[]) {
358

    
359

    
360
    jmethodID MID_foo;
361
    jclass transClass = lookForClass(environi.env, "net/sf/saxon/Query");
362
    char methodName[] = "main";
363
    char args[] = "([Ljava/lang/String;)V";
364
    jobjectArray stringArray = NULL;
365
    MID_foo = (jmethodID)(*(environi.env))->GetStaticMethodID(environi.env, transClass, methodName, args);
366
    if (!MID_foo) {
367
        printf("\nError: MyClassInDll %s() not found\n",methodName);
368
        fflush (stdout);
369
        return -1;
370
    }
371
     if(argc < 2) {
372
        printf("\nError: Not enough arguments in Query");
373
        return 0;
374
    }
375
           jclass stringClass = lookForClass(environi.env, "java/lang/String");
376
           stringArray = (*(environi.env))->NewObjectArray(environi.env, (jint)argc-1, stringClass, 0 );
377
           if(!stringArray) { return 0;}
378
  int i, j;
379
  for(i=1, j=0; i< argc; i++, j++) {
380
             (*(environi.env))->SetObjectArrayElement(environi.env, stringArray, j, (*(environi.env))->NewStringUTF(environi.env, argv[i]));
381
           }
382

    
383
   (*(environi.env))->CallStaticVoidMethod(environi.env, transClass, MID_foo, stringArray);
384
   
385
  (*(environi.env))->DeleteLocalRef(environi.env, stringArray);
386
        return 0;
387
}
388

    
389

    
390

    
391

    
392
int main( int argc, const char* argv[] )
393
{
394
    HANDLE myDllHandle;
395
    //JNIEnv *(environi.env);
396
    //JavaVM *jvm;
397
    jclass  myClassInDll;
398

    
399
    sxnc_environment environi;
400
    /*
401
     * First of all, load required component.
402
     * By the time of JET initialization, all components should be loaded.
403
     */
404
    setDllname();
405
    environi.myDllHandle = loadDll (dllname);
406
   
407

    
408
    /*
409
     * Initialize JET run-time.
410
     * The handle of loaded component is used to retrieve Invocation API.
411
     */
412
    initJavaRT (environi.myDllHandle, &environi.jvm, &environi.env);
413
    query(environi, argc, argv);        
414

    
415
  
416
    fflush(stdout);
417
    /*
418
     * Finalize JET run-time.
419
     */
420
    finalizeJavaRT (environi.jvm);
421

    
422
    return 0;
423
}
(2-2/3)