changeset 899:bb0a51561016 plugins

refactoring
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 18 Jun 2014 13:29:09 +0200
parents 7000fc86fe62
children 1b92ce45cc8d
files Core/HttpServer/MongooseServer.cpp Core/HttpServer/MongooseServer.h OrthancServer/main.cpp Plugins/Engine/IPluginServiceProvider.h Plugins/Engine/PluginsHttpHandler.cpp Plugins/Engine/PluginsHttpHandler.h Plugins/Engine/PluginsManager.cpp Plugins/Engine/PluginsManager.h Plugins/OrthancCPlugin/OrthancCPlugin.h Resources/Samples/Plugins/Basic/Plugin.c
diffstat 10 files changed, 201 insertions(+), 130 deletions(-) [+]
line wrap: on
line diff
--- a/Core/HttpServer/MongooseServer.cpp	Wed Jun 18 09:18:28 2014 +0200
+++ b/Core/HttpServer/MongooseServer.cpp	Wed Jun 18 13:29:09 2014 +0200
@@ -843,23 +843,17 @@
   }
 
 
-  void MongooseServer::RegisterHandler(HttpHandler* handler)
+  void MongooseServer::RegisterHandler(HttpHandler& handler)
   {
     Stop();
 
-    handlers_.push_back(handler);
+    handlers_.push_back(&handler);
   }
 
 
   void MongooseServer::ClearHandlers()
   {
     Stop();
-
-    for (Handlers::iterator it = 
-           handlers_.begin(); it != handlers_.end(); ++it)
-    {
-      delete *it;
-    }
   }
 
 
--- a/Core/HttpServer/MongooseServer.h	Wed Jun 18 09:18:28 2014 +0200
+++ b/Core/HttpServer/MongooseServer.h	Wed Jun 18 13:29:09 2014 +0200
@@ -100,7 +100,7 @@
     void RegisterUser(const char* username,
                       const char* password);
 
-    void RegisterHandler(HttpHandler* handler);  // This takes the ownership
+    void RegisterHandler(HttpHandler& handler);
 
     bool IsAuthenticationEnabled() const
     {
--- a/OrthancServer/main.cpp	Wed Jun 18 09:18:28 2014 +0200
+++ b/OrthancServer/main.cpp	Wed Jun 18 13:29:09 2014 +0200
@@ -374,7 +374,10 @@
 
     LoadLuaScripts(context);
 
+    PluginsHttpHandler httpPlugins;
+
     PluginsManager pluginsManager;
+    pluginsManager.RegisterServiceProvider(httpPlugins);
     LoadPlugins(pluginsManager);
 
     try
@@ -432,15 +435,17 @@
         httpServer.SetSslEnabled(false);
       }
 
-      httpServer.RegisterHandler(new PluginsHttpHandler(pluginsManager));
+      OrthancRestApi restApi(context);
 
 #if ORTHANC_STANDALONE == 1
-      httpServer.RegisterHandler(new EmbeddedResourceHttpHandler("/app", EmbeddedResources::ORTHANC_EXPLORER));
+      EmbeddedResourceHttpHandler staticResources("/app", EmbeddedResources::ORTHANC_EXPLORER);
 #else
-      httpServer.RegisterHandler(new FilesystemHttpHandler("/app", ORTHANC_PATH "/OrthancExplorer"));
+      FilesystemHttpHandler staticResources("/app", ORTHANC_PATH "/OrthancExplorer");
 #endif
 
-      httpServer.RegisterHandler(new OrthancRestApi(context));
+      httpServer.RegisterHandler(httpPlugins);
+      httpServer.RegisterHandler(staticResources);
+      httpServer.RegisterHandler(restApi);
 
       // GO !!! Start the requested servers
       if (Configuration::GetGlobalBoolParameter("HttpServerEnabled", true))
--- a/Plugins/Engine/IPluginServiceProvider.h	Wed Jun 18 09:18:28 2014 +0200
+++ b/Plugins/Engine/IPluginServiceProvider.h	Wed Jun 18 13:29:09 2014 +0200
@@ -41,9 +41,11 @@
   class IPluginServiceProvider : boost::noncopyable
   {
   public:
-    virtual ~IPluginServiceProvider();
+    virtual ~IPluginServiceProvider()
+    {
+    }
 
-    virtual bool Handle(OrthancPluginService service,
-                        const void* parameters) = 0;
+    virtual bool InvokeService(OrthancPluginService service,
+                               const void* parameters) = 0;
   };
 }
