|
1 /* |
|
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
|
3 * |
|
4 * Copyright 2013 Olaf Wintermann. All rights reserved. |
|
5 * |
|
6 * Redistribution and use in source and binary forms, with or without |
|
7 * modification, are permitted provided that the following conditions are met: |
|
8 * |
|
9 * 1. Redistributions of source code must retain the above copyright |
|
10 * notice, this list of conditions and the following disclaimer. |
|
11 * |
|
12 * 2. Redistributions in binary form must reproduce the above copyright |
|
13 * notice, this list of conditions and the following disclaimer in the |
|
14 * documentation and/or other materials provided with the distribution. |
|
15 * |
|
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
26 * POSSIBILITY OF SUCH DAMAGE. |
|
27 */ |
|
28 |
|
29 #include <stdio.h> |
|
30 #include <stdlib.h> |
|
31 #include <dlfcn.h> |
|
32 |
|
33 #include <ucx/map.h> |
|
34 |
|
35 #include "jvm.h" |
|
36 #include "daemon/request.h" |
|
37 |
|
38 #ifdef __i386 |
|
39 #define LIBJVM "/usr/java/jre/lib/i386/server/libjvm.so" |
|
40 #else |
|
41 |
|
42 #endif |
|
43 |
|
44 static JNIEnv *env = NULL; |
|
45 static JavaVM *jvm = NULL; |
|
46 |
|
47 static jobject plugin_instance = NULL; |
|
48 static jmethodID load_jmodules_method = NULL; |
|
49 static jmethodID exec_method = NULL; |
|
50 |
|
51 int jvm_init(pblock *pb, Session *sn, Request *rq) { |
|
52 // load lib |
|
53 void *lib = dlopen(LIBJVM, RTLD_GLOBAL | RTLD_NOW); |
|
54 if(!lib) { |
|
55 log_ereport(LOG_FAILURE, "Cannot load libjvm.so"); |
|
56 return REQ_ABORTED; |
|
57 } |
|
58 |
|
59 // get symbol |
|
60 void *sym = dlsym(lib, "JNI_CreateJavaVM"); |
|
61 if(sym == NULL) { |
|
62 log_ereport( |
|
63 LOG_FAILURE, |
|
64 "Cannot get symbol JNI_CreateJavaVM from lib"); |
|
65 return REQ_ABORTED; |
|
66 } |
|
67 |
|
68 // create JVM |
|
69 JavaVMInitArgs vm_args; |
|
70 JavaVMOption options[2]; |
|
71 options[0].optionString = "-Djava.class.path=lib/wsrt.jar"; |
|
72 options[1].optionString = "-Djava.library.path=lib/"; |
|
73 vm_args.version = JNI_VERSION_1_6; |
|
74 vm_args.options = options; |
|
75 vm_args.nOptions = 2; |
|
76 vm_args.ignoreUnrecognized = JNI_TRUE; |
|
77 |
|
78 CreateJVMFunc create_jvm = (CreateJVMFunc)sym; |
|
79 if(create_jvm(&jvm, (void**)&env, &vm_args)) { |
|
80 dlclose(lib); |
|
81 log_ereport(LOG_FAILURE, "Cannot create JVM"); |
|
82 } |
|
83 |
|
84 // load classes and methods |
|
85 jclass cls = (*env)->FindClass(env, "webserver/ServerPlugin"); |
|
86 if(!cls) { |
|
87 log_ereport( |
|
88 LOG_FAILURE, |
|
89 "jvm-init: missing or broken wsrt.jar"); |
|
90 log_ereport( |
|
91 LOG_FAILURE, |
|
92 "jvm-init: missing class webserver.ServerPlugin"); |
|
93 return REQ_ABORTED; |
|
94 } |
|
95 |
|
96 jmethodID constr = (*env)->GetMethodID(env, cls, "<init>", "()V"); |
|
97 if(!constr) { |
|
98 log_ereport( |
|
99 LOG_FAILURE, |
|
100 "jvm-init: missing or broken wsrt.jar"); |
|
101 log_ereport( |
|
102 LOG_FAILURE, |
|
103 "jvm-init: missing constructor"); |
|
104 return REQ_ABORTED; |
|
105 } |
|
106 plugin_instance = (*env)->NewObject(env, cls, constr); |
|
107 if(!plugin_instance) { |
|
108 log_ereport( |
|
109 LOG_FAILURE, |
|
110 "jvm-init: cannot create ServerPlugin instance"); |
|
111 return REQ_ABORTED; |
|
112 } |
|
113 |
|
114 // methods |
|
115 load_jmodules_method = (*env)->GetMethodID( |
|
116 env, |
|
117 cls, |
|
118 "loadModule", |
|
119 "(Ljava/lang/String;Ljava/lang/String;)I"); |
|
120 if(!load_jmodules_method) { |
|
121 log_ereport(LOG_FAILURE, "jvm-init: missing or broken wsrt.jar"); |
|
122 log_ereport(LOG_FAILURE, "jvm-init: missing method (loadModule)"); |
|
123 return REQ_ABORTED; |
|
124 } |
|
125 |
|
126 exec_method = (*env)->GetMethodID( |
|
127 env, |
|
128 cls, |
|
129 "exec", |
|
130 "(I)I"); |
|
131 if(!exec_method) { |
|
132 log_ereport(LOG_FAILURE, "jvm-init: missing or broken wsrt.jar"); |
|
133 log_ereport(LOG_FAILURE, "jvm-init: missing method (exec)"); |
|
134 return REQ_ABORTED; |
|
135 } |
|
136 |
|
137 |
|
138 return REQ_PROCEED; |
|
139 } |
|
140 |
|
141 int load_jmodules(pblock *pb, Session *sn, Request *rq) { |
|
142 char *jar = pblock_findval("jar", pb); |
|
143 char *classes = pblock_findval("classes", pb); |
|
144 |
|
145 if(!jar || !classes) { |
|
146 log_ereport( |
|
147 LOG_MISCONFIG, |
|
148 "load-jmodule: missing parameters (jar, classes)"); |
|
149 return REQ_ABORTED; |
|
150 } |
|
151 |
|
152 // check jvm |
|
153 if(!plugin_instance) { |
|
154 log_ereport( |
|
155 LOG_FAILURE, |
|
156 "load-jmodules: java plugin not properly loaded"); |
|
157 return REQ_ABORTED; |
|
158 } |
|
159 if(!load_jmodules_method) { |
|
160 log_ereport( |
|
161 LOG_FAILURE, |
|
162 "load-jmodules: java plugin not properly loaded"); |
|
163 return REQ_ABORTED; |
|
164 } |
|
165 |
|
166 // load java module |
|
167 jstring jar_param = (*env)->NewStringUTF(env, jar); |
|
168 jstring classes_param = (*env)->NewStringUTF(env, classes); |
|
169 |
|
170 jint ret = (*env)->CallIntMethod( |
|
171 env, |
|
172 plugin_instance, |
|
173 load_jmodules_method, |
|
174 jar_param, |
|
175 classes_param); |
|
176 |
|
177 // free stuff |
|
178 (*env)->DeleteLocalRef(env, jar_param); |
|
179 (*env)->DeleteLocalRef(env, classes_param); |
|
180 |
|
181 return ret; |
|
182 } |
|
183 |
|
184 int jexec(pblock *pb, Session *sn, Request *rq) { |
|
185 return REQ_NOACTION; |
|
186 } |
|
187 |
|
188 int jvm_method_exec(FuncStruct *func, pblock *pb, Session *sn, Request *rq) { |
|
189 printf("jvm_method_exec: %d\n", func); |
|
190 NSAPIRequest *nrq = (NSAPIRequest*)rq; |
|
191 |
|
192 JNIEnv *e = NULL; |
|
193 int r = (*jvm)->AttachCurrentThread(jvm, (void**)&e, NULL); |
|
194 |
|
195 jint index = (jint)func->exec_data; |
|
196 printf("(C) exec: %d\n", index); |
|
197 |
|
198 jint ret = (*env)->CallIntMethod( |
|
199 env, |
|
200 plugin_instance, |
|
201 exec_method, |
|
202 index); |
|
203 |
|
204 return ret; |
|
205 } |
|
206 |