2 #include "XMLPorts.hxx"
5 #include <libxml/parser.h>
6 #include <libxml/tree.h>
11 #include <sys/types.h>
15 #include "YacsTrace.hxx"
17 using namespace YACS::ENGINE;
20 const char XmlNode::IMPL_NAME[]="XML";
21 const char XmlNode::KIND[]="xmlsh";
22 static YACS::BASES::Mutex MUTEX;
24 XmlNode::XmlNode(const XmlNode& other, ComposedNode *father)
25 : _script(other._script), ServiceNode(other, father)
27 _implementation=IMPL_NAME;
31 XmlNode::XmlNode(const std::string& name)
34 _implementation=IMPL_NAME;
37 Node *XmlNode::simpleClone(ComposedNode *father, bool editionOnly) const
39 return new XmlNode(*this,father);
42 void XmlNode::setRef(const std::string& ref)
44 //No component instance here
48 void XmlNode::setScript(const std::string& script)
53 std::string XmlNode::getKind() const
58 void XmlNode::execute()
61 char dir[]="yacsXXXXXX";
62 // add a lock around mkdtemp (seems not thread safe)
64 char* mdir=mkdtemp(dir);
68 perror("mkdtemp failed");
69 std::cerr << "Problem in mkdtemp " << dir << " " << mdir << std::endl;
70 throw Exception("Execution problem in mkdtemp");
72 std::string sdir(dir);
73 std::string input=sdir+"/input";
74 std::ofstream f(input.c_str());
75 f<<"<methodCall> <methodName>" << _method << "</methodName> <params>"<<std::endl;
76 DEBTRACE("---------------XmlNode::inputs---------------");
77 list<InputPort *>::iterator iter;
78 for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
80 InputXmlPort *p=(InputXmlPort *)*iter;
81 DEBTRACE("port name: " << p->getName());
82 DEBTRACE("port kind: " << p->edGetType()->kind());
83 const char* ob=p->getXml();
84 DEBTRACE("Xml: " << ob );
85 f<<"<param>" << ob << "</param>"<<std::endl;
87 f<<"</params>"<<std::endl;
88 f<<"</methodCall>"<<std::endl;
90 DEBTRACE("--------------XmlNode::calculation---------------" << _ref );
91 std::string call=sdir+"/run.sh";
92 std::ofstream run(call.c_str());
93 run << "#!/bin/sh" << std::endl;
94 run << "cd " << sdir << std::endl;
95 if(_ref[0]=='/' || _ref[0]=='~')
96 run << _ref << "> stdout 2>&1 " << std::endl;
98 run << "../"<<_ref << "> stdout 2>&1 " << std::endl;
99 run << "cat stdout" << std::endl;
101 chmod(call.c_str(),00777);
103 int ret=system(call.c_str());
106 std::cerr << "Problem: " << ret << std::endl;
107 DEBTRACE("Problem: " << ret);
108 throw Exception("Execution problem");
110 std::string output=sdir+"/output";
112 doc = xmlReadFile(output.c_str(), NULL, 0);
115 DEBTRACE("Failed to parse " << output);
116 throw Exception("Execution problem");
119 cur = xmlDocGetRootElement(doc);
122 DEBTRACE("empty document " );
124 throw Exception("Execution problem");
126 if (xmlStrcmp(cur->name, (const xmlChar *) "methodResponse"))
128 DEBTRACE("document of the wrong type, root node != methodResponse");
130 throw Exception("Execution problem");
132 cur = cur->xmlChildrenNode;
133 xmlBufferPtr buf=xmlBufferCreate();
134 list<OutputPort *>::iterator iter2;
135 iter2 = _setOfOutputPort.begin();
137 p=(OutputXmlPort *)*iter2;
142 if ((!xmlStrcmp(cur->name, (const xmlChar *)"fault")))
144 DEBTRACE("exception in shell" );
146 throw Exception("Execution problem");
148 if ((!xmlStrcmp(cur->name, (const xmlChar *)"params")))
150 xmlNodePtr cur0 = cur->xmlChildrenNode;
153 if ((!xmlStrcmp(cur0->name, (const xmlChar *)"param")))
155 xmlNodePtr cur1 = cur0->xmlChildrenNode;
158 if ((!xmlStrcmp(cur1->name, (const xmlChar *)"value")))
160 xmlNodePtr cur2=cur1->xmlChildrenNode;
163 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"int")))
166 if(getNumberOfOutputPorts()!=1)
171 throw Exception("Execution problem:mismatch in output numbers");
174 xmlNodeDump(buf,doc,cur1,0,0);
175 DEBTRACE(xmlBufferContent(buf));
176 p->put(xmlBufferContent(buf));
178 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"double")))
181 if(getNumberOfOutputPorts()!=1)
186 throw Exception("Execution problem:mismatch in output numbers");
189 xmlNodeDump(buf,doc,cur1,0,0);
190 DEBTRACE(xmlBufferContent(buf));
191 p->put(xmlBufferContent(buf));
193 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"string")))
196 if(getNumberOfOutputPorts()!=1)
201 throw Exception("Execution problem:mismatch in output port numbers");
204 xmlNodeDump(buf,doc,cur1,0,0);
205 DEBTRACE(xmlBufferContent(buf));
206 p->put(xmlBufferContent(buf));
208 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"boolean")))
211 if(getNumberOfOutputPorts()!=1)
216 throw Exception("Execution problem:mismatch in output port numbers");
219 xmlNodeDump(buf,doc,cur1,0,0);
220 DEBTRACE(xmlBufferContent(buf));
221 p->put(xmlBufferContent(buf));
223 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"objref")))
226 if(getNumberOfOutputPorts()!=1)
231 throw Exception("Execution problem:mismatch in output port numbers");
234 xmlNodeDump(buf,doc,cur1,0,0);
235 DEBTRACE(xmlBufferContent(buf));
236 p->put(xmlBufferContent(buf));
238 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"struct")))
241 if(getNumberOfOutputPorts()!=1)
246 throw Exception("Execution problem:mismatch in output port numbers");
249 xmlNodeDump(buf,doc,cur1,0,0);
250 DEBTRACE(xmlBufferContent(buf));
251 p->put(xmlBufferContent(buf));
253 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"array")))
255 //got a tuple of results or only one result (but a list)
256 if(getNumberOfOutputPorts()==1)
258 //It's a one result list
260 xmlNodeDump(buf,doc,cur1,0,0);
261 DEBTRACE(xmlBufferContent(buf));
262 p->put(xmlBufferContent(buf));
266 //It's a list of results
267 xmlNodePtr cur3=cur2->xmlChildrenNode;
270 if ((!xmlStrcmp(cur3->name, (const xmlChar *)"data")))
272 xmlNodePtr cur4=cur3->xmlChildrenNode;
275 if ((!xmlStrcmp(cur4->name, (const xmlChar *)"value")))
278 if(nres > getNumberOfOutputPorts())
283 throw Exception("Execution problem:mismatch in output port numbers");
286 xmlNodeDump(buf,doc,cur4,0,0);
287 DEBTRACE(xmlBufferContent(buf));
288 p=(OutputXmlPort *)*iter2;
289 p->put(xmlBufferContent(buf));