--- a/Plugins/Engine/PluginsHttpHandler.cpp	Wed Jun 18 09:18:28 2014 +0200
+++ b/Plugins/Engine/PluginsHttpHandler.cpp	Wed Jun 18 13:29:09 2014 +0200
@@ -34,6 +34,7 @@
 
 #include "../../Core/OrthancException.h"
 #include "../../Core/Toolbox.h"
+#include "../../Core/HttpServer/HttpOutput.h"
 
 #include <boost/regex.hpp> 
 #include <glog/logging.h>
@@ -54,15 +55,9 @@
   };
 
 
-  PluginsHttpHandler::PluginsHttpHandler(const PluginsManager& manager)
+  PluginsHttpHandler::PluginsHttpHandler()
   {
     pimpl_.reset(new PImpl);
-
-    for (PluginsManager::RestCallbacks::const_iterator
-           it = manager.GetRestCallbacks().begin(); it != manager.GetRestCallbacks().end(); ++it)
-    {
-      pimpl_->callbacks_.push_back(std::make_pair(new boost::regex(it->first), it->second));
-    }
   }
 
   
@@ -108,12 +103,14 @@
     std::vector<const char*> getKeys(getArguments.size());
     std::vector<const char*> getValues(getArguments.size());
 
-    OrthancPluginHttpMethod methodPlugin;
+    OrthancPluginHttpRequest request;
+    memset(&request, 0, sizeof(OrthancPluginHttpRequest));
+
     switch (method)
     {
       case HttpMethod_Get:
       {
-        methodPlugin = OrthancPluginHttpMethod_Get;
+        request.method = OrthancPluginHttpMethod_Get;
 
         size_t i = 0;
         for (Arguments::const_iterator it = getArguments.begin(); 
@@ -127,29 +124,36 @@
       }
 
       case HttpMethod_Post:
-        methodPlugin = OrthancPluginHttpMethod_Post;
+        request.method = OrthancPluginHttpMethod_Post;
         break;
 
       case HttpMethod_Delete:
-        methodPlugin = OrthancPluginHttpMethod_Delete;
+        request.method = OrthancPluginHttpMethod_Delete;
         break;
 
       case HttpMethod_Put:
-        methodPlugin = OrthancPluginHttpMethod_Put;
+        request.method = OrthancPluginHttpMethod_Put;
         break;
 
       default:
         throw OrthancException(ErrorCode_InternalError);
     }
 
+
+    request.getCount = getArguments.size();
+    request.body = (postData.size() ? &postData[0] : NULL);
+    request.bodySize = postData.size();
+
+    if (getArguments.size() > 0)
+    {
+      request.getKeys = &getKeys[0];
+      request.getValues = &getValues[0];
+    }
+
     assert(pimpl_->currentCallback_ != NULL);
-    assert(getKeys.size() == getValues.size());
     int32_t error = (*pimpl_->currentCallback_) (reinterpret_cast<OrthancPluginRestOutput*>(&output), 
-                                                 methodPlugin, flatUri.c_str(), 
-                                                 getKeys.size() ? &getKeys[0] : NULL,
-                                                 getKeys.size() ? &getValues[0] : NULL,
-                                                 getKeys.size(), 
-                                                 postData.size() ? &postData[0] : NULL, postData.size());
+                                                 flatUri.c_str(), 
+                                                 &request);
 
     if (error < 0)
     {
@@ -166,4 +170,68 @@
       return true;
     }
   }
