src/server/plugins/java/jvm.c

changeset 84
afd57ce39ec9
child 415
d938228c382e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/plugins/java/jvm.c	Mon Jul 08 11:10:54 2013 +0200
@@ -0,0 +1,206 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h> 
+
+#include <ucx/map.h>
+
+#include "jvm.h"
+#include "daemon/request.h"
+
+#ifdef __i386
+#define LIBJVM "/usr/java/jre/lib/i386/server/libjvm.so"
+#else
+
+#endif
+
+static JNIEnv *env = NULL;
+static JavaVM *jvm = NULL;
+
+static jobject plugin_instance = NULL;
+static jmethodID load_jmodules_method = NULL;
+static jmethodID exec_method = NULL;
+
+int jvm_init(pblock *pb, Session *sn, Request *rq) {
+    // load lib
+    void *lib = dlopen(LIBJVM, RTLD_GLOBAL | RTLD_NOW);
+    if(!lib) {
+        log_ereport(LOG_FAILURE, "Cannot load libjvm.so");
+        return REQ_ABORTED;
+    }
+    
+    // get symbol
+    void *sym = dlsym(lib, "JNI_CreateJavaVM");
+    if(sym == NULL) {
+        log_ereport(
+                LOG_FAILURE,
+                "Cannot get symbol JNI_CreateJavaVM from lib");
+        return REQ_ABORTED;
+    }
+    
+    // create JVM
+    JavaVMInitArgs vm_args;
+    JavaVMOption options[2];
+    options[0].optionString = "-Djava.class.path=lib/wsrt.jar";
+    options[1].optionString = "-Djava.library.path=lib/";
+    vm_args.version = JNI_VERSION_1_6;
+    vm_args.options = options;
+    vm_args.nOptions = 2;
+    vm_args.ignoreUnrecognized = JNI_TRUE;
+    
+    CreateJVMFunc create_jvm = (CreateJVMFunc)sym;
+    if(create_jvm(&jvm, (void**)&env, &vm_args)) {
+        dlclose(lib);
+        log_ereport(LOG_FAILURE, "Cannot create JVM");
+    }
+    
+    // load classes and methods
+    jclass cls = (*env)->FindClass(env, "webserver/ServerPlugin");
+    if(!cls) {
+        log_ereport(
+                LOG_FAILURE,
+                "jvm-init: missing or broken wsrt.jar");
+        log_ereport(
+                LOG_FAILURE,
+                "jvm-init: missing class webserver.ServerPlugin");
+        return REQ_ABORTED;
+    }
+    
+    jmethodID constr = (*env)->GetMethodID(env, cls, "<init>", "()V");
+    if(!constr) {
+        log_ereport(
+                LOG_FAILURE,
+                "jvm-init: missing or broken wsrt.jar");
+        log_ereport(
+                LOG_FAILURE,
+                "jvm-init: missing constructor");
+        return REQ_ABORTED;
+    }
+    plugin_instance = (*env)->NewObject(env, cls, constr);
+    if(!plugin_instance) {
+        log_ereport(
+                LOG_FAILURE,
+                "jvm-init: cannot create ServerPlugin instance");
+        return REQ_ABORTED;
+    }
+    
+    // methods
+    load_jmodules_method = (*env)->GetMethodID(
+            env,
+            cls,
+            "loadModule",
+            "(Ljava/lang/String;Ljava/lang/String;)I");
+    if(!load_jmodules_method) {
+        log_ereport(LOG_FAILURE, "jvm-init: missing or broken wsrt.jar");
+        log_ereport(LOG_FAILURE, "jvm-init: missing method (loadModule)");
+        return REQ_ABORTED;
+    }
+    
+    exec_method = (*env)->GetMethodID(
+            env,
+            cls,
+            "exec",
+            "(I)I");
+    if(!exec_method) {
+        log_ereport(LOG_FAILURE, "jvm-init: missing or broken wsrt.jar");
+        log_ereport(LOG_FAILURE, "jvm-init: missing method (exec)");
+        return REQ_ABORTED;
+    }
+    
+    
+    return REQ_PROCEED;
+}
+
+int load_jmodules(pblock *pb, Session *sn, Request *rq) {
+    char *jar = pblock_findval("jar", pb);
+    char *classes = pblock_findval("classes", pb);
+    
+    if(!jar || !classes) {
+        log_ereport(
+                LOG_MISCONFIG,
+                "load-jmodule: missing parameters (jar, classes)");
+        return REQ_ABORTED;
+    }
+       
+    // check jvm 
+    if(!plugin_instance) {
+        log_ereport(
+                LOG_FAILURE,
+                "load-jmodules: java plugin not properly loaded");
+        return REQ_ABORTED;
+    }
+    if(!load_jmodules_method) {
+        log_ereport(
+                LOG_FAILURE,
+                "load-jmodules: java plugin not properly loaded");
+        return REQ_ABORTED;
+    }
+    
+    // load java module
+    jstring jar_param = (*env)->NewStringUTF(env, jar);
+    jstring classes_param = (*env)->NewStringUTF(env, classes);
+    
+    jint ret = (*env)->CallIntMethod(
+            env,
+            plugin_instance,
+            load_jmodules_method,
+            jar_param,
+            classes_param);
+    
+    // free stuff
+    (*env)->DeleteLocalRef(env, jar_param);
+    (*env)->DeleteLocalRef(env, classes_param);
+    
+    return ret;
+}
+
+int jexec(pblock *pb, Session *sn, Request *rq) {
+    return REQ_NOACTION;
+}
+
+int jvm_method_exec(FuncStruct *func, pblock *pb, Session *sn, Request *rq) {
+    printf("jvm_method_exec: %d\n", func);
+    NSAPIRequest *nrq = (NSAPIRequest*)rq;
+    
+    JNIEnv *e = NULL;
+    int r = (*jvm)->AttachCurrentThread(jvm, (void**)&e, NULL);
+    
+    jint index = (jint)func->exec_data;
+    printf("(C) exec: %d\n", index);
+    
+    jint ret = (*env)->CallIntMethod(
+            env,
+            plugin_instance,
+            exec_method,
+            index);
+    
+    return ret;
+}
+

mercurial