From a3dd2e6efda50a76e8d7308aa168f5d590535956 Mon Sep 17 00:00:00 2001 From: Unbit Date: Mon, 4 Mar 2013 16:50:37 +0100 Subject: [PATCH] added support ring clojure.io.file response --- plugins/jvm/jvm.h | 3 +++ plugins/jvm/jvm_plugin.c | 14 ++++++++++ plugins/ring/ring_plugin.c | 55 +++++++++++++++++++++++++++++--------- 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/plugins/jvm/jvm.h b/plugins/jvm/jvm.h index e1f50dfe..f0bb03bd 100644 --- a/plugins/jvm/jvm.h +++ b/plugins/jvm/jvm.h @@ -16,6 +16,7 @@ struct uwsgi_jvm { jclass str_class; jclass long_class; jclass int_class; + jclass file_class; jclass hashmap_class; jclass set_class; jclass iterator_class; @@ -74,3 +75,5 @@ long uwsgi_jvm_number2c(jobject); long uwsgi_jvm_int2c(jobject); long uwsgi_jvm_long2c(jobject); + +jobject uwsgi_jvm_filename(jobject); diff --git a/plugins/jvm/jvm_plugin.c b/plugins/jvm/jvm_plugin.c index 7fb774ac..d933c04f 100644 --- a/plugins/jvm/jvm_plugin.c +++ b/plugins/jvm/jvm_plugin.c @@ -240,6 +240,17 @@ jobject uwsgi_jvm_auto_iterator(jobject o) { return uwsgi_jvm_call_object(o, mid); } +// returns a java string of the filaname +jobject uwsgi_jvm_filename(jobject o) { + // optimization + static jmethodID mid = 0; + if (!mid) { + mid = uwsgi_jvm_get_method_id(ujvm.file_class, "getPath", "()Ljava/lang/String;"); + if (!mid) return 0; + } + 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; @@ -419,6 +430,9 @@ static void uwsgi_jvm_create(void) { ujvm.long_class = uwsgi_jvm_class("java/lang/Long"); if (!ujvm.long_class) exit(1); + ujvm.file_class = uwsgi_jvm_class("java/io/File"); + if (!ujvm.file_class) exit(1); + ujvm.hashmap_class = uwsgi_jvm_class("java/util/HashMap"); if (!ujvm.hashmap_class) exit(1); diff --git a/plugins/ring/ring_plugin.c b/plugins/ring/ring_plugin.c index a176df54..71862a40 100644 --- a/plugins/ring/ring_plugin.c +++ b/plugins/ring/ring_plugin.c @@ -32,8 +32,6 @@ static jobject uwsgi_ring_invoke1(jobject o, jobject arg1) { static jobject uwsgi_ring_keyword(char *key, size_t len) { jobject j_key = uwsgi_jvm_str(key, len); - char *cn = uwsgi_jvm_str2c( uwsgi_jvm_object_class_name(j_key) ); - uwsgi_log("response type = %s\n", cn); if (!j_key) return NULL; return uwsgi_ring_invoke1(uring.keyword, j_key); } @@ -65,10 +63,6 @@ static jobject uwsgi_ring_response_get(jobject r, char *name, size_t len) { return uwsgi_ring_PersistentArrayMap_get(r, j_key); } -static jobject uwsgi_ring_header_get(jobject headers, jobject key) { - return uwsgi_ring_PersistentArrayMap_get(headers, key); -} - static int uwsgi_ring_request(struct wsgi_request *wsgi_req) { char status_str[1]; uwsgi_log("managing ring request\n"); @@ -161,16 +155,51 @@ static int uwsgi_ring_request(struct wsgi_request *wsgi_req) { goto error; } } - jobject ct = uwsgi_ring_header_get(r_headers, uwsgi_jvm_str("Content-Type", 0)); - if (!ct) { - uwsgi_log("oops\n"); - goto error; + + jobject r_body = uwsgi_ring_response_get(response, "body", 4); + if (!r_body) goto error; + + if (uwsgi_jvm_object_is_instance(r_body, ujvm.str_class)) { + char *c_body = uwsgi_jvm_str2c(r_body); + size_t c_body_len = uwsgi_jvm_strlen(r_body); + uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len); + uwsgi_jvm_release_chars(r_body, c_body); + return UWSGI_OK; + } + + jobject chunks = uwsgi_jvm_auto_iterator(r_body); + if (chunks) { + while(uwsgi_jvm_iterator_hasNext(chunks)) { + jobject chunk = uwsgi_jvm_iterator_next(chunks); + if (!uwsgi_jvm_object_is_instance(chunk, ujvm.str_class)) { + uwsgi_log("body iSeq item must be java/lang/String !!!\n"); + goto error; + } + char *c_body = uwsgi_jvm_str2c(chunk); + size_t c_body_len = uwsgi_jvm_strlen(chunk); + int ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len); + uwsgi_jvm_release_chars(chunk, c_body); + if (ret) goto error; + } + return UWSGI_OK; } - uwsgi_log("type = %s\n", uwsgi_jvm_str2c(ct)); - - return UWSGI_OK; + if (uwsgi_jvm_object_is_instance(r_body, ujvm.file_class)) { + jobject j_filename = uwsgi_jvm_filename(r_body); + if (!j_filename) goto error; + char *c_filename = uwsgi_jvm_str2c(j_filename); + int fd = open(c_filename, O_RDONLY); + if (fd < 0) { + uwsgi_error("clojure/ring->open()"); + goto error; + } + uwsgi_response_sendfile_do(wsgi_req, fd, 0, 0); + uwsgi_log("sendfile fd = %d\n", fd); + uwsgi_jvm_release_chars(j_filename, c_filename); + return UWSGI_OK; + } + uwsgi_log("unsupported clojure/ring body type\n"); error: // destroy the hashmap return -1;