diff -r 28433f06d5ee -r afd57ce39ec9 src/server/plugins/java/jvm.c --- /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 +#include +#include + +#include + +#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, "", "()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; +} +