+
+
+  bool PluginsHttpHandler::InvokeService(OrthancPluginService service,
+                                         const void* parameters)
+  {
+
+
+    /*void PluginsManager::RegisterRestCallback(const OrthancPluginContext* context,
+      const char* pathRegularExpression, 
+      OrthancPluginRestCallback callback)
+      {
+      LOG(INFO) << "Plugin has registered a REST callback on: " << pathRegularExpression;
+      PluginsManager* manager = reinterpret_cast<PluginsManager*>(context->pluginsManager);
+      manager->restCallbacks_.push_back(std::make_pair(pathRegularExpression, callback));
+      }*/
+
+
+    /*static void AnswerBuffer(OrthancPluginRestOutput* output,
+      const char* answer,
+      uint32_t answerSize,
+      const char* mimeType)
+      {
+      HttpOutput* translatedOutput = reinterpret_cast<HttpOutput*>(output);
+      translatedOutput->AnswerBufferWithContentType(answer, answerSize, mimeType);
+      }*/
+
+
+
+    /*for (PluginsManager::RestCallbacks::const_iterator
+           it = manager.GetRestCallbacks().begin(); it != manager.GetRestCallbacks().end(); ++it)
+    {
+      pimpl_->callbacks_.push_back(std::make_pair(new boost::regex(it->first), it->second));
+      }*/
+
+
+    switch (service)
+    {
+      case OrthancPluginService_RegisterRestCallback:
+      {
+        const OrthancPluginRestCallbackParams& p = 
+          *reinterpret_cast<const OrthancPluginRestCallbackParams*>(parameters);
+
+        LOG(INFO) << "Plugin has registered a REST callback on: " << p.pathRegularExpression;
+        pimpl_->callbacks_.push_back(std::make_pair(new boost::regex(p.pathRegularExpression), p.callback));
+
+        return true;
+      }
+
+      case OrthancPluginService_AnswerBuffer:
+      {
+        const OrthancPluginAnswerBufferParams& p = 
+          *reinterpret_cast<const OrthancPluginAnswerBufferParams*>(parameters);
+
+        HttpOutput* translatedOutput = reinterpret_cast<HttpOutput*>(p.output);
+        translatedOutput->AnswerBufferWithContentType(p.answer, p.answerSize, p.mimeType);
+
+        return true;
+      }
+
+      default:
+        return false;
+    }
+  }
+
 }
--- a/Plugins/Engine/PluginsHttpHandler.h	Wed Jun 18 09:18:28 2014 +0200
+++ b/Plugins/Engine/PluginsHttpHandler.h	Wed Jun 18 13:29:09 2014 +0200
@@ -40,7 +40,7 @@
 
 namespace Orthanc
 {
-  class PluginsHttpHandler : public HttpHandler
+  class PluginsHttpHandler : public HttpHandler, public IPluginServiceProvider
   {
   private:
     struct PImpl;
@@ -48,7 +48,7 @@
     boost::shared_ptr<PImpl> pimpl_;
 
   public:
-    PluginsHttpHandler(const PluginsManager& manager);
+    PluginsHttpHandler();
 
     virtual ~PluginsHttpHandler();
 
@@ -60,5 +60,8 @@
                         const Arguments& headers,
                         const Arguments& getArguments,
                         const std::string& postData);
+
+    virtual bool InvokeService(OrthancPluginService service,
+                               const void* parameters);
   };
 }
--- a/Plugins/Engine/PluginsManager.cpp	Wed Jun 18 09:18:28 2014 +0200
+++ b/Plugins/Engine/PluginsManager.cpp	Wed Jun 18 13:29:09 2014 +0200
@@ -134,20 +134,20 @@
 
   int32_t PluginsManager::InvokeService(OrthancPluginContext* context,
                                         OrthancPluginService service, 
-                                        const void* parameters)
+                                        const void* params)
   {
     switch (service)
     {
       case OrthancPluginService_LogError:
-        LOG(ERROR) << reinterpret_cast<const char*>(parameters);
+        LOG(ERROR) << reinterpret_cast<const char*>(params);
         return 0;
 
       case OrthancPluginService_LogWarning:
-        LOG(WARNING) << reinterpret_cast<const char*>(parameters);
+        LOG(WARNING) << reinterpret_cast<const char*>(params);
         return 0;
 
       case OrthancPluginService_LogInfo:
-        LOG(INFO) << reinterpret_cast<const char*>(parameters);
+        LOG(INFO) << reinterpret_cast<const char*>(params);
         return 0;
 
       default:
@@ -156,10 +156,21 @@
 
     PluginsManager* that = reinterpret_cast<PluginsManager*>(context->pluginsManager);
 
-    if (that->HasServiceProvider() &&
-        that->serviceProvider_->Handle(service, parameters))
+    for (std::list<IPluginServiceProvider*>::iterator
+           it = that->serviceProviders_.begin(); 
+         it != that->serviceProviders_.end(); it++)
     {
-      return 0;
+      try
+      {
+        if ((*it)->InvokeService(service, params))
+        {
+          return 0;
+        }
+      }
+      catch (OrthancException&)
+      {
+        // This service provider has failed, go to the next
+      }
     }
 
     LOG(ERROR) << "Plugin invoking unknown service " << service;
@@ -167,36 +178,13 @@
   }
 
 
-  void PluginsManager::RegisterRestCallback(const OrthancPluginContext* context,
-                                            const char* pathRegularExpression, 
-                                            OrthancPluginRestCallback callback)
-  {
-    LOG(INFO) << "Plugin has registered a REST callback on: " << pathRegularExpression;
-    PluginsManager* manager = reinterpret_cast<PluginsManager*>(context->pluginsManager);
-    manager->restCallbacks_.push_back(std::make_pair(pathRegularExpression, callback));
-  }
-
-
-  static void AnswerBuffer(OrthancPluginRestOutput* output,
-                           const char* answer,
-                           uint32_t answerSize,
-                           const char* mimeType)
-  {
-    HttpOutput* translatedOutput = reinterpret_cast<HttpOutput*>(output);
-    translatedOutput->AnswerBufferWithContentType(answer, answerSize, mimeType);
-  }
-
-
-  PluginsManager::PluginsManager() : 
-    serviceProvider_(NULL)
+  PluginsManager::PluginsManager()
   {
     memset(&context_, 0, sizeof(context_));
     context_.pluginsManager = this;
     context_.orthancVersion = ORTHANC_VERSION;
     context_.FreeBuffer = ::free;
     context_.InvokeService = InvokeService;
-    context_.RegisterRestCallback = RegisterRestCallback;
-    context_.AnswerBuffer = AnswerBuffer;
   }
 
   PluginsManager::~PluginsManager()
@@ -298,17 +286,4 @@
       }
     }
   }
