Mercurial > hg > orthanc-java
annotate Plugin/Plugin.cpp @ 34:bb51eb757154 OrthancJava-1.0
OrthancJava-1.0
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 14 Jun 2024 15:01:33 +0200 |
parents | 0bbb4e12b1f0 |
children |
rev | line source |
---|---|
0 | 1 /** |
20 | 2 * SPDX-FileCopyrightText: 2023-2024 Sebastien Jodogne, UCLouvain, Belgium |
0 | 3 * SPDX-License-Identifier: GPL-3.0-or-later |
4 */ | |
5 | |
6 /** | |
7 * Java plugin for Orthanc | |
20 | 8 * Copyright (C) 2023-2024 Sebastien Jodogne, UCLouvain, Belgium |
0 | 9 * |
10 * This program is free software: you can redistribute it and/or | |
11 * modify it under the terms of the GNU General Public License as | |
12 * published by the Free Software Foundation, either version 3 of the | |
13 * License, or (at your option) any later version. | |
14 * | |
15 * This program is distributed in the hope that it will be useful, but | |
16 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 * General Public License for more details. | |
19 * | |
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/>. | |
22 **/ | |
23 | |
24 | |
7 | 25 #include "JavaLocalObject.h" |
26 #include "JavaGlobalReference.h" | |
27 #include "OrthancBytes.h" | |
28 #include "OrthancString.h" | |
29 #include "JavaBytes.h" | |
30 #include "JavaString.h" | |
5 | 31 #include "JavaEnvironment.h" |
32 #include "JavaVirtualMachine.h" | |
33 | |
0 | 34 #include <orthanc/OrthancCPlugin.h> |
35 | |
36 #include <cassert> | |
37 #include <iostream> | |
38 #include <jni.h> | |
39 #include <list> | |
40 #include <map> | |
41 #include <memory> | |
42 #include <set> | |
43 #include <stdexcept> | |
44 #include <vector> | |
45 | |
46 #include <json/reader.h> | |
47 | |
48 #include "Mutex.h" | |
49 | |
22 | 50 #define ORTHANC_PLUGIN_NAME "java" |
51 | |
52 | |
5 | 53 OrthancPluginContext* context_ = NULL; |
0 | 54 |
55 static std::unique_ptr<JavaVirtualMachine> java_; | |
56 | |
57 | |
8
26c08ff926a3
added warning about auto-generated files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
7
diff
changeset
|
58 // This function is implemented in the "NativeSDK.cpp" auto-generated file |
26c08ff926a3
added warning about auto-generated files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
7
diff
changeset
|
59 extern void JNI_LoadNatives(std::vector<JNINativeMethod>& methods); |
0 | 60 |
61 | |
62 #define MAX_REST_CALLBACKS 10 | |
63 | |
64 class CallbacksConfiguration : public NonCopyable | |
65 { | |
66 private: | |
67 Mutex mutex_; | |
68 std::list<JavaGlobalReference*> onChangeCallbacks_; | |
69 std::vector<JavaGlobalReference*> onRestRequestCallbacks_; | |
70 | |
71 static void DestructCallbacks(std::list<JavaGlobalReference*>& lst) | |
72 { | |
73 for (std::list<JavaGlobalReference*>::iterator it = lst.begin(); it != lst.end(); ++it) | |
74 { | |
75 assert(*it != NULL); | |
76 delete *it; | |
77 } | |
78 } | |
79 | |
80 static void DestructCallbacks(std::vector<JavaGlobalReference*>& v) | |
81 { | |
82 for (size_t i = 0; i < v.size(); i++) | |
83 { | |
84 assert(v[i] != NULL); | |
85 delete v[i]; | |
86 } | |
87 } | |
88 | |
89 void CopyCallbacks(std::list<jobject>& target, | |
90 const std::list<JavaGlobalReference*>& lst) | |
91 { | |
92 Mutex::Locker locker(mutex_); | |
93 target.clear(); | |
94 | |
95 for (std::list<JavaGlobalReference*>::const_iterator it = lst.begin(); it != lst.end(); ++it) | |
96 { | |
97 assert(*it != NULL); | |
98 target.push_back((*it)->GetValue()); | |
99 } | |
100 } | |
101 | |
102 void AddCallback(std::list<JavaGlobalReference*>& lst, | |
103 JavaVirtualMachine& jvm, | |
104 jobject callback) | |
105 { | |
106 if (callback == NULL) | |
107 { | |
108 throw std::runtime_error("Null pointer"); | |
109 } | |
110 else | |
111 { | |
112 Mutex::Locker locker(mutex_); | |
113 lst.push_back(new JavaGlobalReference(jvm, callback)); | |
114 } | |
115 } | |
116 | |
117 public: | |
118 CallbacksConfiguration() | |
119 { | |
120 onRestRequestCallbacks_.reserve(MAX_REST_CALLBACKS); | |
121 } | |
122 | |
123 ~CallbacksConfiguration() | |
124 { | |
125 DestructCallbacks(onChangeCallbacks_); | |
126 DestructCallbacks(onRestRequestCallbacks_); | |
127 } | |
128 | |
129 void AddOnChangeCallback(JavaVirtualMachine& jvm, | |
130 jobject callback) | |
131 { | |
132 AddCallback(onChangeCallbacks_, jvm, callback); | |
133 } | |
134 | |
135 void GetOnChangeCallbacks(std::list<jobject>& target) | |
136 { | |
137 CopyCallbacks(target, onChangeCallbacks_); | |
138 } | |
139 | |
140 size_t AddOnRestRequestCallback(JavaVirtualMachine& jvm, | |
141 jobject callback) | |
142 { | |
143 if (callback == NULL) | |
144 { | |
145 throw std::runtime_error("Null pointer"); | |
146 } | |
147 else | |
148 { | |
149 Mutex::Locker locker(mutex_); | |
150 | |
151 if (onRestRequestCallbacks_.size() >= MAX_REST_CALLBACKS) | |
152 { | |
153 char buf[16]; | |
154 sprintf(buf, "%d", MAX_REST_CALLBACKS); | |
155 throw std::runtime_error("The Java plugin for Orthanc has been compiled for a maximum of " + | |
156 std::string(buf) + " REST callbacks"); | |
157 } | |
158 else | |
159 { | |
160 size_t result = onRestRequestCallbacks_.size(); | |
161 onRestRequestCallbacks_.push_back(new JavaGlobalReference(jvm, callback)); | |
162 return result; | |
163 } | |
164 } | |
165 } | |
166 | |
167 jobject GetOnRestCallback(size_t i) | |
168 { | |
169 Mutex::Locker locker(mutex_); | |
170 | |
171 if (i >= onRestRequestCallbacks_.size()) | |
172 { | |
173 throw std::runtime_error("Unknown REST callback"); | |
174 } | |
175 else | |
176 { | |
177 assert(onRestRequestCallbacks_[i] != NULL); | |
178 return onRestRequestCallbacks_[i]->GetValue(); | |
179 } | |
180 } | |
181 }; | |
182 | |
183 static std::unique_ptr<CallbacksConfiguration> callbacksConfiguration_; | |
184 | |
185 | |
186 | |
187 | |
188 template<size_t Index> | |
189 class RestCallbacksPool | |
190 { | |
191 private: | |
192 RestCallbacksPool<Index - 1> next_; | |
193 | |
194 static OrthancPluginErrorCode Callback(OrthancPluginRestOutput* output, | |
195 const char* uri, | |
196 const OrthancPluginHttpRequest* request) | |
197 { | |
198 try | |
199 { | |
200 jobject callback = callbacksConfiguration_->GetOnRestCallback(MAX_REST_CALLBACKS - Index); | |
201 if (callback == NULL) | |
202 { | |
203 throw std::runtime_error("Missing callback"); | |
204 } | |
205 | |
206 std::vector<std::string> groups; | |
207 groups.resize(request->groupsCount); | |
208 for (uint32_t i = 0; i < request->groupsCount; i++) | |
209 { | |
210 groups[i].assign(request->groups[i]); | |
211 } | |
212 | |
213 std::map<std::string, std::string> headers; | |
214 for (uint32_t i = 0; i < request->headersCount; i++) | |
215 { | |
216 headers[request->headersKeys[i]] = request->headersValues[i]; | |
217 } | |
218 | |
219 std::map<std::string, std::string> getParameters; | |
220 for (uint32_t i = 0; i < request->getCount; i++) | |
221 { | |
222 getParameters[request->getKeys[i]] = request->getValues[i]; | |
223 } | |
224 | |
225 JavaEnvironment env(*java_); | |
226 | |
7 | 227 JavaLocalObject joutput(env, env.ConstructJavaWrapper("be/uclouvain/orthanc/RestOutput", output)); |
228 JavaLocalObject jmethod(env, env.ConstructEnumValue("be/uclouvain/orthanc/HttpMethod", request->method)); | |
229 JavaLocalObject juri(env, env.GetValue().NewStringUTF(uri == NULL ? "" : uri)); | |
230 std::unique_ptr<JavaLocalObject> jgroups(JavaLocalObject::CreateArrayOfStrings(env, groups)); | |
231 std::unique_ptr<JavaLocalObject> jheaders(JavaLocalObject::CreateDictionary(env, headers)); | |
232 std::unique_ptr<JavaLocalObject> jgetParameters(JavaLocalObject::CreateDictionary(env, getParameters)); | |
233 JavaLocalObject jbody(env, env.ConstructByteArray(request->bodySize, request->body)); | |
0 | 234 |
235 jmethodID call = env.GetMethodID( | |
236 env.GetObjectClass(callback), "call", | |
237 "(Lbe/uclouvain/orthanc/RestOutput;Lbe/uclouvain/orthanc/HttpMethod;Ljava/lang/String;" | |
238 "[Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;[B)V"); | |
239 | |
240 env.GetValue().CallVoidMethod(callback, call, joutput.GetValue(), jmethod.GetValue(), juri.GetValue(), | |
241 jgroups->GetValue(), jheaders->GetValue(), jgetParameters->GetValue(), jbody.GetValue()); | |
242 env.CheckException(); | |
243 | |
244 return OrthancPluginErrorCode_Success; | |
245 } | |
246 catch (std::runtime_error& e) | |
247 { | |
248 OrthancPluginLogError(context_, e.what()); | |
249 return OrthancPluginErrorCode_Plugin; | |
250 } | |
251 catch (...) | |
252 { | |
253 OrthancPluginLogError(context_, "Caught native exception"); | |
254 return OrthancPluginErrorCode_Plugin; | |
255 } | |
256 } | |
257 | |
258 public: | |
259 OrthancPluginRestCallback GetCallback(size_t i) | |
260 { | |
261 if (i == 0) | |
262 { | |
263 return Callback; | |
264 } | |
265 else | |
266 { | |
267 return next_.GetCallback(i - 1); | |
268 } | |
269 } | |
270 }; | |
271 | |
272 template<> | |
273 class RestCallbacksPool<0> | |
274 { | |
275 public: | |
276 OrthancPluginRestCallback& GetCallback(size_t i) | |
277 { | |
278 throw std::runtime_error("Out of tuple"); | |
279 } | |
280 }; | |
281 | |
282 | |
283 static RestCallbacksPool<MAX_REST_CALLBACKS> restCallbacksPool_; | |
284 | |
285 | |
286 | |
287 OrthancPluginErrorCode OnChangeCallback(OrthancPluginChangeType changeType, | |
288 OrthancPluginResourceType resourceType, | |
289 const char* resourceId) | |
290 { | |
291 try | |
292 { | |
293 std::list<jobject> callbacks; | |
294 callbacksConfiguration_->GetOnChangeCallbacks(callbacks); | |
295 | |
296 if (!callbacks.empty()) | |
297 { | |
298 JavaEnvironment env(*java_); | |
299 | |
7 | 300 JavaLocalObject c(env, env.ConstructEnumValue("be/uclouvain/orthanc/ChangeType", changeType)); |
301 JavaLocalObject r(env, env.ConstructEnumValue("be/uclouvain/orthanc/ResourceType", resourceType)); | |
302 JavaLocalObject s(env, env.GetValue().NewStringUTF(resourceId == NULL ? "" : resourceId)); | |
0 | 303 |
304 for (std::list<jobject>::const_iterator | |
305 callback = callbacks.begin(); callback != callbacks.end(); ++callback) | |
306 { | |
307 assert(*callback != NULL); | |
308 | |
309 jmethodID call = env.GetMethodID( | |
310 env.GetObjectClass(*callback), "call", | |
311 "(Lbe/uclouvain/orthanc/ChangeType;Lbe/uclouvain/orthanc/ResourceType;Ljava/lang/String;)V"); | |
312 | |
313 env.GetValue().CallVoidMethod(*callback, call, c.GetValue(), r.GetValue(), s.GetValue()); | |
314 env.CheckException(); | |
315 } | |
316 } | |
317 | |
318 return OrthancPluginErrorCode_Success; | |
319 } | |
320 catch (std::runtime_error& e) | |
321 { | |
322 OrthancPluginLogError(context_, e.what()); | |
323 return OrthancPluginErrorCode_Plugin; | |
324 } | |
325 catch (...) | |
326 { | |
327 OrthancPluginLogError(context_, "Caught native exception"); | |
328 return OrthancPluginErrorCode_Plugin; | |
329 } | |
330 } | |
331 | |
332 | |
333 JNIEXPORT void RegisterOnChangeCallback(JNIEnv* env, jobject sdkObject, jobject callback) | |
334 { | |
335 try | |
336 { | |
337 callbacksConfiguration_->AddOnChangeCallback(*java_, callback); | |
338 } | |
339 catch (std::runtime_error& e) | |
340 { | |
5 | 341 JavaEnvironment::ThrowOrthancException(env, e.what()); |
0 | 342 } |
343 catch (...) | |
344 { | |
5 | 345 JavaEnvironment::ThrowOrthancException(env, OrthancPluginErrorCode_Plugin); |
0 | 346 } |
347 } | |
348 | |
349 | |
350 JNIEXPORT void RegisterOnRestRequestCallback(JNIEnv* env, jobject sdkObject, jstring regex, jobject callback) | |
351 { | |
352 try | |
353 { | |
354 JavaString cregex(env, regex); | |
355 size_t index = callbacksConfiguration_->AddOnRestRequestCallback(*java_, callback); | |
356 OrthancPluginRegisterRestCallbackNoLock(context_, cregex.GetValue(), restCallbacksPool_.GetCallback(index)); | |
357 } | |
358 catch (std::runtime_error& e) | |
359 { | |
5 | 360 JavaEnvironment::ThrowOrthancException(env, e.what()); |
0 | 361 } |
362 catch (...) | |
363 { | |
5 | 364 JavaEnvironment::ThrowOrthancException(env, OrthancPluginErrorCode_Plugin); |
0 | 365 } |
366 } | |
367 | |
368 | |
4
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
369 static void ParseJson(Json::Value& target, |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
370 const std::string& source) |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
371 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
372 Json::CharReaderBuilder builder; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
373 builder.settings_["collectComments"] = false; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
374 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
375 const std::unique_ptr<Json::CharReader> reader(builder.newCharReader()); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
376 assert(reader.get() != NULL); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
377 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
378 JSONCPP_STRING err; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
379 if (!reader->parse(source.c_str(), source.c_str() + source.size(), &target, &err)) |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
380 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
381 throw std::runtime_error("Cannot parse JSON: " + err); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
382 } |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
383 } |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
384 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
385 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
386 static bool HasOption(const Json::Value& json, |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
387 const std::string& key, |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
388 Json::ValueType type, |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
389 bool isMandatory) |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
390 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
391 if (!json.isMember(key)) |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
392 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
393 if (isMandatory) |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
394 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
395 throw std::runtime_error("Missing configuration option for the Java plugin: \"" + key + "\""); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
396 } |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
397 else |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
398 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
399 return false; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
400 } |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
401 } |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
402 else if (json[key].type() == type) |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
403 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
404 return true; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
405 } |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
406 else |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
407 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
408 throw std::runtime_error("The configuration option \"" + key + "\" for the Java plugin has not the proper type"); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
409 } |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
410 } |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
411 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
412 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
413 static std::string GetMandatoryString(const Json::Value& json, |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
414 const std::string& key) |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
415 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
416 HasOption(json, key, Json::stringValue, true); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
417 assert(json.isMember(key) && |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
418 json[key].type() == Json::stringValue); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
419 return json[key].asString(); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
420 } |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
421 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
422 |
22 | 423 static void SetPluginDescription(const std::string& description) |
424 { | |
425 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) | |
426 OrthancPluginSetDescription2(context_, ORTHANC_PLUGIN_NAME, description.c_str()); | |
427 #else | |
428 _OrthancPluginSetPluginProperty params; | |
429 params.plugin = ORTHANC_PLUGIN_NAME; | |
430 params.property = _OrthancPluginProperty_Description; | |
431 params.value = description.c_str(); | |
432 | |
433 context_->InvokeService(context_, _OrthancPluginService_SetPluginProperty, ¶ms); | |
434 #endif | |
435 } | |
436 | |
437 | |
0 | 438 extern "C" |
439 { | |
440 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context) | |
441 { | |
442 context_ = context; | |
443 | |
444 /* Check the version of the Orthanc core */ | |
445 if (OrthancPluginCheckVersion(context) == 0) | |
446 { | |
447 char info[1024]; | |
448 sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", | |
449 context->orthancVersion, | |
450 ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, | |
451 ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, | |
452 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); | |
453 OrthancPluginLogError(context, info); | |
454 return -1; | |
455 } | |
456 | |
22 | 457 SetPluginDescription("Java plugin for Orthanc"); |
4
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
458 |
0 | 459 try |
460 { | |
461 { | |
462 // Sanity check to ensure that the compiler has created different callback functions | |
463 std::set<intptr_t> c; | |
464 for (unsigned int i = 0; i < MAX_REST_CALLBACKS; i++) | |
465 { | |
466 c.insert(reinterpret_cast<intptr_t>(restCallbacksPool_.GetCallback(i))); | |
467 } | |
468 | |
469 if (c.size() != MAX_REST_CALLBACKS) | |
470 { | |
471 throw std::runtime_error("The Java plugin has not been properly compiled"); | |
472 } | |
473 } | |
474 | |
4
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
475 Json::Value globalConfiguration; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
476 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
477 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
478 OrthancString tmp(OrthancPluginGetConfiguration(context)); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
479 ParseJson(globalConfiguration, tmp.GetValue()); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
480 } |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
481 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
482 static const std::string KEY_JAVA = "Java"; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
483 static const std::string KEY_ENABLED = "Enabled"; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
484 static const std::string KEY_CLASSPATH = "Classpath"; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
485 static const std::string KEY_INITIALIZATION_CLASS = "InitializationClass"; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
486 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
487 if (!HasOption(globalConfiguration, KEY_JAVA, Json::objectValue, false)) |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
488 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
489 OrthancPluginLogInfo(context, "Java plugin is disabled"); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
490 return 0; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
491 } |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
492 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
493 Json::Value javaConfiguration = globalConfiguration[KEY_JAVA]; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
494 assert(javaConfiguration.isObject()); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
495 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
496 if (HasOption(javaConfiguration, KEY_ENABLED, Json::booleanValue, false) && |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
497 !javaConfiguration[KEY_ENABLED].asBool()) |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
498 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
499 OrthancPluginLogInfo(context, "Java plugin is disabled"); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
500 return 0; |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
501 } |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
502 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
503 java_.reset(new JavaVirtualMachine(GetMandatoryString(javaConfiguration, KEY_CLASSPATH))); |
0 | 504 |
505 callbacksConfiguration_.reset(new CallbacksConfiguration); | |
506 OrthancPluginRegisterOnChangeCallback(context_, OnChangeCallback); | |
507 | |
508 JavaEnvironment env(*java_); | |
509 | |
510 { | |
511 std::vector<JNINativeMethod> methods; | |
512 JNI_LoadNatives(methods); | |
513 env.RegisterNatives("be/uclouvain/orthanc/NativeSDK", methods); | |
514 } | |
515 | |
516 { | |
517 std::vector<JNINativeMethod> methods; | |
518 methods.push_back((JNINativeMethod) { | |
519 const_cast<char*>("register"), | |
520 const_cast<char*>("(Lbe/uclouvain/orthanc/Callbacks$OnChange;)V"), | |
521 (void*) RegisterOnChangeCallback }); | |
522 methods.push_back((JNINativeMethod) { | |
523 const_cast<char*>("register"), | |
524 const_cast<char*>("(Ljava/lang/String;Lbe/uclouvain/orthanc/Callbacks$OnRestRequest;)V"), | |
525 (void*) RegisterOnRestRequestCallback }); | |
526 env.RegisterNatives("be/uclouvain/orthanc/Callbacks", methods); | |
527 } | |
4
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
528 |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
529 if (HasOption(javaConfiguration, KEY_INITIALIZATION_CLASS, Json::stringValue, false)) |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
530 { |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
531 env.FindClass(javaConfiguration[KEY_INITIALIZATION_CLASS].asString()); |
9032ffb3a7d5
added configuration options
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
532 } |
0 | 533 } |
534 catch (std::runtime_error& e) | |
535 { | |
536 OrthancPluginLogError(context, e.what()); | |
537 return -1; | |
538 } | |
539 | |
540 return 0; | |
541 } | |
542 | |
543 | |
544 ORTHANC_PLUGINS_API void OrthancPluginFinalize() | |
545 { | |
546 if (java_.get() != NULL) | |
547 { | |
548 callbacksConfiguration_.reset(NULL); | |
549 | |
550 try | |
551 { | |
552 JavaEnvironment env(*java_); | |
553 env.RunGarbageCollector(); | |
554 } | |
555 catch (std::runtime_error& e) | |
556 { | |
557 OrthancPluginLogError(context_, e.what()); | |
558 } | |
559 | |
560 java_.reset(NULL); | |
561 } | |
562 } | |
563 | |
564 | |
565 ORTHANC_PLUGINS_API const char* OrthancPluginGetName() | |
566 { | |
22 | 567 return ORTHANC_PLUGIN_NAME; |
0 | 568 } |
569 | |
570 | |
571 ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() | |
572 { | |
573 return PLUGIN_VERSION; | |
574 } | |
575 } |