diff OrthancServer/ServerContext.cpp @ 1433:461e7554bff7

refactoring: LuaScripting
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 30 Jun 2015 15:09:34 +0200
parents d710ea64f0fd
children f9cd40166269
line wrap: on
line diff
--- a/OrthancServer/ServerContext.cpp	Tue Jun 30 12:51:29 2015 +0200
+++ b/OrthancServer/ServerContext.cpp	Tue Jun 30 15:09:34 2015 +0200
@@ -34,7 +34,6 @@
 #include "ServerContext.h"
 
 #include "../Core/HttpServer/FilesystemHttpSender.h"
-#include "../Core/Lua/LuaFunctionCall.h"
 #include "FromDcmtkBridge.h"
 #include "ServerToolbox.h"
 #include "OrthancInitialization.h"
@@ -55,9 +54,6 @@
 
 #define ENABLE_DICOM_CACHE  1
 
-static const char* RECEIVED_INSTANCE_FILTER = "ReceivedInstanceFilter";
-static const char* ON_STORED_INSTANCE = "OnStoredInstance";
-
 static const size_t DICOM_CACHE_SIZE = 2;
 
 /**
@@ -77,6 +73,7 @@
     provider_(*this),
     dicomCache_(provider_, DICOM_CACHE_SIZE),
     scheduler_(Configuration::GetGlobalIntegerParameter("LimitJobs", 10)),
+    lua_(*this),
     plugins_(NULL),
     pluginsManager_(NULL),
     queryRetrieveArchive_(Configuration::GetGlobalIntegerParameter("QueryRetrieveSize", 10)),
@@ -85,8 +82,7 @@
     uint64_t s = Configuration::GetGlobalIntegerParameter("DicomAssociationCloseDelay", 5);  // In seconds
     scu_.SetMillisecondsBeforeClose(s * 1000);  // Milliseconds are expected here
 
-    lua_.Execute(Orthanc::EmbeddedResources::LUA_TOOLBOX);
-    lua_.SetHttpProxy(Configuration::GetGlobalStringParameter("HttpProxy", ""));
+    listeners_.push_back(ServerListener(lua_, "Lua"));
   }
 
   void ServerContext::SetCompressionEnabled(bool enabled)
@@ -106,191 +102,6 @@
   }
 
 
-  bool ServerContext::ApplyReceivedInstanceFilter(const Json::Value& simplified,
-                                                  const std::string& remoteAet)
-  {
-    LuaContextLocker locker(*this);
-
-    if (locker.GetLua().IsExistingFunction(RECEIVED_INSTANCE_FILTER))
-    {
-      LuaFunctionCall call(locker.GetLua(), RECEIVED_INSTANCE_FILTER);
-      call.PushJson(simplified);
-      call.PushString(remoteAet);
-
-      if (!call.ExecutePredicate())
-      {
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-
-  static IServerCommand* ParseOperation(ServerContext& context,
-                                        const std::string& operation,
-                                        const Json::Value& parameters)
-  {
-    if (operation == "delete")
-    {
-      LOG(INFO) << "Lua script to delete instance " << parameters["Instance"].asString();
-      return new DeleteInstanceCommand(context);
-    }
-
-    if (operation == "store-scu")
-    {
-      std::string localAet;
-      if (parameters.isMember("LocalAet"))
-      {
-        localAet = parameters["LocalAet"].asString();
-      }
-      else
-      {
-        localAet = context.GetDefaultLocalApplicationEntityTitle();
-      }
-
-      std::string modality = parameters["Modality"].asString();
-      LOG(INFO) << "Lua script to send instance " << parameters["Instance"].asString()
-                << " to modality " << modality << " using Store-SCU";
-      return new StoreScuCommand(context, localAet,
-                                 Configuration::GetModalityUsingSymbolicName(modality), true);
-    }
-
-    if (operation == "store-peer")
-    {
-      std::string peer = parameters["Peer"].asString();
-      LOG(INFO) << "Lua script to send instance " << parameters["Instance"].asString()
-                << " to peer " << peer << " using HTTP";
-
-      OrthancPeerParameters parameters;
-      Configuration::GetOrthancPeer(parameters, peer);
-      return new StorePeerCommand(context, parameters, true);
-    }
-
-    if (operation == "modify")
-    {
-      LOG(INFO) << "Lua script to modify instance " << parameters["Instance"].asString();
-      DicomModification modification;
-      OrthancRestApi::ParseModifyRequest(modification, parameters);
-
-      std::auto_ptr<ModifyInstanceCommand> command(new ModifyInstanceCommand(context, modification));
-      return command.release();
-    }
-
-    if (operation == "call-system")
-    {
-      LOG(INFO) << "Lua script to call system command on " << parameters["Instance"].asString();
-
-      const Json::Value& argsIn = parameters["Arguments"];
-      if (argsIn.type() != Json::arrayValue)
-      {
-        throw OrthancException(ErrorCode_BadParameterType);
-      }
-
-      std::vector<std::string> args;
-      args.reserve(argsIn.size());
-      for (Json::Value::ArrayIndex i = 0; i < argsIn.size(); ++i)
-      {
-        // http://jsoncpp.sourceforge.net/namespace_json.html#7d654b75c16a57007925868e38212b4e
-        switch (argsIn[i].type())
-        {
-          case Json::stringValue:
-            args.push_back(argsIn[i].asString());
-            break;
-
-          case Json::intValue:
-            args.push_back(boost::lexical_cast<std::string>(argsIn[i].asInt()));
-            break;
-
-          case Json::uintValue:
-            args.push_back(boost::lexical_cast<std::string>(argsIn[i].asUInt()));
-            break;
-
-          case Json::realValue:
-            args.push_back(boost::lexical_cast<std::string>(argsIn[i].asFloat()));
-            break;
-
-          default:
-            throw OrthancException(ErrorCode_BadParameterType);
-        }
-      }
-
-      return new CallSystemCommand(context, parameters["Command"].asString(), args);
-    }
-
-    throw OrthancException(ErrorCode_ParameterOutOfRange);
-  }
-
-
-  void ServerContext::ApplyLuaOnStoredInstance(const std::string& instanceId,
-                                               const Json::Value& simplifiedDicom,
-                                               const Json::Value& metadata,
-                                               const std::string& remoteAet,
-                                               const std::string& calledAet)
-  {
-    LuaContextLocker locker(*this);
-
-    if (locker.GetLua().IsExistingFunction(ON_STORED_INSTANCE))
-    {
-      locker.GetLua().Execute("_InitializeJob()");
-
-      LuaFunctionCall call(locker.GetLua(), ON_STORED_INSTANCE);
-      call.PushString(instanceId);
-      call.PushJson(simplifiedDicom);
-      call.PushJson(metadata);
-      call.PushJson(remoteAet);
-      call.PushJson(calledAet);
-      call.Execute();
-
-      Json::Value operations;
-      LuaFunctionCall call2(locker.GetLua(), "_AccessJob");
-      call2.ExecuteToJson(operations);
-     
-      if (operations.type() != Json::arrayValue)
-      {
-        throw OrthancException(ErrorCode_InternalError);
-      }
-
-      ServerJob job;
-      ServerCommandInstance* previousCommand = NULL;
-
-      for (Json::Value::ArrayIndex i = 0; i < operations.size(); ++i)
-      {
-        if (operations[i].type() != Json::objectValue ||
-            !operations[i].isMember("Operation"))
-        {
-          throw OrthancException(ErrorCode_InternalError);
-        }
-
-        const Json::Value& parameters = operations[i];
-        std::string operation = parameters["Operation"].asString();
-
-        ServerCommandInstance& command = job.AddCommand(ParseOperation(*this, operation, operations[i]));
-        
-        if (!parameters.isMember("Instance"))
-        {
-          throw OrthancException(ErrorCode_InternalError);
-        }
-
-        std::string instance = parameters["Instance"].asString();
-        if (instance.empty())
-        {
-          previousCommand->ConnectOutput(command);
-        }
-        else 
-        {
-          command.AddInput(instance);
-        }
-
-        previousCommand = &command;
-      }
-
-      job.SetDescription(std::string("Lua script: ") + ON_STORED_INSTANCE);
-      scheduler_.Submit(job);
-    }
-  }
-
-
   StoreStatus ServerContext::Store(std::string& resultPublicId,
                                    DicomInstanceToStore& dicom)
   {
@@ -303,7 +114,27 @@
       SimplifyTags(simplified, dicom.GetJson());
 
       // Test if the instance must be filtered out
-      if (!ApplyReceivedInstanceFilter(simplified, dicom.GetRemoteAet()))
+      bool accepted = true;
+
+      for (ServerListeners::iterator it = listeners_.begin(); it != listeners_.end(); ++it)
+      {
+        try
+        {
+          if (!it->GetListener().FilterIncomingInstance(simplified, dicom.GetRemoteAet()))
+          {
+            accepted = false;
+            break;
+          }
+        }
+        catch (OrthancException& e)
+        {
+          LOG(ERROR) << "Error in the " << it->GetDescription() 
+                     << " callback while receiving an instance: " << e.What();
+          throw;
+        }
+      }
+
+      if (!accepted)
       {
         LOG(INFO) << "An incoming instance has been discarded by the filter";
         return StoreStatus_FilteredOut;
@@ -330,6 +161,7 @@
       StoreStatus status = index_.Store(instanceMetadata, dicom.GetSummary(), attachments, 
                                         dicom.GetRemoteAet(), dicom.GetMetadata());
 
+      // Only keep the metadata for the "instance" level
       dicom.GetMetadata().clear();
 
       for (InstanceMetadata::const_iterator it = instanceMetadata.begin();
@@ -367,33 +199,16 @@
       if (status == StoreStatus_Success ||
           status == StoreStatus_AlreadyStored)
       {
-        Json::Value metadata = Json::objectValue;
-        for (std::map<MetadataType, std::string>::const_iterator 
-               it = instanceMetadata.begin(); 
-             it != instanceMetadata.end(); ++it)
-        {
-          metadata[EnumerationToString(it->first)] = it->second;
-        }
-
-        try
-        {
-          ApplyLuaOnStoredInstance(resultPublicId, simplified, metadata, 
-                                   dicom.GetRemoteAet(), dicom.GetCalledAet());
-        }
-        catch (OrthancException& e)
-        {
-          LOG(ERROR) << "Error in " << ON_STORED_INSTANCE << " callback (Lua): " << e.What();
-        }
-
-        if (plugins_ != NULL)
+        for (ServerListeners::iterator it = listeners_.begin(); it != listeners_.end(); ++it)
         {
           try
           {
-            plugins_->SignalStoredInstance(dicom, resultPublicId);
+            it->GetListener().SignalStoredInstance(resultPublicId, dicom, simplified);
           }
           catch (OrthancException& e)
           {
-            LOG(ERROR) << "Error in " << ON_STORED_INSTANCE << " callback (plugins): " << e.What();
+            LOG(ERROR) << "Error in the " << it->GetDescription() 
+                       << " callback while receiving an instance: " << e.What();
           }
         }
       }
@@ -546,15 +361,16 @@
 
   void ServerContext::SignalChange(const ServerIndexChange& change)
   {
-    if (plugins_ != NULL)
+    for (ServerListeners::iterator it = listeners_.begin(); it != listeners_.end(); ++it)
     {
       try
       {
-        plugins_->SignalChange(change);
+        it->GetListener().SignalChange(change);
       }
       catch (OrthancException& e)
       {
-        LOG(ERROR) << "Error in OnChangeCallback (plugins): " << e.What();
+        LOG(ERROR) << "Error in the " << it->GetDescription() 
+                   << " callback while signaling a change: " << e.What();
       }
     }
   }