comparison OrthancServer/Sources/OrthancInitialization.cpp @ 4696:dd6274412ff4

new configuration option "ExternalDictionaries" to load external DICOM dictionaries
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 17 Jun 2021 15:47:21 +0200
parents 3badc205cb4c
children f0038043fb97 7053502fbf97
comparison
equal deleted inserted replaced
4695:651f069c7f77 4696:dd6274412ff4
51 #include "../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h" 51 #include "../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h"
52 #include "../../OrthancFramework/Sources/FileStorage/FilesystemStorage.h" 52 #include "../../OrthancFramework/Sources/FileStorage/FilesystemStorage.h"
53 #include "../../OrthancFramework/Sources/HttpClient.h" 53 #include "../../OrthancFramework/Sources/HttpClient.h"
54 #include "../../OrthancFramework/Sources/Logging.h" 54 #include "../../OrthancFramework/Sources/Logging.h"
55 #include "../../OrthancFramework/Sources/OrthancException.h" 55 #include "../../OrthancFramework/Sources/OrthancException.h"
56 #include "../../OrthancFramework/Sources/SerializationToolbox.h"
56 57
57 #include "Database/SQLiteDatabaseWrapper.h" 58 #include "Database/SQLiteDatabaseWrapper.h"
58 #include "OrthancConfiguration.h" 59 #include "OrthancConfiguration.h"
59 60
60 #include <OrthancServerResources.h> 61 #include <OrthancServerResources.h>
61 62
62 #include <dcmtk/dcmnet/diutil.h> // For DCM_dcmnetLogger 63 #include <dcmtk/dcmnet/diutil.h> // For DCM_dcmnetLogger
63 64
65
66 static const char* const STORAGE_DIRECTORY = "StorageDirectory";
67 static const char* const ORTHANC_STORAGE = "OrthancStorage";
64 68
65 69
66 namespace Orthanc 70 namespace Orthanc
67 { 71 {
68 static void RegisterUserMetadata(const Json::Value& config) 72 static void RegisterUserMetadata(const Json::Value& config)
69 { 73 {
70 if (config.isMember("UserMetadata")) 74 static const char* const USER_METADATA = "UserMetadata";
71 { 75
72 const Json::Value& parameter = config["UserMetadata"]; 76 if (config.isMember(USER_METADATA))
77 {
78 const Json::Value& parameter = config[USER_METADATA];
73 79
74 Json::Value::Members members = parameter.getMemberNames(); 80 Json::Value::Members members = parameter.getMemberNames();
75 for (size_t i = 0; i < members.size(); i++) 81 for (size_t i = 0; i < members.size(); i++)
76 { 82 {
77 const std::string& name = members[i]; 83 const std::string& name = members[i];
101 } 107 }
102 108
103 109
104 static void RegisterUserContentType(const Json::Value& config) 110 static void RegisterUserContentType(const Json::Value& config)
105 { 111 {
106 if (config.isMember("UserContentType")) 112 static const char* const USER_CONTENT_TYPE = "UserContentType";
107 { 113
108 const Json::Value& parameter = config["UserContentType"]; 114 if (config.isMember(USER_CONTENT_TYPE))
115 {
116 const Json::Value& parameter = config[USER_CONTENT_TYPE];
109 117
110 Json::Value::Members members = parameter.getMemberNames(); 118 Json::Value::Members members = parameter.getMemberNames();
111 for (size_t i = 0; i < members.size(); i++) 119 for (size_t i = 0; i < members.size(); i++)
112 { 120 {
113 const std::string& name = members[i]; 121 const std::string& name = members[i];
148 } 156 }
149 } 157 }
150 } 158 }
151 159
152 160
161 static void LoadExternalDictionaries(const Json::Value& configuration)
162 {
163 static const char* const EXTERNAL_DICTIONARIES = "ExternalDictionaries";
164
165 if (configuration.type() == Json::objectValue &&
166 configuration.isMember(EXTERNAL_DICTIONARIES))
167 {
168 std::vector<std::string> dictionaries;
169 SerializationToolbox::ReadArrayOfStrings(dictionaries, configuration, EXTERNAL_DICTIONARIES);
170 FromDcmtkBridge::LoadExternalDictionaries(dictionaries);
171 }
172 }
173
174
153 static void LoadCustomDictionary(const Json::Value& configuration) 175 static void LoadCustomDictionary(const Json::Value& configuration)
154 { 176 {
177 static const char* const DICTIONARY = "Dictionary";
178
155 if (configuration.type() != Json::objectValue || 179 if (configuration.type() != Json::objectValue ||
156 !configuration.isMember("Dictionary") || 180 !configuration.isMember(DICTIONARY) ||
157 configuration["Dictionary"].type() != Json::objectValue) 181 configuration[DICTIONARY].type() != Json::objectValue)
158 { 182 {
159 return; 183 return;
160 } 184 }
161 185
162 Json::Value::Members tags(configuration["Dictionary"].getMemberNames()); 186 Json::Value::Members tags(configuration[DICTIONARY].getMemberNames());
163 187
164 for (Json::Value::ArrayIndex i = 0; i < tags.size(); i++) 188 for (Json::Value::ArrayIndex i = 0; i < tags.size(); i++)
165 { 189 {
166 const Json::Value& content = configuration["Dictionary"][tags[i]]; 190 const Json::Value& content = configuration[DICTIONARY][tags[i]];
167 if (content.type() != Json::arrayValue || 191 if (content.type() != Json::arrayValue ||
168 content.size() < 2 || 192 content.size() < 2 ||
169 content.size() > 5 || 193 content.size() > 5 ||
170 content[0].type() != Json::stringValue || 194 content[0].type() != Json::stringValue ||
171 content[1].type() != Json::stringValue || 195 content[1].type() != Json::stringValue ||
188 } 212 }
189 213
190 214
191 static void ConfigurePkcs11(const Json::Value& config) 215 static void ConfigurePkcs11(const Json::Value& config)
192 { 216 {
217 static const char* const MODULE = "Module";
218 static const char* const VERBOSE = "Verbose";
219 static const char* const PIN = "Pin";
220
193 if (config.type() != Json::objectValue || 221 if (config.type() != Json::objectValue ||
194 !config.isMember("Module") || 222 !config.isMember(MODULE) ||
195 config["Module"].type() != Json::stringValue) 223 config[MODULE].type() != Json::stringValue)
196 { 224 {
197 throw OrthancException(ErrorCode_BadFileFormat, 225 throw OrthancException(ErrorCode_BadFileFormat,
198 "No path to the PKCS#11 module (DLL or .so) is provided " 226 "No path to the PKCS#11 module (DLL or .so) is provided "
199 "for HTTPS client authentication"); 227 "for HTTPS client authentication");
200 } 228 }
201 229
202 std::string pin; 230 std::string pin;
203 if (config.isMember("Pin")) 231 if (config.isMember(PIN))
204 { 232 {
205 if (config["Pin"].type() == Json::stringValue) 233 if (config[PIN].type() == Json::stringValue)
206 { 234 {
207 pin = config["Pin"].asString(); 235 pin = config[PIN].asString();
208 } 236 }
209 else 237 else
210 { 238 {
211 throw OrthancException(ErrorCode_BadFileFormat, 239 throw OrthancException(ErrorCode_BadFileFormat,
212 "The PIN number in the PKCS#11 configuration must be a string"); 240 "The PIN number in the PKCS#11 configuration must be a string");
213 } 241 }
214 } 242 }
215 243
216 bool verbose = false; 244 bool verbose = false;
217 if (config.isMember("Verbose")) 245 if (config.isMember(VERBOSE))
218 { 246 {
219 if (config["Verbose"].type() == Json::booleanValue) 247 if (config[VERBOSE].type() == Json::booleanValue)
220 { 248 {
221 verbose = config["Verbose"].asBool(); 249 verbose = config[VERBOSE].asBool();
222 } 250 }
223 else 251 else
224 { 252 {
225 throw OrthancException(ErrorCode_BadFileFormat, 253 throw OrthancException(ErrorCode_BadFileFormat,
226 "The Verbose option in the PKCS#11 configuration must be a Boolean"); 254 "The Verbose option in the PKCS#11 configuration must be a Boolean");
227 } 255 }
228 } 256 }
229 257
230 HttpClient::InitializePkcs11(config["Module"].asString(), pin, verbose); 258 HttpClient::InitializePkcs11(config[MODULE].asString(), pin, verbose);
231 } 259 }
232 260
233 261
234 262
235 void OrthancInitialize(const char* configurationFile) 263 void OrthancInitialize(const char* configurationFile)
236 { 264 {
237 static const char* LOCALE = "Locale"; 265 static const char* const LOCALE = "Locale";
238 static const char* PKCS11 = "Pkcs11"; 266 static const char* const PKCS11 = "Pkcs11";
239 static const char* DEFAULT_ENCODING = "DefaultEncoding"; 267 static const char* const DEFAULT_ENCODING = "DefaultEncoding";
240 static const char* MALLOC_ARENA_MAX = "MallocArenaMax"; 268 static const char* const MALLOC_ARENA_MAX = "MallocArenaMax";
269 static const char* const LOAD_PRIVATE_DICTIONARY = "LoadPrivateDictionary";
241 270
242 OrthancConfiguration::WriterLock lock; 271 OrthancConfiguration::WriterLock lock;
243 272
244 InitializeServerEnumerations(); 273 InitializeServerEnumerations();
245 274
252 if (lock.GetJson().isMember(LOCALE)) 281 if (lock.GetJson().isMember(LOCALE))
253 { 282 {
254 locale = lock.GetConfiguration().GetStringParameter(LOCALE, ""); 283 locale = lock.GetConfiguration().GetStringParameter(LOCALE, "");
255 } 284 }
256 285
257 bool loadPrivate = lock.GetConfiguration().GetBooleanParameter("LoadPrivateDictionary", true); 286 bool loadPrivate = lock.GetConfiguration().GetBooleanParameter(LOAD_PRIVATE_DICTIONARY, true);
258 Orthanc::InitializeFramework(locale, loadPrivate); 287 Orthanc::InitializeFramework(locale, loadPrivate);
259 } 288 }
260 289
261 // The Orthanc framework is now initialized 290 // The Orthanc framework is now initialized
262 291
276 } 305 }
277 306
278 RegisterUserMetadata(lock.GetJson()); 307 RegisterUserMetadata(lock.GetJson());
279 RegisterUserContentType(lock.GetJson()); 308 RegisterUserContentType(lock.GetJson());
280 309
310 LoadExternalDictionaries(lock.GetJson()); // New in Orthanc 1.9.4
281 LoadCustomDictionary(lock.GetJson()); 311 LoadCustomDictionary(lock.GetJson());
282 312
283 lock.GetConfiguration().RegisterFont(ServerResources::FONT_UBUNTU_MONO_BOLD_16); 313 lock.GetConfiguration().RegisterFont(ServerResources::FONT_UBUNTU_MONO_BOLD_16);
284 314
285 #if HAVE_MALLOPT == 1 315 #if HAVE_MALLOPT == 1
317 static IDatabaseWrapper* CreateSQLiteWrapper() 347 static IDatabaseWrapper* CreateSQLiteWrapper()
318 { 348 {
319 OrthancConfiguration::ReaderLock lock; 349 OrthancConfiguration::ReaderLock lock;
320 350
321 std::string storageDirectoryStr = 351 std::string storageDirectoryStr =
322 lock.GetConfiguration().GetStringParameter("StorageDirectory", "OrthancStorage"); 352 lock.GetConfiguration().GetStringParameter(STORAGE_DIRECTORY, ORTHANC_STORAGE);
323 353
324 // Open the database 354 // Open the database
325 boost::filesystem::path indexDirectory = lock.GetConfiguration().InterpretStringParameterAsPath( 355 boost::filesystem::path indexDirectory = lock.GetConfiguration().InterpretStringParameterAsPath(
326 lock.GetConfiguration().GetStringParameter("IndexDirectory", storageDirectoryStr)); 356 lock.GetConfiguration().GetStringParameter("IndexDirectory", storageDirectoryStr));
327 357
411 } 441 }
412 442
413 443
414 static IStorageArea* CreateFilesystemStorage() 444 static IStorageArea* CreateFilesystemStorage()
415 { 445 {
446 static const char* const SYNC_STORAGE_AREA = "SyncStorageArea";
447 static const char* const STORE_DICOM = "StoreDicom";
448
416 OrthancConfiguration::ReaderLock lock; 449 OrthancConfiguration::ReaderLock lock;
417 450
418 std::string storageDirectoryStr = 451 std::string storageDirectoryStr =
419 lock.GetConfiguration().GetStringParameter("StorageDirectory", "OrthancStorage"); 452 lock.GetConfiguration().GetStringParameter(STORAGE_DIRECTORY, ORTHANC_STORAGE);
420 453
421 boost::filesystem::path storageDirectory = 454 boost::filesystem::path storageDirectory =
422 lock.GetConfiguration().InterpretStringParameterAsPath(storageDirectoryStr); 455 lock.GetConfiguration().InterpretStringParameterAsPath(storageDirectoryStr);
423 456
424 LOG(WARNING) << "Storage directory: " << storageDirectory; 457 LOG(WARNING) << "Storage directory: " << storageDirectory;
425 458
426 // New in Orthanc 1.7.4 459 // New in Orthanc 1.7.4
427 bool fsyncOnWrite = lock.GetConfiguration().GetBooleanParameter("SyncStorageArea", true); 460 bool fsyncOnWrite = lock.GetConfiguration().GetBooleanParameter(SYNC_STORAGE_AREA, true);
428 461
429 if (lock.GetConfiguration().GetBooleanParameter("StoreDicom", true)) 462 if (lock.GetConfiguration().GetBooleanParameter(STORE_DICOM, true))
430 { 463 {
431 return new FilesystemStorage(storageDirectory.string(), fsyncOnWrite); 464 return new FilesystemStorage(storageDirectory.string(), fsyncOnWrite);
432 } 465 }
433 else 466 else
434 { 467 {