diff --git a/CMake/mitkFunctionGetLibrarySearchPaths.cmake b/CMake/mitkFunctionGetLibrarySearchPaths.cmake index 470f75bf72..d976646f12 100644 --- a/CMake/mitkFunctionGetLibrarySearchPaths.cmake +++ b/CMake/mitkFunctionGetLibrarySearchPaths.cmake @@ -1,197 +1,213 @@ #! Helper function that gets all library search paths. #! #! Usage: #! #! mitkFunctionGetLibrarySearchPaths(search_path intermediate_dir [DEBUG|MINSIZEREL|RELWITHDEBINFO]) #! #! #! The function creates the variable ${search_path}. The variable intermediate_dir contains #! paths that should be added to the search_path but should not be checked for existance, #! because the are not yet created. The option DEBUG, MINSIZEREL or RELWITHDEBINFO can be used to indicate that #! not the paths for release configuration are requested but the debug, min size release or "release with debug info" #! paths. #! function(mitkFunctionGetLibrarySearchPaths search_path intermediate_dir) cmake_parse_arguments(PARSE_ARGV 2 GLS "RELEASE;DEBUG;MINSIZEREL;RELWITHDEBINFO" "" "") set(_dir_candidates "${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins" "${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}" "${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins" ) if(MITK_EXTERNAL_PROJECT_PREFIX) list(APPEND _dir_candidates "${MITK_EXTERNAL_PROJECT_PREFIX}/bin" "${MITK_EXTERNAL_PROJECT_PREFIX}/lib" ) endif() # Determine the Qt5 library installation prefix set(_qmake_location ) if(MITK_USE_Qt5 AND TARGET ${Qt5Core_QMAKE_EXECUTABLE}) get_property(_qmake_location TARGET ${Qt5Core_QMAKE_EXECUTABLE} PROPERTY IMPORT_LOCATION) endif() if(_qmake_location) if(NOT _qt_install_libs) if(WIN32) execute_process(COMMAND ${_qmake_location} -query QT_INSTALL_BINS OUTPUT_VARIABLE _qt_install_libs OUTPUT_STRIP_TRAILING_WHITESPACE) else() execute_process(COMMAND ${_qmake_location} -query QT_INSTALL_LIBS OUTPUT_VARIABLE _qt_install_libs OUTPUT_STRIP_TRAILING_WHITESPACE) endif() file(TO_CMAKE_PATH "${_qt_install_libs}" _qt_install_libs) set(_qt_install_libs ${_qt_install_libs} CACHE INTERNAL "Qt library installation prefix" FORCE) endif() if(_qt_install_libs) list(APPEND _dir_candidates ${_qt_install_libs}) endif() elseif(MITK_USE_Qt5) message(WARNING "The qmake executable could not be found.") endif() get_property(_additional_paths GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) + if(TARGET OpenSSL::SSL) + if(GLS_DEBUG) + get_target_property(_openssl_location OpenSSL::SSL IMPORTED_LOCATION_DEBUG) + else() + get_target_property(_openssl_location OpenSSL::SSL IMPORTED_LOCATION_RELEASE) + endif() + if(_openssl_location) + get_filename_component(_openssl_location ${_openssl_location} DIRECTORY) + set(_openssl_location "${_openssl_location}/../../bin") + if(EXISTS ${_openssl_location}) + get_filename_component(_openssl_location ${_openssl_location} ABSOLUTE) + list(APPEND _dir_candidates ${_openssl_location}) + endif() + endif() + endif() + if(MITK_USE_HDF5) FIND_PACKAGE(HDF5 COMPONENTS C HL NO_MODULE REQUIRED shared) get_target_property(_location hdf5-shared LOCATION) get_filename_component(_location ${_location} PATH) list(APPEND _additional_paths ${_location}) # This is a work-around. The hdf5-config.cmake file is not robust enough # to be included several times via find_pakcage calls. set(HDF5_LIBRARIES ${HDF5_LIBRARIES} PARENT_SCOPE) endif() if(MITK_USE_Vigra) # we cannot use _find_package(Vigra) here because the vigra-config.cmake file # always includes the target-exports files without using an include guard. This # would lead to errors when another find_package(Vigra) call is processed. The # (bad) assumption here is that for the time being, only the Classification module # is using Vigra. if(UNIX) list(APPEND _additional_paths ${Vigra_DIR}/lib) else() list(APPEND _additional_paths ${Vigra_DIR}/bin) endif() endif() if(_additional_paths) list(APPEND _dir_candidates ${_additional_paths}) endif() # The code below is sub-optimal. It makes assumptions about # the structure of the build directories, pointed to by # the *_DIR variables. Instead, we should rely on package # specific "LIBRARY_DIRS" variables, if they exist. if(WIN32) list(APPEND _dir_candidates "${ITK_DIR}/bin") endif() if(MITK_USE_MatchPoint) if(WIN32) list(APPEND _dir_candidates "${MatchPoint_DIR}/bin") else() list(APPEND _dir_candidates "${MatchPoint_DIR}/lib") endif() endif() # If OpenCV is built within the MITK superbuild set the binary directory # according to the lib path provided by OpenCV. # In the case where an external OpenCV is provided use the binary directory # of this OpenCV directory if(MITK_USE_OpenCV) if(WIN32) if (EXISTS ${OpenCV_LIB_PATH}) list(APPEND _dir_candidates "${OpenCV_LIB_PATH}/../bin") # OpenCV is built in superbuild else() list(APPEND _dir_candidates "${OpenCV_DIR}/bin") # External OpenCV build is used endif() endif() endif() if(MITK_USE_Python) list(APPEND _dir_candidates "${CTK_DIR}/CMakeExternals/Install/bin") get_filename_component(_python_dir ${PYTHON_EXECUTABLE} DIRECTORY) list(APPEND _dir_candidates "${_python_dir}") endif() if(MITK_USE_TOF_PMDO3 OR MITK_USE_TOF_PMDCAMCUBE OR MITK_USE_TOF_PMDCAMBOARD) list(APPEND _dir_candidates "${MITK_PMD_SDK_DIR}/plugins" "${MITK_PMD_SDK_DIR}/bin") endif() if(MITK_USE_CTK) list(APPEND _dir_candidates "${CTK_LIBRARY_DIRS}") foreach(_ctk_library ${CTK_LIBRARIES}) if(${_ctk_library}_LIBRARY_DIRS) list(APPEND _dir_candidates "${${_ctk_library}_LIBRARY_DIRS}") endif() endforeach() endif() if(MITK_USE_BLUEBERRY) if(DEFINED CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY) if(IS_ABSOLUTE "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") list(APPEND _dir_candidates "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") else() list(APPEND _dir_candidates "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") endif() endif() endif() if(MITK_LIBRARY_DIRS) list(APPEND _dir_candidates ${MITK_LIBRARY_DIRS}) endif() ################################################################### #get the search paths added by the mitkFunctionAddLibrarySearchPath file(GLOB _additional_path_info_files "${MITK_SUPERBUILD_BINARY_DIR}/MITK-AdditionalLibPaths/*.cmake") foreach(_additional_path_info_file ${_additional_path_info_files}) get_filename_component(_additional_info_name ${_additional_path_info_file} NAME_WE) include(${_additional_path_info_file}) if(GLS_DEBUG) list(APPEND _dir_candidates ${${_additional_info_name}_ADDITIONAL_DEBUG_LIBRARY_SEARCH_PATHS}) elseif(GLS_MINSIZEREL) list(APPEND _dir_candidates ${${_additional_info_name}_ADDITIONAL_MINSIZEREL_LIBRARY_SEARCH_PATHS}) elseif(GLS_RELWITHDEBINFO) list(APPEND _dir_candidates ${${_additional_info_name}_ADDITIONAL_RELWITHDEBINFO_LIBRARY_SEARCH_PATHS}) else() #Release list(APPEND _dir_candidates ${${_additional_info_name}_ADDITIONAL_RELEASE_LIBRARY_SEARCH_PATHS}) endif() endforeach(_additional_path_info_file ${_additional_path_info_files}) ############################################### #sanitize all candidates and compile final list list(REMOVE_DUPLICATES _dir_candidates) set(_search_dirs ) foreach(_dir ${_dir_candidates}) if(EXISTS "${_dir}/${intermediate_dir}") list(APPEND _search_dirs "${_dir}/${intermediate_dir}") else() list(APPEND _search_dirs "${_dir}") endif() endforeach() # Special handling for "internal" search dirs. The intermediate directory # might not have been created yet, so we can't check for its existence. # Hence we just add it for Windows without checking. set(_internal_search_dirs "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins") if(WIN32) foreach(_dir ${_internal_search_dirs}) set(_search_dirs "${_dir}/${intermediate_dir}" ${_search_dirs}) endforeach() else() set(_search_dirs ${_internal_search_dirs} ${_search_dirs}) endif() list(REMOVE_DUPLICATES _search_dirs) set(${search_path} ${_search_dirs} PARENT_SCOPE) endfunction() diff --git a/Modules/CppRestSdk/include/mitkIRESTManager.h b/Modules/CppRestSdk/include/mitkIRESTManager.h index 3e67c71f6b..3797fa2eee 100644 --- a/Modules/CppRestSdk/include/mitkIRESTManager.h +++ b/Modules/CppRestSdk/include/mitkIRESTManager.h @@ -1,105 +1,105 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkIRESTManager_h #define mitkIRESTManager_h #include "cpprest/json.h" #include "cpprest/uri.h" #include #include #include #include #include namespace mitk { /** * @class IRESTManager * @brief this is a microservice interface for managing REST-requests. * * There are two microservices implementing this interface. * 1. The RESTManager in the CppRestSdk Module is the service used for non-Qt applications * 2. The RESTManagerQt in the CppRestSdkQt Module which is used for Qt-applications. * If a Qt application is running, the RESTManagerQt is the default service which is automatically selected. */ class RESTServer; class MITKCPPRESTSDK_EXPORT IRESTManager { public: virtual ~IRESTManager(); /** * @brief request type for client requests by calling SendRequest */ enum class RequestType { Get, Post, Put }; /** * @brief Executes a HTTP request in the mitkRESTClient class * * @param uri defines the URI the request is send to * @param type the RequestType of the HTTP request (optional) * @param body the body for the request (optional) * @return task to wait for */ virtual pplx::task SendRequest(const web::uri &uri, const RequestType &type = RequestType::Get, const web::json::value *body = nullptr, - const utility::string_t &filePath = L"") = 0; + const utility::string_t &filePath = {}) = 0; /** * @brief starts listening for requests if there isn't another observer listening and the port is free * * @param uri defines the URI for which incoming requests should be send to the observer * @param observer the observer which handles the incoming requests */ virtual void ReceiveRequest(const web::uri &uri, IRESTObserver *observer) = 0; /** * @brief Handles incoming requests by notifying the observer which should receive it * * @param uri defines the URI of the request * @param body the body of the request * @return the data which is modified by the notified observer */ virtual web::json::value Handle(const web::uri &uri, const web::json::value &body) = 0; /** * @brief Handles the deletion of an observer for all or a specific uri * * @param observer the observer which shouldn't receive requests anymore * @param uri the uri for which the observer doesn't handle requests anymore (optional) */ - virtual void HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri = L"") = 0; + virtual void HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri = {}) = 0; virtual const std::map& GetServerMap() = 0; virtual const std::map, IRESTObserver *>& GetObservers() = 0; }; } // namespace mitk MITK_DECLARE_SERVICE_INTERFACE(mitk::IRESTManager, "org.mitk.IRESTManager") #endif diff --git a/Modules/CppRestSdk/include/mitkRESTManager.h b/Modules/CppRestSdk/include/mitkRESTManager.h index ac123b80b8..a7df8f23b8 100644 --- a/Modules/CppRestSdk/include/mitkRESTManager.h +++ b/Modules/CppRestSdk/include/mitkRESTManager.h @@ -1,123 +1,121 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkRESTManager_h #define mitkRESTManager_h #include #include - - namespace mitk { /** * @class RESTManager * @brief this is a microservice for managing REST-requests, used for non-qt applications. * * RESTManagerQt in the CppRestSdkQt module inherits from this class and is the equivalent microservice * used for Qt applications. */ class MITKCPPRESTSDK_EXPORT RESTManager : public IRESTManager { public: RESTManager(); ~RESTManager() override; /** * @brief Executes a HTTP request in the mitkRESTClient class * * @throw mitk::Exception if RequestType is not suported * @param uri defines the URI the request is send to * @param type the RequestType of the HTTP request (optional) * @param body the body for the request (optional) * @param filePath the file path to store the request to * @return task to wait for */ pplx::task SendRequest(const web::uri &uri, const RequestType &type = RequestType::Get, - const web::json::value *body= nullptr, - const utility::string_t &filePath = L"") override; + const web::json::value *body = nullptr, + const utility::string_t &filePath = {}) override; /** * @brief starts listening for requests if there isn't another observer listening and the port is free * * @param uri defines the URI for which incoming requests should be send to the observer * @param observer the observer which handles the incoming requests */ void ReceiveRequest(const web::uri &uri, IRESTObserver *observer) override; /** * @brief Handles incoming requests by notifying the observer which should receive it * * @param uri defines the URI of the request * @param body the body of the request * @return the data which is modified by the notified observer */ web::json::value Handle(const web::uri &uri, const web::json::value &body) override; /** * @brief Handles the deletion of an observer for all or a specific uri * * @param observer the observer which shouldn't receive requests anymore * @param uri the uri for which the observer doesn't handle requests anymore (optional) */ - virtual void HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri) override; + virtual void HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri = {}) override; /** * @brief internal use only */ virtual const std::map& GetServerMap() override; virtual std::map, IRESTObserver *>& GetObservers() override; protected: /** * @brief adds an observer if a port is free, called by ReceiveRequest method * * @param uri the uri which builds the key for the observer map * @param observer the observer which is added */ void AddObserver(const web::uri &uri, IRESTObserver *observer); /** * @brief handles server management if there is already a server under a port, called by ReceiveRequest method * * @param uri the uri which which is requested to be added * @param observer the observer which proceeds the request */ void RequestForATakenPort(const web::uri &uri, IRESTObserver *observer); /** * @brief deletes an observer, called by HandleDeleteObserver method * * @param it the iterator comparing the observers in HandleDeleteObserver method * @param the uri for which the observer doesn't want to receive requests anymore * @return bool if there is another observer under the port */ - bool DeleteObserver(std::map < std::pair, IRESTObserver *>::iterator &it, const web::uri &uri); + bool DeleteObserver(std::map, IRESTObserver *>::iterator &it, const web::uri &uri); void SetServerMap(const int port, RESTServer *server); void DeleteFromServerMap(const int port); void SetObservers(const std::pair key, IRESTObserver *observer); private: std::map m_ServerMap; // Map with port server pairs std::map, IRESTObserver *> m_Observers; // Map with all observers }; } // namespace mitk #endif // !mitkRESTManager_h diff --git a/Modules/CppRestSdk/src/mitkRESTClient.cpp b/Modules/CppRestSdk/src/mitkRESTClient.cpp index 003d66fff3..88368ebac6 100644 --- a/Modules/CppRestSdk/src/mitkRESTClient.cpp +++ b/Modules/CppRestSdk/src/mitkRESTClient.cpp @@ -1,210 +1,210 @@ #include "mitkRESTClient.h" #include "mitkRESTUtil.h" #include mitk::RESTClient::RESTClient() {} mitk::RESTClient::~RESTClient() {} pplx::task mitk::RESTClient::Get(const web::uri &uri) { //Create new HTTP client MitkClient *client = new MitkClient(uri); MITK_INFO << "Calling GET with " << mitk::RESTUtil::convertToUtf8(uri.path()) << " on client " << mitk::RESTUtil::convertToUtf8(uri.authority().to_string()); //create get request MitkRequest getRequest(MitkRESTMethods::GET); //make request return client->request(getRequest).then([=](pplx::task responseTask) { try { //get response of the request MitkResponse response = responseTask.get(); auto status = response.status_code(); MITK_INFO << " status: " << status; if (MitkRestStatusCodes::OK != status) { //throw if something went wrong (e.g. invalid uri) //this exception can be handled by client mitkThrow() << "response was not OK"; } try { //parse content type to application/json if it isn't already //this is important if the content type is e.g. application/dicom+json utility::string_t requestContentType = response.headers().content_type(); - if (L"application/json" != requestContentType) + if (_XPLATSTR("application/json") != requestContentType) { - response.headers().set_content_type(L"application/json"); + response.headers().set_content_type(_XPLATSTR("application/json")); } //return json answer return response.extract_json().get(); } catch (...) { mitkThrow() << "extracting json went wrong"; } } catch (...) { mitkThrow() << "getting response went wrong"; } }); } pplx::task mitk::RESTClient::Get(const web::uri &uri, const utility::string_t &filePath) { // Create new HTTP client MitkClient *client = new MitkClient(uri); MITK_INFO << "Calling GET with " << mitk::RESTUtil::convertToUtf8(uri.path()) << " on client " << mitk::RESTUtil::convertToUtf8(uri.authority().to_string()) << " save into " << mitk::RESTUtil::convertToUtf8(filePath); //create new file buffer auto fileBuffer = std::make_shared>(); // create get request MitkRequest getRequest(MitkRESTMethods::GET); //open file stream for the specified file path return concurrency::streams::file_buffer::open(filePath, std::ios::out) .then([=](concurrency::streams::streambuf outFile) -> pplx::task { *fileBuffer = outFile; //make the get request return client->request(MitkRESTMethods::GET); }) // Write the response body into the file buffer. .then([=](MitkResponse response) -> pplx::task { auto status = response.status_code(); MITK_INFO << "Status code: " << status; if (web::http::status_codes::OK != status) { // throw if something went wrong (e.g. invalid uri) // this exception can be handled by client mitkThrow() << "GET ended up with response " << mitk::RESTUtil::convertToUtf8(response.to_string()); } return response.body().read_to_end(*fileBuffer); }) // Close the file buffer. .then([=](size_t) { return fileBuffer->close(); }) .then([=]() { //return empty json object web::json::value data; return data; }); } pplx::task mitk::RESTClient::Put(const web::uri &uri, const web::json::value *content) { // Create new HTTP client MitkClient *client = new MitkClient(uri); MITK_INFO << "Calling PUT with " << mitk::RESTUtil::convertToUtf8(uri.path()) << " on client " << mitk::RESTUtil::convertToUtf8(uri.authority().to_string()); // create put request MitkRequest putRequest(MitkRESTMethods::PUT); //set body of the put request with data given by client if (nullptr != content) { putRequest.set_body(*content); } //make put request return client->request(putRequest).then([=](pplx::task responseTask) { try { // get response of the request MitkResponse response = responseTask.get(); auto status = response.status_code(); MITK_INFO << " status: " << status; if (MitkRestStatusCodes::OK != status) { // throw if something went wrong (e.g. invalid uri) // this exception can be handled by client mitkThrow() << "response was not OK"; } try { // parse content type to application/json if it isn't already // this is important if the content type is e.g. application/dicom+json utility::string_t requestContentType = response.headers().content_type(); - if (L"application/json" != requestContentType) + if (_XPLATSTR("application/json") != requestContentType) { - response.headers().set_content_type(L"application/json"); + response.headers().set_content_type(_XPLATSTR("application/json")); } // return json answer return response.extract_json().get(); } catch (...) { mitkThrow() << "extracting json went wrong"; } } catch (...) { mitkThrow() << "getting response went wrong"; } }); } pplx::task mitk::RESTClient::Post(const web::uri &uri, const web::json::value *content) { // Create new HTTP client MitkClient *client = new MitkClient(uri); MITK_INFO << "Calling POST with " << mitk::RESTUtil::convertToUtf8(uri.path()) << " on client " << mitk::RESTUtil::convertToUtf8(uri.authority().to_string()); // Create post request MitkRequest postRequest(MitkRESTMethods::POST); // set body of the put request with data given by client if (nullptr != content) { postRequest.set_body(*content); } //make post request return client->request(postRequest).then([=](pplx::task responseTask) { try { // get response of the request MitkResponse response = responseTask.get(); auto status = response.status_code(); MITK_INFO << " status: " << status; if (MitkRestStatusCodes::Created != status) { // throw if something went wrong (e.g. invalid uri) // this exception can be handled by client mitkThrow() << "response was not Created"; } try { // parse content type to application/json if it isn't already // this is important if the content type is e.g. application/dicom+json utility::string_t requestContentType = response.headers().content_type(); - if (L"application/json" != requestContentType) + if (_XPLATSTR("application/json") != requestContentType) { - response.headers().set_content_type(L"application/json"); + response.headers().set_content_type(_XPLATSTR("application/json")); } // return json answer return response.extract_json().get(); } catch (...) { mitkThrow() << "extracting json went wrong"; } } catch(...) { mitkThrow() << "getting response went wrong"; } }); } diff --git a/Modules/CppRestSdk/src/mitkRESTManager.cpp b/Modules/CppRestSdk/src/mitkRESTManager.cpp index 0ed61bda41..08cd5d367f 100644 --- a/Modules/CppRestSdk/src/mitkRESTManager.cpp +++ b/Modules/CppRestSdk/src/mitkRESTManager.cpp @@ -1,218 +1,218 @@ #include "mitkRESTManager.h" #include #include mitk::RESTManager::RESTManager() {} mitk::RESTManager::~RESTManager() {} pplx::task mitk::RESTManager::SendRequest(const web::uri &uri, const RequestType &type, const web::json::value *content, const utility::string_t &filePath) { pplx::task answer; auto client = new RESTClient(); // according to the RequestType, different HTTP requests are made switch (type) { case RequestType::Get: if (filePath.empty()) { // no file path specified, starts a normal get request returning the normal json result answer = client->Get(uri); } else { // file path ist specified, the result of the get request ist stored in this file // and an empty json object is returned answer = client->Get(uri, filePath); } break; case RequestType::Post: if (nullptr == content) { // warning because normally you won't create an empty ressource MITK_WARN << "Content for put is empty, this will create an empty ressource"; } answer = client->Post(uri, content); break; case RequestType::Put: if (nullptr == content) { // warning because normally you won't empty a ressource MITK_WARN << "Content for put is empty, this will empty the ressource"; } answer = client->Put(uri, content); break; default: mitkThrow() << "Request Type not supported"; break; } return answer; } void mitk::RESTManager::ReceiveRequest(const web::uri &uri, mitk::IRESTObserver *observer) { // New instance of RESTServer in m_ServerMap, key is port of the request int port = uri.port(); // Checking if port is free to add a new Server if (0 == m_ServerMap.count(port)) { this->AddObserver(uri, observer); // creating server instance auto server = new RESTServer(uri.authority()); // add reference to server instance to map m_ServerMap[port] = server; // start Server server->OpenListener(); MITK_INFO << "new server " << mitk::RESTUtil::convertToUtf8(uri.authority().to_string()) << " at port " << port; } // If there is already a server under this port else { this->RequestForATakenPort(uri, observer); } } web::json::value mitk::RESTManager::Handle(const web::uri &uri, const web::json::value &body) { // Checking if there is an observer for the port and path std::pair key(uri.port(), uri.path()); if (0 != m_Observers.count(key)) { return m_Observers[key]->Notify(uri, body); } // No observer under this port, return null which results in status code 404 (s. RESTServer) else { MITK_WARN << "No Observer can handle the data"; return NULL; } } -void mitk::RESTManager::HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri = L"") +void mitk::RESTManager::HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri) { for (auto it = m_Observers.begin(); it != m_Observers.end();) { mitk::IRESTObserver *obsMap = it->second; // Check wether observer is at this place in map if (observer == obsMap) { // Check wether it is the right uri to be deleted if (uri.is_empty() || uri.path() == it->first.second) { int port = it->first.first; bool noObserverForPort = this->DeleteObserver(it, uri); if (noObserverForPort) { // there isn't an observer at this port, delete m_ServerMap entry for this port // close listener m_ServerMap[port]->CloseListener(); delete m_ServerMap[port]; // delete server from map m_ServerMap.erase(port); } } else { ++it; } } else { ++it; } } } const std::map &mitk::RESTManager::GetServerMap() { return m_ServerMap; } std::map, mitk::IRESTObserver *> &mitk::RESTManager::GetObservers() { return m_Observers; } void mitk::RESTManager::AddObserver(const web::uri &uri, IRESTObserver *observer) { // new observer has to be added std::pair key(uri.port(), uri.path()); m_Observers[key] = observer; } void mitk::RESTManager::RequestForATakenPort(const web::uri &uri, IRESTObserver *observer) { // Same host, means new observer but not a new server instance if (uri.authority() == m_ServerMap[uri.port()]->GetUri()) { // new observer has to be added std::pair key(uri.port(), uri.path()); // only add a new observer if there isn't already an observer for this uri if (0 == m_Observers.count(key)) { this->AddObserver(uri, observer); // info output MITK_INFO << "started listening, no new server instance has been created"; } else { MITK_ERROR << "Threre is already a observer handeling this data"; } } // Error, since another server can't be added under this port else { MITK_ERROR << "There is already another server listening under this port"; } } bool mitk::RESTManager::DeleteObserver(std::map, IRESTObserver *>::iterator &it, const web::uri &uri) { // if yes // 1. store port and path in a temporary variable // (path is only needed to create a key for info output) int port = it->first.first; utility::string_t path = it->first.second; std::pair key(port, path); // 2. delete map entry it = m_Observers.erase(it); // 3. check, if there is another observer under this port in observer map (with bool flag) for (auto o : m_Observers) { if (port == o.first.first) { // there still exists an observer for this port return false; } } return true; } void mitk::RESTManager::SetServerMap(const int port, RESTServer *server) { m_ServerMap[port] = server; } void mitk::RESTManager::DeleteFromServerMap(const int port) { m_ServerMap.erase(port); } void mitk::RESTManager::SetObservers(const std::pair key, IRESTObserver *observer) { m_Observers[key] = observer; } diff --git a/Modules/CppRestSdk/test/mitkRESTClientTest.cpp b/Modules/CppRestSdk/test/mitkRESTClientTest.cpp index a0dc6c713f..d5c21d73b0 100644 --- a/Modules/CppRestSdk/test/mitkRESTClientTest.cpp +++ b/Modules/CppRestSdk/test/mitkRESTClientTest.cpp @@ -1,252 +1,252 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Testing #include "mitkTestFixture.h" #include "mitkTestingMacros.h" // MITK includes #include "mitkRESTClient.h" // VTK includes #include #include "mitkIRESTManager.h" #include #include #include #include #include #include class mitkRESTClientTestSuite : public mitk::TestFixture, mitk::IRESTObserver { CPPUNIT_TEST_SUITE(mitkRESTClientTestSuite); MITK_TEST(GetRequestValidURI_ReturnsExpectedJSON); MITK_TEST(MultipleGetRequestValidURI_AllTasksFinish); MITK_TEST(PutRequestValidURI_ReturnsExpectedJSON); MITK_TEST(PostRequestValidURI_ReturnsExpectedJSON); MITK_TEST(GetRequestInvalidURI_ThrowsException); MITK_TEST(PutRequestInvalidURI_ThrowsException); MITK_TEST(PostRequestInvalidURI_ThrowsException); CPPUNIT_TEST_SUITE_END(); public: mitk::IRESTManager *m_Service; web::json::value m_Data; web::json::value Notify(const web::uri &uri, const web::json::value &data) override { return m_Data; } /** * @brief Setup Always call this method before each Test-case to ensure correct and new intialization of the used * members for a new test case. (If the members are not used in a test, the method does not need to be called). */ void setUp() override { - m_Data[L"userId"] = web::json::value(1); - m_Data[L"id"] = web::json::value(1); - m_Data[L"title"] = web::json::value(U("this is a title")); - m_Data[L"body"] = web::json::value(U("this is a body")); + m_Data[_XPLATSTR("userId")] = web::json::value(1); + m_Data[_XPLATSTR("id")] = web::json::value(1); + m_Data[_XPLATSTR("title")] = web::json::value(U("this is a title")); + m_Data[_XPLATSTR("body")] = web::json::value(U("this is a body")); us::ServiceReference serviceRef = us::GetModuleContext()->GetServiceReference(); if (serviceRef) { m_Service = us::GetModuleContext()->GetService(serviceRef); } if (!m_Service) { CPPUNIT_FAIL("Getting Service in setUp() failed"); } - m_Service->ReceiveRequest(L"http://localhost:8080/test", this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8080/test"), this); } void tearDown() override { m_Service->HandleDeleteObserver(this); } void GetRequestValidURI_ReturnsExpectedJSON() { web::json::value *result = new web::json::value(); - m_Service->SendRequest(L"http://localhost:8080/test") + m_Service->SendRequest(_XPLATSTR("http://localhost:8080/test")) .then([=](pplx::task resultTask) { try { *result = resultTask.get(); } catch (const mitk::Exception &exception) { MITK_ERROR << exception.what(); return; } }) .wait(); CPPUNIT_ASSERT_MESSAGE("Result is the expected JSON value", *result == m_Data); } void MultipleGetRequestValidURI_AllTasksFinish() { int *count = new int(0); // Create multiple tasks e.g. as shown below std::vector> tasks; for (int i = 0; i < 20; ++i) { pplx::task singleTask = - m_Service->SendRequest(L"http://localhost:8080/test") + m_Service->SendRequest(_XPLATSTR("http://localhost:8080/test")) .then([=](pplx::task resultTask) { // Do something when a single task is done try { resultTask.get(); *count +=1; } catch (const mitk::Exception &exception) { MITK_ERROR << exception.what(); return; } }); tasks.emplace_back(singleTask); } // Create a joinTask which includes all tasks you've created auto joinTask = pplx::when_all(begin(tasks), end(tasks)); // Run asynchonously joinTask.then([=](pplx::task resultTask) { // Do something when all tasks are finished try { resultTask.get(); *count += 1; } catch (const mitk::Exception &exception) { MITK_ERROR << exception.what(); return; } }).wait(); CPPUNIT_ASSERT_MESSAGE("Multiple Requests", 21 == *count); } void PutRequestValidURI_ReturnsExpectedJSON() { // optional: link might get invalid or content is changed web::json::value *result = new web::json::value(); m_Service - ->SendRequest(L"https://jsonplaceholder.typicode.com/posts/1", mitk::IRESTManager::RequestType::Put, &m_Data) + ->SendRequest(_XPLATSTR("https://jsonplaceholder.typicode.com/posts/1"), mitk::IRESTManager::RequestType::Put, &m_Data) .then([=](pplx::task resultTask) { try { *result = resultTask.get(); } catch (const mitk::Exception &exception) { MITK_ERROR << exception.what(); return; } }) .wait(); CPPUNIT_ASSERT_MESSAGE( "Result is the expected JSON value, check if the link is still valid since this is an optional test", *result == m_Data); } void PostRequestValidURI_ReturnsExpectedJSON() { // optional: link might get invalid or content is changed web::json::value *result = new web::json::value(); web::json::value data; - data[L"userId"] = m_Data[L"userId"]; - data[L"title"] = m_Data[L"title"]; - data[L"body"] = m_Data[L"body"]; + data[_XPLATSTR("userId")] = m_Data[_XPLATSTR("userId")]; + data[_XPLATSTR("title")] = m_Data[_XPLATSTR("title")]; + data[_XPLATSTR("body")] = m_Data[_XPLATSTR("body")]; - m_Service->SendRequest(L"https://jsonplaceholder.typicode.com/posts", mitk::IRESTManager::RequestType::Post, &data) + m_Service->SendRequest(_XPLATSTR("https://jsonplaceholder.typicode.com/posts"), mitk::IRESTManager::RequestType::Post, &data) .then([=](pplx::task resultTask) { try { *result = resultTask.get(); } catch (const mitk::Exception &exception) { MITK_ERROR << exception.what(); return; } }) .wait(); - data[L"id"] = web::json::value(101); + data[_XPLATSTR("id")] = web::json::value(101); CPPUNIT_ASSERT_MESSAGE( "Result is the expected JSON value, check if the link is still valid since this is an optional test", *result == data); } void GetException() { //Method which makes a get request to an invalid uri web::json::value *result = new web::json::value(); - m_Service->SendRequest(L"http://localhost:1234/invalid") + m_Service->SendRequest(_XPLATSTR("http://localhost:1234/invalid")) .then([=](pplx::task resultTask) { *result = resultTask.get(); }) .wait(); } void GetRequestInvalidURI_ThrowsException() { CPPUNIT_ASSERT_THROW(GetException(), mitk::Exception); } void PutException() { //Method which makes a put request to an invalid uri web::json::value *result = new web::json::value(); - m_Service->SendRequest(L"http://localhost:1234/invalid", mitk::IRESTManager::RequestType::Put, &m_Data) + m_Service->SendRequest(_XPLATSTR("http://localhost:1234/invalid"), mitk::IRESTManager::RequestType::Put, &m_Data) .then([=](pplx::task resultTask) { *result = resultTask.get();}) .wait(); } void PutRequestInvalidURI_ThrowsException() { CPPUNIT_ASSERT_THROW(PutException(), mitk::Exception); } void PostException() { //Method which makes a post request to an invalid uri web::json::value *result = new web::json::value(); - m_Service->SendRequest(L"http://localhost:1234/invalid", mitk::IRESTManager::RequestType::Post, &m_Data) + m_Service->SendRequest(_XPLATSTR("http://localhost:1234/invalid"), mitk::IRESTManager::RequestType::Post, &m_Data) .then([=](pplx::task resultTask) { *result = resultTask.get(); }) .wait(); } void PostRequestInvalidURI_ThrowsException() { CPPUNIT_ASSERT_THROW(PostException(), mitk::Exception); } }; -MITK_TEST_SUITE_REGISTRATION(mitkRESTClient) \ No newline at end of file +MITK_TEST_SUITE_REGISTRATION(mitkRESTClient) diff --git a/Modules/CppRestSdk/test/mitkRESTServerTest.cpp b/Modules/CppRestSdk/test/mitkRESTServerTest.cpp index 8fb6b6ea9a..bc0473954f 100644 --- a/Modules/CppRestSdk/test/mitkRESTServerTest.cpp +++ b/Modules/CppRestSdk/test/mitkRESTServerTest.cpp @@ -1,217 +1,217 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Testing #include "mitkTestFixture.h" #include "mitkTestingMacros.h" // MITK includes #include "mitkRESTServer.h" // VTK includes #include class mitkRESTServerTestSuite : public mitk::TestFixture, mitk::IRESTObserver { CPPUNIT_TEST_SUITE(mitkRESTServerTestSuite); MITK_TEST(OpenListener_Succeed); MITK_TEST(TwoListenerSameHostSamePort_OnlyOneOpened); MITK_TEST(CloseListener_Succeed); MITK_TEST(OpenMultipleListenerCloseOne_Succeed); MITK_TEST(OpenMultipleListenerCloseAll_Succeed); MITK_TEST(OpenListenerGetRequestSamePath_ReturnExpectedJSON); MITK_TEST(CloseListener_NoRequestPossible); MITK_TEST(OpenListenerGetRequestDifferentPath_ReturnNotFound); MITK_TEST(OpenListenerCloseAndReopen_Succeed); CPPUNIT_TEST_SUITE_END(); public: mitk::IRESTManager *m_Service; web::json::value m_Data; web::json::value Notify(const web::uri &uri, const web::json::value &data) override { return m_Data; } /** * @brief Setup Always call this method before each Test-case to ensure correct and new intialization of the used * members for a new test case. (If the members are not used in a test, the method does not need to be called). */ void setUp() override { - m_Data[L"userId"] = web::json::value(1); - m_Data[L"id"] = web::json::value(1); - m_Data[L"title"] = web::json::value(U("this is a title")); - m_Data[L"body"] = web::json::value(U("this is a body")); + m_Data[_XPLATSTR("userId")] = web::json::value(1); + m_Data[_XPLATSTR("id")] = web::json::value(1); + m_Data[_XPLATSTR("title")] = web::json::value(U("this is a title")); + m_Data[_XPLATSTR("body")] = web::json::value(U("this is a body")); us::ServiceReference serviceRef = us::GetModuleContext()->GetServiceReference(); if (serviceRef) { m_Service = us::GetModuleContext()->GetService(serviceRef); } if (!m_Service) { CPPUNIT_FAIL("Getting Service in setUp() failed"); } } void tearDown() override { m_Service->HandleDeleteObserver(this); } void OpenListener_Succeed() { - m_Service->ReceiveRequest(L"http://localhost:8080/test", this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8080/test"), this); CPPUNIT_ASSERT_MESSAGE("Open one listener, observer map size is one", 1 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Open one listener, server map size is one", 1 == m_Service->GetServerMap().size()); } void TwoListenerSameHostSamePort_OnlyOneOpened() { - m_Service->ReceiveRequest(L"http://localhost:8080/test", this); - m_Service->ReceiveRequest(L"http://localhost:8080/example", this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8080/test"), this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8080/example"), this); CPPUNIT_ASSERT_MESSAGE("Open two listener with a different path,same host, same port, observer map size is two", 2 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Open two listener with a different path,same host, same port, server map size is one", 1 == m_Service->GetServerMap().size()); } void CloseListener_Succeed() { - m_Service->ReceiveRequest(L"http://localhost:8080/test", this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8080/test"), this); CPPUNIT_ASSERT_MESSAGE("Open one listener, observer map size is one", 1 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Open one listener, server map size is one", 1 == m_Service->GetServerMap().size()); m_Service->HandleDeleteObserver(this); CPPUNIT_ASSERT_MESSAGE("Closed listener, observer map is empty", 0 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Closed listener, server map is empty", 0 == m_Service->GetServerMap().size()); } void OpenMultipleListenerCloseOne_Succeed() { - m_Service->ReceiveRequest(L"http://localhost:8080/test", this); - m_Service->ReceiveRequest(L"http://localhost:8090/example", this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8080/test"), this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8090/example"), this); CPPUNIT_ASSERT_MESSAGE("Open two listener, observer map size is two", 2 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Open two listener, server map size is two", 2 == m_Service->GetServerMap().size()); - m_Service->HandleDeleteObserver(this, L"http://localhost:8080/test"); + m_Service->HandleDeleteObserver(this, _XPLATSTR("http://localhost:8080/test")); CPPUNIT_ASSERT_MESSAGE("Closed one of two listeners, observer map is size is one", 1 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Closed one of two listener, server map size is one", 1 == m_Service->GetServerMap().size()); } void OpenMultipleListenerCloseAll_Succeed() { - m_Service->ReceiveRequest(L"http://localhost:8080/test", this); - m_Service->ReceiveRequest(L"http://localhost:8090/example", this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8080/test"), this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8090/example"), this); CPPUNIT_ASSERT_MESSAGE("Open two listener, observer map size is two", 2 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Open two listener, server map size is two", 2 == m_Service->GetServerMap().size()); m_Service->HandleDeleteObserver(this); CPPUNIT_ASSERT_MESSAGE("Closed all listeners, observer map is empty", 0 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Closed all listeners, server map is empty", 0 == m_Service->GetServerMap().size()); } void OpenListenerGetRequestSamePath_ReturnExpectedJSON() { - m_Service->ReceiveRequest(L"http://localhost:8080/test", this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8080/test"), this); web::json::value *result = new web::json::value(); - m_Service->SendRequest(L"http://localhost:8080/test") + m_Service->SendRequest(_XPLATSTR("http://localhost:8080/test")) .then([=](pplx::task resultTask) { try { *result = resultTask.get(); } catch (const mitk::Exception &exception) { MITK_ERROR << exception.what(); return; } }) .wait(); CPPUNIT_ASSERT_MESSAGE("Opened listener and send request to same uri, returned expected JSON", *result == m_Data); } void RequestToClosedListener() { web::json::value *result = new web::json::value(); - m_Service->SendRequest(L"http://localhost:8080/test") + m_Service->SendRequest(_XPLATSTR("http://localhost:8080/test")) .then([=](pplx::task resultTask) { *result = resultTask.get(); }) .wait(); } void CloseListener_NoRequestPossible() { - m_Service->ReceiveRequest(L"http://localhost:8080/test", this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8080/test"), this); CPPUNIT_ASSERT_MESSAGE("Open one listener, observer map size is one", 1 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Open one listener, server map size is one", 1 == m_Service->GetServerMap().size()); m_Service->HandleDeleteObserver(this); CPPUNIT_ASSERT_MESSAGE("Closed listener, observer map is empty", 0 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Closed listener, server map is empty", 0 == m_Service->GetServerMap().size()); CPPUNIT_ASSERT_THROW(RequestToClosedListener(), mitk::Exception); } void RequestToDifferentPathNotFound() { - m_Service->ReceiveRequest(L"http://localhost:8080/test", this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8080/test"), this); web::json::value *result = new web::json::value(); - m_Service->SendRequest(L"http://localhost:8080/example") + m_Service->SendRequest(_XPLATSTR("http://localhost:8080/example")) .then([=](pplx::task resultTask) { *result = resultTask.get(); }) .wait(); } void OpenListenerGetRequestDifferentPath_ReturnNotFound() { CPPUNIT_ASSERT_THROW(RequestToDifferentPathNotFound(), mitk::Exception); } void OpenListenerCloseAndReopen_Succeed() { - m_Service->ReceiveRequest(L"http://localhost:8080/test", this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8080/test"), this); CPPUNIT_ASSERT_MESSAGE("Open one listener, observer map size is one", 1 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Open one listener, server map size is one", 1 == m_Service->GetServerMap().size()); m_Service->HandleDeleteObserver(this); CPPUNIT_ASSERT_MESSAGE("Closed listener, observer map is empty", 0 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Closed listener, server map is empty", 0 == m_Service->GetServerMap().size()); - m_Service->ReceiveRequest(L"http://localhost:8080/test", this); + m_Service->ReceiveRequest(_XPLATSTR("http://localhost:8080/test"), this); CPPUNIT_ASSERT_MESSAGE("Reopened listener, observer map size is one", 1 == m_Service->GetObservers().size()); CPPUNIT_ASSERT_MESSAGE("Reopened listener, server map size is one", 1 == m_Service->GetServerMap().size()); } }; -MITK_TEST_SUITE_REGISTRATION(mitkRESTServer) \ No newline at end of file +MITK_TEST_SUITE_REGISTRATION(mitkRESTServer) diff --git a/Modules/CppRestSdkQt/include/mitkRESTManagerQt.h b/Modules/CppRestSdkQt/include/mitkRESTManagerQt.h index 1cbc47bdfa..2d18707e64 100644 --- a/Modules/CppRestSdkQt/include/mitkRESTManagerQt.h +++ b/Modules/CppRestSdkQt/include/mitkRESTManagerQt.h @@ -1,69 +1,69 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkRESTManagerQt_h #define mitkRESTManagerQt_h #include #include #include #include #include #include #include namespace mitk { /** * @class RESTManagerQt * @brief this is a microservice for managing REST-requests, used for Qt applications. * * This class inherits from the RESTManager in the CppRestSdk Module, which is the equivalent service for * non-Qt applications. */ class MITKCPPRESTSDKQT_EXPORT RESTManagerQt : public QObject, public RESTManager { Q_OBJECT public: RESTManagerQt(); ~RESTManagerQt() override; /** * @brief starts listening for requests if there isn't another observer listening and the port is free * * @param uri defines the URI for which incoming requests should be send to the observer * @param observer the observer which handles the incoming requests */ void ReceiveRequest(const web::uri &uri, IRESTObserver *observer) override; /** * @brief Handles the deletion of an observer for all or a specific uri * * @param observer the observer which shouldn't receive requests anymore * @param uri the uri for which the observer doesn't handle requests anymore (optional) */ - void HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri) override; + void HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri = {}) override; private: std::map m_ServerThreadMap; // Map with threads for servers }; } // namespace mitk #endif // !mitkRESTManager_h \ No newline at end of file diff --git a/Modules/CppRestSdkQt/src/mitkRESTManagerQt.cpp b/Modules/CppRestSdkQt/src/mitkRESTManagerQt.cpp index d9bac35b67..0d5f84ca5d 100644 --- a/Modules/CppRestSdkQt/src/mitkRESTManagerQt.cpp +++ b/Modules/CppRestSdkQt/src/mitkRESTManagerQt.cpp @@ -1,80 +1,80 @@ #include "mitkRESTManagerQt.h" #include #include mitk::RESTManagerQt::RESTManagerQt() {} mitk::RESTManagerQt::~RESTManagerQt() {} void mitk::RESTManagerQt::ReceiveRequest(const web::uri &uri, mitk::IRESTObserver *observer) { // New instance of RESTServer in m_ServerMap, key is port of the request int port = uri.port(); // Checking if port is free to add a new Server if (0 == GetServerMap().count(port)) { mitk::RESTManager::AddObserver(uri, observer); // creating server instance auto server = new RESTServerQt(uri.authority()); // add reference to server instance to map mitk::RESTManager::SetServerMap(port, server); // Move server to seperate Thread and create connections between threads m_ServerThreadMap[port] = new QThread; server->moveToThread(m_ServerThreadMap[port]); connect(m_ServerThreadMap[port], &QThread::finished, server, &QObject::deleteLater); // starting Server m_ServerThreadMap[port]->start(); QMetaObject::invokeMethod(server, "OpenListener"); MITK_INFO << "new server " << mitk::RESTUtil::convertToUtf8(uri.authority().to_string()) << " at port " << port; } // If there is already a server under this port else { mitk::RESTManager::RequestForATakenPort(uri, observer); } } -void mitk::RESTManagerQt::HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri = L"") +void mitk::RESTManagerQt::HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri) { auto &observerMap = mitk::RESTManager::GetObservers(); for (auto it = observerMap.begin(); it != observerMap.end();) { mitk::IRESTObserver *obsMap = it->second; // Check wether observer is at this place in map if (observer == obsMap) { // Check wether it is the right uri to be deleted if (uri.is_empty() || uri.path() == it->first.second) { int port = it->first.first; bool noObserverForPort = mitk::RESTManager::DeleteObserver(it, uri); if (noObserverForPort) { // there isn't an observer at this port, delete m_ServerMap entry for this port // close listener QMetaObject::invokeMethod(static_cast(mitk::RESTManager::GetServerMap().at(port)), "CloseListener"); // end thread m_ServerThreadMap[port]->quit(); m_ServerThreadMap[port]->wait(); // delete server from map mitk::RESTManager::DeleteFromServerMap(port); } } else { ++it; } } else { ++it; } } }