completed status and headers management for the ring plugin

This commit is contained in:
Unbit
2013-03-04 15:43:52 +01:00
parent 980b4f3c9a
commit af3860dbd7
3 changed files with 159 additions and 6 deletions
+12
View File
@@ -14,6 +14,8 @@ struct uwsgi_jvm {
struct uwsgi_string_list *main_classes;
jclass str_class;
jclass long_class;
jclass int_class;
jclass hashmap_class;
jclass set_class;
jclass iterator_class;
@@ -62,3 +64,13 @@ int uwsgi_jvm_iterator_hasNext(jobject);
jobject uwsgi_jvm_iterator_next(jobject);
jobject uwsgi_jvm_iterator(jobject);
jobject uwsgi_jvm_auto_iterator(jobject);
jobject uwsgi_jvm_getKey(jobject);
jobject uwsgi_jvm_getValue(jobject);
size_t uwsgi_jvm_strlen(jobject);
long uwsgi_jvm_number2c(jobject);
long uwsgi_jvm_int2c(jobject);
long uwsgi_jvm_long2c(jobject);
+69
View File
@@ -117,6 +117,45 @@ jobject uwsgi_jvm_object_class_name(jobject o) {
return uwsgi_jvm_call_object(oc, mid);
}
long uwsgi_jvm_int2c(jobject o) {
static jmethodID mid = 0;
if (!mid) {
mid = uwsgi_jvm_get_method_id(ujvm.int_class, "intValue", "()I");
if (!mid) return -1 ;
}
long value = (*ujvm_env)->CallIntMethod(ujvm_env, o, mid);
if (uwsgi_jvm_exception()) {
return -1;
}
return value;
}
long uwsgi_jvm_long2c(jobject o) {
static jmethodID mid = 0;
if (!mid) {
mid = uwsgi_jvm_get_method_id(ujvm.long_class, "longValue", "()J");
if (!mid) return -1;
}
long value = (*ujvm_env)->CallLongMethod(ujvm_env, o, mid);
if (uwsgi_jvm_exception()) {
return -1;
}
return value;
}
long uwsgi_jvm_number2c(jobject o) {
if (uwsgi_jvm_object_is_instance(o, ujvm.int_class)) {
return uwsgi_jvm_int2c(o);
}
if (uwsgi_jvm_object_is_instance(o, ujvm.long_class)) {
return uwsgi_jvm_long2c(o);
}
return -1;
}
// returns the method id, given the method name and its signature
jmethodID uwsgi_jvm_get_method_id(jclass cls, char *name, char *signature) {
jmethodID mid = (*ujvm_env)->GetMethodID(ujvm_env, cls, name, signature);
@@ -193,6 +232,30 @@ jobject uwsgi_jvm_iterator(jobject set) {
return uwsgi_jvm_call_object(set, mid);
}
jobject uwsgi_jvm_auto_iterator(jobject o) {
jclass c = uwsgi_jvm_class_from_object(o);
if (!c) return NULL;
jmethodID mid = uwsgi_jvm_get_method_id(c, "iterator", "()Ljava/util/Iterator;");
if (!mid) return NULL;
return uwsgi_jvm_call_object(o, mid);
}
jobject uwsgi_jvm_getKey(jobject item) {
jclass c = uwsgi_jvm_class_from_object(item);
if (!c) return NULL;
jmethodID mid = uwsgi_jvm_get_method_id(c, "getKey", "()Ljava/lang/Object;");
if (!mid) return NULL;
return uwsgi_jvm_call_object(item, mid);
}
jobject uwsgi_jvm_getValue(jobject item) {
jclass c = uwsgi_jvm_class_from_object(item);
if (!c) return NULL;
jmethodID mid = uwsgi_jvm_get_method_id(c, "getValue", "()Ljava/lang/Object;");
if (!mid) return NULL;
return uwsgi_jvm_call_object(item, mid);
}
int uwsgi_jvm_iterator_hasNext(jobject iterator) {
// optimization
static jmethodID mid = 0;
@@ -350,6 +413,12 @@ static void uwsgi_jvm_create(void) {
ujvm.str_class = uwsgi_jvm_class("java/lang/String");
if (!ujvm.str_class) exit(1);
ujvm.int_class = uwsgi_jvm_class("java/lang/Integer");
if (!ujvm.int_class) exit(1);
ujvm.long_class = uwsgi_jvm_class("java/lang/Long");
if (!ujvm.long_class) exit(1);
ujvm.hashmap_class = uwsgi_jvm_class("java/util/HashMap");
if (!ujvm.hashmap_class) exit(1);
+78 -6
View File
@@ -2,6 +2,8 @@
#define UWSGI_JVM_REQUEST_HANDLER_RING 1
extern struct uwsgi_jvm ujvm;
struct uwsgi_ring {
char *app;
jobject handler;
@@ -14,6 +16,9 @@ struct uwsgi_ring {
jclass PersistentArrayMap;
jmethodID PersistentArrayMap_get;
jmethodID PersistentArrayMap_entrySet;
jclass PersistentVector;
jclass PersistentList;
} uring;
static struct uwsgi_option uwsgi_ring_options[] = {
@@ -65,6 +70,7 @@ static jobject uwsgi_ring_header_get(jobject headers, jobject key) {
}
static int uwsgi_ring_request(struct wsgi_request *wsgi_req) {
char status_str[1];
uwsgi_log("managing ring request\n");
jobject hm = uwsgi_jvm_hashmap();
if (!hm) return -1;
@@ -83,21 +89,77 @@ static int uwsgi_ring_request(struct wsgi_request *wsgi_req) {
jobject r_status = uwsgi_ring_response_get(response, "status", 6);
if (!r_status) goto error;
if (!uwsgi_jvm_object_is_instance(r_status, ujvm.long_class) && !uwsgi_jvm_object_is_instance(r_status, ujvm.int_class)) {
uwsgi_log("invalid ring response status type, must be: java.lang.Long\n");
goto error;
}
long n_status = uwsgi_jvm_number2c(r_status);
if (n_status == -1) goto error;
if (uwsgi_num2str2(n_status, status_str) != 3) {
goto error;
}
if (uwsgi_response_prepare_headers(wsgi_req, status_str, 3)) goto error;
jobject r_headers = uwsgi_ring_response_get(response, "headers", 7);
if (!r_headers) goto error;
char *cn = uwsgi_jvm_str2c( uwsgi_jvm_object_class_name(r_headers) );
uwsgi_log("headers type = %s\n", cn);
cn = uwsgi_jvm_str2c( uwsgi_jvm_object_class_name(r_status) );
uwsgi_log("status type = %s\n", cn);
if (!uwsgi_jvm_object_is_instance(r_headers, uring.PersistentArrayMap)) {
uwsgi_log("invalid ring response headers type, must be: clojure.lang.PersistentArrayMap\n");
goto error;
}
jobject entries = uwsgi_ring_PersistentArrayMap_iterator(r_headers);
if (!entries) goto error;
while(uwsgi_jvm_iterator_hasNext(entries)) {
jobject hh = uwsgi_jvm_iterator_next(entries);
uwsgi_log("hh = %p\n", hh);
if (!hh) goto error;
jobject h_key = uwsgi_jvm_getKey(hh);
if (!h_key) goto error;
jobject h_value = uwsgi_jvm_getValue(hh);
if (!h_value) goto error;
if (!uwsgi_jvm_object_is_instance(h_key, ujvm.str_class)) {
uwsgi_log("headers key must be java/lang/String !!!\n");
goto error;
}
if (uwsgi_jvm_object_is_instance(h_value, ujvm.str_class)) {
char *c_h_key = uwsgi_jvm_str2c(h_key);
uint16_t c_h_keylen = uwsgi_jvm_strlen(h_key);
char *c_h_value = uwsgi_jvm_str2c(h_value);
uint16_t c_h_vallen = uwsgi_jvm_strlen(h_value);
int ret = uwsgi_response_add_header(wsgi_req, c_h_key, c_h_keylen, c_h_value, c_h_vallen);
uwsgi_jvm_release_chars(h_key, c_h_key);
uwsgi_jvm_release_chars(h_value, c_h_value);
if (ret) goto error;
}
else if (uwsgi_jvm_object_is_instance(h_value, uring.PersistentVector) || uwsgi_jvm_object_is_instance(h_value, uring.PersistentList)) {
jobject values = uwsgi_jvm_auto_iterator(h_value);
if (!values) goto error;
while(uwsgi_jvm_iterator_hasNext(values)) {
jobject hh_value = uwsgi_jvm_iterator_next(values);
if (!uwsgi_jvm_object_is_instance(hh_value, ujvm.str_class)) {
uwsgi_log("headers value must be java/lang/String !!!\n");
goto error;
}
char *c_h_key = uwsgi_jvm_str2c(h_key);
uint16_t c_h_keylen = uwsgi_jvm_strlen(h_key);
char *c_h_value = uwsgi_jvm_str2c(hh_value);
uint16_t c_h_vallen = uwsgi_jvm_strlen(hh_value);
int ret = uwsgi_response_add_header(wsgi_req, c_h_key, c_h_keylen, c_h_value, c_h_vallen);
uwsgi_jvm_release_chars(h_key, c_h_key);
uwsgi_jvm_release_chars(hh_value, c_h_value);
if (ret) goto error;
}
}
else {
uwsgi_log("unsupported header value !!! (must be java/lang/String, clojure/lang/PersistentVector or clojure/lang/PersistentList)\n");
goto error;
}
}
jobject ct = uwsgi_ring_header_get(r_headers, uwsgi_jvm_str("Content-Type", 0));
if (!ct) {
@@ -132,6 +194,16 @@ static int uwsgi_ring_setup() {
exit(1);
}
uring.PersistentVector = uwsgi_jvm_class("clojure/lang/PersistentVector");
if (!uring.PersistentVector) {
exit(1);
}
uring.PersistentList = uwsgi_jvm_class("clojure/lang/PersistentList");
if (!uring.PersistentList) {
exit(1);
}
jmethodID clojure_loadresourcescript = uwsgi_jvm_get_static_method_id(clojure, "loadResourceScript", "(Ljava/lang/String;)V");
if (!clojure_loadresourcescript) {
exit(1);