diff Plugins/Engine/PluginsManager.cpp @ 888:d44b845c1c89 plugins

recursive scan for plugins
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sat, 14 Jun 2014 19:47:51 +0200
parents 4066e6f2d134
children d2a393061eb6
line wrap: on
line diff
--- a/Plugins/Engine/PluginsManager.cpp	Sat Jun 14 19:20:38 2014 +0200
+++ b/Plugins/Engine/PluginsManager.cpp	Sat Jun 14 19:47:51 2014 +0200
@@ -35,6 +35,16 @@
 #include <glog/logging.h>
 #include <cassert>
 #include <memory>
+#include <boost/filesystem.hpp>
+
+#ifdef WIN32
+#define PLUGIN_EXTENSION ".dll"
+#elif defined(__linux)
+#define PLUGIN_EXTENSION ".so"
+#else
+#error Support your platform here
+#endif
+
 
 namespace Orthanc
 {
@@ -79,6 +89,30 @@
   }
 
 
+  static const char* CallGetName(SharedLibrary& plugin)
+  {
+    typedef const char* (*GetName) ();
+
+    GetName getName;
+    *(void **) (&getName) = plugin.GetFunction("OrthancPluginGetName");
+    assert(getName != NULL);
+
+    return getName();
+  }
+
+
+  static const char* CallGetVersion(SharedLibrary& plugin)
+  {
+    typedef const char* (*GetVersion) ();
+
+    GetVersion getVersion;
+    *(void **) (&getVersion) = plugin.GetFunction("OrthancPluginGetVersion");
+    assert(getVersion != NULL);
+
+    return getVersion();
+  }
+
+
   static void LogError(const char* str)
   {
     LOG(ERROR) << str;
@@ -114,32 +148,95 @@
   {
     for (Plugins::iterator it = plugins_.begin(); it != plugins_.end(); it++)
     {
-      if (*it != NULL)
+      if (it->second != NULL)
       {
-        CallFinalize(**it);
-        delete *it;
+        CallFinalize(*(it->second));
+        delete it->second;
       }
     }
   }
 
+
+  static bool IsOrthancPlugin(SharedLibrary& library)
+  {
+    return (library.HasFunction("OrthancPluginInitialize") &&
+            library.HasFunction("OrthancPluginFinalize") &&
+            library.HasFunction("OrthancPluginGetName") &&
+            library.HasFunction("OrthancPluginGetVersion"));
+  }
+
   
   void PluginsManager::RegisterPlugin(const std::string& path)
   {
     std::auto_ptr<SharedLibrary> plugin(new SharedLibrary(path));
 
-    if (!plugin->HasFunction("OrthancPluginInitialize") ||
-        !plugin->HasFunction("OrthancPluginFinalize"))
+    if (!IsOrthancPlugin(*plugin))
     {
       LOG(ERROR) << "Plugin " << plugin->GetPath()
                  << " does not declare the proper entry functions";
       throw OrthancException(ErrorCode_SharedLibrary);
     }
 
-    LOG(WARNING) << "Registering plugin " << path;
+    std::string name(CallGetName(*plugin));
+    if (plugins_.find(name) != plugins_.end())
+    {
+      LOG(ERROR) << "Plugin '" << name << "' already registered";
+      throw OrthancException(ErrorCode_SharedLibrary);
+    }
+
+    LOG(WARNING) << "Registering plugin '" << name
+                 << "' (version " << CallGetVersion(*plugin) << ")";
 
     CallInitialize(*plugin, context_);
 
-    plugins_.push_back(plugin.release());
+    plugins_[name] = plugin.release();
+  }
+
+
+  void PluginsManager::ScanFolderForPlugins(const std::string& path,
+                                            bool isRecursive)
+  {
+    using namespace boost::filesystem;
+
+    if (!exists(path))
+    {
+      return;
+    }
+
+    LOG(INFO) << "Scanning folder " << path << " for plugins";
+
+    directory_iterator end_it; // default construction yields past-the-end
+    for (directory_iterator it(path);
+          it != end_it;
+          ++it)
+    {
+      if (is_directory(it->status()))
+      {
+        if (isRecursive)
+        {
+          ScanFolderForPlugins(it->path().string(), true);
+        }
+      }
+      else
+      {
+        if (boost::filesystem::extension(it->path()) == PLUGIN_EXTENSION)
+        {
+          LOG(INFO) << "Found a shared library: " << it->path();
+
+          try
+          {
+            SharedLibrary plugin(it->path().string());
+            if (IsOrthancPlugin(plugin))
+            {
+              RegisterPlugin(it->path().string());
+            }
+          }
+          catch (OrthancException&)
+          {
+          }
+        }
+      }
+    }
   }
 
 }