diff --git a/plugins/jvm/jvm.h b/plugins/jvm/jvm.h new file mode 100644 index 00000000..0ed85975 --- /dev/null +++ b/plugins/jvm/jvm.h @@ -0,0 +1,41 @@ +#include "../../uwsgi.h"; +#include + +#define MAX_CLASSPATH 64 + +#define LONG_ARGS_JVM_BASE 17000 + (300 * 100) +#define LONG_ARGS_JVM_CLASS LONG_ARGS_JVM_BASE + 1 +#define LONG_ARGS_JVM_CLASSPATH LONG_ARGS_JVM_BASE + 2 + +struct uwsgi_jvm { + + char *classpath[MAX_CLASSPATH]; + int classpath_cnt; + + JNIEnv *env; + char *class; + jclass main_class; + + jclass str_class; + jclass ht_class; + jclass fd_class; +}; + + +jmethodID uwsgi_jvm_get_method_id(jclass, char *, char *); +jmethodID uwsgi_jvm_get_static_method_id(jclass, char *, char *); +jclass uwsgi_jvm_get_class(char *); +jclass uwsgi_jvm_get_object_class(jobject); +int uwsgi_jvm_exception(void); + +jobject uwsgi_jvm_str_new(char *, int ); +jobject uwsgi_jvm_str(char *); + +jobject uwsgi_jvm_array_get(jobject , int ); +jobject uwsgi_jvm_ht_new(void); +jobject uwsgi_jvm_ht_put(jobject, jobject, jobject); + +jobject uwsgi_jvm_fd(int); + +char *uwsgi_jvm_str2c(jobject); +int uwsgi_jvm_strlen2c(jobject); diff --git a/plugins/jvm/jvm_plugin.c b/plugins/jvm/jvm_plugin.c index 31b8d6e8..82d592f9 100644 --- a/plugins/jvm/jvm_plugin.c +++ b/plugins/jvm/jvm_plugin.c @@ -1,22 +1,13 @@ -#include "../../uwsgi.h"; -#include +#include "jvm.h"; -#define MAX_CLASSPATH 64 +/* -#define LONG_ARGS_JVM_BASE 17000 + (300 * 100) -#define LONG_ARGS_JVM_CLASS LONG_ARGS_JVM_BASE + 1 -#define LONG_ARGS_JVM_CLASSPATH LONG_ARGS_JVM_BASE + 2 +with javap -s -p +you can get method signatures -struct uwsgi_jvm { +*/ - char *classpath[MAX_CLASSPATH]; - int classpath_cnt; - - JNIEnv *env; - char *class; - jclass main_class; - -} ujvm; +struct uwsgi_jvm ujvm; struct option uwsgi_jvm_options[] = { {"jvm-main-class", required_argument, 0, LONG_ARGS_JVM_CLASS}, @@ -35,6 +26,10 @@ int uwsgi_jvm_exception(void) { return 0; } +jclass uwsgi_jvm_get_object_class(jobject obj) { + return (*ujvm.env)->GetObjectClass(ujvm.env, obj); +} + jclass uwsgi_jvm_get_class(char *name) { jclass my_class = (*ujvm.env)->FindClass(ujvm.env, name); @@ -64,6 +59,26 @@ jmethodID uwsgi_jvm_get_static_method_id(jclass cls, char *name, char *signature return mid; } +jobject uwsgi_jvm_str_new(char *str, int len) { + + jbyteArray ba; + static jmethodID str_new_mid = 0; + + if (!str_new_mid) { + str_new_mid = uwsgi_jvm_get_method_id(ujvm.str_class, "", "([BLjava/lang/String;)V"); + } + + ba = (*ujvm.env)->NewByteArray(ujvm.env, len); + (*ujvm.env)->SetByteArrayRegion(ujvm.env, ba, 0, len, (jbyte *) str); + return (*ujvm.env)->NewObject(ujvm.env, ujvm.str_class, str_new_mid, ba, + (*ujvm.env)->NewStringUTF(ujvm.env, "UTF-8")); +} + +jobject uwsgi_jvm_str(char *str) { + return (*ujvm.env)->NewStringUTF(ujvm.env, str); +} + + int jvm_init(void) { jint res; @@ -120,10 +135,69 @@ int jvm_init(void) { } } + ujvm.str_class = uwsgi_jvm_get_class("java/lang/String"); + ujvm.ht_class = uwsgi_jvm_get_class("java/util/Hashtable"); + ujvm.fd_class = uwsgi_jvm_get_class("java/io/FileDescriptor"); + return 1; } +jobject uwsgi_jvm_array_get(jobject obj, int index) { + return (*ujvm.env)->GetObjectArrayElement(ujvm.env, obj, index); +} + +jobject uwsgi_jvm_ht_new() { + static jmethodID htimid = 0; + + if (!htimid) { + htimid = uwsgi_jvm_get_method_id(ujvm.ht_class, "", "()V"); + } + + return (*ujvm.env)->NewObject(ujvm.env, ujvm.ht_class, htimid); +} + +jobject uwsgi_jvm_ht_put(jobject obj, jobject key, jobject val) { + + static jmethodID htpmid = 0 ; + + if (!htpmid) { + htpmid = uwsgi_jvm_get_method_id(ujvm.ht_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + } + + return (*ujvm.env)->CallObjectMethod(ujvm.env, obj, htpmid, key, val); +} + +jobject uwsgi_jvm_fd(int fd) { + + jobject fd_obj; + static jmethodID fd_mid = 0; + static jfieldID fd_field = 0 ; + + if (!fd_mid) { + fd_mid = uwsgi_jvm_get_method_id( ujvm.fd_class, "", "()V"); + } + + fd_obj = (*ujvm.env)->NewObject(ujvm.env, ujvm.fd_class, fd_mid); + + if (!fd_field) { + fd_field = (*ujvm.env)->GetFieldID(ujvm.env, ujvm.fd_class, "fd", "I"); + } + + (*ujvm.env)->SetIntField(ujvm.env, fd_obj, fd_field, fd); + + return fd_obj; +} + +char *uwsgi_jvm_str2c(jobject obj) { + + return (char *) (*ujvm.env)->GetStringUTFChars(ujvm.env, obj, NULL); +} + +int uwsgi_jvm_strlen2c(jobject obj) { + + return (*ujvm.env)->GetStringUTFLength(ujvm.env, obj); +} int uwsgi_jvm_manage_opt(int i, char *optarg) { diff --git a/plugins/jwsgi/jwsgi_plugin.c b/plugins/jwsgi/jwsgi_plugin.c new file mode 100644 index 00000000..f94fa5b5 --- /dev/null +++ b/plugins/jwsgi/jwsgi_plugin.c @@ -0,0 +1,112 @@ +#include "../jvm/jvm.h" + +extern struct uwsgi_server uwsgi; +extern struct uwsgi_jvm ujvm; + +void uwsgi_jwsgi_init(void) { + + +} + +int uwsgi_jwsgi_request(struct wsgi_request *wsgi_req) { + + jmethodID jmid; + int i; + jobject env; + jobject hkey, hval; + jobject response; + + jobject status; + jobject headers, header; + jobject body; + + jclass hc; + + jmethodID hh_size, hh_get; + int hlen; + + if (!wsgi_req->uh.pktsize) { + uwsgi_log("Invalid JWSGI request. skip.\n"); + return -1; + } + + + if (uwsgi_parse_vars(wsgi_req)) { + uwsgi_log("Invalid JWSGI request. skip.\n"); + return -1; + } + + + jmid = uwsgi_jvm_get_static_method_id(ujvm.main_class, "jwsgi", "(Ljava/util/Hashtable;)[Ljava/lang/Object;"); + + uwsgi_log("jwsgi method id = %d\n", jmid); + + env = uwsgi_jvm_ht_new(); + + for(i=0;ivar_cnt;i++) { + + uwsgi_jvm_ht_put(env, + uwsgi_jvm_str_new(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len), + uwsgi_jvm_str_new(wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len) + ); + + // check if something is going wrong during hashtable fill + uwsgi_jvm_exception(); + + i++; + } + + + uwsgi_jvm_ht_put(env, uwsgi_jvm_str("jwsgi.input"), uwsgi_jvm_fd(wsgi_req->poll.fd)); + + response = (*ujvm.env)->CallObjectMethod(ujvm.env, ujvm.main_class, jmid, env); + + uwsgi_log("RESPONSE SIZE %d\n", (*ujvm.env)->GetArrayLength(ujvm.env, response)); + + status = uwsgi_jvm_array_get(response, 0); + uwsgi_jvm_exception(); + + write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len); + write(wsgi_req->poll.fd, " ", 1); + write(wsgi_req->poll.fd, uwsgi_jvm_str2c(status), uwsgi_jvm_strlen2c(status)); + write(wsgi_req->poll.fd, "\r\n", 2); + + + headers = uwsgi_jvm_array_get(response, 1); + hc = uwsgi_jvm_get_object_class(headers); + hh_size = uwsgi_jvm_get_method_id(hc, "size","()I"); + hh_get = uwsgi_jvm_get_method_id(hc, "get","(I)Ljava/lang/Object;"); + + hlen = (*ujvm.env)->CallIntMethod(ujvm.env, headers, hh_size); + + for(i=0;iCallObjectMethod(ujvm.env, headers, hh_get, i); + hkey = uwsgi_jvm_array_get(header, 0); + hval = uwsgi_jvm_array_get(header, 1); + + write(wsgi_req->poll.fd, uwsgi_jvm_str2c(hkey), uwsgi_jvm_strlen2c(hkey)); + write(wsgi_req->poll.fd, ": ", 2); + write(wsgi_req->poll.fd, uwsgi_jvm_str2c(hval), uwsgi_jvm_strlen2c(hval)); + write(wsgi_req->poll.fd, "\r\n", 2); + } + + write(wsgi_req->poll.fd, "\r\n", 2); + + body = uwsgi_jvm_array_get(response, 2); + + wsgi_req->response_size = write(wsgi_req->poll.fd, (*ujvm.env)->GetStringUTFChars(ujvm.env, body, NULL), (*ujvm.env)->GetStringUTFLength(ujvm.env, body)); + + return 1; +} + +void uwsgi_jwsgi_after_request(struct wsgi_request *wsgi_req) { + log_request(wsgi_req); +} + +struct uwsgi_plugin jwsgi_plugin = { + + .name = "jwsgi", + .modifier1 = 8, + .request = uwsgi_jwsgi_request, + .after_request = uwsgi_jwsgi_after_request, +}; diff --git a/plugins/jwsgi/uwsgiplugin.py b/plugins/jwsgi/uwsgiplugin.py new file mode 100644 index 00000000..63848cb4 --- /dev/null +++ b/plugins/jwsgi/uwsgiplugin.py @@ -0,0 +1,17 @@ +import os,sys + +NAME='jwsgi' + +JVM_INCPATH = "/Developer/SDKs/MacOSX10.6.sdk//System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Headers/" +JVM_LIBPATH = "/Developer/SDKs/MacOSX10.6.sdk//System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Libraries/ -framework JavaVM" + + +CFLAGS = ['-I' + JVM_INCPATH] +LDFLAGS = ['-L' + JVM_LIBPATH] +LIBS = ['-ljvm'] +GCC_LIST = ['jwsgi_plugin'] + +if os.environ.has_key('LD_RUN_PATH'): + os.environ['LD_RUN_PATH'] += ':' + JVM_LIBPATH +else: + os.environ['LD_RUN_PATH'] = JVM_LIBPATH