xref: /unit/src/nxt_java.c (revision 1157)
1977Smax.romanov@gmail.com 
2977Smax.romanov@gmail.com /*
3977Smax.romanov@gmail.com  * Copyright (C) NGINX, Inc.
4977Smax.romanov@gmail.com  */
5977Smax.romanov@gmail.com 
6977Smax.romanov@gmail.com 
7977Smax.romanov@gmail.com #include <jni.h>
8977Smax.romanov@gmail.com 
9977Smax.romanov@gmail.com #include <nxt_main.h>
10977Smax.romanov@gmail.com #include <nxt_runtime.h>
11977Smax.romanov@gmail.com #include <nxt_router.h>
12977Smax.romanov@gmail.com #include <nxt_unit.h>
13977Smax.romanov@gmail.com #include <nxt_unit_field.h>
14977Smax.romanov@gmail.com #include <nxt_unit_request.h>
15977Smax.romanov@gmail.com #include <nxt_unit_response.h>
16*1157Smax.romanov@nginx.com #include <nxt_unit_websocket.h>
17977Smax.romanov@gmail.com 
18977Smax.romanov@gmail.com #include <java/nxt_jni.h>
19977Smax.romanov@gmail.com 
20977Smax.romanov@gmail.com #include "java/nxt_jni_Thread.h"
21977Smax.romanov@gmail.com #include "java/nxt_jni_Context.h"
22977Smax.romanov@gmail.com #include "java/nxt_jni_Request.h"
23977Smax.romanov@gmail.com #include "java/nxt_jni_Response.h"
24977Smax.romanov@gmail.com #include "java/nxt_jni_InputStream.h"
25977Smax.romanov@gmail.com #include "java/nxt_jni_OutputStream.h"
26977Smax.romanov@gmail.com #include "java/nxt_jni_URLClassLoader.h"
27977Smax.romanov@gmail.com 
28977Smax.romanov@gmail.com #include "nxt_jars.h"
29977Smax.romanov@gmail.com 
30977Smax.romanov@gmail.com static nxt_int_t nxt_java_pre_init(nxt_task_t *task,
31977Smax.romanov@gmail.com     nxt_common_app_conf_t *conf);
32977Smax.romanov@gmail.com static nxt_int_t nxt_java_init(nxt_task_t *task, nxt_common_app_conf_t *conf);
33977Smax.romanov@gmail.com static void nxt_java_request_handler(nxt_unit_request_info_t *req);
34*1157Smax.romanov@nginx.com static void nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws);
35*1157Smax.romanov@nginx.com static void nxt_java_close_handler(nxt_unit_request_info_t *req);
36977Smax.romanov@gmail.com 
37977Smax.romanov@gmail.com static uint32_t  compat[] = {
38977Smax.romanov@gmail.com     NXT_VERNUM, NXT_DEBUG,
39977Smax.romanov@gmail.com };
40977Smax.romanov@gmail.com 
41977Smax.romanov@gmail.com char  *nxt_java_modules;
42977Smax.romanov@gmail.com 
43977Smax.romanov@gmail.com 
44977Smax.romanov@gmail.com #define NXT_STRING(x)   _NXT_STRING(x)
45977Smax.romanov@gmail.com #define _NXT_STRING(x)  #x
46977Smax.romanov@gmail.com 
47977Smax.romanov@gmail.com NXT_EXPORT nxt_app_module_t  nxt_app_module = {
48977Smax.romanov@gmail.com     sizeof(compat),
49977Smax.romanov@gmail.com     compat,
50977Smax.romanov@gmail.com     nxt_string("java"),
51977Smax.romanov@gmail.com     NXT_STRING(NXT_JAVA_VERSION),
52977Smax.romanov@gmail.com     nxt_java_pre_init,
53977Smax.romanov@gmail.com     nxt_java_init,
54977Smax.romanov@gmail.com };
55977Smax.romanov@gmail.com 
56977Smax.romanov@gmail.com typedef struct {
57977Smax.romanov@gmail.com     JNIEnv   *env;
58977Smax.romanov@gmail.com     jobject  ctx;
59977Smax.romanov@gmail.com } nxt_java_data_t;
60977Smax.romanov@gmail.com 
61977Smax.romanov@gmail.com 
62977Smax.romanov@gmail.com static nxt_int_t
63977Smax.romanov@gmail.com nxt_java_pre_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
64977Smax.romanov@gmail.com {
65977Smax.romanov@gmail.com     const char  *unit_jars;
66977Smax.romanov@gmail.com 
67977Smax.romanov@gmail.com     unit_jars = conf->u.java.unit_jars;
68977Smax.romanov@gmail.com     if (unit_jars == NULL) {
69977Smax.romanov@gmail.com         unit_jars = NXT_JARS;
70977Smax.romanov@gmail.com     }
71977Smax.romanov@gmail.com 
72977Smax.romanov@gmail.com     nxt_java_modules = realpath(unit_jars, NULL);
73977Smax.romanov@gmail.com     if (nxt_java_modules == NULL) {
741103Smax.romanov@nginx.com         nxt_alert(task, "realpath(%s) failed: %E", unit_jars, nxt_errno);
75977Smax.romanov@gmail.com         return NXT_ERROR;
76977Smax.romanov@gmail.com     }
77977Smax.romanov@gmail.com 
78977Smax.romanov@gmail.com     return NXT_OK;
79977Smax.romanov@gmail.com }
80977Smax.romanov@gmail.com 
81977Smax.romanov@gmail.com 
82977Smax.romanov@gmail.com static char **
83977Smax.romanov@gmail.com nxt_java_module_jars(const char *jars[], int jar_count)
84977Smax.romanov@gmail.com {
85977Smax.romanov@gmail.com     char        **res, *jurl;
86977Smax.romanov@gmail.com     nxt_int_t   modules_len, jlen, i;
87977Smax.romanov@gmail.com     const char  **jar;
88977Smax.romanov@gmail.com 
89977Smax.romanov@gmail.com     res = nxt_malloc(jar_count * sizeof(char*));
90977Smax.romanov@gmail.com     if (res == NULL) {
91977Smax.romanov@gmail.com         return NULL;
92977Smax.romanov@gmail.com     }
93977Smax.romanov@gmail.com 
94977Smax.romanov@gmail.com     modules_len = nxt_strlen(nxt_java_modules);
95977Smax.romanov@gmail.com 
96977Smax.romanov@gmail.com     for (i = 0, jar = jars; *jar != NULL; jar++) {
97977Smax.romanov@gmail.com         jlen = nxt_length("file:") + modules_len + nxt_length("/")
98977Smax.romanov@gmail.com               + nxt_strlen(*jar) + 1;
99977Smax.romanov@gmail.com         jurl = nxt_malloc(jlen);
100977Smax.romanov@gmail.com         if (jurl == NULL) {
101977Smax.romanov@gmail.com             return NULL;
102977Smax.romanov@gmail.com         }
103977Smax.romanov@gmail.com 
104977Smax.romanov@gmail.com         res[i++] = jurl;
105977Smax.romanov@gmail.com 
106977Smax.romanov@gmail.com         jurl = nxt_cpymem(jurl, "file:", nxt_length("file:"));
107977Smax.romanov@gmail.com         jurl = nxt_cpymem(jurl, nxt_java_modules, modules_len);
108977Smax.romanov@gmail.com         *jurl++ = '/';
109977Smax.romanov@gmail.com         jurl = nxt_cpymem(jurl, *jar, nxt_strlen(*jar));
110977Smax.romanov@gmail.com         *jurl++ = '\0';
111977Smax.romanov@gmail.com     }
112977Smax.romanov@gmail.com 
113977Smax.romanov@gmail.com     return res;
114977Smax.romanov@gmail.com }
115977Smax.romanov@gmail.com 
116977Smax.romanov@gmail.com 
117977Smax.romanov@gmail.com static nxt_int_t
118977Smax.romanov@gmail.com nxt_java_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
119977Smax.romanov@gmail.com {
120977Smax.romanov@gmail.com     jint                 rc;
121977Smax.romanov@gmail.com     char                 *opt, *real_path;
122977Smax.romanov@gmail.com     char                 **classpath_arr, **unit_jars, **system_jars;
123977Smax.romanov@gmail.com     JavaVM               *jvm;
124977Smax.romanov@gmail.com     JNIEnv               *env;
125977Smax.romanov@gmail.com     jobject              cl, classpath;
126977Smax.romanov@gmail.com     nxt_str_t            str;
127977Smax.romanov@gmail.com     nxt_int_t            opt_len, real_path_len;
128977Smax.romanov@gmail.com     nxt_uint_t           i, unit_jars_count, classpath_count, system_jars_count;
129977Smax.romanov@gmail.com     JavaVMOption         *jvm_opt;
130977Smax.romanov@gmail.com     JavaVMInitArgs       jvm_args;
131977Smax.romanov@gmail.com     nxt_unit_ctx_t       *ctx;
132977Smax.romanov@gmail.com     nxt_unit_init_t      java_init;
133977Smax.romanov@gmail.com     nxt_java_data_t      data;
134977Smax.romanov@gmail.com     nxt_conf_value_t     *value;
135977Smax.romanov@gmail.com     nxt_java_app_conf_t  *c;
136977Smax.romanov@gmail.com 
137977Smax.romanov@gmail.com     //setenv("ASAN_OPTIONS", "handle_segv=0", 1);
138977Smax.romanov@gmail.com 
139977Smax.romanov@gmail.com     jvm_args.version = JNI_VERSION_1_6;
140977Smax.romanov@gmail.com     jvm_args.nOptions = 0;
141977Smax.romanov@gmail.com     jvm_args.ignoreUnrecognized = 0;
142977Smax.romanov@gmail.com 
143977Smax.romanov@gmail.com     c = &conf->u.java;
144977Smax.romanov@gmail.com 
145977Smax.romanov@gmail.com     if (c->options != NULL) {
146977Smax.romanov@gmail.com         jvm_args.nOptions += nxt_conf_array_elements_count(c->options);
147977Smax.romanov@gmail.com     }
148977Smax.romanov@gmail.com 
149977Smax.romanov@gmail.com     jvm_opt = nxt_malloc(jvm_args.nOptions * sizeof(JavaVMOption));
150977Smax.romanov@gmail.com     if (jvm_opt == NULL) {
151977Smax.romanov@gmail.com         nxt_alert(task, "failed to allocate jvm_opt");
152977Smax.romanov@gmail.com         return NXT_ERROR;
153977Smax.romanov@gmail.com     }
154977Smax.romanov@gmail.com 
155977Smax.romanov@gmail.com     jvm_args.options = jvm_opt;
156977Smax.romanov@gmail.com 
157977Smax.romanov@gmail.com     unit_jars_count = nxt_nitems(nxt_java_unit_jars) - 1;
158977Smax.romanov@gmail.com 
159977Smax.romanov@gmail.com     unit_jars = nxt_java_module_jars(nxt_java_unit_jars, unit_jars_count);
160977Smax.romanov@gmail.com     if (unit_jars == NULL) {
161977Smax.romanov@gmail.com         nxt_alert(task, "failed to allocate buffer for unit_jars array");
162977Smax.romanov@gmail.com 
163977Smax.romanov@gmail.com         return NXT_ERROR;
164977Smax.romanov@gmail.com     }
165977Smax.romanov@gmail.com 
166977Smax.romanov@gmail.com     system_jars_count = nxt_nitems(nxt_java_system_jars) - 1;
167977Smax.romanov@gmail.com 
168977Smax.romanov@gmail.com     system_jars = nxt_java_module_jars(nxt_java_system_jars, system_jars_count);
169977Smax.romanov@gmail.com     if (system_jars == NULL) {
170977Smax.romanov@gmail.com         nxt_alert(task, "failed to allocate buffer for system_jars array");
171977Smax.romanov@gmail.com 
172977Smax.romanov@gmail.com         return NXT_ERROR;
173977Smax.romanov@gmail.com     }
174977Smax.romanov@gmail.com 
175977Smax.romanov@gmail.com     if (c->options != NULL) {
176977Smax.romanov@gmail.com 
177977Smax.romanov@gmail.com         for (i = 0; /* void */ ; i++) {
178977Smax.romanov@gmail.com             value = nxt_conf_get_array_element(c->options, i);
179977Smax.romanov@gmail.com             if (value == NULL) {
180977Smax.romanov@gmail.com                 break;
181977Smax.romanov@gmail.com             }
182977Smax.romanov@gmail.com 
183977Smax.romanov@gmail.com             nxt_conf_get_string(value, &str);
184977Smax.romanov@gmail.com 
185977Smax.romanov@gmail.com             opt = nxt_malloc(str.length + 1);
186977Smax.romanov@gmail.com             if (opt == NULL) {
187977Smax.romanov@gmail.com                 nxt_alert(task, "failed to allocate jvm_opt");
188977Smax.romanov@gmail.com                 return NXT_ERROR;
189977Smax.romanov@gmail.com             }
190977Smax.romanov@gmail.com 
191977Smax.romanov@gmail.com             memcpy(opt, str.start, str.length);
192977Smax.romanov@gmail.com             opt[str.length] = '\0';
193977Smax.romanov@gmail.com 
194977Smax.romanov@gmail.com             jvm_opt[i].optionString = opt;
195977Smax.romanov@gmail.com         }
196977Smax.romanov@gmail.com     }
197977Smax.romanov@gmail.com 
198977Smax.romanov@gmail.com     if (c->classpath != NULL) {
199977Smax.romanov@gmail.com         classpath_count = nxt_conf_array_elements_count(c->classpath);
200977Smax.romanov@gmail.com         classpath_arr = nxt_malloc(classpath_count * sizeof(char *));
201977Smax.romanov@gmail.com 
202977Smax.romanov@gmail.com         for (i = 0; /* void */ ; i++) {
203977Smax.romanov@gmail.com             value = nxt_conf_get_array_element(c->classpath, i);
204977Smax.romanov@gmail.com             if (value == NULL) {
205977Smax.romanov@gmail.com                 break;
206977Smax.romanov@gmail.com             }
207977Smax.romanov@gmail.com 
208977Smax.romanov@gmail.com             nxt_conf_get_string(value, &str);
209977Smax.romanov@gmail.com 
210977Smax.romanov@gmail.com             opt_len = str.length + 1;
211977Smax.romanov@gmail.com 
212977Smax.romanov@gmail.com             char *sc = memchr(str.start, ':', str.length);
213977Smax.romanov@gmail.com             if (sc == NULL && str.start[0] == '/') {
214977Smax.romanov@gmail.com                 opt_len += nxt_length("file:");
215977Smax.romanov@gmail.com             }
216977Smax.romanov@gmail.com 
217977Smax.romanov@gmail.com             opt = nxt_malloc(opt_len);
218977Smax.romanov@gmail.com             if (opt == NULL) {
219977Smax.romanov@gmail.com                 nxt_alert(task, "failed to allocate classpath");
220977Smax.romanov@gmail.com                 return NXT_ERROR;
221977Smax.romanov@gmail.com             }
222977Smax.romanov@gmail.com 
223977Smax.romanov@gmail.com             if (sc == NULL && str.start[0] != '/') {
224977Smax.romanov@gmail.com                 nxt_memcpy(opt, str.start, str.length);
225977Smax.romanov@gmail.com                 opt[str.length] = '\0';
226977Smax.romanov@gmail.com 
227977Smax.romanov@gmail.com                 real_path = realpath(opt, NULL);
228977Smax.romanov@gmail.com                 if (real_path == NULL) {
229977Smax.romanov@gmail.com                     nxt_alert(task, "realpath(%s) failed: %E", opt, nxt_errno);
230977Smax.romanov@gmail.com                     return NXT_ERROR;
231977Smax.romanov@gmail.com                 }
232977Smax.romanov@gmail.com 
233977Smax.romanov@gmail.com                 real_path_len = nxt_strlen(real_path);
234977Smax.romanov@gmail.com 
235977Smax.romanov@gmail.com                 free(opt);
236977Smax.romanov@gmail.com 
237977Smax.romanov@gmail.com                 opt_len = nxt_length("file:") + real_path_len + 1;
238977Smax.romanov@gmail.com 
239977Smax.romanov@gmail.com                 opt = nxt_malloc(opt_len);
240977Smax.romanov@gmail.com                 if (opt == NULL) {
241977Smax.romanov@gmail.com                     nxt_alert(task, "failed to allocate classpath");
242977Smax.romanov@gmail.com                     return NXT_ERROR;
243977Smax.romanov@gmail.com                 }
244977Smax.romanov@gmail.com 
245977Smax.romanov@gmail.com             } else {
246977Smax.romanov@gmail.com                 real_path = (char *) str.start;  /* I love this cast! */
247977Smax.romanov@gmail.com                 real_path_len = str.length;
248977Smax.romanov@gmail.com             }
249977Smax.romanov@gmail.com 
250977Smax.romanov@gmail.com             classpath_arr[i] = opt;
251977Smax.romanov@gmail.com 
252977Smax.romanov@gmail.com             if (sc == NULL) {
253977Smax.romanov@gmail.com                 opt = nxt_cpymem(opt, "file:", nxt_length("file:"));
254977Smax.romanov@gmail.com             }
255977Smax.romanov@gmail.com 
256977Smax.romanov@gmail.com             opt = nxt_cpymem(opt, real_path, real_path_len);
257977Smax.romanov@gmail.com             *opt = '\0';
258977Smax.romanov@gmail.com         }
259977Smax.romanov@gmail.com 
260977Smax.romanov@gmail.com     } else {
261977Smax.romanov@gmail.com         classpath_count = 0;
262977Smax.romanov@gmail.com         classpath_arr = NULL;
263977Smax.romanov@gmail.com     }
264977Smax.romanov@gmail.com 
265977Smax.romanov@gmail.com     rc = JNI_CreateJavaVM(&jvm, (void **) &env, &jvm_args);
266977Smax.romanov@gmail.com     if (rc != JNI_OK) {
267977Smax.romanov@gmail.com         nxt_alert(task, "failed to create Java VM: %d", (int) rc);
268977Smax.romanov@gmail.com         return NXT_ERROR;
269977Smax.romanov@gmail.com     }
270977Smax.romanov@gmail.com 
271977Smax.romanov@gmail.com     rc = nxt_java_initThread(env);
272977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
273977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initThread() failed");
274977Smax.romanov@gmail.com         goto env_failed;
275977Smax.romanov@gmail.com     }
276977Smax.romanov@gmail.com 
277977Smax.romanov@gmail.com     rc = nxt_java_initURLClassLoader(env);
278977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
279977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initURLClassLoader() failed");
280977Smax.romanov@gmail.com         goto env_failed;
281977Smax.romanov@gmail.com     }
282977Smax.romanov@gmail.com 
283977Smax.romanov@gmail.com     cl = nxt_java_newURLClassLoader(env, system_jars_count, system_jars);
284977Smax.romanov@gmail.com     if (cl == NULL) {
285977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_newURLClassLoader failed");
286977Smax.romanov@gmail.com         goto env_failed;
287977Smax.romanov@gmail.com     }
288977Smax.romanov@gmail.com 
289977Smax.romanov@gmail.com     nxt_java_setContextClassLoader(env, cl);
290977Smax.romanov@gmail.com 
291977Smax.romanov@gmail.com     cl = nxt_java_newURLClassLoader_parent(env, unit_jars_count, unit_jars, cl);
292977Smax.romanov@gmail.com     if (cl == NULL) {
293977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_newURLClassLoader_parent failed");
294977Smax.romanov@gmail.com         goto env_failed;
295977Smax.romanov@gmail.com     }
296977Smax.romanov@gmail.com 
297977Smax.romanov@gmail.com     nxt_java_setContextClassLoader(env, cl);
298977Smax.romanov@gmail.com 
299977Smax.romanov@gmail.com     rc = nxt_java_initContext(env, cl);
300977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
301977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initContext() failed");
302977Smax.romanov@gmail.com         goto env_failed;
303977Smax.romanov@gmail.com     }
304977Smax.romanov@gmail.com 
305977Smax.romanov@gmail.com     rc = nxt_java_initRequest(env, cl);
306977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
307977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initRequest() failed");
308977Smax.romanov@gmail.com         goto env_failed;
309977Smax.romanov@gmail.com     }
310977Smax.romanov@gmail.com 
311977Smax.romanov@gmail.com     rc = nxt_java_initResponse(env, cl);
312977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
313977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initResponse() failed");
314977Smax.romanov@gmail.com         goto env_failed;
315977Smax.romanov@gmail.com     }
316977Smax.romanov@gmail.com 
317977Smax.romanov@gmail.com     rc = nxt_java_initInputStream(env, cl);
318977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
319977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initInputStream() failed");
320977Smax.romanov@gmail.com         goto env_failed;
321977Smax.romanov@gmail.com     }
322977Smax.romanov@gmail.com 
323977Smax.romanov@gmail.com     rc = nxt_java_initOutputStream(env, cl);
324977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
325977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initOutputStream() failed");
326977Smax.romanov@gmail.com         goto env_failed;
327977Smax.romanov@gmail.com     }
328977Smax.romanov@gmail.com 
329977Smax.romanov@gmail.com     nxt_java_jni_init(env);
330977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
331977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_jni_init() failed");
332977Smax.romanov@gmail.com         goto env_failed;
333977Smax.romanov@gmail.com     }
334977Smax.romanov@gmail.com 
335977Smax.romanov@gmail.com     classpath = nxt_java_newURLs(env, classpath_count, classpath_arr);
336977Smax.romanov@gmail.com     if (classpath == NULL) {
337977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_newURLs failed");
338977Smax.romanov@gmail.com         goto env_failed;
339977Smax.romanov@gmail.com     }
340977Smax.romanov@gmail.com 
341977Smax.romanov@gmail.com     data.env = env;
342977Smax.romanov@gmail.com     data.ctx = nxt_java_startContext(env, c->webapp, classpath);
343977Smax.romanov@gmail.com 
344977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
345977Smax.romanov@gmail.com         nxt_alert(task, "Unhandled exception in application start");
346977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
347977Smax.romanov@gmail.com         return NXT_ERROR;
348977Smax.romanov@gmail.com     }
349977Smax.romanov@gmail.com 
350977Smax.romanov@gmail.com     nxt_unit_default_init(task, &java_init);
351977Smax.romanov@gmail.com 
352977Smax.romanov@gmail.com     java_init.callbacks.request_handler = nxt_java_request_handler;
353*1157Smax.romanov@nginx.com     java_init.callbacks.websocket_handler = nxt_java_websocket_handler;
354*1157Smax.romanov@nginx.com     java_init.callbacks.close_handler = nxt_java_close_handler;
355977Smax.romanov@gmail.com     java_init.request_data_size = sizeof(nxt_java_request_data_t);
356977Smax.romanov@gmail.com     java_init.data = &data;
357977Smax.romanov@gmail.com 
358977Smax.romanov@gmail.com     ctx = nxt_unit_init(&java_init);
359977Smax.romanov@gmail.com     if (nxt_slow_path(ctx == NULL)) {
360977Smax.romanov@gmail.com         nxt_alert(task, "nxt_unit_init() failed");
361977Smax.romanov@gmail.com         return NXT_ERROR;
362977Smax.romanov@gmail.com     }
363977Smax.romanov@gmail.com 
364977Smax.romanov@gmail.com     rc = nxt_unit_run(ctx);
365977Smax.romanov@gmail.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
366977Smax.romanov@gmail.com         /* TODO report error */
367977Smax.romanov@gmail.com     }
368977Smax.romanov@gmail.com 
369977Smax.romanov@gmail.com     nxt_java_stopContext(env, data.ctx);
370977Smax.romanov@gmail.com 
371977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
372977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
373977Smax.romanov@gmail.com     }
374977Smax.romanov@gmail.com 
375*1157Smax.romanov@nginx.com     nxt_unit_done(ctx);
376*1157Smax.romanov@nginx.com 
377977Smax.romanov@gmail.com     (*jvm)->DestroyJavaVM(jvm);
378977Smax.romanov@gmail.com 
379977Smax.romanov@gmail.com     exit(0);
380977Smax.romanov@gmail.com 
381977Smax.romanov@gmail.com     return NXT_OK;
382977Smax.romanov@gmail.com 
383977Smax.romanov@gmail.com env_failed:
384977Smax.romanov@gmail.com 
385977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
386977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
387977Smax.romanov@gmail.com     }
388977Smax.romanov@gmail.com 
389977Smax.romanov@gmail.com     return NXT_ERROR;
390977Smax.romanov@gmail.com }
391977Smax.romanov@gmail.com 
392977Smax.romanov@gmail.com 
393977Smax.romanov@gmail.com static void
394977Smax.romanov@gmail.com nxt_java_request_handler(nxt_unit_request_info_t *req)
395977Smax.romanov@gmail.com {
396977Smax.romanov@gmail.com     JNIEnv                   *env;
397977Smax.romanov@gmail.com     jobject                  jreq, jresp;
398977Smax.romanov@gmail.com     nxt_java_data_t          *java_data;
399977Smax.romanov@gmail.com     nxt_java_request_data_t  *data;
400977Smax.romanov@gmail.com 
401977Smax.romanov@gmail.com     java_data = req->unit->data;
402977Smax.romanov@gmail.com     env = java_data->env;
403977Smax.romanov@gmail.com     data = req->data;
404977Smax.romanov@gmail.com 
405977Smax.romanov@gmail.com     jreq = nxt_java_newRequest(env, java_data->ctx, req);
406977Smax.romanov@gmail.com     if (jreq == NULL) {
407977Smax.romanov@gmail.com         nxt_unit_req_alert(req, "failed to create Request instance");
408977Smax.romanov@gmail.com 
409977Smax.romanov@gmail.com         if ((*env)->ExceptionCheck(env)) {
410977Smax.romanov@gmail.com             (*env)->ExceptionDescribe(env);
411977Smax.romanov@gmail.com             (*env)->ExceptionClear(env);
412977Smax.romanov@gmail.com         }
413977Smax.romanov@gmail.com 
414977Smax.romanov@gmail.com         nxt_unit_request_done(req, NXT_UNIT_ERROR);
415977Smax.romanov@gmail.com         return;
416977Smax.romanov@gmail.com     }
417977Smax.romanov@gmail.com 
418977Smax.romanov@gmail.com     jresp = nxt_java_newResponse(env, req);
419977Smax.romanov@gmail.com     if (jresp == NULL) {
420977Smax.romanov@gmail.com         nxt_unit_req_alert(req, "failed to create Response instance");
421977Smax.romanov@gmail.com 
422977Smax.romanov@gmail.com         if ((*env)->ExceptionCheck(env)) {
423977Smax.romanov@gmail.com             (*env)->ExceptionDescribe(env);
424977Smax.romanov@gmail.com             (*env)->ExceptionClear(env);
425977Smax.romanov@gmail.com         }
426977Smax.romanov@gmail.com 
427977Smax.romanov@gmail.com         (*env)->DeleteLocalRef(env, jreq);
428977Smax.romanov@gmail.com 
429977Smax.romanov@gmail.com         nxt_unit_request_done(req, NXT_UNIT_ERROR);
430977Smax.romanov@gmail.com         return;
431977Smax.romanov@gmail.com     }
432977Smax.romanov@gmail.com 
433977Smax.romanov@gmail.com     data->header_size = 10 * 1024;
434977Smax.romanov@gmail.com     data->buf_size = 32 * 1024; /* from Jetty */
435977Smax.romanov@gmail.com     data->jreq = jreq;
436977Smax.romanov@gmail.com     data->jresp = jresp;
437977Smax.romanov@gmail.com     data->buf = NULL;
438977Smax.romanov@gmail.com 
439977Smax.romanov@gmail.com     nxt_unit_request_group_dup_fields(req);
440977Smax.romanov@gmail.com 
441977Smax.romanov@gmail.com     nxt_java_service(env, java_data->ctx, jreq, jresp);
442977Smax.romanov@gmail.com 
443977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
444977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
445977Smax.romanov@gmail.com         (*env)->ExceptionClear(env);
446977Smax.romanov@gmail.com     }
447977Smax.romanov@gmail.com 
448977Smax.romanov@gmail.com     if (!nxt_unit_response_is_init(req)) {
449977Smax.romanov@gmail.com         nxt_unit_response_init(req, 200, 0, 0);
450977Smax.romanov@gmail.com     }
451977Smax.romanov@gmail.com 
452977Smax.romanov@gmail.com     if (!nxt_unit_response_is_sent(req)) {
453977Smax.romanov@gmail.com         nxt_unit_response_send(req);
454977Smax.romanov@gmail.com     }
455977Smax.romanov@gmail.com 
456977Smax.romanov@gmail.com     if (data->buf != NULL) {
457977Smax.romanov@gmail.com         nxt_unit_buf_send(data->buf);
458977Smax.romanov@gmail.com 
459977Smax.romanov@gmail.com         data->buf = NULL;
460977Smax.romanov@gmail.com     }
461977Smax.romanov@gmail.com 
462*1157Smax.romanov@nginx.com     if (nxt_unit_response_is_websocket(req)) {
463*1157Smax.romanov@nginx.com         data->jreq = (*env)->NewGlobalRef(env, jreq);
464*1157Smax.romanov@nginx.com         data->jresp = (*env)->NewGlobalRef(env, jresp);
465*1157Smax.romanov@nginx.com 
466*1157Smax.romanov@nginx.com     } else {
467*1157Smax.romanov@nginx.com         nxt_unit_request_done(req, NXT_UNIT_OK);
468*1157Smax.romanov@nginx.com     }
469*1157Smax.romanov@nginx.com 
470977Smax.romanov@gmail.com     (*env)->DeleteLocalRef(env, jresp);
471977Smax.romanov@gmail.com     (*env)->DeleteLocalRef(env, jreq);
472*1157Smax.romanov@nginx.com }
473*1157Smax.romanov@nginx.com 
474*1157Smax.romanov@nginx.com 
475*1157Smax.romanov@nginx.com static void
476*1157Smax.romanov@nginx.com nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws)
477*1157Smax.romanov@nginx.com {
478*1157Smax.romanov@nginx.com     void                     *b;
479*1157Smax.romanov@nginx.com     JNIEnv                   *env;
480*1157Smax.romanov@nginx.com     jobject                  jbuf;
481*1157Smax.romanov@nginx.com     nxt_java_data_t          *java_data;
482*1157Smax.romanov@nginx.com     nxt_java_request_data_t  *data;
483*1157Smax.romanov@nginx.com 
484*1157Smax.romanov@nginx.com     java_data = ws->req->unit->data;
485*1157Smax.romanov@nginx.com     env = java_data->env;
486*1157Smax.romanov@nginx.com     data = ws->req->data;
487*1157Smax.romanov@nginx.com 
488*1157Smax.romanov@nginx.com     b = malloc(ws->payload_len);
489*1157Smax.romanov@nginx.com     if (b != NULL) {
490*1157Smax.romanov@nginx.com         nxt_unit_websocket_read(ws, b, ws->payload_len);
491*1157Smax.romanov@nginx.com 
492*1157Smax.romanov@nginx.com         jbuf = (*env)->NewDirectByteBuffer(env, b, ws->payload_len);
493*1157Smax.romanov@nginx.com         if (jbuf != NULL) {
494*1157Smax.romanov@nginx.com             nxt_java_Request_websocket(env, data->jreq, jbuf,
495*1157Smax.romanov@nginx.com                                        ws->header->opcode, ws->header->fin);
496*1157Smax.romanov@nginx.com 
497*1157Smax.romanov@nginx.com             if ((*env)->ExceptionCheck(env)) {
498*1157Smax.romanov@nginx.com                 (*env)->ExceptionDescribe(env);
499*1157Smax.romanov@nginx.com                 (*env)->ExceptionClear(env);
500*1157Smax.romanov@nginx.com             }
501*1157Smax.romanov@nginx.com 
502*1157Smax.romanov@nginx.com             (*env)->DeleteLocalRef(env, jbuf);
503*1157Smax.romanov@nginx.com         }
504*1157Smax.romanov@nginx.com 
505*1157Smax.romanov@nginx.com         free(b);
506*1157Smax.romanov@nginx.com     }
507*1157Smax.romanov@nginx.com 
508*1157Smax.romanov@nginx.com     nxt_unit_websocket_done(ws);
509*1157Smax.romanov@nginx.com }
510*1157Smax.romanov@nginx.com 
511*1157Smax.romanov@nginx.com 
512*1157Smax.romanov@nginx.com static void
513*1157Smax.romanov@nginx.com nxt_java_close_handler(nxt_unit_request_info_t *req)
514*1157Smax.romanov@nginx.com {
515*1157Smax.romanov@nginx.com     JNIEnv                   *env;
516*1157Smax.romanov@nginx.com     nxt_java_data_t          *java_data;
517*1157Smax.romanov@nginx.com     nxt_java_request_data_t  *data;
518*1157Smax.romanov@nginx.com 
519*1157Smax.romanov@nginx.com     java_data = req->unit->data;
520*1157Smax.romanov@nginx.com     env = java_data->env;
521*1157Smax.romanov@nginx.com     data = req->data;
522*1157Smax.romanov@nginx.com 
523*1157Smax.romanov@nginx.com     nxt_java_Request_close(env, data->jreq);
524*1157Smax.romanov@nginx.com 
525*1157Smax.romanov@nginx.com     (*env)->DeleteGlobalRef(env, data->jresp);
526*1157Smax.romanov@nginx.com     (*env)->DeleteGlobalRef(env, data->jreq);
527977Smax.romanov@gmail.com 
528977Smax.romanov@gmail.com     nxt_unit_request_done(req, NXT_UNIT_OK);
529977Smax.romanov@gmail.com }
530977Smax.romanov@gmail.com 
531