xref: /unit/src/nxt_java.c (revision 977)
1*977Smax.romanov@gmail.com 
2*977Smax.romanov@gmail.com /*
3*977Smax.romanov@gmail.com  * Copyright (C) NGINX, Inc.
4*977Smax.romanov@gmail.com  */
5*977Smax.romanov@gmail.com 
6*977Smax.romanov@gmail.com 
7*977Smax.romanov@gmail.com #include <jni.h>
8*977Smax.romanov@gmail.com 
9*977Smax.romanov@gmail.com #include <nxt_main.h>
10*977Smax.romanov@gmail.com #include <nxt_runtime.h>
11*977Smax.romanov@gmail.com #include <nxt_router.h>
12*977Smax.romanov@gmail.com #include <nxt_unit.h>
13*977Smax.romanov@gmail.com #include <nxt_unit_field.h>
14*977Smax.romanov@gmail.com #include <nxt_unit_request.h>
15*977Smax.romanov@gmail.com #include <nxt_unit_response.h>
16*977Smax.romanov@gmail.com 
17*977Smax.romanov@gmail.com #include <java/nxt_jni.h>
18*977Smax.romanov@gmail.com 
19*977Smax.romanov@gmail.com #include "java/nxt_jni_Thread.h"
20*977Smax.romanov@gmail.com #include "java/nxt_jni_Context.h"
21*977Smax.romanov@gmail.com #include "java/nxt_jni_Request.h"
22*977Smax.romanov@gmail.com #include "java/nxt_jni_Response.h"
23*977Smax.romanov@gmail.com #include "java/nxt_jni_InputStream.h"
24*977Smax.romanov@gmail.com #include "java/nxt_jni_OutputStream.h"
25*977Smax.romanov@gmail.com #include "java/nxt_jni_URLClassLoader.h"
26*977Smax.romanov@gmail.com 
27*977Smax.romanov@gmail.com #include "nxt_jars.h"
28*977Smax.romanov@gmail.com 
29*977Smax.romanov@gmail.com static nxt_int_t nxt_java_pre_init(nxt_task_t *task,
30*977Smax.romanov@gmail.com     nxt_common_app_conf_t *conf);
31*977Smax.romanov@gmail.com static nxt_int_t nxt_java_init(nxt_task_t *task, nxt_common_app_conf_t *conf);
32*977Smax.romanov@gmail.com static void nxt_java_request_handler(nxt_unit_request_info_t *req);
33*977Smax.romanov@gmail.com 
34*977Smax.romanov@gmail.com static uint32_t  compat[] = {
35*977Smax.romanov@gmail.com     NXT_VERNUM, NXT_DEBUG,
36*977Smax.romanov@gmail.com };
37*977Smax.romanov@gmail.com 
38*977Smax.romanov@gmail.com char  *nxt_java_modules;
39*977Smax.romanov@gmail.com 
40*977Smax.romanov@gmail.com 
41*977Smax.romanov@gmail.com #define NXT_STRING(x)   _NXT_STRING(x)
42*977Smax.romanov@gmail.com #define _NXT_STRING(x)  #x
43*977Smax.romanov@gmail.com 
44*977Smax.romanov@gmail.com NXT_EXPORT nxt_app_module_t  nxt_app_module = {
45*977Smax.romanov@gmail.com     sizeof(compat),
46*977Smax.romanov@gmail.com     compat,
47*977Smax.romanov@gmail.com     nxt_string("java"),
48*977Smax.romanov@gmail.com     NXT_STRING(NXT_JAVA_VERSION),
49*977Smax.romanov@gmail.com     nxt_java_pre_init,
50*977Smax.romanov@gmail.com     nxt_java_init,
51*977Smax.romanov@gmail.com };
52*977Smax.romanov@gmail.com 
53*977Smax.romanov@gmail.com typedef struct {
54*977Smax.romanov@gmail.com     JNIEnv   *env;
55*977Smax.romanov@gmail.com     jobject  ctx;
56*977Smax.romanov@gmail.com } nxt_java_data_t;
57*977Smax.romanov@gmail.com 
58*977Smax.romanov@gmail.com 
59*977Smax.romanov@gmail.com static nxt_int_t
60*977Smax.romanov@gmail.com nxt_java_pre_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
61*977Smax.romanov@gmail.com {
62*977Smax.romanov@gmail.com     const char  *unit_jars;
63*977Smax.romanov@gmail.com 
64*977Smax.romanov@gmail.com     unit_jars = conf->u.java.unit_jars;
65*977Smax.romanov@gmail.com     if (unit_jars == NULL) {
66*977Smax.romanov@gmail.com         unit_jars = NXT_JARS;
67*977Smax.romanov@gmail.com     }
68*977Smax.romanov@gmail.com 
69*977Smax.romanov@gmail.com     nxt_java_modules = realpath(unit_jars, NULL);
70*977Smax.romanov@gmail.com     if (nxt_java_modules == NULL) {
71*977Smax.romanov@gmail.com         nxt_alert(task, "realpath(%s) failed: %E", NXT_JARS, nxt_errno);
72*977Smax.romanov@gmail.com         return NXT_ERROR;
73*977Smax.romanov@gmail.com     }
74*977Smax.romanov@gmail.com 
75*977Smax.romanov@gmail.com     return NXT_OK;
76*977Smax.romanov@gmail.com }
77*977Smax.romanov@gmail.com 
78*977Smax.romanov@gmail.com 
79*977Smax.romanov@gmail.com static char **
80*977Smax.romanov@gmail.com nxt_java_module_jars(const char *jars[], int jar_count)
81*977Smax.romanov@gmail.com {
82*977Smax.romanov@gmail.com     char        **res, *jurl;
83*977Smax.romanov@gmail.com     nxt_int_t   modules_len, jlen, i;
84*977Smax.romanov@gmail.com     const char  **jar;
85*977Smax.romanov@gmail.com 
86*977Smax.romanov@gmail.com     res = nxt_malloc(jar_count * sizeof(char*));
87*977Smax.romanov@gmail.com     if (res == NULL) {
88*977Smax.romanov@gmail.com         return NULL;
89*977Smax.romanov@gmail.com     }
90*977Smax.romanov@gmail.com 
91*977Smax.romanov@gmail.com     modules_len = nxt_strlen(nxt_java_modules);
92*977Smax.romanov@gmail.com 
93*977Smax.romanov@gmail.com     for (i = 0, jar = jars; *jar != NULL; jar++) {
94*977Smax.romanov@gmail.com         jlen = nxt_length("file:") + modules_len + nxt_length("/")
95*977Smax.romanov@gmail.com               + nxt_strlen(*jar) + 1;
96*977Smax.romanov@gmail.com         jurl = nxt_malloc(jlen);
97*977Smax.romanov@gmail.com         if (jurl == NULL) {
98*977Smax.romanov@gmail.com             return NULL;
99*977Smax.romanov@gmail.com         }
100*977Smax.romanov@gmail.com 
101*977Smax.romanov@gmail.com         res[i++] = jurl;
102*977Smax.romanov@gmail.com 
103*977Smax.romanov@gmail.com         jurl = nxt_cpymem(jurl, "file:", nxt_length("file:"));
104*977Smax.romanov@gmail.com         jurl = nxt_cpymem(jurl, nxt_java_modules, modules_len);
105*977Smax.romanov@gmail.com         *jurl++ = '/';
106*977Smax.romanov@gmail.com         jurl = nxt_cpymem(jurl, *jar, nxt_strlen(*jar));
107*977Smax.romanov@gmail.com         *jurl++ = '\0';
108*977Smax.romanov@gmail.com     }
109*977Smax.romanov@gmail.com 
110*977Smax.romanov@gmail.com     return res;
111*977Smax.romanov@gmail.com }
112*977Smax.romanov@gmail.com 
113*977Smax.romanov@gmail.com 
114*977Smax.romanov@gmail.com static nxt_int_t
115*977Smax.romanov@gmail.com nxt_java_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
116*977Smax.romanov@gmail.com {
117*977Smax.romanov@gmail.com     jint                 rc;
118*977Smax.romanov@gmail.com     char                 *opt, *real_path;
119*977Smax.romanov@gmail.com     char                 **classpath_arr, **unit_jars, **system_jars;
120*977Smax.romanov@gmail.com     JavaVM               *jvm;
121*977Smax.romanov@gmail.com     JNIEnv               *env;
122*977Smax.romanov@gmail.com     jobject              cl, classpath;
123*977Smax.romanov@gmail.com     nxt_str_t            str;
124*977Smax.romanov@gmail.com     nxt_int_t            opt_len, real_path_len;
125*977Smax.romanov@gmail.com     nxt_uint_t           i, unit_jars_count, classpath_count, system_jars_count;
126*977Smax.romanov@gmail.com     JavaVMOption         *jvm_opt;
127*977Smax.romanov@gmail.com     JavaVMInitArgs       jvm_args;
128*977Smax.romanov@gmail.com     nxt_unit_ctx_t       *ctx;
129*977Smax.romanov@gmail.com     nxt_unit_init_t      java_init;
130*977Smax.romanov@gmail.com     nxt_java_data_t      data;
131*977Smax.romanov@gmail.com     nxt_conf_value_t     *value;
132*977Smax.romanov@gmail.com     nxt_java_app_conf_t  *c;
133*977Smax.romanov@gmail.com 
134*977Smax.romanov@gmail.com     //setenv("ASAN_OPTIONS", "handle_segv=0", 1);
135*977Smax.romanov@gmail.com 
136*977Smax.romanov@gmail.com     jvm_args.version = JNI_VERSION_1_6;
137*977Smax.romanov@gmail.com     jvm_args.nOptions = 0;
138*977Smax.romanov@gmail.com     jvm_args.ignoreUnrecognized = 0;
139*977Smax.romanov@gmail.com 
140*977Smax.romanov@gmail.com     c = &conf->u.java;
141*977Smax.romanov@gmail.com 
142*977Smax.romanov@gmail.com     if (c->options != NULL) {
143*977Smax.romanov@gmail.com         jvm_args.nOptions += nxt_conf_array_elements_count(c->options);
144*977Smax.romanov@gmail.com     }
145*977Smax.romanov@gmail.com 
146*977Smax.romanov@gmail.com     jvm_opt = nxt_malloc(jvm_args.nOptions * sizeof(JavaVMOption));
147*977Smax.romanov@gmail.com     if (jvm_opt == NULL) {
148*977Smax.romanov@gmail.com         nxt_alert(task, "failed to allocate jvm_opt");
149*977Smax.romanov@gmail.com         return NXT_ERROR;
150*977Smax.romanov@gmail.com     }
151*977Smax.romanov@gmail.com 
152*977Smax.romanov@gmail.com     jvm_args.options = jvm_opt;
153*977Smax.romanov@gmail.com 
154*977Smax.romanov@gmail.com     unit_jars_count = nxt_nitems(nxt_java_unit_jars) - 1;
155*977Smax.romanov@gmail.com 
156*977Smax.romanov@gmail.com     unit_jars = nxt_java_module_jars(nxt_java_unit_jars, unit_jars_count);
157*977Smax.romanov@gmail.com     if (unit_jars == NULL) {
158*977Smax.romanov@gmail.com         nxt_alert(task, "failed to allocate buffer for unit_jars array");
159*977Smax.romanov@gmail.com 
160*977Smax.romanov@gmail.com         return NXT_ERROR;
161*977Smax.romanov@gmail.com     }
162*977Smax.romanov@gmail.com 
163*977Smax.romanov@gmail.com     system_jars_count = nxt_nitems(nxt_java_system_jars) - 1;
164*977Smax.romanov@gmail.com 
165*977Smax.romanov@gmail.com     system_jars = nxt_java_module_jars(nxt_java_system_jars, system_jars_count);
166*977Smax.romanov@gmail.com     if (system_jars == NULL) {
167*977Smax.romanov@gmail.com         nxt_alert(task, "failed to allocate buffer for system_jars array");
168*977Smax.romanov@gmail.com 
169*977Smax.romanov@gmail.com         return NXT_ERROR;
170*977Smax.romanov@gmail.com     }
171*977Smax.romanov@gmail.com 
172*977Smax.romanov@gmail.com     if (c->options != NULL) {
173*977Smax.romanov@gmail.com 
174*977Smax.romanov@gmail.com         for (i = 0; /* void */ ; i++) {
175*977Smax.romanov@gmail.com             value = nxt_conf_get_array_element(c->options, i);
176*977Smax.romanov@gmail.com             if (value == NULL) {
177*977Smax.romanov@gmail.com                 break;
178*977Smax.romanov@gmail.com             }
179*977Smax.romanov@gmail.com 
180*977Smax.romanov@gmail.com             nxt_conf_get_string(value, &str);
181*977Smax.romanov@gmail.com 
182*977Smax.romanov@gmail.com             opt = nxt_malloc(str.length + 1);
183*977Smax.romanov@gmail.com             if (opt == NULL) {
184*977Smax.romanov@gmail.com                 nxt_alert(task, "failed to allocate jvm_opt");
185*977Smax.romanov@gmail.com                 return NXT_ERROR;
186*977Smax.romanov@gmail.com             }
187*977Smax.romanov@gmail.com 
188*977Smax.romanov@gmail.com             memcpy(opt, str.start, str.length);
189*977Smax.romanov@gmail.com             opt[str.length] = '\0';
190*977Smax.romanov@gmail.com 
191*977Smax.romanov@gmail.com             jvm_opt[i].optionString = opt;
192*977Smax.romanov@gmail.com         }
193*977Smax.romanov@gmail.com     }
194*977Smax.romanov@gmail.com 
195*977Smax.romanov@gmail.com     if (c->classpath != NULL) {
196*977Smax.romanov@gmail.com         classpath_count = nxt_conf_array_elements_count(c->classpath);
197*977Smax.romanov@gmail.com         classpath_arr = nxt_malloc(classpath_count * sizeof(char *));
198*977Smax.romanov@gmail.com 
199*977Smax.romanov@gmail.com         for (i = 0; /* void */ ; i++) {
200*977Smax.romanov@gmail.com             value = nxt_conf_get_array_element(c->classpath, i);
201*977Smax.romanov@gmail.com             if (value == NULL) {
202*977Smax.romanov@gmail.com                 break;
203*977Smax.romanov@gmail.com             }
204*977Smax.romanov@gmail.com 
205*977Smax.romanov@gmail.com             nxt_conf_get_string(value, &str);
206*977Smax.romanov@gmail.com 
207*977Smax.romanov@gmail.com             opt_len = str.length + 1;
208*977Smax.romanov@gmail.com 
209*977Smax.romanov@gmail.com             char *sc = memchr(str.start, ':', str.length);
210*977Smax.romanov@gmail.com             if (sc == NULL && str.start[0] == '/') {
211*977Smax.romanov@gmail.com                 opt_len += nxt_length("file:");
212*977Smax.romanov@gmail.com             }
213*977Smax.romanov@gmail.com 
214*977Smax.romanov@gmail.com             opt = nxt_malloc(opt_len);
215*977Smax.romanov@gmail.com             if (opt == NULL) {
216*977Smax.romanov@gmail.com                 nxt_alert(task, "failed to allocate classpath");
217*977Smax.romanov@gmail.com                 return NXT_ERROR;
218*977Smax.romanov@gmail.com             }
219*977Smax.romanov@gmail.com 
220*977Smax.romanov@gmail.com             if (sc == NULL && str.start[0] != '/') {
221*977Smax.romanov@gmail.com                 nxt_memcpy(opt, str.start, str.length);
222*977Smax.romanov@gmail.com                 opt[str.length] = '\0';
223*977Smax.romanov@gmail.com 
224*977Smax.romanov@gmail.com                 real_path = realpath(opt, NULL);
225*977Smax.romanov@gmail.com                 if (real_path == NULL) {
226*977Smax.romanov@gmail.com                     nxt_alert(task, "realpath(%s) failed: %E", opt, nxt_errno);
227*977Smax.romanov@gmail.com                     return NXT_ERROR;
228*977Smax.romanov@gmail.com                 }
229*977Smax.romanov@gmail.com 
230*977Smax.romanov@gmail.com                 real_path_len = nxt_strlen(real_path);
231*977Smax.romanov@gmail.com 
232*977Smax.romanov@gmail.com                 free(opt);
233*977Smax.romanov@gmail.com 
234*977Smax.romanov@gmail.com                 opt_len = nxt_length("file:") + real_path_len + 1;
235*977Smax.romanov@gmail.com 
236*977Smax.romanov@gmail.com                 opt = nxt_malloc(opt_len);
237*977Smax.romanov@gmail.com                 if (opt == NULL) {
238*977Smax.romanov@gmail.com                     nxt_alert(task, "failed to allocate classpath");
239*977Smax.romanov@gmail.com                     return NXT_ERROR;
240*977Smax.romanov@gmail.com                 }
241*977Smax.romanov@gmail.com 
242*977Smax.romanov@gmail.com             } else {
243*977Smax.romanov@gmail.com                 real_path = (char *) str.start;  /* I love this cast! */
244*977Smax.romanov@gmail.com                 real_path_len = str.length;
245*977Smax.romanov@gmail.com             }
246*977Smax.romanov@gmail.com 
247*977Smax.romanov@gmail.com             classpath_arr[i] = opt;
248*977Smax.romanov@gmail.com 
249*977Smax.romanov@gmail.com             if (sc == NULL) {
250*977Smax.romanov@gmail.com                 opt = nxt_cpymem(opt, "file:", nxt_length("file:"));
251*977Smax.romanov@gmail.com             }
252*977Smax.romanov@gmail.com 
253*977Smax.romanov@gmail.com             opt = nxt_cpymem(opt, real_path, real_path_len);
254*977Smax.romanov@gmail.com             *opt = '\0';
255*977Smax.romanov@gmail.com         }
256*977Smax.romanov@gmail.com 
257*977Smax.romanov@gmail.com     } else {
258*977Smax.romanov@gmail.com         classpath_count = 0;
259*977Smax.romanov@gmail.com         classpath_arr = NULL;
260*977Smax.romanov@gmail.com     }
261*977Smax.romanov@gmail.com 
262*977Smax.romanov@gmail.com     rc = JNI_CreateJavaVM(&jvm, (void **) &env, &jvm_args);
263*977Smax.romanov@gmail.com     if (rc != JNI_OK) {
264*977Smax.romanov@gmail.com         nxt_alert(task, "failed to create Java VM: %d", (int) rc);
265*977Smax.romanov@gmail.com         return NXT_ERROR;
266*977Smax.romanov@gmail.com     }
267*977Smax.romanov@gmail.com 
268*977Smax.romanov@gmail.com     rc = nxt_java_initThread(env);
269*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
270*977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initThread() failed");
271*977Smax.romanov@gmail.com         goto env_failed;
272*977Smax.romanov@gmail.com     }
273*977Smax.romanov@gmail.com 
274*977Smax.romanov@gmail.com     rc = nxt_java_initURLClassLoader(env);
275*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
276*977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initURLClassLoader() failed");
277*977Smax.romanov@gmail.com         goto env_failed;
278*977Smax.romanov@gmail.com     }
279*977Smax.romanov@gmail.com 
280*977Smax.romanov@gmail.com     cl = nxt_java_newURLClassLoader(env, system_jars_count, system_jars);
281*977Smax.romanov@gmail.com     if (cl == NULL) {
282*977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_newURLClassLoader failed");
283*977Smax.romanov@gmail.com         goto env_failed;
284*977Smax.romanov@gmail.com     }
285*977Smax.romanov@gmail.com 
286*977Smax.romanov@gmail.com     nxt_java_setContextClassLoader(env, cl);
287*977Smax.romanov@gmail.com 
288*977Smax.romanov@gmail.com     cl = nxt_java_newURLClassLoader_parent(env, unit_jars_count, unit_jars, cl);
289*977Smax.romanov@gmail.com     if (cl == NULL) {
290*977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_newURLClassLoader_parent failed");
291*977Smax.romanov@gmail.com         goto env_failed;
292*977Smax.romanov@gmail.com     }
293*977Smax.romanov@gmail.com 
294*977Smax.romanov@gmail.com     nxt_java_setContextClassLoader(env, cl);
295*977Smax.romanov@gmail.com 
296*977Smax.romanov@gmail.com     rc = nxt_java_initContext(env, cl);
297*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
298*977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initContext() failed");
299*977Smax.romanov@gmail.com         goto env_failed;
300*977Smax.romanov@gmail.com     }
301*977Smax.romanov@gmail.com 
302*977Smax.romanov@gmail.com     rc = nxt_java_initRequest(env, cl);
303*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
304*977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initRequest() failed");
305*977Smax.romanov@gmail.com         goto env_failed;
306*977Smax.romanov@gmail.com     }
307*977Smax.romanov@gmail.com 
308*977Smax.romanov@gmail.com     rc = nxt_java_initResponse(env, cl);
309*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
310*977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initResponse() failed");
311*977Smax.romanov@gmail.com         goto env_failed;
312*977Smax.romanov@gmail.com     }
313*977Smax.romanov@gmail.com 
314*977Smax.romanov@gmail.com     rc = nxt_java_initInputStream(env, cl);
315*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
316*977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initInputStream() failed");
317*977Smax.romanov@gmail.com         goto env_failed;
318*977Smax.romanov@gmail.com     }
319*977Smax.romanov@gmail.com 
320*977Smax.romanov@gmail.com     rc = nxt_java_initOutputStream(env, cl);
321*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
322*977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initOutputStream() failed");
323*977Smax.romanov@gmail.com         goto env_failed;
324*977Smax.romanov@gmail.com     }
325*977Smax.romanov@gmail.com 
326*977Smax.romanov@gmail.com     nxt_java_jni_init(env);
327*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
328*977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_jni_init() failed");
329*977Smax.romanov@gmail.com         goto env_failed;
330*977Smax.romanov@gmail.com     }
331*977Smax.romanov@gmail.com 
332*977Smax.romanov@gmail.com     classpath = nxt_java_newURLs(env, classpath_count, classpath_arr);
333*977Smax.romanov@gmail.com     if (classpath == NULL) {
334*977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_newURLs failed");
335*977Smax.romanov@gmail.com         goto env_failed;
336*977Smax.romanov@gmail.com     }
337*977Smax.romanov@gmail.com 
338*977Smax.romanov@gmail.com     data.env = env;
339*977Smax.romanov@gmail.com     data.ctx = nxt_java_startContext(env, c->webapp, classpath);
340*977Smax.romanov@gmail.com 
341*977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
342*977Smax.romanov@gmail.com         nxt_alert(task, "Unhandled exception in application start");
343*977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
344*977Smax.romanov@gmail.com         return NXT_ERROR;
345*977Smax.romanov@gmail.com     }
346*977Smax.romanov@gmail.com 
347*977Smax.romanov@gmail.com     nxt_unit_default_init(task, &java_init);
348*977Smax.romanov@gmail.com 
349*977Smax.romanov@gmail.com     java_init.callbacks.request_handler = nxt_java_request_handler;
350*977Smax.romanov@gmail.com     java_init.request_data_size = sizeof(nxt_java_request_data_t);
351*977Smax.romanov@gmail.com     java_init.data = &data;
352*977Smax.romanov@gmail.com 
353*977Smax.romanov@gmail.com     ctx = nxt_unit_init(&java_init);
354*977Smax.romanov@gmail.com     if (nxt_slow_path(ctx == NULL)) {
355*977Smax.romanov@gmail.com         nxt_alert(task, "nxt_unit_init() failed");
356*977Smax.romanov@gmail.com         return NXT_ERROR;
357*977Smax.romanov@gmail.com     }
358*977Smax.romanov@gmail.com 
359*977Smax.romanov@gmail.com     rc = nxt_unit_run(ctx);
360*977Smax.romanov@gmail.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
361*977Smax.romanov@gmail.com         /* TODO report error */
362*977Smax.romanov@gmail.com     }
363*977Smax.romanov@gmail.com 
364*977Smax.romanov@gmail.com     nxt_unit_done(ctx);
365*977Smax.romanov@gmail.com 
366*977Smax.romanov@gmail.com     nxt_java_stopContext(env, data.ctx);
367*977Smax.romanov@gmail.com 
368*977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
369*977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
370*977Smax.romanov@gmail.com     }
371*977Smax.romanov@gmail.com 
372*977Smax.romanov@gmail.com     (*jvm)->DestroyJavaVM(jvm);
373*977Smax.romanov@gmail.com 
374*977Smax.romanov@gmail.com     exit(0);
375*977Smax.romanov@gmail.com 
376*977Smax.romanov@gmail.com     return NXT_OK;
377*977Smax.romanov@gmail.com 
378*977Smax.romanov@gmail.com env_failed:
379*977Smax.romanov@gmail.com 
380*977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
381*977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
382*977Smax.romanov@gmail.com     }
383*977Smax.romanov@gmail.com 
384*977Smax.romanov@gmail.com     return NXT_ERROR;
385*977Smax.romanov@gmail.com }
386*977Smax.romanov@gmail.com 
387*977Smax.romanov@gmail.com 
388*977Smax.romanov@gmail.com static void
389*977Smax.romanov@gmail.com nxt_java_request_handler(nxt_unit_request_info_t *req)
390*977Smax.romanov@gmail.com {
391*977Smax.romanov@gmail.com     JNIEnv                   *env;
392*977Smax.romanov@gmail.com     jobject                  jreq, jresp;
393*977Smax.romanov@gmail.com     nxt_java_data_t          *java_data;
394*977Smax.romanov@gmail.com     nxt_java_request_data_t  *data;
395*977Smax.romanov@gmail.com 
396*977Smax.romanov@gmail.com     java_data = req->unit->data;
397*977Smax.romanov@gmail.com     env = java_data->env;
398*977Smax.romanov@gmail.com     data = req->data;
399*977Smax.romanov@gmail.com 
400*977Smax.romanov@gmail.com     jreq = nxt_java_newRequest(env, java_data->ctx, req);
401*977Smax.romanov@gmail.com     if (jreq == NULL) {
402*977Smax.romanov@gmail.com         nxt_unit_req_alert(req, "failed to create Request instance");
403*977Smax.romanov@gmail.com 
404*977Smax.romanov@gmail.com         if ((*env)->ExceptionCheck(env)) {
405*977Smax.romanov@gmail.com             (*env)->ExceptionDescribe(env);
406*977Smax.romanov@gmail.com             (*env)->ExceptionClear(env);
407*977Smax.romanov@gmail.com         }
408*977Smax.romanov@gmail.com 
409*977Smax.romanov@gmail.com         nxt_unit_request_done(req, NXT_UNIT_ERROR);
410*977Smax.romanov@gmail.com         return;
411*977Smax.romanov@gmail.com     }
412*977Smax.romanov@gmail.com 
413*977Smax.romanov@gmail.com     jresp = nxt_java_newResponse(env, req);
414*977Smax.romanov@gmail.com     if (jresp == NULL) {
415*977Smax.romanov@gmail.com         nxt_unit_req_alert(req, "failed to create Response instance");
416*977Smax.romanov@gmail.com 
417*977Smax.romanov@gmail.com         if ((*env)->ExceptionCheck(env)) {
418*977Smax.romanov@gmail.com             (*env)->ExceptionDescribe(env);
419*977Smax.romanov@gmail.com             (*env)->ExceptionClear(env);
420*977Smax.romanov@gmail.com         }
421*977Smax.romanov@gmail.com 
422*977Smax.romanov@gmail.com         (*env)->DeleteLocalRef(env, jreq);
423*977Smax.romanov@gmail.com 
424*977Smax.romanov@gmail.com         nxt_unit_request_done(req, NXT_UNIT_ERROR);
425*977Smax.romanov@gmail.com         return;
426*977Smax.romanov@gmail.com     }
427*977Smax.romanov@gmail.com 
428*977Smax.romanov@gmail.com     data->header_size = 10 * 1024;
429*977Smax.romanov@gmail.com     data->buf_size = 32 * 1024; /* from Jetty */
430*977Smax.romanov@gmail.com     data->jreq = jreq;
431*977Smax.romanov@gmail.com     data->jresp = jresp;
432*977Smax.romanov@gmail.com     data->buf = NULL;
433*977Smax.romanov@gmail.com 
434*977Smax.romanov@gmail.com     nxt_unit_request_group_dup_fields(req);
435*977Smax.romanov@gmail.com 
436*977Smax.romanov@gmail.com     nxt_java_service(env, java_data->ctx, jreq, jresp);
437*977Smax.romanov@gmail.com 
438*977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
439*977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
440*977Smax.romanov@gmail.com         (*env)->ExceptionClear(env);
441*977Smax.romanov@gmail.com     }
442*977Smax.romanov@gmail.com 
443*977Smax.romanov@gmail.com     if (!nxt_unit_response_is_init(req)) {
444*977Smax.romanov@gmail.com         nxt_unit_response_init(req, 200, 0, 0);
445*977Smax.romanov@gmail.com     }
446*977Smax.romanov@gmail.com 
447*977Smax.romanov@gmail.com     if (!nxt_unit_response_is_sent(req)) {
448*977Smax.romanov@gmail.com         nxt_unit_response_send(req);
449*977Smax.romanov@gmail.com     }
450*977Smax.romanov@gmail.com 
451*977Smax.romanov@gmail.com     if (data->buf != NULL) {
452*977Smax.romanov@gmail.com         nxt_unit_buf_send(data->buf);
453*977Smax.romanov@gmail.com 
454*977Smax.romanov@gmail.com         data->buf = NULL;
455*977Smax.romanov@gmail.com     }
456*977Smax.romanov@gmail.com 
457*977Smax.romanov@gmail.com     (*env)->DeleteLocalRef(env, jresp);
458*977Smax.romanov@gmail.com     (*env)->DeleteLocalRef(env, jreq);
459*977Smax.romanov@gmail.com 
460*977Smax.romanov@gmail.com     nxt_unit_request_done(req, NXT_UNIT_OK);
461*977Smax.romanov@gmail.com }
462*977Smax.romanov@gmail.com 
463