1 // Copyright (C) 2006-2024 CEA, EDF
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"
24 #include "AutoLocker.hxx"
26 #include <libxml/parser.h>
27 #include <libxml/tree.h>
32 #include <sys/types.h>
41 #include <unistd.h> // for mkdtemp
45 #include "YacsTrace.hxx"
47 using namespace YACS::ENGINE;
50 const char XmlNode::IMPL_NAME[]="XML";
51 const char XmlNode::KIND[]="xmlsh";
52 static YACS::BASES::Mutex MUTEX;
54 XmlNode::XmlNode(const XmlNode& other, ComposedNode *father)
55 : _script(other._script), ServiceNode(other, father)
57 _implementation=IMPL_NAME;
61 XmlNode::XmlNode(const std::string& name)
64 _implementation=IMPL_NAME;
67 Node *XmlNode::simpleClone(ComposedNode *father, bool editionOnly) const
69 return new XmlNode(*this,father);
72 void XmlNode::setRef(const std::string& ref)
74 //No component instance here
78 void XmlNode::setScript(const std::string& script)
83 std::string XmlNode::getScript() const
88 std::string XmlNode::getKind() const
93 void XmlNode::execute()
96 char dir[]="yacsXXXXXX";
97 // add a lock around mkdtemp (seems not thread safe)
99 YACS::BASES::AutoLocker<YACS::BASES::Mutex> alck(&MUTEX);
102 wchar_t mdir[512 + 1];
106 GetTempPath(MAX_PATH+1, mdir);
107 CreateDirectory(mdir, NULL);
109 char* mdir=mkdtemp(dir);
113 perror("mkdtemp failed");
114 std::cerr << "Problem in mkdtemp " << dir << " " << mdir << std::endl;
115 throw Exception("Execution problem in mkdtemp");
118 std::string sdir(dir);
119 std::string input=sdir+"/input";
120 std::ofstream f(input.c_str());
121 f<<"<methodCall> <methodName>" << _method << "</methodName> <params>"<<std::endl;
122 DEBTRACE("---------------XmlNode::inputs---------------");
123 list<InputPort *>::iterator iter;
124 for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
126 InputXmlPort *p=(InputXmlPort *)*iter;
127 DEBTRACE("port name: " << p->getName());
128 DEBTRACE("port kind: " << p->edGetType()->kind());
129 const char* ob=p->getXml();
130 DEBTRACE("Xml: " << ob );
131 f<<"<param>" << ob << "</param>"<<std::endl;
133 f<<"</params>"<<std::endl;
134 f<<"</methodCall>"<<std::endl;
136 DEBTRACE("--------------XmlNode::calculation---------------" << _ref );
137 std::string call=sdir+"/run.sh";
138 std::ofstream run(call.c_str());
139 run << "#!/bin/sh" << std::endl;
140 run << "cd " << sdir << std::endl;
141 if(_ref[0]=='/' || _ref[0]=='~')
142 run << _ref << "> stdout 2>&1 " << std::endl;
144 run << "../"<<_ref << "> stdout 2>&1 " << std::endl;
145 //run << "cat stdout" << std::endl;
147 chmod(call.c_str(),00777);
149 std::string call2="/bin/sh "+call;
150 int ret=system(call2.c_str());
153 std::cerr << "Problem: " << ret << std::endl;
154 DEBTRACE("Problem: " << ret);
155 throw Exception("Execution problem");
157 std::string output=sdir+"/output";
159 doc = xmlReadFile(output.c_str(), NULL, 0);
162 DEBTRACE("Failed to parse " << output);
163 throw Exception("Execution problem");
166 cur = xmlDocGetRootElement(doc);
169 DEBTRACE("empty document " );
171 throw Exception("Execution problem");
173 if (xmlStrcmp(cur->name, (const xmlChar *) "methodResponse"))
175 DEBTRACE("document of the wrong type, root node != methodResponse");
177 throw Exception("Execution problem");
179 cur = cur->xmlChildrenNode;
180 xmlBufferPtr buf=xmlBufferCreate();
181 list<OutputPort *>::iterator iter2;
182 iter2 = _setOfOutputPort.begin();
184 p=(OutputXmlPort *)*iter2;
189 if ((!xmlStrcmp(cur->name, (const xmlChar *)"fault")))
191 DEBTRACE("exception in shell" );
193 throw Exception("Execution problem");
195 if ((!xmlStrcmp(cur->name, (const xmlChar *)"params")))
197 xmlNodePtr cur0 = cur->xmlChildrenNode;
200 if ((!xmlStrcmp(cur0->name, (const xmlChar *)"param")))
202 xmlNodePtr cur1 = cur0->xmlChildrenNode;
205 if ((!xmlStrcmp(cur1->name, (const xmlChar *)"value")))
207 xmlNodePtr cur2=cur1->xmlChildrenNode;
210 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"int")))
213 if(getNumberOfOutputPorts()!=1)
218 throw Exception("Execution problem:mismatch in output numbers");
221 xmlNodeDump(buf,doc,cur1,0,0);
222 DEBTRACE(xmlBufferContent(buf));
223 p->put(xmlBufferContent(buf));
225 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"double")))
228 if(getNumberOfOutputPorts()!=1)
233 throw Exception("Execution problem:mismatch in output numbers");
236 xmlNodeDump(buf,doc,cur1,0,0);
237 DEBTRACE(xmlBufferContent(buf));
238 p->put(xmlBufferContent(buf));
240 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"string")))
243 if(getNumberOfOutputPorts()!=1)
248 throw Exception("Execution problem:mismatch in output port numbers");
251 xmlNodeDump(buf,doc,cur1,0,0);
252 DEBTRACE(xmlBufferContent(buf));
253 p->put(xmlBufferContent(buf));
255 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"boolean")))
258 if(getNumberOfOutputPorts()!=1)
263 throw Exception("Execution problem:mismatch in output port numbers");
266 xmlNodeDump(buf,doc,cur1,0,0);
267 DEBTRACE(xmlBufferContent(buf));
268 p->put(xmlBufferContent(buf));
270 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"objref")))
273 if(getNumberOfOutputPorts()!=1)
278 throw Exception("Execution problem:mismatch in output port numbers");
281 xmlNodeDump(buf,doc,cur1,0,0);
282 DEBTRACE(xmlBufferContent(buf));
283 p->put(xmlBufferContent(buf));
285 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"struct")))
288 if(getNumberOfOutputPorts()!=1)
293 throw Exception("Execution problem:mismatch in output port numbers");
296 xmlNodeDump(buf,doc,cur1,0,0);
297 DEBTRACE(xmlBufferContent(buf));
298 p->put(xmlBufferContent(buf));
300 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"array")))
302 //got a tuple of results or only one result (but a list)
303 if(getNumberOfOutputPorts()==1)
305 //It's a one result list
307 xmlNodeDump(buf,doc,cur1,0,0);
308 DEBTRACE(xmlBufferContent(buf));
309 p->put(xmlBufferContent(buf));
313 //It's a list of results
314 xmlNodePtr cur3=cur2->xmlChildrenNode;
317 if ((!xmlStrcmp(cur3->name, (const xmlChar *)"data")))
319 xmlNodePtr cur4=cur3->xmlChildrenNode;
322 if ((!xmlStrcmp(cur4->name, (const xmlChar *)"value")))
325 if(nres > getNumberOfOutputPorts())
330 throw Exception("Execution problem:mismatch in output port numbers");
333 xmlNodeDump(buf,doc,cur4,0,0);
334 DEBTRACE(xmlBufferContent(buf));
335 p=(OutputXmlPort *)*iter2;
336 p->put(xmlBufferContent(buf));