1 // Copyright (C) 2006-2014 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "XMLNode.hxx"
21 #include "XMLPorts.hxx"
23 #include "TypeCode.hxx"
25 #include <libxml/parser.h>
26 #include <libxml/tree.h>
31 #include <sys/types.h>
41 #include "YacsTrace.hxx"
43 using namespace YACS::ENGINE;
46 const char XmlNode::IMPL_NAME[]="XML";
47 const char XmlNode::KIND[]="xmlsh";
48 static YACS::BASES::Mutex MUTEX;
50 XmlNode::XmlNode(const XmlNode& other, ComposedNode *father)
51 : _script(other._script), ServiceNode(other, father)
53 _implementation=IMPL_NAME;
57 XmlNode::XmlNode(const std::string& name)
60 _implementation=IMPL_NAME;
63 Node *XmlNode::simpleClone(ComposedNode *father, bool editionOnly) const
65 return new XmlNode(*this,father);
68 void XmlNode::setRef(const std::string& ref)
70 //No component instance here
74 void XmlNode::setScript(const std::string& script)
79 std::string XmlNode::getScript() const
84 std::string XmlNode::getKind() const
89 void XmlNode::execute()
92 char dir[]="yacsXXXXXX";
93 // add a lock around mkdtemp (seems not thread safe)
97 GetTempPath(MAX_PATH+1, mdir);
98 CreateDirectory(mdir, NULL);
100 char* mdir=mkdtemp(dir);
105 perror("mkdtemp failed");
106 std::cerr << "Problem in mkdtemp " << dir << " " << mdir << std::endl;
107 throw Exception("Execution problem in mkdtemp");
109 std::string sdir(dir);
110 std::string input=sdir+"/input";
111 std::ofstream f(input.c_str());
112 f<<"<methodCall> <methodName>" << _method << "</methodName> <params>"<<std::endl;
113 DEBTRACE("---------------XmlNode::inputs---------------");
114 list<InputPort *>::iterator iter;
115 for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
117 InputXmlPort *p=(InputXmlPort *)*iter;
118 DEBTRACE("port name: " << p->getName());
119 DEBTRACE("port kind: " << p->edGetType()->kind());
120 const char* ob=p->getXml();
121 DEBTRACE("Xml: " << ob );
122 f<<"<param>" << ob << "</param>"<<std::endl;
124 f<<"</params>"<<std::endl;
125 f<<"</methodCall>"<<std::endl;
127 DEBTRACE("--------------XmlNode::calculation---------------" << _ref );
128 std::string call=sdir+"/run.sh";
129 std::ofstream run(call.c_str());
130 run << "#!/bin/sh" << std::endl;
131 run << "cd " << sdir << std::endl;
132 if(_ref[0]=='/' || _ref[0]=='~')
133 run << _ref << "> stdout 2>&1 " << std::endl;
135 run << "../"<<_ref << "> stdout 2>&1 " << std::endl;
136 //run << "cat stdout" << std::endl;
138 chmod(call.c_str(),00777);
140 std::string call2="/bin/sh "+call;
141 int ret=system(call2.c_str());
144 std::cerr << "Problem: " << ret << std::endl;
145 DEBTRACE("Problem: " << ret);
146 throw Exception("Execution problem");
148 std::string output=sdir+"/output";
150 doc = xmlReadFile(output.c_str(), NULL, 0);
153 DEBTRACE("Failed to parse " << output);
154 throw Exception("Execution problem");
157 cur = xmlDocGetRootElement(doc);
160 DEBTRACE("empty document " );
162 throw Exception("Execution problem");
164 if (xmlStrcmp(cur->name, (const xmlChar *) "methodResponse"))
166 DEBTRACE("document of the wrong type, root node != methodResponse");
168 throw Exception("Execution problem");
170 cur = cur->xmlChildrenNode;
171 xmlBufferPtr buf=xmlBufferCreate();
172 list<OutputPort *>::iterator iter2;
173 iter2 = _setOfOutputPort.begin();
175 p=(OutputXmlPort *)*iter2;
180 if ((!xmlStrcmp(cur->name, (const xmlChar *)"fault")))
182 DEBTRACE("exception in shell" );
184 throw Exception("Execution problem");
186 if ((!xmlStrcmp(cur->name, (const xmlChar *)"params")))
188 xmlNodePtr cur0 = cur->xmlChildrenNode;
191 if ((!xmlStrcmp(cur0->name, (const xmlChar *)"param")))
193 xmlNodePtr cur1 = cur0->xmlChildrenNode;
196 if ((!xmlStrcmp(cur1->name, (const xmlChar *)"value")))
198 xmlNodePtr cur2=cur1->xmlChildrenNode;
201 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"int")))
204 if(getNumberOfOutputPorts()!=1)
209 throw Exception("Execution problem:mismatch in output numbers");
212 xmlNodeDump(buf,doc,cur1,0,0);
213 DEBTRACE(xmlBufferContent(buf));
214 p->put(xmlBufferContent(buf));
216 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"double")))
219 if(getNumberOfOutputPorts()!=1)
224 throw Exception("Execution problem:mismatch in output numbers");
227 xmlNodeDump(buf,doc,cur1,0,0);
228 DEBTRACE(xmlBufferContent(buf));
229 p->put(xmlBufferContent(buf));
231 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"string")))
234 if(getNumberOfOutputPorts()!=1)
239 throw Exception("Execution problem:mismatch in output port numbers");
242 xmlNodeDump(buf,doc,cur1,0,0);
243 DEBTRACE(xmlBufferContent(buf));
244 p->put(xmlBufferContent(buf));
246 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"boolean")))
249 if(getNumberOfOutputPorts()!=1)
254 throw Exception("Execution problem:mismatch in output port numbers");
257 xmlNodeDump(buf,doc,cur1,0,0);
258 DEBTRACE(xmlBufferContent(buf));
259 p->put(xmlBufferContent(buf));
261 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"objref")))
264 if(getNumberOfOutputPorts()!=1)
269 throw Exception("Execution problem:mismatch in output port numbers");
272 xmlNodeDump(buf,doc,cur1,0,0);
273 DEBTRACE(xmlBufferContent(buf));
274 p->put(xmlBufferContent(buf));
276 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"struct")))
279 if(getNumberOfOutputPorts()!=1)
284 throw Exception("Execution problem:mismatch in output port numbers");
287 xmlNodeDump(buf,doc,cur1,0,0);
288 DEBTRACE(xmlBufferContent(buf));
289 p->put(xmlBufferContent(buf));
291 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"array")))
293 //got a tuple of results or only one result (but a list)
294 if(getNumberOfOutputPorts()==1)
296 //It's a one result list
298 xmlNodeDump(buf,doc,cur1,0,0);
299 DEBTRACE(xmlBufferContent(buf));
300 p->put(xmlBufferContent(buf));
304 //It's a list of results
305 xmlNodePtr cur3=cur2->xmlChildrenNode;
308 if ((!xmlStrcmp(cur3->name, (const xmlChar *)"data")))
310 xmlNodePtr cur4=cur3->xmlChildrenNode;
313 if ((!xmlStrcmp(cur4->name, (const xmlChar *)"value")))
316 if(nres > getNumberOfOutputPorts())
321 throw Exception("Execution problem:mismatch in output port numbers");
324 xmlNodeDump(buf,doc,cur4,0,0);
325 DEBTRACE(xmlBufferContent(buf));
326 p=(OutputXmlPort *)*iter2;
327 p->put(xmlBufferContent(buf));