1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
#include <jvm.h>
extern struct uwsgi_server uwsgi;
extern struct uwsgi_jvm ujvm;
#define UWSGI_JVM_REQUEST_HANDLER_JWSGI 0
struct uwsgi_jwsgi {
char *app;
jmethodID app_mid;
jclass app_class;
jobject app_instance;
} ujwsgi;
static struct uwsgi_option uwsgi_jwsgi_options[] = {
{"jwsgi", required_argument, 0, "load the specified JWSGI application (syntax class:method)", uwsgi_opt_set_str, &ujwsgi.app, 0},
{0, 0, 0, 0},
};
static int uwsgi_jwsgi_add_request_item(jobject hm, char *key, uint16_t key_len, char *value, uint16_t value_len) {
jobject j_key = uwsgi_jvm_str(key, key_len);
if (!j_key) return -1;
jobject j_value = NULL;
// avoid clobbering vars
if (value_len > 0) {
j_value = uwsgi_jvm_str(value, value_len);
}
else {
char *tmp = uwsgi_str("");
j_value = uwsgi_jvm_str(tmp, 0);
free(tmp);
}
if (!j_value) {
uwsgi_jvm_local_unref(j_value);
return -1;
}
int ret = uwsgi_jvm_hashmap_put(hm, j_key, j_value);
uwsgi_jvm_local_unref(j_key);
uwsgi_jvm_local_unref(j_value);
return ret;
}
static int uwsgi_jwsgi_add_request_input(jobject hm, char *key, uint16_t key_len) {
jobject j_key = uwsgi_jvm_str(key, key_len);
if (!j_key) return -1;
jobject j_value = uwsgi_jvm_request_body_input_stream();
if (!j_value) {
uwsgi_jvm_local_unref(j_value);
return -1;
}
int ret = uwsgi_jvm_hashmap_put(hm, j_key, j_value);
uwsgi_jvm_local_unref(j_key);
uwsgi_jvm_local_unref(j_value);
return ret;
}
static int uwsgi_jwsgi_request(struct wsgi_request *wsgi_req) {
char status_str[11];
jobject hm = NULL;
jobject response = NULL;
jobject r_status = NULL;
jobject r_headers = NULL;
jobject r_headers_entries = NULL;
jobject r_body = NULL;
hm = uwsgi_jvm_hashmap();
if (!hm) return -1;
int i;
for(i=0;i<wsgi_req->var_cnt;i+=2) {
char *hk = wsgi_req->hvec[i].iov_base;
uint16_t hk_l = wsgi_req->hvec[i].iov_len;
char *hv = wsgi_req->hvec[i+1].iov_base;
uint16_t hv_l = wsgi_req->hvec[i+1].iov_len;
if (uwsgi_jwsgi_add_request_item(hm, hk, hk_l, hv, hv_l)) goto end;
}
if (uwsgi_jwsgi_add_request_input(hm, "jwsgi.input", 11)) goto end;
if (!ujwsgi.app_instance) {
response = uwsgi_jvm_call_object_static(ujwsgi.app_class, ujwsgi.app_mid, hm);
}
else {
response = uwsgi_jvm_call_object(ujwsgi.app_instance, ujwsgi.app_mid, hm);
}
if (!response) goto end;
if (uwsgi_jvm_array_len(response) != 3) {
uwsgi_log("invalid JWSGI response object\n");
goto end;
}
r_status = uwsgi_jvm_array_get(response, 0);
if (!r_status) goto end;
long n_status = uwsgi_jvm_number2c(r_status);
if (n_status == -1) goto end;
if (uwsgi_num2str2(n_status, status_str) != 3) {
goto end;
}
if (uwsgi_response_prepare_headers(wsgi_req, status_str, 3)) goto end;
r_headers = uwsgi_jvm_array_get(response, 1);
if (!r_headers) goto end;
// get entrySet
r_headers_entries = uwsgi_jvm_entryset(r_headers);
if (!r_headers_entries) goto end;
// get iterator
jobject values = uwsgi_jvm_auto_iterator(r_headers_entries);
if (values) {
int ret = uwsgi_jvm_iterator_to_response_headers(wsgi_req, values);
uwsgi_jvm_local_unref(values);
if (ret) goto end;
}
else {
uwsgi_log("unsupported response headers type !!! (must be java/util/HashMap)\n");
goto end;
}
r_body = uwsgi_jvm_array_get(response, 2);
if (!r_body) goto end;
if (uwsgi_jvm_object_to_response_body(wsgi_req, r_body)) {
uwsgi_log("unsupported JWSGI response body type\n");
}
end:
if (r_status) uwsgi_jvm_local_unref(r_status);
if (r_headers_entries) uwsgi_jvm_local_unref(r_headers_entries);
if (r_headers) uwsgi_jvm_local_unref(r_headers);
if (r_body) uwsgi_jvm_local_unref(r_body);
if (response) {
uwsgi_jvm_local_unref(response);
}
uwsgi_jvm_local_unref(hm);
return UWSGI_OK;
}
static int uwsgi_jwsgi_setup() {
char *app = uwsgi_str(ujwsgi.app);
char *method = "application";
char *colon = strchr(app, ':');
if (colon) {
*colon = 0;
method = colon + 1;
}
ujwsgi.app_class = uwsgi_jvm_class(app);
if (!ujwsgi.app_class) {
exit(1);
}
ujwsgi.app_mid = uwsgi_jvm_get_static_method_id_quiet(ujwsgi.app_class, method, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
if (uwsgi_jvm_exception() || !ujwsgi.app_mid) {
jmethodID mid = uwsgi_jvm_get_method_id(ujwsgi.app_class, "<init>", "()V");
if (uwsgi_jvm_exception() || !mid) exit(1);
ujwsgi.app_instance = (*ujvm_env)->NewObject(ujvm_env, ujwsgi.app_class, mid);
if (uwsgi_jvm_exception() || !ujwsgi.app_instance) {
exit(1);
}
ujwsgi.app_mid = uwsgi_jvm_get_method_id(ujwsgi.app_class, method, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
if (uwsgi_jvm_exception() || !ujwsgi.app_mid) {
exit(1);
}
}
uwsgi_log("JWSGI app \"%s\" loaded\n", ujwsgi.app);
return 0;
}
static int uwsgi_jwsgi_init() {
if (!ujwsgi.app) return 0;
if (uwsgi_jvm_register_request_handler(UWSGI_JVM_REQUEST_HANDLER_JWSGI, uwsgi_jwsgi_setup, uwsgi_jwsgi_request)) {
exit(1);
}
return 0;
}
struct uwsgi_plugin jwsgi_plugin = {
.name = "jwsgi",
.options = uwsgi_jwsgi_options,
.init = uwsgi_jwsgi_init,
};
|