comparison OrthancServer/LuaScripting.cpp @ 1433:461e7554bff7

refactoring: LuaScripting
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 30 Jun 2015 15:09:34 +0200
parents
children 6406f5493d92
comparison
equal deleted inserted replaced
1432:0ac74fa21db8 1433:461e7554bff7
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 *
6 * This program is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * In addition, as a special exception, the copyright holders of this
12 * program give permission to link the code of its release with the
13 * OpenSSL project's "OpenSSL" library (or with modified versions of it
14 * that use the same license as the "OpenSSL" library), and distribute
15 * the linked executables. You must obey the GNU General Public License
16 * in all respects for all of the code used other than "OpenSSL". If you
17 * modify file(s) with this exception, you may extend this exception to
18 * your version of the file(s), but you are not obligated to do so. If
19 * you do not wish to do so, delete this exception statement from your
20 * version. If you delete this exception statement from all source files
21 * in the program, then also delete it here.
22 *
23 * This program is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 **/
31
32
33 #include "PrecompiledHeadersServer.h"
34 #include "LuaScripting.h"
35
36 #include "ServerContext.h"
37 #include "OrthancInitialization.h"
38 #include "../Core/Lua/LuaFunctionCall.h"
39
40 #include "Scheduler/DeleteInstanceCommand.h"
41 #include "Scheduler/StoreScuCommand.h"
42 #include "Scheduler/StorePeerCommand.h"
43 #include "Scheduler/ModifyInstanceCommand.h"
44 #include "Scheduler/CallSystemCommand.h"
45 #include "OrthancRestApi/OrthancRestApi.h"
46
47 #include <glog/logging.h>
48 #include <EmbeddedResources.h>
49
50 static const char* RECEIVED_INSTANCE_FILTER = "ReceivedInstanceFilter";
51 static const char* ON_STORED_INSTANCE = "OnStoredInstance";
52
53
54 namespace Orthanc
55 {
56 IServerCommand* LuaScripting::ParseOperation(const std::string& operation,
57 const Json::Value& parameters)
58 {
59 if (operation == "delete")
60 {
61 LOG(INFO) << "Lua script to delete instance " << parameters["Instance"].asString();
62 return new DeleteInstanceCommand(context_);
63 }
64
65 if (operation == "store-scu")
66 {
67 std::string localAet;
68 if (parameters.isMember("LocalAet"))
69 {
70 localAet = parameters["LocalAet"].asString();
71 }
72 else
73 {
74 localAet = context_.GetDefaultLocalApplicationEntityTitle();
75 }
76
77 std::string modality = parameters["Modality"].asString();
78 LOG(INFO) << "Lua script to send instance " << parameters["Instance"].asString()
79 << " to modality " << modality << " using Store-SCU";
80 return new StoreScuCommand(context_, localAet,
81 Configuration::GetModalityUsingSymbolicName(modality), true);
82 }
83
84 if (operation == "store-peer")
85 {
86 std::string peer = parameters["Peer"].asString();
87 LOG(INFO) << "Lua script to send instance " << parameters["Instance"].asString()
88 << " to peer " << peer << " using HTTP";
89
90 OrthancPeerParameters parameters;
91 Configuration::GetOrthancPeer(parameters, peer);
92 return new StorePeerCommand(context_, parameters, true);
93 }
94
95 if (operation == "modify")
96 {
97 LOG(INFO) << "Lua script to modify instance " << parameters["Instance"].asString();
98 DicomModification modification;
99 OrthancRestApi::ParseModifyRequest(modification, parameters);
100
101 std::auto_ptr<ModifyInstanceCommand> command(new ModifyInstanceCommand(context_, modification));
102 return command.release();
103 }
104
105 if (operation == "call-system")
106 {
107 LOG(INFO) << "Lua script to call system command on " << parameters["Instance"].asString();
108
109 const Json::Value& argsIn = parameters["Arguments"];
110 if (argsIn.type() != Json::arrayValue)
111 {
112 throw OrthancException(ErrorCode_BadParameterType);
113 }
114
115 std::vector<std::string> args;
116 args.reserve(argsIn.size());
117 for (Json::Value::ArrayIndex i = 0; i < argsIn.size(); ++i)
118 {
119 // http://jsoncpp.sourceforge.net/namespace_json.html#7d654b75c16a57007925868e38212b4e
120 switch (argsIn[i].type())
121 {
122 case Json::stringValue:
123 args.push_back(argsIn[i].asString());
124 break;
125
126 case Json::intValue:
127 args.push_back(boost::lexical_cast<std::string>(argsIn[i].asInt()));
128 break;
129
130 case Json::uintValue:
131 args.push_back(boost::lexical_cast<std::string>(argsIn[i].asUInt()));
132 break;
133
134 case Json::realValue:
135 args.push_back(boost::lexical_cast<std::string>(argsIn[i].asFloat()));
136 break;
137
138 default:
139 throw OrthancException(ErrorCode_BadParameterType);
140 }
141 }
142
143 return new CallSystemCommand(context_, parameters["Command"].asString(), args);
144 }
145
146 throw OrthancException(ErrorCode_ParameterOutOfRange);
147 }
148
149
150 LuaScripting::LuaScripting(ServerContext& context) : context_(context)
151 {
152 lua_.Execute(Orthanc::EmbeddedResources::LUA_TOOLBOX);
153 lua_.SetHttpProxy(Configuration::GetGlobalStringParameter("HttpProxy", ""));
154 }
155
156
157 void LuaScripting::ApplyOnStoredInstance(const std::string& instanceId,
158 const Json::Value& simplifiedTags,
159 const Json::Value& metadata,
160 const std::string& remoteAet,
161 const std::string& calledAet)
162 {
163 if (lua_.IsExistingFunction(ON_STORED_INSTANCE))
164 {
165 lua_.Execute("_InitializeJob()");
166
167 LuaFunctionCall call(lua_, ON_STORED_INSTANCE);
168 call.PushString(instanceId);
169 call.PushJson(simplifiedTags);
170 call.PushJson(metadata);
171 call.PushJson(remoteAet);
172 call.PushJson(calledAet);
173 call.Execute();
174
175 Json::Value operations;
176 LuaFunctionCall call2(lua_, "_AccessJob");
177 call2.ExecuteToJson(operations);
178
179 if (operations.type() != Json::arrayValue)
180 {
181 throw OrthancException(ErrorCode_InternalError);
182 }
183
184 ServerJob job;
185 ServerCommandInstance* previousCommand = NULL;
186
187 for (Json::Value::ArrayIndex i = 0; i < operations.size(); ++i)
188 {
189 if (operations[i].type() != Json::objectValue ||
190 !operations[i].isMember("Operation"))
191 {
192 throw OrthancException(ErrorCode_InternalError);
193 }
194
195 const Json::Value& parameters = operations[i];
196 std::string operation = parameters["Operation"].asString();
197
198 ServerCommandInstance& command = job.AddCommand(ParseOperation(operation, operations[i]));
199
200 if (!parameters.isMember("Instance"))
201 {
202 throw OrthancException(ErrorCode_InternalError);
203 }
204
205 std::string instance = parameters["Instance"].asString();
206 if (instance.empty())
207 {
208 previousCommand->ConnectOutput(command);
209 }
210 else
211 {
212 command.AddInput(instance);
213 }
214
215 previousCommand = &command;
216 }
217
218 job.SetDescription(std::string("Lua script: ") + ON_STORED_INSTANCE);
219 context_.GetScheduler().Submit(job);
220 }
221 }
222
223
224 void LuaScripting::SignalStoredInstance(const std::string& publicId,
225 DicomInstanceToStore& instance,
226 const Json::Value& simplifiedTags)
227 {
228 boost::mutex::scoped_lock lock(mutex_);
229
230 Json::Value metadata = Json::objectValue;
231
232 for (ServerIndex::MetadataMap::const_iterator
233 it = instance.GetMetadata().begin();
234 it != instance.GetMetadata().end(); ++it)
235 {
236 if (it->first.first == ResourceType_Instance)
237 {
238 metadata[EnumerationToString(it->first.second)] = it->second;
239 }
240 }
241
242 ApplyOnStoredInstance(publicId, simplifiedTags, metadata,
243 instance.GetRemoteAet(), instance.GetCalledAet());
244 }
245
246
247 void LuaScripting::SignalChange(const ServerIndexChange& change)
248 {
249 boost::mutex::scoped_lock lock(mutex_);
250
251 // TODO
252 }
253
254
255 bool LuaScripting::FilterIncomingInstance(const Json::Value& simplified,
256 const std::string& remoteAet)
257 {
258 boost::mutex::scoped_lock lock(mutex_);
259
260 if (lua_.IsExistingFunction(RECEIVED_INSTANCE_FILTER))
261 {
262 LuaFunctionCall call(lua_, RECEIVED_INSTANCE_FILTER);
263 call.PushJson(simplified);
264 call.PushString(remoteAet);
265
266 if (!call.ExecutePredicate())
267 {
268 return false;
269 }
270 }
271
272 return true;
273 }
274 }