Project

Profile

Help

Bug #4595 » Transform.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

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

    
96

    
97
//===============================================================================================//
98

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

    
107
//===============================================================================================//
108

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

    
117
jobject cpp;
118

    
119

    
120

    
121
const char * failure;
122

    
123

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

    
135

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

    
144
#ifdef DEBUG
145

    
146
                printf("envDir: %s\n", env);
147

    
148

    
149
#endif
150

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

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

    
178
                }
179
        }
180

    
181

    
182
#ifdef DEBUG
183

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

    
192
}
193

    
194

    
195
/*
196
 * Load dll.
197
 */
198
HANDLE loadDll(char* name)
199
{
200

    
201
    HANDLE hDll = LoadLibrary (name);
202

    
203
    if (!hDll) {
204
        printf ("Unable to load %s\n", name);
205
        exit(1);
206
    }
207
#ifdef DEBUG
208
    printf ("%s loaded\n", name);
209
#endif
210
    return hDll;
211
}
212

    
213

    
214
jint (JNICALL * JNI_GetDefaultJavaVMInitArgs_func) (void *args);
215
jint (JNICALL * JNI_CreateJavaVM_func) (JavaVM **pvm, void **penv, void *args);
216

    
217
/*
218
 * Initialize JET run-time.
219
 */
220
void initJavaRT(HANDLE myDllHandle, JavaVM** pjvm, JNIEnv** penv)
221
{
222
    int            result;
223
    JavaVMInitArgs args;
224

    
225
    JNI_GetDefaultJavaVMInitArgs_func = 
226
             (jint (JNICALL *) (void *args))
227
             GetProcAddress (myDllHandle, "JNI_GetDefaultJavaVMInitArgs");
228

    
229
    JNI_CreateJavaVM_func =
230
             (jint (JNICALL *) (JavaVM **pvm, void **penv, void *args))
231
             GetProcAddress (myDllHandle, "JNI_CreateJavaVM");
232

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

    
238
    if(!JNI_CreateJavaVM_func) {
239
        printf ("%s doesn't contain public JNI_CreateJavaVM\n", dllname);
240
        exit (1);
241
    }
242

    
243
    memset (&args, 0, sizeof(args));
244

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

    
267

    
268
/*
269
 * Look for class.
270
 */
271
jclass lookForClass (JNIEnv* penv, char* name)
272
{
273
    jclass clazz = (*penv)->FindClass (penv, name);
274

    
275
    if (!clazz) {
276
        printf("Unable to find class %s\n", name);
277
        return NULL;
278
    }
279
#ifdef DEBUG
280
    printf ("Class %s found\n", name);
281
    fflush (stdout);
282
#endif
283

    
284
    return clazz;
285
}
286

    
287

    
288

    
289

    
290
jmethodID findConstructor (JNIEnv* penv, jclass myClassInDll, char* arguments)
291
{
292
    jmethodID MID_init, mID;
293
    jobject obj;
294

    
295
    MID_init = (jmethodID)(*penv)->GetMethodID (penv, myClassInDll, "<init>", arguments);
296
    if (!MID_init) {
297
        printf("Error: MyClassInDll.<init>() not found\n");
298
        fflush (stdout);
299
        return 0;
300
    }
301

    
302
  return MID_init;
303
}
304

    
305
jobject createObject (JNIEnv* penv, jclass myClassInDll, const char * arguments)
306
{
307
    jmethodID MID_init, mID;
308
    jobject obj;
309

    
310
    MID_init = (jmethodID)(*(penv))->GetMethodID (penv, myClassInDll, "<init>", arguments);
311
    if (!MID_init) {
312
        printf("Error: MyClassInDll.<init>() not found\n");
313
        return NULL;
314
    }
315

    
316
      obj = (jobject)(*(penv))->NewObject(penv, myClassInDll, MID_init, (jboolean)true);
317
      if (!obj) {
318
        printf("Error: failed to allocate an object\n");
319
        return NULL;
320
      }
321
    return obj;
322
}
323

    
324
void checkForException(sxnc_environment environi, jclass callingClass,  jobject callingObject){
325

    
326
    if ((*(environi.env))->ExceptionCheck(environi.env)) {
327
        char *  result1;
328
        const char * errorCode = NULL;
329
        jthrowable exc = (*(environi.env))->ExceptionOccurred(environi.env);
330
        (*(environi.env))->ExceptionDescribe(environi.env); //comment code
331
         jclass exccls = (jclass)(*(environi.env))->GetObjectClass(environi.env, exc);
332
        jclass clscls = (jclass)(*(environi.env))->FindClass(environi.env, "java/lang/Class");
333

    
334
        jmethodID getName = (jmethodID)(*(environi.env))->GetMethodID(environi.env, clscls, "getName", "()Ljava/lang/String;");
335
        jstring name =(jstring)((*(environi.env))->CallObjectMethod(environi.env, exccls, getName));
336
        char const* utfName = (char const*)(*(environi.env))->GetStringUTFChars(environi.env, name, 0);
337
        printf(utfName);
338

    
339
         jmethodID  getMessage = (jmethodID)(*(environi.env))->GetMethodID(environi.env, exccls, "getMessage", "()Ljava/lang/String;");
340
        if(getMessage) {
341

    
342
                jstring message = (jstring)((*(environi.env))->CallObjectMethod(environi.env, exc, getMessage));
343
                if(message) {                
344
                        char const* utfMessage = (char const*)(*(environi.env))->GetStringUTFChars(environi.env, message, 0);
345
                }
346
        
347
        }
348

    
349
     }
350
        //return NULL;
351

    
352
}
353

    
354

    
355
void finalizeJavaRT (JavaVM* jvm)
356
{
357
    (*jvm)->DestroyJavaVM (jvm);
358
}
359

    
360

    
361

    
362

    
363

    
364
int transform(sxnc_environment environi, int argc, const char* argv[]) {
365

    
366

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

    
390
   (*(environi.env))->CallStaticVoidMethod(environi.env, transClass, MID_foo, stringArray);
391
   
392
  (*(environi.env))->DeleteLocalRef(environi.env, stringArray);
393
        return 0;
394
}
395

    
396

    
397

    
398

    
399
int main( int argc, const char* argv[] )
400
{
401
    HANDLE myDllHandle;
402
    //JNIEnv *(environi.env);
403
    //JavaVM *jvm;
404
    jclass  myClassInDll;
405
    setDllname();
406
    sxnc_environment environi;
407
    /*
408
     * First of all, load required component.
409
     * By the time of JET initialization, all components should be loaded.
410
     */
411
    environi.myDllHandle = loadDll (dllname);
412
   
413

    
414
    /*
415
     * Initialize JET run-time.
416
     * The handle of loaded component is used to retrieve Invocation API.
417
     */
418
    initJavaRT (environi.myDllHandle, &environi.jvm, &environi.env);
419
    transform(environi, argc, argv);
420

    
421
  
422
fflush(stdout);
423
    /*
424
     * Finalize JET run-time.
425
     */
426
    finalizeJavaRT (environi.jvm);
427

    
428
    return 0;
429
}
(3-3/3)