xref: /unit/src/nxt_java.c (revision 1489)
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>
161157Smax.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"
29*1489St.nateldemoura@f5.com #include "nxt_java_mounts.h"
30977Smax.romanov@gmail.com 
311488St.nateldemoura@f5.com static nxt_int_t nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
32977Smax.romanov@gmail.com     nxt_common_app_conf_t *conf);
331488St.nateldemoura@f5.com static nxt_int_t nxt_java_start(nxt_task_t *task,
341488St.nateldemoura@f5.com     nxt_process_data_t *data);
35977Smax.romanov@gmail.com static void nxt_java_request_handler(nxt_unit_request_info_t *req);
361157Smax.romanov@nginx.com static void nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws);
371157Smax.romanov@nginx.com static void nxt_java_close_handler(nxt_unit_request_info_t *req);
38977Smax.romanov@gmail.com 
39977Smax.romanov@gmail.com static uint32_t  compat[] = {
40977Smax.romanov@gmail.com     NXT_VERNUM, NXT_DEBUG,
41977Smax.romanov@gmail.com };
42977Smax.romanov@gmail.com 
43977Smax.romanov@gmail.com char  *nxt_java_modules;
44977Smax.romanov@gmail.com 
45977Smax.romanov@gmail.com 
46977Smax.romanov@gmail.com #define NXT_STRING(x)   _NXT_STRING(x)
47977Smax.romanov@gmail.com #define _NXT_STRING(x)  #x
48977Smax.romanov@gmail.com 
49977Smax.romanov@gmail.com NXT_EXPORT nxt_app_module_t  nxt_app_module = {
50977Smax.romanov@gmail.com     sizeof(compat),
51977Smax.romanov@gmail.com     compat,
52977Smax.romanov@gmail.com     nxt_string("java"),
53977Smax.romanov@gmail.com     NXT_STRING(NXT_JAVA_VERSION),
54*1489St.nateldemoura@f5.com     nxt_java_mounts,
55*1489St.nateldemoura@f5.com     nxt_nitems(nxt_java_mounts),
561488St.nateldemoura@f5.com     nxt_java_setup,
571488St.nateldemoura@f5.com     nxt_java_start,
58977Smax.romanov@gmail.com };
59977Smax.romanov@gmail.com 
60977Smax.romanov@gmail.com typedef struct {
61977Smax.romanov@gmail.com     JNIEnv   *env;
62977Smax.romanov@gmail.com     jobject  ctx;
63977Smax.romanov@gmail.com } nxt_java_data_t;
64977Smax.romanov@gmail.com 
65977Smax.romanov@gmail.com 
66977Smax.romanov@gmail.com static nxt_int_t
671488St.nateldemoura@f5.com nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
681488St.nateldemoura@f5.com     nxt_common_app_conf_t *conf)
69977Smax.romanov@gmail.com {
70*1489St.nateldemoura@f5.com     char        *path, *relpath, *p, *rootfs;
71*1489St.nateldemoura@f5.com     size_t      jars_dir_len, rootfs_len;
72977Smax.romanov@gmail.com     const char  *unit_jars;
73977Smax.romanov@gmail.com 
74*1489St.nateldemoura@f5.com     rootfs = (char *) process->isolation.rootfs;
75*1489St.nateldemoura@f5.com     rootfs_len = 0;
76*1489St.nateldemoura@f5.com 
77977Smax.romanov@gmail.com     unit_jars = conf->u.java.unit_jars;
78977Smax.romanov@gmail.com     if (unit_jars == NULL) {
79*1489St.nateldemoura@f5.com         if (rootfs != NULL) {
80*1489St.nateldemoura@f5.com             unit_jars = "/";
81*1489St.nateldemoura@f5.com         } else {
82*1489St.nateldemoura@f5.com             unit_jars = NXT_JARS;
83*1489St.nateldemoura@f5.com         }
84977Smax.romanov@gmail.com     }
85977Smax.romanov@gmail.com 
86*1489St.nateldemoura@f5.com     relpath = strdup(unit_jars);
87*1489St.nateldemoura@f5.com     if (nxt_slow_path(relpath == NULL)) {
88977Smax.romanov@gmail.com         return NXT_ERROR;
89977Smax.romanov@gmail.com     }
90977Smax.romanov@gmail.com 
91*1489St.nateldemoura@f5.com     if (rootfs != NULL) {
92*1489St.nateldemoura@f5.com         jars_dir_len = strlen(unit_jars);
93*1489St.nateldemoura@f5.com         rootfs_len = strlen(rootfs);
94*1489St.nateldemoura@f5.com 
95*1489St.nateldemoura@f5.com         path = nxt_malloc(jars_dir_len + rootfs_len + 1);
96*1489St.nateldemoura@f5.com         if (nxt_slow_path(path == NULL)) {
97*1489St.nateldemoura@f5.com             free(relpath);
98*1489St.nateldemoura@f5.com             return NXT_ERROR;
99*1489St.nateldemoura@f5.com         }
100*1489St.nateldemoura@f5.com 
101*1489St.nateldemoura@f5.com         p = nxt_cpymem(path, process->isolation.rootfs, rootfs_len);
102*1489St.nateldemoura@f5.com         p = nxt_cpymem(p, relpath, jars_dir_len);
103*1489St.nateldemoura@f5.com         *p = '\0';
104*1489St.nateldemoura@f5.com 
105*1489St.nateldemoura@f5.com         free(relpath);
106*1489St.nateldemoura@f5.com 
107*1489St.nateldemoura@f5.com     } else {
108*1489St.nateldemoura@f5.com         path = relpath;
109*1489St.nateldemoura@f5.com     }
110*1489St.nateldemoura@f5.com 
111*1489St.nateldemoura@f5.com     nxt_java_modules = realpath(path, NULL);
112*1489St.nateldemoura@f5.com     if (nxt_java_modules == NULL) {
113*1489St.nateldemoura@f5.com         nxt_alert(task, "realpath(\"%s\") failed %E", path, nxt_errno);
114*1489St.nateldemoura@f5.com         goto free;
115*1489St.nateldemoura@f5.com     }
116*1489St.nateldemoura@f5.com 
117*1489St.nateldemoura@f5.com     if (rootfs != NULL && strlen(path) > rootfs_len) {
118*1489St.nateldemoura@f5.com         nxt_java_modules = path + rootfs_len;
119*1489St.nateldemoura@f5.com     }
120*1489St.nateldemoura@f5.com 
121*1489St.nateldemoura@f5.com     nxt_debug(task, "JAVA MODULES: %s", nxt_java_modules);
122*1489St.nateldemoura@f5.com 
123977Smax.romanov@gmail.com     return NXT_OK;
124*1489St.nateldemoura@f5.com 
125*1489St.nateldemoura@f5.com free:
126*1489St.nateldemoura@f5.com 
127*1489St.nateldemoura@f5.com     nxt_free(path);
128*1489St.nateldemoura@f5.com 
129*1489St.nateldemoura@f5.com     return NXT_ERROR;
130977Smax.romanov@gmail.com }
131977Smax.romanov@gmail.com 
132977Smax.romanov@gmail.com 
133977Smax.romanov@gmail.com static char **
134977Smax.romanov@gmail.com nxt_java_module_jars(const char *jars[], int jar_count)
135977Smax.romanov@gmail.com {
136977Smax.romanov@gmail.com     char        **res, *jurl;
137*1489St.nateldemoura@f5.com     uint8_t     pathsep;
138977Smax.romanov@gmail.com     nxt_int_t   modules_len, jlen, i;
139977Smax.romanov@gmail.com     const char  **jar;
140977Smax.romanov@gmail.com 
141977Smax.romanov@gmail.com     res = nxt_malloc(jar_count * sizeof(char*));
142977Smax.romanov@gmail.com     if (res == NULL) {
143977Smax.romanov@gmail.com         return NULL;
144977Smax.romanov@gmail.com     }
145977Smax.romanov@gmail.com 
146977Smax.romanov@gmail.com     modules_len = nxt_strlen(nxt_java_modules);
147977Smax.romanov@gmail.com 
148*1489St.nateldemoura@f5.com     pathsep = nxt_java_modules[modules_len - 1] == '/';
149*1489St.nateldemoura@f5.com 
150977Smax.romanov@gmail.com     for (i = 0, jar = jars; *jar != NULL; jar++) {
151*1489St.nateldemoura@f5.com         jlen = nxt_length("file:") + modules_len
152*1489St.nateldemoura@f5.com                + (!pathsep ? nxt_length("/") : 0)
153*1489St.nateldemoura@f5.com                + nxt_strlen(*jar) + 1;
154*1489St.nateldemoura@f5.com 
155977Smax.romanov@gmail.com         jurl = nxt_malloc(jlen);
156977Smax.romanov@gmail.com         if (jurl == NULL) {
157977Smax.romanov@gmail.com             return NULL;
158977Smax.romanov@gmail.com         }
159977Smax.romanov@gmail.com 
160977Smax.romanov@gmail.com         res[i++] = jurl;
161977Smax.romanov@gmail.com 
162977Smax.romanov@gmail.com         jurl = nxt_cpymem(jurl, "file:", nxt_length("file:"));
163977Smax.romanov@gmail.com         jurl = nxt_cpymem(jurl, nxt_java_modules, modules_len);
164*1489St.nateldemoura@f5.com 
165*1489St.nateldemoura@f5.com         if (!pathsep) {
166*1489St.nateldemoura@f5.com             *jurl++ = '/';
167*1489St.nateldemoura@f5.com         }
168*1489St.nateldemoura@f5.com 
169977Smax.romanov@gmail.com         jurl = nxt_cpymem(jurl, *jar, nxt_strlen(*jar));
170977Smax.romanov@gmail.com         *jurl++ = '\0';
171977Smax.romanov@gmail.com     }
172977Smax.romanov@gmail.com 
173977Smax.romanov@gmail.com     return res;
174977Smax.romanov@gmail.com }
175977Smax.romanov@gmail.com 
176977Smax.romanov@gmail.com 
177977Smax.romanov@gmail.com static nxt_int_t
1781488St.nateldemoura@f5.com nxt_java_start(nxt_task_t *task, nxt_process_data_t *data)
179977Smax.romanov@gmail.com {
1801488St.nateldemoura@f5.com     jint                   rc;
1811488St.nateldemoura@f5.com     char                   *opt, *real_path;
1821488St.nateldemoura@f5.com     char                   **classpath_arr, **unit_jars, **system_jars;
1831488St.nateldemoura@f5.com     JavaVM                 *jvm;
1841488St.nateldemoura@f5.com     JNIEnv                 *env;
1851488St.nateldemoura@f5.com     jobject                cl, classpath;
1861488St.nateldemoura@f5.com     nxt_str_t              str;
1871488St.nateldemoura@f5.com     nxt_int_t              opt_len, real_path_len;
1881488St.nateldemoura@f5.com     nxt_uint_t             i, unit_jars_count, classpath_count;
1891488St.nateldemoura@f5.com     nxt_uint_t             system_jars_count;
1901488St.nateldemoura@f5.com     JavaVMOption           *jvm_opt;
1911488St.nateldemoura@f5.com     JavaVMInitArgs         jvm_args;
1921488St.nateldemoura@f5.com     nxt_unit_ctx_t         *ctx;
1931488St.nateldemoura@f5.com     nxt_unit_init_t        java_init;
1941488St.nateldemoura@f5.com     nxt_java_data_t        java_data;
1951488St.nateldemoura@f5.com     nxt_conf_value_t       *value;
1961488St.nateldemoura@f5.com     nxt_java_app_conf_t    *c;
1971488St.nateldemoura@f5.com     nxt_common_app_conf_t  *app_conf;
198977Smax.romanov@gmail.com 
199977Smax.romanov@gmail.com     //setenv("ASAN_OPTIONS", "handle_segv=0", 1);
200977Smax.romanov@gmail.com 
201977Smax.romanov@gmail.com     jvm_args.version = JNI_VERSION_1_6;
202977Smax.romanov@gmail.com     jvm_args.nOptions = 0;
203977Smax.romanov@gmail.com     jvm_args.ignoreUnrecognized = 0;
204977Smax.romanov@gmail.com 
2051488St.nateldemoura@f5.com     app_conf = data->app;
2061488St.nateldemoura@f5.com     c = &app_conf->u.java;
207977Smax.romanov@gmail.com 
208977Smax.romanov@gmail.com     if (c->options != NULL) {
209977Smax.romanov@gmail.com         jvm_args.nOptions += nxt_conf_array_elements_count(c->options);
210977Smax.romanov@gmail.com     }
211977Smax.romanov@gmail.com 
212977Smax.romanov@gmail.com     jvm_opt = nxt_malloc(jvm_args.nOptions * sizeof(JavaVMOption));
213977Smax.romanov@gmail.com     if (jvm_opt == NULL) {
214977Smax.romanov@gmail.com         nxt_alert(task, "failed to allocate jvm_opt");
215977Smax.romanov@gmail.com         return NXT_ERROR;
216977Smax.romanov@gmail.com     }
217977Smax.romanov@gmail.com 
218977Smax.romanov@gmail.com     jvm_args.options = jvm_opt;
219977Smax.romanov@gmail.com 
220977Smax.romanov@gmail.com     unit_jars_count = nxt_nitems(nxt_java_unit_jars) - 1;
221977Smax.romanov@gmail.com 
222977Smax.romanov@gmail.com     unit_jars = nxt_java_module_jars(nxt_java_unit_jars, unit_jars_count);
223977Smax.romanov@gmail.com     if (unit_jars == NULL) {
224977Smax.romanov@gmail.com         nxt_alert(task, "failed to allocate buffer for unit_jars array");
225977Smax.romanov@gmail.com 
226977Smax.romanov@gmail.com         return NXT_ERROR;
227977Smax.romanov@gmail.com     }
228977Smax.romanov@gmail.com 
229977Smax.romanov@gmail.com     system_jars_count = nxt_nitems(nxt_java_system_jars) - 1;
230977Smax.romanov@gmail.com 
231977Smax.romanov@gmail.com     system_jars = nxt_java_module_jars(nxt_java_system_jars, system_jars_count);
232977Smax.romanov@gmail.com     if (system_jars == NULL) {
233977Smax.romanov@gmail.com         nxt_alert(task, "failed to allocate buffer for system_jars array");
234977Smax.romanov@gmail.com 
235977Smax.romanov@gmail.com         return NXT_ERROR;
236977Smax.romanov@gmail.com     }
237977Smax.romanov@gmail.com 
238977Smax.romanov@gmail.com     if (c->options != NULL) {
239977Smax.romanov@gmail.com 
240977Smax.romanov@gmail.com         for (i = 0; /* void */ ; i++) {
241977Smax.romanov@gmail.com             value = nxt_conf_get_array_element(c->options, i);
242977Smax.romanov@gmail.com             if (value == NULL) {
243977Smax.romanov@gmail.com                 break;
244977Smax.romanov@gmail.com             }
245977Smax.romanov@gmail.com 
246977Smax.romanov@gmail.com             nxt_conf_get_string(value, &str);
247977Smax.romanov@gmail.com 
248977Smax.romanov@gmail.com             opt = nxt_malloc(str.length + 1);
249977Smax.romanov@gmail.com             if (opt == NULL) {
250977Smax.romanov@gmail.com                 nxt_alert(task, "failed to allocate jvm_opt");
251977Smax.romanov@gmail.com                 return NXT_ERROR;
252977Smax.romanov@gmail.com             }
253977Smax.romanov@gmail.com 
254977Smax.romanov@gmail.com             memcpy(opt, str.start, str.length);
255977Smax.romanov@gmail.com             opt[str.length] = '\0';
256977Smax.romanov@gmail.com 
257977Smax.romanov@gmail.com             jvm_opt[i].optionString = opt;
258977Smax.romanov@gmail.com         }
259977Smax.romanov@gmail.com     }
260977Smax.romanov@gmail.com 
261977Smax.romanov@gmail.com     if (c->classpath != NULL) {
262977Smax.romanov@gmail.com         classpath_count = nxt_conf_array_elements_count(c->classpath);
263977Smax.romanov@gmail.com         classpath_arr = nxt_malloc(classpath_count * sizeof(char *));
264977Smax.romanov@gmail.com 
265977Smax.romanov@gmail.com         for (i = 0; /* void */ ; i++) {
266977Smax.romanov@gmail.com             value = nxt_conf_get_array_element(c->classpath, i);
267977Smax.romanov@gmail.com             if (value == NULL) {
268977Smax.romanov@gmail.com                 break;
269977Smax.romanov@gmail.com             }
270977Smax.romanov@gmail.com 
271977Smax.romanov@gmail.com             nxt_conf_get_string(value, &str);
272977Smax.romanov@gmail.com 
273977Smax.romanov@gmail.com             opt_len = str.length + 1;
274977Smax.romanov@gmail.com 
275977Smax.romanov@gmail.com             char *sc = memchr(str.start, ':', str.length);
276977Smax.romanov@gmail.com             if (sc == NULL && str.start[0] == '/') {
277977Smax.romanov@gmail.com                 opt_len += nxt_length("file:");
278977Smax.romanov@gmail.com             }
279977Smax.romanov@gmail.com 
280977Smax.romanov@gmail.com             opt = nxt_malloc(opt_len);
281977Smax.romanov@gmail.com             if (opt == NULL) {
282977Smax.romanov@gmail.com                 nxt_alert(task, "failed to allocate classpath");
283977Smax.romanov@gmail.com                 return NXT_ERROR;
284977Smax.romanov@gmail.com             }
285977Smax.romanov@gmail.com 
286977Smax.romanov@gmail.com             if (sc == NULL && str.start[0] != '/') {
287977Smax.romanov@gmail.com                 nxt_memcpy(opt, str.start, str.length);
288977Smax.romanov@gmail.com                 opt[str.length] = '\0';
289977Smax.romanov@gmail.com 
290977Smax.romanov@gmail.com                 real_path = realpath(opt, NULL);
291977Smax.romanov@gmail.com                 if (real_path == NULL) {
292977Smax.romanov@gmail.com                     nxt_alert(task, "realpath(%s) failed: %E", opt, nxt_errno);
293977Smax.romanov@gmail.com                     return NXT_ERROR;
294977Smax.romanov@gmail.com                 }
295977Smax.romanov@gmail.com 
296977Smax.romanov@gmail.com                 real_path_len = nxt_strlen(real_path);
297977Smax.romanov@gmail.com 
298977Smax.romanov@gmail.com                 free(opt);
299977Smax.romanov@gmail.com 
300977Smax.romanov@gmail.com                 opt_len = nxt_length("file:") + real_path_len + 1;
301977Smax.romanov@gmail.com 
302977Smax.romanov@gmail.com                 opt = nxt_malloc(opt_len);
303977Smax.romanov@gmail.com                 if (opt == NULL) {
304977Smax.romanov@gmail.com                     nxt_alert(task, "failed to allocate classpath");
305977Smax.romanov@gmail.com                     return NXT_ERROR;
306977Smax.romanov@gmail.com                 }
307977Smax.romanov@gmail.com 
308977Smax.romanov@gmail.com             } else {
309977Smax.romanov@gmail.com                 real_path = (char *) str.start;  /* I love this cast! */
310977Smax.romanov@gmail.com                 real_path_len = str.length;
311977Smax.romanov@gmail.com             }
312977Smax.romanov@gmail.com 
313977Smax.romanov@gmail.com             classpath_arr[i] = opt;
314977Smax.romanov@gmail.com 
315977Smax.romanov@gmail.com             if (sc == NULL) {
316977Smax.romanov@gmail.com                 opt = nxt_cpymem(opt, "file:", nxt_length("file:"));
317977Smax.romanov@gmail.com             }
318977Smax.romanov@gmail.com 
319977Smax.romanov@gmail.com             opt = nxt_cpymem(opt, real_path, real_path_len);
320977Smax.romanov@gmail.com             *opt = '\0';
321977Smax.romanov@gmail.com         }
322977Smax.romanov@gmail.com 
323977Smax.romanov@gmail.com     } else {
324977Smax.romanov@gmail.com         classpath_count = 0;
325977Smax.romanov@gmail.com         classpath_arr = NULL;
326977Smax.romanov@gmail.com     }
327977Smax.romanov@gmail.com 
328977Smax.romanov@gmail.com     rc = JNI_CreateJavaVM(&jvm, (void **) &env, &jvm_args);
329977Smax.romanov@gmail.com     if (rc != JNI_OK) {
330977Smax.romanov@gmail.com         nxt_alert(task, "failed to create Java VM: %d", (int) rc);
331977Smax.romanov@gmail.com         return NXT_ERROR;
332977Smax.romanov@gmail.com     }
333977Smax.romanov@gmail.com 
334977Smax.romanov@gmail.com     rc = nxt_java_initThread(env);
335977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
336977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initThread() failed");
337977Smax.romanov@gmail.com         goto env_failed;
338977Smax.romanov@gmail.com     }
339977Smax.romanov@gmail.com 
340977Smax.romanov@gmail.com     rc = nxt_java_initURLClassLoader(env);
341977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
342977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initURLClassLoader() failed");
343977Smax.romanov@gmail.com         goto env_failed;
344977Smax.romanov@gmail.com     }
345977Smax.romanov@gmail.com 
346977Smax.romanov@gmail.com     cl = nxt_java_newURLClassLoader(env, system_jars_count, system_jars);
347977Smax.romanov@gmail.com     if (cl == NULL) {
348977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_newURLClassLoader failed");
349977Smax.romanov@gmail.com         goto env_failed;
350977Smax.romanov@gmail.com     }
351977Smax.romanov@gmail.com 
352977Smax.romanov@gmail.com     nxt_java_setContextClassLoader(env, cl);
353977Smax.romanov@gmail.com 
354977Smax.romanov@gmail.com     cl = nxt_java_newURLClassLoader_parent(env, unit_jars_count, unit_jars, cl);
355977Smax.romanov@gmail.com     if (cl == NULL) {
356977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_newURLClassLoader_parent failed");
357977Smax.romanov@gmail.com         goto env_failed;
358977Smax.romanov@gmail.com     }
359977Smax.romanov@gmail.com 
360977Smax.romanov@gmail.com     nxt_java_setContextClassLoader(env, cl);
361977Smax.romanov@gmail.com 
362977Smax.romanov@gmail.com     rc = nxt_java_initContext(env, cl);
363977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
364977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initContext() failed");
365977Smax.romanov@gmail.com         goto env_failed;
366977Smax.romanov@gmail.com     }
367977Smax.romanov@gmail.com 
368977Smax.romanov@gmail.com     rc = nxt_java_initRequest(env, cl);
369977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
370977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initRequest() failed");
371977Smax.romanov@gmail.com         goto env_failed;
372977Smax.romanov@gmail.com     }
373977Smax.romanov@gmail.com 
374977Smax.romanov@gmail.com     rc = nxt_java_initResponse(env, cl);
375977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
376977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initResponse() failed");
377977Smax.romanov@gmail.com         goto env_failed;
378977Smax.romanov@gmail.com     }
379977Smax.romanov@gmail.com 
380977Smax.romanov@gmail.com     rc = nxt_java_initInputStream(env, cl);
381977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
382977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initInputStream() failed");
383977Smax.romanov@gmail.com         goto env_failed;
384977Smax.romanov@gmail.com     }
385977Smax.romanov@gmail.com 
386977Smax.romanov@gmail.com     rc = nxt_java_initOutputStream(env, cl);
387977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
388977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initOutputStream() failed");
389977Smax.romanov@gmail.com         goto env_failed;
390977Smax.romanov@gmail.com     }
391977Smax.romanov@gmail.com 
392977Smax.romanov@gmail.com     nxt_java_jni_init(env);
393977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
394977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_jni_init() failed");
395977Smax.romanov@gmail.com         goto env_failed;
396977Smax.romanov@gmail.com     }
397977Smax.romanov@gmail.com 
398977Smax.romanov@gmail.com     classpath = nxt_java_newURLs(env, classpath_count, classpath_arr);
399977Smax.romanov@gmail.com     if (classpath == NULL) {
400977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_newURLs failed");
401977Smax.romanov@gmail.com         goto env_failed;
402977Smax.romanov@gmail.com     }
403977Smax.romanov@gmail.com 
4041488St.nateldemoura@f5.com     java_data.env = env;
4051488St.nateldemoura@f5.com     java_data.ctx = nxt_java_startContext(env, c->webapp, classpath);
406977Smax.romanov@gmail.com 
407977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
408977Smax.romanov@gmail.com         nxt_alert(task, "Unhandled exception in application start");
409977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
410977Smax.romanov@gmail.com         return NXT_ERROR;
411977Smax.romanov@gmail.com     }
412977Smax.romanov@gmail.com 
413977Smax.romanov@gmail.com     nxt_unit_default_init(task, &java_init);
414977Smax.romanov@gmail.com 
415977Smax.romanov@gmail.com     java_init.callbacks.request_handler = nxt_java_request_handler;
4161157Smax.romanov@nginx.com     java_init.callbacks.websocket_handler = nxt_java_websocket_handler;
4171157Smax.romanov@nginx.com     java_init.callbacks.close_handler = nxt_java_close_handler;
418977Smax.romanov@gmail.com     java_init.request_data_size = sizeof(nxt_java_request_data_t);
4191488St.nateldemoura@f5.com     java_init.data = &java_data;
4201488St.nateldemoura@f5.com     java_init.shm_limit = app_conf->shm_limit;
421977Smax.romanov@gmail.com 
422977Smax.romanov@gmail.com     ctx = nxt_unit_init(&java_init);
423977Smax.romanov@gmail.com     if (nxt_slow_path(ctx == NULL)) {
424977Smax.romanov@gmail.com         nxt_alert(task, "nxt_unit_init() failed");
425977Smax.romanov@gmail.com         return NXT_ERROR;
426977Smax.romanov@gmail.com     }
427977Smax.romanov@gmail.com 
428977Smax.romanov@gmail.com     rc = nxt_unit_run(ctx);
429977Smax.romanov@gmail.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
430977Smax.romanov@gmail.com         /* TODO report error */
431977Smax.romanov@gmail.com     }
432977Smax.romanov@gmail.com 
4331488St.nateldemoura@f5.com     nxt_java_stopContext(env, java_data.ctx);
434977Smax.romanov@gmail.com 
435977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
436977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
437977Smax.romanov@gmail.com     }
438977Smax.romanov@gmail.com 
4391157Smax.romanov@nginx.com     nxt_unit_done(ctx);
4401157Smax.romanov@nginx.com 
441977Smax.romanov@gmail.com     (*jvm)->DestroyJavaVM(jvm);
442977Smax.romanov@gmail.com 
443977Smax.romanov@gmail.com     exit(0);
444977Smax.romanov@gmail.com 
445977Smax.romanov@gmail.com     return NXT_OK;
446977Smax.romanov@gmail.com 
447977Smax.romanov@gmail.com env_failed:
448977Smax.romanov@gmail.com 
449977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
450977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
451977Smax.romanov@gmail.com     }
452977Smax.romanov@gmail.com 
453977Smax.romanov@gmail.com     return NXT_ERROR;
454977Smax.romanov@gmail.com }
455977Smax.romanov@gmail.com 
456977Smax.romanov@gmail.com 
457977Smax.romanov@gmail.com static void
458977Smax.romanov@gmail.com nxt_java_request_handler(nxt_unit_request_info_t *req)
459977Smax.romanov@gmail.com {
460977Smax.romanov@gmail.com     JNIEnv                   *env;
461977Smax.romanov@gmail.com     jobject                  jreq, jresp;
462977Smax.romanov@gmail.com     nxt_java_data_t          *java_data;
463977Smax.romanov@gmail.com     nxt_java_request_data_t  *data;
464977Smax.romanov@gmail.com 
465977Smax.romanov@gmail.com     java_data = req->unit->data;
466977Smax.romanov@gmail.com     env = java_data->env;
467977Smax.romanov@gmail.com     data = req->data;
468977Smax.romanov@gmail.com 
469977Smax.romanov@gmail.com     jreq = nxt_java_newRequest(env, java_data->ctx, req);
470977Smax.romanov@gmail.com     if (jreq == NULL) {
471977Smax.romanov@gmail.com         nxt_unit_req_alert(req, "failed to create Request instance");
472977Smax.romanov@gmail.com 
473977Smax.romanov@gmail.com         if ((*env)->ExceptionCheck(env)) {
474977Smax.romanov@gmail.com             (*env)->ExceptionDescribe(env);
475977Smax.romanov@gmail.com             (*env)->ExceptionClear(env);
476977Smax.romanov@gmail.com         }
477977Smax.romanov@gmail.com 
478977Smax.romanov@gmail.com         nxt_unit_request_done(req, NXT_UNIT_ERROR);
479977Smax.romanov@gmail.com         return;
480977Smax.romanov@gmail.com     }
481977Smax.romanov@gmail.com 
482977Smax.romanov@gmail.com     jresp = nxt_java_newResponse(env, req);
483977Smax.romanov@gmail.com     if (jresp == NULL) {
484977Smax.romanov@gmail.com         nxt_unit_req_alert(req, "failed to create Response instance");
485977Smax.romanov@gmail.com 
486977Smax.romanov@gmail.com         if ((*env)->ExceptionCheck(env)) {
487977Smax.romanov@gmail.com             (*env)->ExceptionDescribe(env);
488977Smax.romanov@gmail.com             (*env)->ExceptionClear(env);
489977Smax.romanov@gmail.com         }
490977Smax.romanov@gmail.com 
491977Smax.romanov@gmail.com         (*env)->DeleteLocalRef(env, jreq);
492977Smax.romanov@gmail.com 
493977Smax.romanov@gmail.com         nxt_unit_request_done(req, NXT_UNIT_ERROR);
494977Smax.romanov@gmail.com         return;
495977Smax.romanov@gmail.com     }
496977Smax.romanov@gmail.com 
497977Smax.romanov@gmail.com     data->header_size = 10 * 1024;
498977Smax.romanov@gmail.com     data->buf_size = 32 * 1024; /* from Jetty */
499977Smax.romanov@gmail.com     data->jreq = jreq;
500977Smax.romanov@gmail.com     data->jresp = jresp;
501977Smax.romanov@gmail.com     data->buf = NULL;
502977Smax.romanov@gmail.com 
503977Smax.romanov@gmail.com     nxt_unit_request_group_dup_fields(req);
504977Smax.romanov@gmail.com 
505977Smax.romanov@gmail.com     nxt_java_service(env, java_data->ctx, jreq, jresp);
506977Smax.romanov@gmail.com 
507977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
508977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
509977Smax.romanov@gmail.com         (*env)->ExceptionClear(env);
510977Smax.romanov@gmail.com     }
511977Smax.romanov@gmail.com 
512977Smax.romanov@gmail.com     if (!nxt_unit_response_is_init(req)) {
513977Smax.romanov@gmail.com         nxt_unit_response_init(req, 200, 0, 0);
514977Smax.romanov@gmail.com     }
515977Smax.romanov@gmail.com 
516977Smax.romanov@gmail.com     if (!nxt_unit_response_is_sent(req)) {
517977Smax.romanov@gmail.com         nxt_unit_response_send(req);
518977Smax.romanov@gmail.com     }
519977Smax.romanov@gmail.com 
520977Smax.romanov@gmail.com     if (data->buf != NULL) {
521977Smax.romanov@gmail.com         nxt_unit_buf_send(data->buf);
522977Smax.romanov@gmail.com 
523977Smax.romanov@gmail.com         data->buf = NULL;
524977Smax.romanov@gmail.com     }
525977Smax.romanov@gmail.com 
5261157Smax.romanov@nginx.com     if (nxt_unit_response_is_websocket(req)) {
5271157Smax.romanov@nginx.com         data->jreq = (*env)->NewGlobalRef(env, jreq);
5281157Smax.romanov@nginx.com         data->jresp = (*env)->NewGlobalRef(env, jresp);
5291157Smax.romanov@nginx.com 
5301157Smax.romanov@nginx.com     } else {
5311157Smax.romanov@nginx.com         nxt_unit_request_done(req, NXT_UNIT_OK);
5321157Smax.romanov@nginx.com     }
5331157Smax.romanov@nginx.com 
534977Smax.romanov@gmail.com     (*env)->DeleteLocalRef(env, jresp);
535977Smax.romanov@gmail.com     (*env)->DeleteLocalRef(env, jreq);
5361157Smax.romanov@nginx.com }
5371157Smax.romanov@nginx.com 
5381157Smax.romanov@nginx.com 
5391157Smax.romanov@nginx.com static void
5401157Smax.romanov@nginx.com nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws)
5411157Smax.romanov@nginx.com {
5421157Smax.romanov@nginx.com     void                     *b;
5431157Smax.romanov@nginx.com     JNIEnv                   *env;
5441157Smax.romanov@nginx.com     jobject                  jbuf;
5451157Smax.romanov@nginx.com     nxt_java_data_t          *java_data;
5461157Smax.romanov@nginx.com     nxt_java_request_data_t  *data;
5471157Smax.romanov@nginx.com 
5481157Smax.romanov@nginx.com     java_data = ws->req->unit->data;
5491157Smax.romanov@nginx.com     env = java_data->env;
5501157Smax.romanov@nginx.com     data = ws->req->data;
5511157Smax.romanov@nginx.com 
5521157Smax.romanov@nginx.com     b = malloc(ws->payload_len);
5531157Smax.romanov@nginx.com     if (b != NULL) {
5541157Smax.romanov@nginx.com         nxt_unit_websocket_read(ws, b, ws->payload_len);
5551157Smax.romanov@nginx.com 
5561157Smax.romanov@nginx.com         jbuf = (*env)->NewDirectByteBuffer(env, b, ws->payload_len);
5571157Smax.romanov@nginx.com         if (jbuf != NULL) {
5581157Smax.romanov@nginx.com             nxt_java_Request_websocket(env, data->jreq, jbuf,
5591157Smax.romanov@nginx.com                                        ws->header->opcode, ws->header->fin);
5601157Smax.romanov@nginx.com 
5611157Smax.romanov@nginx.com             if ((*env)->ExceptionCheck(env)) {
5621157Smax.romanov@nginx.com                 (*env)->ExceptionDescribe(env);
5631157Smax.romanov@nginx.com                 (*env)->ExceptionClear(env);
5641157Smax.romanov@nginx.com             }
5651157Smax.romanov@nginx.com 
5661157Smax.romanov@nginx.com             (*env)->DeleteLocalRef(env, jbuf);
5671157Smax.romanov@nginx.com         }
5681157Smax.romanov@nginx.com 
5691157Smax.romanov@nginx.com         free(b);
5701157Smax.romanov@nginx.com     }
5711157Smax.romanov@nginx.com 
5721157Smax.romanov@nginx.com     nxt_unit_websocket_done(ws);
5731157Smax.romanov@nginx.com }
5741157Smax.romanov@nginx.com 
5751157Smax.romanov@nginx.com 
5761157Smax.romanov@nginx.com static void
5771157Smax.romanov@nginx.com nxt_java_close_handler(nxt_unit_request_info_t *req)
5781157Smax.romanov@nginx.com {
5791157Smax.romanov@nginx.com     JNIEnv                   *env;
5801157Smax.romanov@nginx.com     nxt_java_data_t          *java_data;
5811157Smax.romanov@nginx.com     nxt_java_request_data_t  *data;
5821157Smax.romanov@nginx.com 
5831157Smax.romanov@nginx.com     java_data = req->unit->data;
5841157Smax.romanov@nginx.com     env = java_data->env;
5851157Smax.romanov@nginx.com     data = req->data;
5861157Smax.romanov@nginx.com 
5871157Smax.romanov@nginx.com     nxt_java_Request_close(env, data->jreq);
5881157Smax.romanov@nginx.com 
5891157Smax.romanov@nginx.com     (*env)->DeleteGlobalRef(env, data->jresp);
5901157Smax.romanov@nginx.com     (*env)->DeleteGlobalRef(env, data->jreq);
591977Smax.romanov@gmail.com 
592977Smax.romanov@gmail.com     nxt_unit_request_done(req, NXT_UNIT_OK);
593977Smax.romanov@gmail.com }
594977Smax.romanov@gmail.com 
595