-
-
-  IPluginServiceProvider& PluginsManager::GetServiceProvider() const
-  {
-    if (!HasServiceProvider())
-    {
-      throw OrthancException(ErrorCode_BadRequest);
-    }
-    else
-    {
-      return *serviceProvider_;
-    }
-  }
 }
--- a/Plugins/Engine/PluginsManager.h	Wed Jun 18 09:18:28 2014 +0200
+++ b/Plugins/Engine/PluginsManager.h	Wed Jun 18 13:29:09 2014 +0200
@@ -42,25 +42,17 @@
 {
   class PluginsManager : boost::noncopyable
   {
-  public:
-    typedef std::list< std::pair<std::string, OrthancPluginRestCallback> >  RestCallbacks;
-
   private:
     typedef std::map<std::string, SharedLibrary*>  Plugins;
 
     OrthancPluginContext  context_;
     Plugins  plugins_;
-    RestCallbacks  restCallbacks_;
-    IPluginServiceProvider *serviceProvider_;
+    std::list<IPluginServiceProvider*> serviceProviders_;
 
     static int32_t InvokeService(OrthancPluginContext* context,
                                  OrthancPluginService service,
                                  const void* parameters);
 
-    static void RegisterRestCallback(const OrthancPluginContext* context,
-                                     const char* path, 
-                                     OrthancPluginRestCallback callback);
-
   public:
     PluginsManager();
 
@@ -71,21 +63,9 @@
     void ScanFolderForPlugins(const std::string& path,
                               bool isRecursive);
 
-    void SetServiceProvider(IPluginServiceProvider& provider)
-    {
-      serviceProvider_ = &provider;
-    }
-
-    bool HasServiceProvider() const
+    void RegisterServiceProvider(IPluginServiceProvider& provider)
     {
-      return serviceProvider_ != NULL;
-    }
-
-    IPluginServiceProvider& GetServiceProvider() const;
-
-    const RestCallbacks& GetRestCallbacks() const
-    {
-      return restCallbacks_;
+      serviceProviders_.push_back(&provider);
     }
   };
 }
--- a/Plugins/OrthancCPlugin/OrthancCPlugin.h	Wed Jun 18 09:18:28 2014 +0200
+++ b/Plugins/OrthancCPlugin/OrthancCPlugin.h	Wed Jun 18 13:29:09 2014 +0200
@@ -110,18 +110,35 @@
 
   typedef enum 
   {
+    /* Generic services */
     OrthancPluginService_LogInfo = 1,
     OrthancPluginService_LogWarning = 2,
-    OrthancPluginService_LogError = 3
+    OrthancPluginService_LogError = 3,
+
+    /* Registration of callbacks */
+    OrthancPluginService_RegisterRestCallback = 1000,
+
+    /* Sending answers to REST calls */
+    OrthancPluginService_AnswerBuffer = 2000
   } OrthancPluginService;
 
+  typedef struct
+  {
+    OrthancPluginHttpMethod method;
+
+    /* For GET requests */
+    const char* const*      getKeys;
+    const char* const*      getValues;
+    uint32_t                getCount;
+
+    /* For POST and PUT requests */
+    const char*             body;
+    uint32_t                bodySize;
+  } OrthancPluginHttpRequest;
+
   typedef int32_t (*OrthancPluginRestCallback) (OrthancPluginRestOutput* output,
-                                                OrthancPluginHttpMethod method,
                                                 const char* url,
-                                                const char* const* getKeys,
-                                                const char* const* getValues,
-                                                uint32_t getSize,
-                                                const char* body, uint32_t bodySize);
+                                                const OrthancPluginHttpRequest* request);
 
   typedef struct OrthancPluginContext_t
   {
@@ -131,18 +148,24 @@
     void (*FreeBuffer) (void* buffer);
     int32_t (*InvokeService) (struct OrthancPluginContext_t* context,
                               OrthancPluginService service,
-                              const void* parameters);
+                              const void* params);
+  } OrthancPluginContext;
+
 
