Mercurial > hg > orthanc-java
comparison Plugin/Plugin.cpp @ 7:b14ed1ea3a23
reorganization
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 19 Oct 2023 11:14:45 +0200 |
parents | c8f19e93ff99 |
children | 26c08ff926a3 |
comparison
equal
deleted
inserted
replaced
6:709e5347a390 | 7:b14ed1ea3a23 |
---|---|
20 * You should have received a copy of the GNU General Public License | 20 * You should have received a copy of the GNU General Public License |
21 * along with this program. If not, see <http://www.gnu.org/licenses/>. | 21 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 **/ | 22 **/ |
23 | 23 |
24 | 24 |
25 #include "JavaLocalObject.h" | |
26 #include "JavaGlobalReference.h" | |
27 #include "OrthancBytes.h" | |
28 #include "OrthancString.h" | |
29 #include "JavaBytes.h" | |
30 #include "JavaString.h" | |
25 #include "JavaEnvironment.h" | 31 #include "JavaEnvironment.h" |
26 #include "JavaVirtualMachine.h" | 32 #include "JavaVirtualMachine.h" |
27 | 33 |
28 #include <orthanc/OrthancCPlugin.h> | 34 #include <orthanc/OrthancCPlugin.h> |
29 | 35 |
44 OrthancPluginContext* context_ = NULL; | 50 OrthancPluginContext* context_ = NULL; |
45 | 51 |
46 static std::unique_ptr<JavaVirtualMachine> java_; | 52 static std::unique_ptr<JavaVirtualMachine> java_; |
47 | 53 |
48 | 54 |
49 | |
50 class JavaString : public NonCopyable | |
51 { | |
52 private: | |
53 JNIEnv* env_; | |
54 jstring javaStr_; | |
55 const char* cStr_; | |
56 jboolean isCopy_; | |
57 | |
58 public: | |
59 JavaString(JNIEnv* env, | |
60 jstring javaStr) : | |
61 env_(env), | |
62 javaStr_(javaStr) | |
63 { | |
64 if (env == NULL || | |
65 javaStr == NULL) | |
66 { | |
67 throw std::runtime_error("Null pointer"); | |
68 } | |
69 | |
70 cStr_ = env_->GetStringUTFChars(javaStr_, &isCopy_); | |
71 if (cStr_ == NULL) | |
72 { | |
73 throw std::runtime_error("Cannot read string"); | |
74 } | |
75 } | |
76 | |
77 ~JavaString() | |
78 { | |
79 /** | |
80 * "The ReleaseString-Chars call is necessary whether | |
81 * GetStringChars has set isCopy to JNI_TRUE or JNI_FALSE." | |
82 * https://stackoverflow.com/a/5863081 | |
83 **/ | |
84 env_->ReleaseStringUTFChars(javaStr_, cStr_); | |
85 } | |
86 | |
87 const char* GetValue() const | |
88 { | |
89 return cStr_; | |
90 } | |
91 }; | |
92 | |
93 | |
94 class JavaBytes : public NonCopyable | |
95 { | |
96 private: | |
97 JNIEnv* env_; | |
98 jbyteArray bytes_; | |
99 jbyte* data_; | |
100 jsize size_; | |
101 jboolean isCopy_; | |
102 | |
103 public: | |
104 JavaBytes(JNIEnv* env, | |
105 jbyteArray bytes) : | |
106 env_(env), | |
107 bytes_(bytes) | |
108 { | |
109 if (env == NULL || | |
110 bytes == NULL) | |
111 { | |
112 throw std::runtime_error("Null pointer"); | |
113 } | |
114 | |
115 size_ = env->GetArrayLength(bytes); | |
116 | |
117 if (size_ == 0) | |
118 { | |
119 data_ = NULL; | |
120 } | |
121 else | |
122 { | |
123 data_ = env->GetByteArrayElements(bytes_, &isCopy_); | |
124 if (data_ == NULL) | |
125 { | |
126 throw std::runtime_error("Cannot read array of bytes"); | |
127 } | |
128 } | |
129 } | |
130 | |
131 ~JavaBytes() | |
132 { | |
133 if (size_ > 0) | |
134 { | |
135 env_->ReleaseByteArrayElements(bytes_, data_, 0); | |
136 } | |
137 } | |
138 | |
139 const void* GetData() const | |
140 { | |
141 return data_; | |
142 } | |
143 | |
144 size_t GetSize() const | |
145 { | |
146 return size_; | |
147 } | |
148 }; | |
149 | |
150 | |
151 class OrthancString : public NonCopyable | |
152 { | |
153 private: | |
154 char* str_; | |
155 | |
156 public: | |
157 OrthancString(char* str) : | |
158 str_(str) | |
159 { | |
160 } | |
161 | |
162 ~OrthancString() | |
163 { | |
164 if (str_ != NULL) | |
165 { | |
166 OrthancPluginFreeString(context_, str_); | |
167 } | |
168 } | |
169 | |
170 const char* GetValue() const | |
171 { | |
172 return str_; | |
173 } | |
174 }; | |
175 | |
176 | |
177 class OrthancBytes : public NonCopyable | |
178 { | |
179 private: | |
180 OrthancPluginMemoryBuffer buffer_; | |
181 | |
182 public: | |
183 OrthancBytes() | |
184 { | |
185 buffer_.data = NULL; | |
186 buffer_.size = 0; | |
187 } | |
188 | |
189 ~OrthancBytes() | |
190 { | |
191 OrthancPluginFreeMemoryBuffer(context_, &buffer_); | |
192 } | |
193 | |
194 OrthancPluginMemoryBuffer* GetMemoryBuffer() | |
195 { | |
196 return &buffer_; | |
197 } | |
198 | |
199 const void* GetData() const | |
200 { | |
201 return buffer_.data; | |
202 } | |
203 | |
204 size_t GetSize() const | |
205 { | |
206 return buffer_.size; | |
207 } | |
208 }; | |
209 | |
210 | |
211 class JavaGlobalReference : public NonCopyable | |
212 { | |
213 private: | |
214 JavaVirtualMachine& jvm_; | |
215 jobject obj_; | |
216 | |
217 public: | |
218 JavaGlobalReference(JavaVirtualMachine& jvm, | |
219 jobject obj) : | |
220 jvm_(jvm), | |
221 obj_(NULL) | |
222 { | |
223 if (obj == NULL) | |
224 { | |
225 throw std::runtime_error("Null pointer"); | |
226 } | |
227 | |
228 JavaEnvironment env(jvm); | |
229 | |
230 obj_ = env.GetValue().NewGlobalRef(obj); | |
231 if (obj_ == NULL) | |
232 { | |
233 throw std::runtime_error("Cannot create global reference"); | |
234 } | |
235 } | |
236 | |
237 ~JavaGlobalReference() | |
238 { | |
239 assert(obj_ != NULL); | |
240 | |
241 try | |
242 { | |
243 JavaEnvironment env(jvm_); | |
244 env.GetValue().DeleteGlobalRef(obj_); | |
245 } | |
246 catch (std::runtime_error& e) | |
247 { | |
248 OrthancPluginLogError(context_, e.what()); | |
249 } | |
250 } | |
251 | |
252 jobject GetValue() | |
253 { | |
254 assert(obj_ != NULL); | |
255 return obj_; | |
256 } | |
257 }; | |
258 | |
259 | |
260 class LocalJavaObject : public NonCopyable | |
261 { | |
262 private: | |
263 JNIEnv* env_; | |
264 jobject obj_; | |
265 | |
266 public: | |
267 LocalJavaObject(JavaEnvironment& env, | |
268 jobject obj, | |
269 bool objCanBeNull = false) : | |
270 env_(&env.GetValue()), | |
271 obj_(obj) | |
272 { | |
273 if (!objCanBeNull && obj == NULL) | |
274 { | |
275 throw std::runtime_error("Null pointer"); | |
276 } | |
277 } | |
278 | |
279 ~LocalJavaObject() | |
280 { | |
281 env_->DeleteLocalRef(obj_); | |
282 } | |
283 | |
284 jobject GetValue() | |
285 { | |
286 return obj_; | |
287 } | |
288 | |
289 static LocalJavaObject* CreateArrayOfStrings(JavaEnvironment& env, | |
290 const std::vector<std::string>& items) | |
291 { | |
292 LocalJavaObject emptyString(env, env.GetValue().NewStringUTF("")); | |
293 | |
294 jobjectArray obj = env.GetValue().NewObjectArray( | |
295 items.size(), env.GetValue().FindClass("java/lang/String"), | |
296 emptyString.GetValue()); | |
297 | |
298 if (obj == NULL) | |
299 { | |
300 throw std::runtime_error("Cannot create an array of Java strings"); | |
301 } | |
302 else | |
303 { | |
304 std::unique_ptr<LocalJavaObject> result(new LocalJavaObject(env, obj)); | |
305 | |
306 for (size_t i = 0; i < items.size(); i++) | |
307 { | |
308 LocalJavaObject item(env, env.GetValue().NewStringUTF(items[i].c_str())); | |
309 env.GetValue().SetObjectArrayElement(obj, i, item.GetValue()); | |
310 } | |
311 | |
312 return result.release(); | |
313 } | |
314 } | |
315 | |
316 static LocalJavaObject* CreateDictionary(JavaEnvironment& env, | |
317 const std::map<std::string, std::string>& items) | |
318 { | |
319 // NB: In JNI, there are no generics. All the templated arguments | |
320 // are taken as instances of the "Object" base class. | |
321 | |
322 jclass cls = env.FindClass("java/util/HashMap"); | |
323 jmethodID constructor = env.GetMethodID(cls, "<init>", "()V"); | |
324 jmethodID setter = env.GetMethodID(cls, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); | |
325 jobject obj = env.GetValue().NewObject(cls, constructor); | |
326 | |
327 if (obj == NULL) | |
328 { | |
329 throw std::runtime_error("Cannot create a Java dictionary"); | |
330 } | |
331 else | |
332 { | |
333 std::unique_ptr<LocalJavaObject> result(new LocalJavaObject(env, obj)); | |
334 | |
335 for (std::map<std::string, std::string>::const_iterator it = items.begin(); it != items.end(); ++it) | |
336 { | |
337 LocalJavaObject key(env, env.GetValue().NewStringUTF(it->first.c_str())); | |
338 LocalJavaObject value(env, env.GetValue().NewStringUTF(it->second.c_str())); | |
339 LocalJavaObject previousValue(env, env.GetValue().CallObjectMethod(obj, setter, key.GetValue(), value.GetValue()), true); | |
340 env.CheckException(); | |
341 } | |
342 | |
343 return result.release(); | |
344 } | |
345 } | |
346 }; | |
347 | |
348 | |
349 | |
350 #include "NativeSDK.cpp" | 55 #include "NativeSDK.cpp" |
351 | 56 |
352 | 57 |
353 | 58 |
354 #define MAX_REST_CALLBACKS 10 | 59 #define MAX_REST_CALLBACKS 10 |
514 getParameters[request->getKeys[i]] = request->getValues[i]; | 219 getParameters[request->getKeys[i]] = request->getValues[i]; |
515 } | 220 } |
516 | 221 |
517 JavaEnvironment env(*java_); | 222 JavaEnvironment env(*java_); |
518 | 223 |
519 LocalJavaObject joutput(env, env.ConstructJavaWrapper("be/uclouvain/orthanc/RestOutput", output)); | 224 JavaLocalObject joutput(env, env.ConstructJavaWrapper("be/uclouvain/orthanc/RestOutput", output)); |
520 LocalJavaObject jmethod(env, env.ConstructEnumValue("be/uclouvain/orthanc/HttpMethod", request->method)); | 225 JavaLocalObject jmethod(env, env.ConstructEnumValue("be/uclouvain/orthanc/HttpMethod", request->method)); |
521 LocalJavaObject juri(env, env.GetValue().NewStringUTF(uri == NULL ? "" : uri)); | 226 JavaLocalObject juri(env, env.GetValue().NewStringUTF(uri == NULL ? "" : uri)); |
522 std::unique_ptr<LocalJavaObject> jgroups(LocalJavaObject::CreateArrayOfStrings(env, groups)); | 227 std::unique_ptr<JavaLocalObject> jgroups(JavaLocalObject::CreateArrayOfStrings(env, groups)); |
523 std::unique_ptr<LocalJavaObject> jheaders(LocalJavaObject::CreateDictionary(env, headers)); | 228 std::unique_ptr<JavaLocalObject> jheaders(JavaLocalObject::CreateDictionary(env, headers)); |
524 std::unique_ptr<LocalJavaObject> jgetParameters(LocalJavaObject::CreateDictionary(env, getParameters)); | 229 std::unique_ptr<JavaLocalObject> jgetParameters(JavaLocalObject::CreateDictionary(env, getParameters)); |
525 LocalJavaObject jbody(env, env.ConstructByteArray(request->bodySize, request->body)); | 230 JavaLocalObject jbody(env, env.ConstructByteArray(request->bodySize, request->body)); |
526 | 231 |
527 jmethodID call = env.GetMethodID( | 232 jmethodID call = env.GetMethodID( |
528 env.GetObjectClass(callback), "call", | 233 env.GetObjectClass(callback), "call", |
529 "(Lbe/uclouvain/orthanc/RestOutput;Lbe/uclouvain/orthanc/HttpMethod;Ljava/lang/String;" | 234 "(Lbe/uclouvain/orthanc/RestOutput;Lbe/uclouvain/orthanc/HttpMethod;Ljava/lang/String;" |
530 "[Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;[B)V"); | 235 "[Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;[B)V"); |
587 | 292 |
588 if (!callbacks.empty()) | 293 if (!callbacks.empty()) |
589 { | 294 { |
590 JavaEnvironment env(*java_); | 295 JavaEnvironment env(*java_); |
591 | 296 |
592 LocalJavaObject c(env, env.ConstructEnumValue("be/uclouvain/orthanc/ChangeType", changeType)); | 297 JavaLocalObject c(env, env.ConstructEnumValue("be/uclouvain/orthanc/ChangeType", changeType)); |
593 LocalJavaObject r(env, env.ConstructEnumValue("be/uclouvain/orthanc/ResourceType", resourceType)); | 298 JavaLocalObject r(env, env.ConstructEnumValue("be/uclouvain/orthanc/ResourceType", resourceType)); |
594 LocalJavaObject s(env, env.GetValue().NewStringUTF(resourceId == NULL ? "" : resourceId)); | 299 JavaLocalObject s(env, env.GetValue().NewStringUTF(resourceId == NULL ? "" : resourceId)); |
595 | 300 |
596 for (std::list<jobject>::const_iterator | 301 for (std::list<jobject>::const_iterator |
597 callback = callbacks.begin(); callback != callbacks.end(); ++callback) | 302 callback = callbacks.begin(); callback != callbacks.end(); ++callback) |
598 { | 303 { |
599 assert(*callback != NULL); | 304 assert(*callback != NULL); |