Mercurial > hg > orthanc
diff Plugins/Engine/OrthancPlugins.cpp @ 3786:3801435e34a1 SylvainRouquette/fix-issue169-95b752c
integration Orthanc-1.6.0->SylvainRouquette
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 19 Mar 2020 11:48:30 +0100 |
parents | 56f2397f027a |
children | e7003b2203a7 |
line wrap: on
line diff
--- a/Plugins/Engine/OrthancPlugins.cpp Wed Mar 18 08:59:06 2020 +0100 +++ b/Plugins/Engine/OrthancPlugins.cpp Thu Mar 19 11:48:30 2020 +0100 @@ -2,7 +2,7 @@ * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2019 Osimis S.A., Belgium + * Copyright (C) 2017-2020 Osimis S.A., Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -367,7 +367,7 @@ public: DicomWebBinaryFormatter(const _OrthancPluginEncodeDicomWeb& parameters) : - callback_(parameters.callback) + callback_(parameters.callback) { } @@ -435,7 +435,7 @@ }; HttpOutput& output_; - std::auto_ptr<std::string> errorDetails_; + std::unique_ptr<std::string> errorDetails_; bool logDetails_; MultipartState multipartState_; std::string multipartSubType_; @@ -665,8 +665,8 @@ public: ChunkedRestCallback(_OrthancPluginChunkedRestCallback parameters) : - parameters_(parameters), - regex_(parameters.pathRegularExpression) + parameters_(parameters), + regex_(parameters.pathRegularExpression) { } @@ -682,6 +682,110 @@ }; + + class StorageCommitmentScp : public IStorageCommitmentFactory + { + private: + class Handler : public IStorageCommitmentFactory::ILookupHandler + { + private: + _OrthancPluginRegisterStorageCommitmentScpCallback parameters_; + void* handler_; + + public: + Handler(_OrthancPluginRegisterStorageCommitmentScpCallback parameters, + void* handler) : + parameters_(parameters), + handler_(handler) + { + if (handler == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + } + + virtual ~Handler() + { + assert(handler_ != NULL); + parameters_.destructor(handler_); + handler_ = NULL; + } + + virtual StorageCommitmentFailureReason Lookup(const std::string& sopClassUid, + const std::string& sopInstanceUid) + { + assert(handler_ != NULL); + OrthancPluginStorageCommitmentFailureReason reason = + OrthancPluginStorageCommitmentFailureReason_Success; + OrthancPluginErrorCode error = parameters_.lookup( + &reason, handler_, sopClassUid.c_str(), sopInstanceUid.c_str()); + if (error == OrthancPluginErrorCode_Success) + { + return Plugins::Convert(reason); + } + else + { + throw OrthancException(static_cast<ErrorCode>(error)); + } + } + }; + + _OrthancPluginRegisterStorageCommitmentScpCallback parameters_; + + public: + StorageCommitmentScp(_OrthancPluginRegisterStorageCommitmentScpCallback parameters) : + parameters_(parameters) + { + } + + virtual ILookupHandler* CreateStorageCommitment( + const std::string& jobId, + const std::string& transactionUid, + const std::vector<std::string>& sopClassUids, + const std::vector<std::string>& sopInstanceUids, + const std::string& remoteAet, + const std::string& calledAet) ORTHANC_OVERRIDE + { + const size_t n = sopClassUids.size(); + + if (sopInstanceUids.size() != n) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + std::vector<const char*> a, b; + a.resize(n); + b.resize(n); + + for (size_t i = 0; i < n; i++) + { + a[i] = sopClassUids[i].c_str(); + b[i] = sopInstanceUids[i].c_str(); + } + + void* handler = NULL; + OrthancPluginErrorCode error = parameters_.factory( + &handler, jobId.c_str(), transactionUid.c_str(), + a.empty() ? NULL : &a[0], b.empty() ? NULL : &b[0], static_cast<uint32_t>(n), + remoteAet.c_str(), calledAet.c_str()); + + if (error != OrthancPluginErrorCode_Success) + { + throw OrthancException(static_cast<ErrorCode>(error)); + } + else if (handler == NULL) + { + // This plugin won't handle this storage commitment request + return NULL; + } + else + { + return new Handler(parameters_, handler); + } + } + }; + + class ServerContextLock { private: @@ -690,8 +794,8 @@ public: ServerContextLock(PImpl& that) : - lock_(that.contextMutex_), - context_(that.context_) + lock_(that.contextMutex_), + context_(that.context_) { if (context_ == NULL) { @@ -724,6 +828,7 @@ typedef std::list<OrthancPluginDecodeImageCallback> DecodeImageCallbacks; typedef std::list<OrthancPluginJobsUnserializer> JobsUnserializers; typedef std::list<OrthancPluginRefreshMetricsCallback> RefreshMetricsCallbacks; + typedef std::list<StorageCommitmentScp*> StorageCommitmentScpCallbacks; typedef std::map<Property, std::string> Properties; PluginsManager manager_; @@ -740,7 +845,8 @@ IncomingHttpRequestFilters incomingHttpRequestFilters_; IncomingHttpRequestFilters2 incomingHttpRequestFilters2_; RefreshMetricsCallbacks refreshMetricsCallbacks_; - std::auto_ptr<StorageAreaFactory> storageArea_; + StorageCommitmentScpCallbacks storageCommitmentScpCallbacks_; + std::unique_ptr<StorageAreaFactory> storageArea_; boost::recursive_mutex restCallbackMutex_; boost::recursive_mutex storedCallbackMutex_; @@ -750,12 +856,13 @@ boost::mutex decodeImageCallbackMutex_; boost::mutex jobsUnserializersMutex_; boost::mutex refreshMetricsMutex_; + boost::mutex storageCommitmentScpMutex_; boost::recursive_mutex invokeServiceMutex_; Properties properties_; int argc_; char** argv_; - std::auto_ptr<OrthancPluginDatabase> database_; + std::unique_ptr<OrthancPluginDatabase> database_; PluginsErrorDictionary dictionary_; PImpl() : @@ -775,8 +882,8 @@ { private: OrthancPlugins& that_; - std::auto_ptr<HierarchicalMatcher> matcher_; - std::auto_ptr<ParsedDicomFile> filtered_; + std::unique_ptr<HierarchicalMatcher> matcher_; + std::unique_ptr<ParsedDicomFile> filtered_; ParsedDicomFile* currentQuery_; void Reset() @@ -824,7 +931,8 @@ Json::Value target; call.ExecuteToJson(target, true); - filtered_.reset(ParsedDicomFile::CreateFromJson(target, DicomFromJsonFlags_None)); + filtered_.reset(ParsedDicomFile::CreateFromJson(target, DicomFromJsonFlags_None, + "" /* no private creator */)); currentQuery_ = filtered_.get(); } } @@ -888,7 +996,7 @@ } ParsedDicomFile f(dicom, size); - std::auto_ptr<ParsedDicomFile> summary(matcher_->Extract(f)); + std::unique_ptr<ParsedDicomFile> summary(matcher_->Extract(f)); reinterpret_cast<DicomFindAnswers*>(answers)->Add(*summary); } }; @@ -898,7 +1006,7 @@ { private: OrthancPlugins& that_; - std::auto_ptr<DicomArray> currentQuery_; + std::unique_ptr<DicomArray> currentQuery_; void Reset() { @@ -1260,6 +1368,7 @@ sizeof(int32_t) != sizeof(OrthancPluginConstraintType) || sizeof(int32_t) != sizeof(OrthancPluginMetricsType) || sizeof(int32_t) != sizeof(OrthancPluginDicomWebBinaryMode) || + sizeof(int32_t) != sizeof(OrthancPluginStorageCommitmentFailureReason) || static_cast<int>(OrthancPluginDicomToJsonFlags_IncludeBinary) != static_cast<int>(DicomToJsonFlags_IncludeBinary) || static_cast<int>(OrthancPluginDicomToJsonFlags_IncludePrivateTags) != static_cast<int>(DicomToJsonFlags_IncludePrivateTags) || static_cast<int>(OrthancPluginDicomToJsonFlags_IncludeUnknownTags) != static_cast<int>(DicomToJsonFlags_IncludeUnknownTags) || @@ -1303,6 +1412,13 @@ { delete *it; } + + for (PImpl::StorageCommitmentScpCallbacks::iterator + it = pimpl_->storageCommitmentScpCallbacks_.begin(); + it != pimpl_->storageCommitmentScpCallbacks_.end(); ++it) + { + delete *it; + } } @@ -1350,7 +1466,7 @@ public: RestCallbackMatcher(const UriComponents& uri) : - flatUri_(Toolbox::FlattenUri(uri)) + flatUri_(Toolbox::FlattenUri(uri)) { } @@ -1863,6 +1979,18 @@ } + void OrthancPlugins::RegisterStorageCommitmentScpCallback(const void* parameters) + { + const _OrthancPluginRegisterStorageCommitmentScpCallback& p = + *reinterpret_cast<const _OrthancPluginRegisterStorageCommitmentScpCallback*>(parameters); + + boost::mutex::scoped_lock lock(pimpl_->storageCommitmentScpMutex_); + LOG(INFO) << "Plugin has registered a storage commitment callback"; + + pimpl_->storageCommitmentScpCallbacks_.push_back(new PImpl::StorageCommitmentScp(p)); + } + + void OrthancPlugins::AnswerBuffer(const void* parameters) { const _OrthancPluginAnswerBuffer& p = @@ -2355,7 +2483,7 @@ std::string result; { - std::auto_ptr<DeflateBaseCompressor> compressor; + std::unique_ptr<DeflateBaseCompressor> compressor; switch (p.compression) { @@ -2405,14 +2533,14 @@ } - static OrthancPluginImage* ReturnImage(std::auto_ptr<ImageAccessor>& image) + static OrthancPluginImage* ReturnImage(std::unique_ptr<ImageAccessor>& image) { // Images returned to plugins are assumed to be writeable. If the // input image is read-only, we return a copy so that it can be modified. if (image->IsReadOnly()) { - std::auto_ptr<Image> copy(new Image(image->GetFormat(), image->GetWidth(), image->GetHeight(), false)); + std::unique_ptr<Image> copy(new Image(image->GetFormat(), image->GetWidth(), image->GetHeight(), false)); ImageProcessing::Copy(*copy, *image); image.reset(NULL); return reinterpret_cast<OrthancPluginImage*>(copy.release()); @@ -2428,7 +2556,7 @@ { const _OrthancPluginUncompressImage& p = *reinterpret_cast<const _OrthancPluginUncompressImage*>(parameters); - std::auto_ptr<ImageAccessor> image; + std::unique_ptr<ImageAccessor> image; switch (p.format) { @@ -2812,7 +2940,7 @@ const _OrthancPluginConvertPixelFormat& p = *reinterpret_cast<const _OrthancPluginConvertPixelFormat*>(parameters); const ImageAccessor& source = *reinterpret_cast<const ImageAccessor*>(p.source); - std::auto_ptr<ImageAccessor> target(new Image(Plugins::Convert(p.targetFormat), source.GetWidth(), source.GetHeight(), false)); + std::unique_ptr<ImageAccessor> target(new Image(Plugins::Convert(p.targetFormat), source.GetWidth(), source.GetHeight(), false)); ImageProcessing::Convert(*target, source); *(p.target) = ReturnImage(target); @@ -2865,7 +2993,7 @@ const _OrthancPluginDicomToJson& p = *reinterpret_cast<const _OrthancPluginDicomToJson*>(parameters); - std::auto_ptr<ParsedDicomFile> dicom; + std::unique_ptr<ParsedDicomFile> dicom; if (service == _OrthancPluginService_DicomBufferToJson) { @@ -2921,8 +3049,18 @@ std::string dicom; { - std::auto_ptr<ParsedDicomFile> file - (ParsedDicomFile::CreateFromJson(json, static_cast<DicomFromJsonFlags>(p.flags))); + // Fix issue 168 (Plugins can't read private tags from the + // configuration file) + // https://bitbucket.org/sjodogne/orthanc/issues/168/ + std::string privateCreator; + { + OrthancConfiguration::ReaderLock lock; + privateCreator = lock.GetConfiguration().GetDefaultPrivateCreator(); + } + + std::unique_ptr<ParsedDicomFile> file + (ParsedDicomFile::CreateFromJson(json, static_cast<DicomFromJsonFlags>(p.flags), + privateCreator)); if (p.pixelData) { @@ -2984,7 +3122,7 @@ const _OrthancPluginCreateImage& p = *reinterpret_cast<const _OrthancPluginCreateImage*>(parameters); - std::auto_ptr<ImageAccessor> result; + std::unique_ptr<ImageAccessor> result; switch (service) { @@ -3095,7 +3233,25 @@ DcmTagKey tag2(tag.GetGroup(), tag.GetElement()); DictionaryReadLocker locker; - const DcmDictEntry* entry = locker->findEntry(tag2, NULL); + const DcmDictEntry* entry = NULL; + + if (tag.IsPrivate()) + { + // Fix issue 168 (Plugins can't read private tags from the + // configuration file) + // https://bitbucket.org/sjodogne/orthanc/issues/168/ + std::string privateCreator; + { + OrthancConfiguration::ReaderLock lock; + privateCreator = lock.GetConfiguration().GetDefaultPrivateCreator(); + } + + entry = locker->findEntry(tag2, privateCreator.c_str()); + } + else + { + entry = locker->findEntry(tag2, NULL); + } if (entry == NULL) { @@ -3882,6 +4038,10 @@ RegisterRefreshMetricsCallback(parameters); return true; + case _OrthancPluginService_RegisterStorageCommitmentScpCallback: + RegisterStorageCommitmentScpCallback(parameters); + return true; + case _OrthancPluginService_RegisterStorageArea: { LOG(INFO) << "Plugin has registered a custom storage area"; @@ -4452,7 +4612,7 @@ }; - bool OrthancPlugins::CreateChunkedRequestReader(std::auto_ptr<IChunkedRequestReader>& target, + bool OrthancPlugins::CreateChunkedRequestReader(std::unique_ptr<IChunkedRequestReader>& target, RequestOrigin origin, const char* remoteIp, const char* username, @@ -4539,4 +4699,32 @@ } } } + + + IStorageCommitmentFactory::ILookupHandler* OrthancPlugins::CreateStorageCommitment( + const std::string& jobId, + const std::string& transactionUid, + const std::vector<std::string>& sopClassUids, + const std::vector<std::string>& sopInstanceUids, + const std::string& remoteAet, + const std::string& calledAet) + { + boost::mutex::scoped_lock lock(pimpl_->storageCommitmentScpMutex_); + + for (PImpl::StorageCommitmentScpCallbacks::iterator + it = pimpl_->storageCommitmentScpCallbacks_.begin(); + it != pimpl_->storageCommitmentScpCallbacks_.end(); ++it) + { + assert(*it != NULL); + IStorageCommitmentFactory::ILookupHandler* handler = (*it)->CreateStorageCommitment + (jobId, transactionUid, sopClassUids, sopInstanceUids, remoteAet, calledAet); + + if (handler != NULL) + { + return handler; + } + } + + return NULL; + } }