Wed, 27 Nov 2024 23:00:07 +0100
add TODO to use a future ucx feature
/* * 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 <cx/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; }