-    /* REST API */
-    void (*RegisterRestCallback) (const struct OrthancPluginContext_t* context,
-                                  const char* pathRegularExpression, 
-                                  OrthancPluginRestCallback callback);
+  typedef struct
+  {
+    const char* pathRegularExpression;
+    OrthancPluginRestCallback callback;
+  } OrthancPluginRestCallbackParams;
+
 
-    void (*AnswerBuffer) (OrthancPluginRestOutput* output,
-                          const char* answer,
-                          uint32_t answerSize,
-                          const char* mimeType);
-  } OrthancPluginContext;
+  typedef struct
+  {
+    OrthancPluginRestOutput* output;
+    const char*              answer;
+    uint32_t                 answerSize;
+    const char*              mimeType;
+  } OrthancPluginAnswerBufferParams;
 
 
   ORTHANC_PLUGIN_INLINE void OrthancPluginLogError(OrthancPluginContext* context,
@@ -166,6 +189,32 @@
   }
 
 
+  ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterRestCallback(OrthancPluginContext* context,
+                                                               const char* pathRegularExpression,
+                                                               OrthancPluginRestCallback callback)
+  {
+    OrthancPluginRestCallbackParams params;
+    params.pathRegularExpression = pathRegularExpression;
+    params.callback = callback;
+    context->InvokeService(context, OrthancPluginService_RegisterRestCallback, &params);
+  }
+
+
+  ORTHANC_PLUGIN_INLINE void OrthancPluginAnswerBuffer(OrthancPluginContext*    context,
+                                                       OrthancPluginRestOutput* output,
+                                                       const char*              answer,
+                                                       uint32_t                 answerSize,
+                                                       const char*              mimeType)
+  {
+    OrthancPluginAnswerBufferParams params;
+    params.output = output;
+    params.answer = answer;
+    params.answerSize = answerSize;
+    params.mimeType = mimeType;
+    context->InvokeService(context, OrthancPluginService_AnswerBuffer, &params);
+  }
+
+
 
   /**
      Each plugin must define 4 functions, whose signature are:
--- a/Resources/Samples/Plugins/Basic/Plugin.c	Wed Jun 18 09:18:28 2014 +0200
+++ b/Resources/Samples/Plugins/Basic/Plugin.c	Wed Jun 18 13:29:09 2014 +0200
@@ -34,25 +34,20 @@
 
 
 ORTHANC_PLUGINS_API int32_t Callback(OrthancPluginRestOutput* output,
-                                     OrthancPluginHttpMethod method,
                                      const char* url,
-                                     const char* const* getKeys,
-                                     const char* const* getValues,
-                                     uint32_t getSize,
-                                     const char* body,
-                                     uint32_t bodySize)
+                                     const OrthancPluginHttpRequest* request)
 {
   char buffer[1024];
   uint32_t i;
 
-  sprintf(buffer, "Callback on URL [%s] with body [%s]", url, body);
+  sprintf(buffer, "Callback on URL [%s] with body [%s]", url, request->body);
   OrthancPluginLogInfo(context, buffer);
 
-  context->AnswerBuffer(output, buffer, strlen(buffer), "text/plain");
+  OrthancPluginAnswerBuffer(context, output, buffer, strlen(buffer), "text/plain");
 
-  for (i = 0; i < getSize; i++)
+  for (i = 0; i < request->getCount; i++)
   {
-    sprintf(buffer, "  [%s] = [%s]", getKeys[i], getValues[i]);
+    sprintf(buffer, "  [%s] = [%s]", request->getKeys[i], request->getValues[i]);
     OrthancPluginLogInfo(context, buffer);    
   }
 
@@ -70,7 +65,7 @@
   sprintf(info, "The version of Orthanc is '%s'", context->orthancVersion);
   OrthancPluginLogInfo(context, info);
 
-  context->RegisterRestCallback(c, "/plu.*/hello", Callback);
+  OrthancPluginRegisterRestCallback(context, "/plu.*/hello", Callback);
 
   return 0;
 }