Project

Profile

Help

Bug #4595 » Validate.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 GetProcAddress(x,y) dlsym(x,y)
11
#else
12
    #include <windows.h>
13
#endif
14

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

    
27

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

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

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

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

    
92

    
93
//===============================================================================================//
94

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

    
103
//===============================================================================================//
104

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

    
113
jobject cpp;
114

    
115

    
116

    
117
const char * failure;
118

    
119

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

    
131

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

    
140
#ifdef DEBUG
141

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

    
144

    
145
#endif
146

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

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

    
174
                }
175
        }
176

    
177

    
178
#ifdef DEBUG
179

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

    
188
}
189

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

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

    
207

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

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

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

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

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

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

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

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

    
261

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

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

    
278
    return clazz;
279
}
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 validate(sxnc_environment environi, int argc, const char* argv[]) {
358

    
359

    
360
    jmethodID MID_foo;
361
    jclass transClass = lookForClass(environi.env, "com/saxonica/Validate");
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 Validate");
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
    validate(environi, argc, argv);        
414

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

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