Mercurial > hg > orthanc
diff OrthancServer/Plugins/Samples/WebDavFilesystem/Plugin.cpp @ 4943:47d734fa30f6
adding function OrthancPluginRegisterWebDavCollection() to the plugin SDK
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 16 Mar 2022 17:21:02 +0100 |
parents | |
children | 0ea402b4d901 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Samples/WebDavFilesystem/Plugin.cpp Wed Mar 16 17:21:02 2022 +0100 @@ -0,0 +1,390 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2022 Osimis S.A., Belgium + * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "../Common/OrthancPluginCppWrapper.h" + +#include <boost/thread/mutex.hpp> + + +class Resource : public boost::noncopyable +{ +private: + boost::posix_time::ptime dateTime_; + +public: + Resource() : + dateTime_(boost::posix_time::second_clock::universal_time()) + { + } + + virtual ~Resource() + { + } + + const boost::posix_time::ptime& GetDateTime() const + { + return dateTime_; + } + + virtual bool IsFolder() const = 0; + + virtual Resource* LookupPath(const std::vector<std::string>& path) = 0; +}; + + +class File : public Resource +{ +private: + std::string content_; + +public: + File(const void* data, + size_t size) : + content_(reinterpret_cast<const char*>(data), size) + { + } + + const std::string& GetContent() const + { + return content_; + } + + virtual bool IsFolder() const + { + return false; + } + + virtual Resource* LookupPath(const std::vector<std::string>& path) + { + if (path.empty()) + { + return this; + } + else + { + return NULL; + } + } +}; + + +class Folder : public Resource +{ +private: + typedef std::map<std::string, Resource*> Content; + + Content content_; + +public: + virtual ~Folder() + { + for (Content::iterator it = content_.begin(); it != content_.end(); ++it) + { + assert(it->second != NULL); + delete it->second; + } + } + + virtual bool IsFolder() const + { + return true; + } + + virtual Resource* LookupPath(const std::vector<std::string>& path) + { + if (path.empty()) + { + return this; + } + else + { + Content::const_iterator found = content_.find(path[0]); + if (found == content_.end()) + { + return NULL; + } + else + { + std::vector<std::string> childPath(path.size() - 1); + + for (size_t i = 0; i < childPath.size(); i++) + { + childPath[i] = path[i + 1]; + } + + return found->second->LookupPath(childPath); + } + } + } + + void ListContent(std::list<OrthancPlugins::IWebDavCollection::FileInfo>& files, + std::list<OrthancPlugins::IWebDavCollection::FolderInfo>& subfolders) const + { + for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it) + { + assert(it->second != NULL); + + const std::string dateTime = boost::posix_time::to_iso_string(it->second->GetDateTime()); + + if (it->second->IsFolder()) + { + subfolders.push_back(OrthancPlugins::IWebDavCollection::FolderInfo(it->first, dateTime)); + } + else + { + const File& f = dynamic_cast<const File&>(*it->second); + files.push_back(OrthancPlugins::IWebDavCollection::FileInfo(it->first, f.GetContent().size(), dateTime)); + } + } + } + + void StoreFile(const std::string& name, + File* f) + { + std::unique_ptr<File> protection(f); + + if (content_.find(name) != content_.end()) + { + OrthancPlugins::LogError("Already existing: " + name); + ORTHANC_PLUGINS_THROW_EXCEPTION(BadRequest); + } + else + { + content_[name] = protection.release(); + } + } + + void CreateSubfolder(const std::string& name) + { + if (content_.find(name) != content_.end()) + { + OrthancPlugins::LogError("Already existing: " + name); + ORTHANC_PLUGINS_THROW_EXCEPTION(BadRequest); + } + else + { + content_[name] = new Folder; + } + } + + void DeleteItem(const std::string& name) + { + Content::iterator found = content_.find(name); + + if (found == content_.end()) + { + OrthancPlugins::LogError("Cannot delete inexistent path: " + name); + ORTHANC_PLUGINS_THROW_EXCEPTION(InexistentItem); + } + else + { + assert(found->second != NULL); + delete found->second; + content_.erase(found); + } + } +}; + + +class WebDavFilesystem : public OrthancPlugins::IWebDavCollection +{ +private: + boost::mutex mutex_; + std::unique_ptr<Resource> root_; + + static std::vector<std::string> GetParentPath(const std::vector<std::string>& path) + { + if (path.empty()) + { + OrthancPlugins::LogError("Empty path"); + ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); + } + else + { + std::vector<std::string> p(path.size() - 1); + + for (size_t i = 0; i < p.size(); i++) + { + p[i] = path[i]; + } + + return p; + } + } + +public: + WebDavFilesystem() : + root_(new Folder) + { + } + + virtual bool IsExistingFolder(const std::vector<std::string>& path) + { + boost::mutex::scoped_lock lock(mutex_); + + Resource* resource = root_->LookupPath(path); + return (resource != NULL && + resource->IsFolder()); + } + + virtual bool ListFolder(std::list<FileInfo>& files, + std::list<FolderInfo>& subfolders, + const std::vector<std::string>& path) + { + boost::mutex::scoped_lock lock(mutex_); + + Resource* resource = root_->LookupPath(path); + if (resource != NULL && + resource->IsFolder()) + { + dynamic_cast<Folder&>(*resource).ListContent(files, subfolders); + return true; + } + else + { + return false; + } + } + + virtual bool GetFile(std::string& content /* out */, + std::string& mime /* out */, + std::string& dateTime /* out */, + const std::vector<std::string>& path) + { + boost::mutex::scoped_lock lock(mutex_); + + Resource* resource = root_->LookupPath(path); + if (resource != NULL && + !resource->IsFolder()) + { + const File& file = dynamic_cast<const File&>(*resource); + content = file.GetContent(); + mime = ""; // Let the Orthanc core autodetect the MIME type + dateTime = boost::posix_time::to_iso_string(file.GetDateTime()); + return true; + } + else + { + return false; + } + } + + virtual bool StoreFile(const std::vector<std::string>& path, + const void* data, + size_t size) + { + boost::mutex::scoped_lock lock(mutex_); + + Resource* parent = root_->LookupPath(GetParentPath(path)); + if (parent != NULL && + parent->IsFolder()) + { + dynamic_cast<Folder&>(*parent).StoreFile(path.back(), new File(data, size)); + return true; + } + else + { + return false; + } + } + + virtual bool CreateFolder(const std::vector<std::string>& path) + { + boost::mutex::scoped_lock lock(mutex_); + + Resource* parent = root_->LookupPath(GetParentPath(path)); + if (parent != NULL && + parent->IsFolder()) + { + dynamic_cast<Folder&>(*parent).CreateSubfolder(path.back()); + return true; + } + else + { + return false; + } + } + + virtual bool DeleteItem(const std::vector<std::string>& path) + { + boost::mutex::scoped_lock lock(mutex_); + + Resource* parent = root_->LookupPath(GetParentPath(path)); + if (parent != NULL && + parent->IsFolder()) + { + dynamic_cast<Folder&>(*parent).DeleteItem(path.back()); + return true; + } + else + { + return false; + } + } +}; + + + +extern "C" +{ + ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* c) + { + OrthancPlugins::SetGlobalContext(c); + OrthancPluginLogWarning(c, "WebDAV plugin is initializing"); + + /* Check the version of the Orthanc core */ + if (OrthancPluginCheckVersion(c) == 0) + { + char info[1024]; + sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", + c->orthancVersion, + ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, + ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, + ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); + OrthancPluginLogError(c, info); + return -1; + } + + static WebDavFilesystem filesystem; + OrthancPlugins::IWebDavCollection::Register("/webdav-plugin", filesystem); + + return 0; + } + + + ORTHANC_PLUGINS_API void OrthancPluginFinalize() + { + OrthancPluginLogWarning(OrthancPlugins::GetGlobalContext(), "WebDAV plugin is finalizing"); + } + + + ORTHANC_PLUGINS_API const char* OrthancPluginGetName() + { + return "webdav-sample"; + } + + + ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() + { + return "0.0"; + } +}