Salome HOME
Test for workload manager.
[modules/yacs.git] / src / runtime / RuntimeSALOME.cxx
1 // Copyright (C) 2006-2019  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 //#define REFCNT
21 //
22 #ifdef REFCNT
23 #define private public
24 #define protected public
25 #include <omniORB4/CORBA.h>
26 #include <omniORB4/internal/typecode.h>
27 #include <omniORB4/internal/corbaOrb.h>
28 #endif
29
30 #include "yacsconfig.h"
31 #include "YACS_version.h"
32 #include "RuntimeSALOME.hxx"
33 #include "SALOMEDispatcher.hxx"
34 #include "Proc.hxx"
35 #include "TypeCode.hxx"
36 #include "WhileLoop.hxx"
37 #include "ForLoop.hxx"
38 #include "ForEachLoop.hxx"
39 #include "SalomeOptimizerLoop.hxx"
40 #include "Bloc.hxx"
41 #include "InputPort.hxx"
42 #include "OutputPort.hxx"
43 #include "PresetPorts.hxx"
44 #include "InputDataStreamPort.hxx"
45 #include "OutputDataStreamPort.hxx"
46 #include "Switch.hxx"
47 #include "SalomeProc.hxx"
48 #include "PyStdout.hxx"
49 //Catalog Loaders
50 #include "SessionCataLoader.hxx"
51
52 //Components
53 #include "CORBAComponent.hxx"
54 #include "SalomeComponent.hxx"
55 #include "SalomeHPComponent.hxx"
56 #include "SalomePythonComponent.hxx"
57 #include "CppComponent.hxx"
58
59 #include "SalomeContainer.hxx"
60 #include "CppContainer.hxx"
61 #include "SalomeHPContainer.hxx"
62
63 //Nodes
64 #include "PythonNode.hxx"
65 #include "CORBANode.hxx"
66 #include "XMLNode.hxx"
67 #include "CppNode.hxx"
68 #include "PresetNode.hxx"
69 #include "OutNode.hxx"
70 #include "StudyNodes.hxx"
71 #include "SalomePythonNode.hxx"
72 #include "DistributedPythonNode.hxx"
73
74 //CORBA proxy ports
75 #include "CORBACORBAConv.hxx"
76 #include "CORBAPythonConv.hxx"
77 #include "CORBAXMLConv.hxx"
78 #include "CORBACppConv.hxx"
79 #include "CORBANeutralConv.hxx"
80
81 #include "TypeConversions.hxx"
82 //Python proxy ports
83 #include "PythonCORBAConv.hxx"
84 #include "PythonXMLConv.hxx"
85 #include "PythonCppConv.hxx"
86 #include "PythonNeutralConv.hxx"
87 #include "PythonInitConv.hxx"
88
89 //Neutral proxy ports
90 #include "NeutralCORBAConv.hxx"
91 #include "NeutralPythonConv.hxx"
92 #include "NeutralXMLConv.hxx"
93 #include "NeutralCppConv.hxx"
94 #include "NeutralInitConv.hxx"
95
96 //C++ proxy ports
97 #include "CppCORBAConv.hxx"
98 #include "CppPythonConv.hxx"
99 #include "CppXMLConv.hxx"
100 #include "CppCppConv.hxx"
101 #include "CppNeutralConv.hxx"
102
103 //XML proxy ports
104 #include "XMLCORBAConv.hxx"
105 #include "XMLPythonConv.hxx"
106 #include "XMLCppConv.hxx"
107 #include "XMLNeutralConv.hxx"
108
109 //Calcium specific ports
110 #include "CalStreamPort.hxx"
111
112 #ifdef SALOME_KERNEL
113 #include "SALOME_NamingService.hxx"
114 #include "SALOME_LifeCycleCORBA.hxx"
115 #include "SALOME_NamingService.hxx"
116 #include "SALOME_ResourcesManager.hxx"
117 #include "SALOME_ContainerManager.hxx"
118 #include "SALOMEconfig.h"
119 #include CORBA_CLIENT_HEADER(SALOME_ContainerManager)
120
121 #endif
122   
123 #include <libxml/parser.h>
124 #include <omniORB4/CORBA.h>
125 #include <iostream>
126 #include <sstream>
127 #include <cassert>
128
129 //#define _DEVDEBUG_
130 #include "YacsTrace.hxx"
131
132 using namespace std;
133 using namespace YACS::ENGINE;
134
135 void RuntimeSALOME::setRuntime(long flags, int argc, char* argv[]) // singleton creation (not thread safe!)
136 {
137   if (! Runtime::_singleton)
138     {
139       RuntimeSALOME* r=new RuntimeSALOME(flags, argc, argv);
140       Runtime::_singleton = r;
141       r->initBuiltins();
142     }
143   DEBTRACE("RuntimeSALOME::setRuntime() done !");
144 }
145
146 RuntimeSALOME* YACS::ENGINE::getSALOMERuntime()
147 {
148   YASSERT(RuntimeSALOME::getSingleton());
149   return dynamic_cast< RuntimeSALOME* >(RuntimeSALOME::getSingleton());
150 }
151
152 /**
153  *  Singleton creation, initialize converter map
154  */
155   
156 RuntimeSALOME::RuntimeSALOME()
157 {
158   YASSERT(0);
159 }
160
161 void RuntimeSALOME::initBuiltins()
162 {
163   //Fill the builtin catalog with nodes specific to the runtime
164   std::map<std::string,TypeCode*>& typeMap=_builtinCatalog->_typeMap;
165   std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
166   std::map<std::string,ComposedNode*>& composednodeMap=_builtinCatalog->_composednodeMap;
167   std::map<std::string,ComponentDefinition*>& componentMap=_builtinCatalog->_componentMap;
168   nodeMap["PyFunction"]=new PyFuncNode("PyFunction");
169   nodeMap["PyScript"]=new PythonNode("PyScript");
170   nodeMap["CORBANode"]=new CORBANode("CORBANode");
171   nodeMap["XmlNode"]=new XmlNode("XmlNode");
172   nodeMap["SalomeNode"]=new SalomeNode("SalomeNode");
173   nodeMap["CppNode"]=new CppNode("CppNode");
174   nodeMap["SalomePythonNode"]=new SalomePythonNode("SalomePythonNode");
175   nodeMap["PresetNode"]=new PresetNode("PresetNode");
176   nodeMap["OutNode"]=new OutNode("OutNode");
177   nodeMap["StudyInNode"]=new StudyInNode("StudyInNode");
178   nodeMap["StudyOutNode"]=new StudyOutNode("StudyOutNode");
179   composednodeMap["OptimizerLoop"]=createOptimizerLoop("OptimizerLoop","","",true);
180   typeMap["dblevec"]= createSequenceTc("dblevec","dblevec",_tc_double);
181   typeMap["intvec"]= createSequenceTc("intvec","intvec",_tc_int);
182   typeMap["stringvec"]= createSequenceTc("stringvec","stringvec",_tc_string);
183   typeMap["boolvec"]= createSequenceTc("boolvec","boolvec",_tc_bool);
184   typeMap["seqdblevec"]= createSequenceTc("seqdblevec","seqdblevec",typeMap["dblevec"]);
185   typeMap["seqintvec"]= createSequenceTc("seqintvec","seqintvec",typeMap["intvec"]);
186   typeMap["seqstringvec"]= createSequenceTc("seqstringvec","seqstringvec",typeMap["stringvec"]);
187   typeMap["seqboolvec"]= createSequenceTc("seqboolvec","seqboolvec",typeMap["boolvec"]);
188   std::list<TypeCodeObjref *> ltc;
189   typeMap["pyobj"]= createInterfaceTc("python:obj:1.0","pyobj",ltc);
190   typeMap["seqpyobj"]= createSequenceTc("seqpyobj","seqpyobj",typeMap["pyobj"]);
191   composednodeMap["Bloc"]=createBloc("Bloc");
192   composednodeMap["Switch"]=createSwitch("Switch");
193   composednodeMap["WhileLoop"]=createWhileLoop("WhileLoop");
194   composednodeMap["ForLoop"]=createForLoop("ForLoop");
195   composednodeMap["ForEachLoop_double"]=createForEachLoop("ForEachLoop_double",Runtime::_tc_double);
196   composednodeMap["ForEachLoop_string"]=createForEachLoop("ForEachLoop_string",Runtime::_tc_string);
197   composednodeMap["ForEachLoop_int"]=createForEachLoop("ForEachLoop_int",Runtime::_tc_int);
198   composednodeMap["ForEachLoop_bool"]=createForEachLoop("ForEachLoop_bool",Runtime::_tc_bool);
199   composednodeMap["ForEachLoop_pyobj"]=createForEachLoop("ForEachLoop_pyobj",typeMap["pyobj"]);;
200   ENGINE::TypeCodeStruct *t = createStructTc("","Engines/dataref");
201   t->addMember("ref",_tc_string);
202   typeMap["dataref"]= t;
203 }
204
205 RuntimeSALOME::RuntimeSALOME(long flags, int argc, char* argv[])
206 {
207   // If all flags (apart the IsPyExt flags) are unset, force them to true
208   if ((flags - flags & RuntimeSALOME::IsPyExt) == 0)
209     flags += RuntimeSALOME::UseCorba + RuntimeSALOME::UsePython
210           +  RuntimeSALOME::UseCpp + RuntimeSALOME::UseXml;
211
212   // Salome Nodes implies Corba Nodes
213   if (flags & RuntimeSALOME::UseSalome)
214     flags |= RuntimeSALOME::UseCorba;
215
216   // Corba Nodes implies Python Nodes
217   if (flags & RuntimeSALOME::UseCorba)
218     flags |= RuntimeSALOME::UsePython;
219
220   _useCorba = flags & RuntimeSALOME::UseCorba;
221   _usePython = flags & RuntimeSALOME::UsePython;
222   _useCpp = flags & RuntimeSALOME::UseCpp;
223   _useXml = flags & RuntimeSALOME::UseXml;
224
225   /* Init libxml */
226   xmlInitParser();
227
228   if (_useCpp)    _setOfImplementation.insert(CppNode::IMPL_NAME);
229   if (_usePython) _setOfImplementation.insert(PythonNode::IMPL_NAME);
230   if (_useCorba)  _setOfImplementation.insert(CORBANode::IMPL_NAME);
231   if (_useXml)    _setOfImplementation.insert(XmlNode::IMPL_NAME);
232   init(flags, argc, argv);
233 }
234
235 RuntimeSALOME::~RuntimeSALOME()
236 {
237   DEBTRACE("RuntimeSALOME::~RuntimeSALOME");
238   // destroy catalog loader prototypes
239   std::map<std::string, CatalogLoader*>::const_iterator pt;
240   for(pt=_catalogLoaderFactoryMap.begin();pt!=_catalogLoaderFactoryMap.end();pt++)
241     {
242       delete (*pt).second;
243     }
244 }
245
246 //! CORBA and Python initialization
247 /*!
248  *  \param flags contains several bits
249  *            bit0 (ispyext) true when method is called from Python
250  *                           (Python initialization must not be done!)
251  *            bit1 (UsePython) true if python nodes are needed
252  *            bit1 (UseCorba)  true if CORBA nodes are needed
253  *            bit1 (UseXml)    true if python nodes are needed
254  *            bit1 (UseCpp)    true if C++ nodes are needed
255  *            bit1 (UseSalome) true if Salome nodes are needed
256  *  \param argc number of command line arguments (used to initialize the Python interpreter)
257  *  \param argv command line arguments (used to initialize the Python interpreter)
258  *
259  */
260
261 void RuntimeSALOME::init(long flags, int argc, char* argv[])
262 {
263   bool ispyext = flags & RuntimeSALOME::IsPyExt;
264   if (_useCorba)
265     {
266       PortableServer::POA_var root_poa;
267       PortableServer::POAManager_var pman;
268       CORBA::Object_var obj;
269       int nbargs = 0; char **args = 0;
270       _orb = CORBA::ORB_init (nbargs, args);
271       obj = _orb->resolve_initial_references("RootPOA");
272       root_poa = PortableServer::POA::_narrow(obj);
273       pman = root_poa->the_POAManager();
274       pman->activate();
275
276 #ifdef REFCNT
277       DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
278 #endif
279       obj = _orb->resolve_initial_references("DynAnyFactory");
280       _dynFactory = DynamicAny::DynAnyFactory::_narrow(obj);
281     }
282
283   if (_usePython)
284     {
285       DEBTRACE("RuntimeSALOME::init, is python extension = " << ispyext);
286
287       // Initialize Python interpreter in embedded mode
288       if (!Py_IsInitialized())
289         {
290 #if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
291           Py_Initialize(); 
292 #else
293           Py_InitializeEx(0); // do not install signal handlers
294 #endif
295           if (argc > 0 && argv != NULL)
296             {
297               wchar_t **changed_argv = new wchar_t*[argc];
298               for (int i = 0; i < argc; i++)
299               {
300                 changed_argv[i] = Py_DecodeLocale(argv[i], NULL);
301               }
302               PySys_SetArgv(argc, changed_argv);
303             } 
304           else
305             {
306               int pyArgc = 1;
307               char* pyArgv[1];
308               char defaultName[] = "SALOME_YACS_RUNTIME";
309               wchar_t **changed_pyArgv = new wchar_t*[pyArgc];
310               pyArgv[0] = defaultName;
311               for (int i = 0; i < pyArgc; i++)
312               {
313                 changed_pyArgv[i] = Py_DecodeLocale(pyArgv[i], NULL);
314               }
315               PySys_SetArgv(pyArgc, changed_pyArgv);
316             }
317           PyEval_InitThreads(); /* Create (and acquire) the interpreter lock (for threads)*/
318           PyEval_SaveThread(); /* Release the thread state */
319           //here we do not have the Global Interpreter Lock
320         }
321
322       PyObject *mainmod,*pyapi,*res ;
323       PyObject *globals;
324       PyGILState_STATE gstate;
325       gstate = PyGILState_Ensure(); // acquire the Global Interpreter Lock
326     
327       mainmod = PyImport_AddModule("__main__");
328       globals = PyModule_GetDict(mainmod);
329       /* globals is a borrowed reference */
330   
331       if (PyDict_GetItemString(globals, "__builtins__") == NULL) 
332         {
333           PyObject *bimod = PyImport_ImportModule("builtins");
334           if (bimod == NULL || PyDict_SetItemString(globals, "__builtins__", bimod) != 0)
335             Py_FatalError("can't add __builtins__ to __main__");
336           Py_DECREF(bimod);
337         }
338
339       _bltins = PyEval_GetBuiltins();  /* borrowed ref */
340
341       if (_useCorba)
342         {
343
344           //init section
345           _omnipy = PyImport_ImportModule((char*)"_omnipy");
346           if (!_omnipy)
347             {
348               PyErr_Print();
349               PyErr_SetString(PyExc_ImportError, (char*)"Cannot import _omnipy");
350               goto out;
351             }
352           pyapi = PyObject_GetAttrString(_omnipy, (char*)"API");
353           if (!pyapi)
354             {
355               goto out;
356             }
357           _api = (omniORBpyAPI*)PyCapsule_GetPointer(pyapi,"_omnipy.API");
358           Py_DECREF(pyapi);
359
360           res=PyRun_String("\n"
361                            "from math import *\n"
362                            "import sys\n"
363                            "sys.path.insert(0,'.')\n"
364                            "from omniORB import CORBA\n"
365                            "from omniORB import any\n"
366                            "orb = CORBA.ORB_init([], CORBA.ORB_ID)\n"
367                            "#print(sys.getrefcount(orb))\n"
368                            "try:\n"
369                            "  import SALOME\n"
370                            "except:\n"
371                            "  pass\n"
372                            "\n",
373                            Py_file_input,globals,globals );
374           if(res == NULL)
375             {
376               PyErr_Print();
377               goto out;
378             }
379           Py_DECREF(res);
380
381           _pyorb = PyDict_GetItemString(globals,"orb");
382           /* PyDict_GetItemString returns a borrowed reference. There is no need to decref _pyorb */
383
384           PyObject *pyany;
385           pyany = PyDict_GetItemString(globals,"any");
386           /* PyDict_GetItemString returns a borrowed reference. There is no need to decref pyany */
387
388 #ifdef REFCNT
389           DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
390 #endif
391         }
392       out:
393         PyGILState_Release(gstate); // Release the Global Interpreter Lock
394     }
395   if (_useCorba)
396     {
397       // initialize the catalogLoaderFactory map with the session one
398       _catalogLoaderFactoryMap["session"]=new SessionCataLoader;
399     }
400 }
401
402 void RuntimeSALOME::fini()
403 {
404   if (_usePython)
405     {
406       PyGILState_STATE gstate = PyGILState_Ensure();
407 #ifdef REFCNT
408       DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
409 #endif
410       PyObject *mainmod, *globals;
411       mainmod = PyImport_AddModule("__main__");
412       globals = PyModule_GetDict(mainmod);
413       if (_useCorba)
414         {
415           PyObject* res;
416           res=PyRun_String("orb.destroy()\n"
417                            "\n",
418                            Py_file_input,globals,globals );
419           if(res == NULL)
420             PyErr_Print();
421           else
422             Py_DECREF(res);
423         }
424       std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
425       delete nodeMap["PyFunction"];
426       delete nodeMap["PyScript"];
427       delete nodeMap["SalomePythonNode"];
428       nodeMap.erase("PyFunction");
429       nodeMap.erase("PyScript");
430       nodeMap.erase("SalomePythonNode");
431
432       Py_Finalize();
433 #ifdef REFCNT
434       DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
435 #endif
436     }
437   else
438     {
439       if (_useCorba)
440         {
441 #ifdef REFCNT
442           DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
443 #endif
444           _orb->destroy();
445         }
446     }
447 }
448
449 std::vector< std::pair<std::string,int> > RuntimeSALOME::getCatalogOfComputeNodes() const
450 {
451   CORBA::ORB_ptr orb(getOrb());
452   SALOME_NamingService namingService;
453   try
454   {
455     namingService.init_orb(orb);
456   }
457   catch(SALOME_Exception& e)
458   {
459     throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Unable to contact the SALOME Naming Service");
460   }
461   CORBA::Object_var obj(namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS));
462   if(CORBA::is_nil(obj))
463     throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Unable to access to the resource manager !");
464   Engines::ResourcesManager_var resManager(Engines::ResourcesManager::_narrow(obj));
465   if(CORBA::is_nil(resManager))
466     throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Internal error ! The entry attached to the res manager in NS does not have right type !");
467   std::vector< std::pair<std::string,int> > ret;
468   Engines::ResourceParameters params;
469   params.name = "";
470   params.hostname = "";
471   params.OS = "";
472   params.nb_proc = 0;
473   params.mem_mb = 0;
474   params.cpu_clock = 0;
475   params.nb_node = 0;
476   params.nb_proc_per_node = 0;
477   params.policy = "";
478   params.can_launch_batch_jobs = false;
479   params.can_run_containers = true;
480   params.componentList.length(0);
481   try
482   {
483     Engines::ResourceList_var resourceList;
484     resourceList = resManager->GetFittingResources(params);
485     ret.reserve(resourceList->length());
486     for(int i = 0; i<resourceList->length(); i++)
487     {
488       const char* resource_name = resourceList[i];
489       std::string std_resource_name = resource_name;
490       Engines::ResourceDefinition_var resource_definition
491                               = resManager->GetResourceDefinition(resource_name);
492       int nb_cores = resource_definition->nb_node *
493                      resource_definition->nb_proc_per_node;
494       ret.push_back(std::pair<std::string,int>(resource_name, nb_cores));
495     }
496   }
497   catch(SALOME::SALOME_Exception& e)
498   {
499     std::string message;
500     message=e.details.text.in();
501     throw Exception(message);
502   }
503
504   return ret;
505 }
506
507 std::string RuntimeSALOME::getVersion() const
508 {
509 #ifdef YACS_DEVELOPMENT
510   return CORBA::string_dup(YACS_VERSION_STR"dev");
511 #else
512   return CORBA::string_dup(YACS_VERSION_STR);
513 #endif
514 }
515
516 Proc* RuntimeSALOME::createProc(const std::string& name)
517 {
518   return new SalomeProc(name);
519 }
520
521 TypeCode * RuntimeSALOME::createInterfaceTc(const std::string& id, const std::string& name,
522                                             std::list<TypeCodeObjref *> ltc)
523 {
524   std::string myName;
525   if(id == "") myName = "IDL:" + name + ":1.0";
526   else myName = id;
527   return TypeCode::interfaceTc(myName.c_str(),name.c_str(),ltc);
528 }
529
530 TypeCode * RuntimeSALOME::createSequenceTc(const std::string& id,
531                                            const std::string& name,
532                                            TypeCode *content)
533 {
534   return TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
535 };
536
537 TypeCodeStruct * RuntimeSALOME::createStructTc(const std::string& id, const std::string& name)
538 {
539   std::string myName;
540   if(id == "") myName = "IDL:" + name + ":1.0";
541   else myName = id;
542   return (TypeCodeStruct *)TypeCode::structTc(myName.c_str(),name.c_str());
543 }
544
545 Bloc* RuntimeSALOME::createBloc(const std::string& name)
546 {
547   return new Bloc(name);
548 }
549
550 WhileLoop* RuntimeSALOME::createWhileLoop(const std::string& name)
551 {
552   return new WhileLoop(name);
553 }
554
555 ForLoop* RuntimeSALOME::createForLoop(const std::string& name)
556 {
557   return new ForLoop(name);
558 }
559
560 OptimizerLoop* RuntimeSALOME::createOptimizerLoop(const std::string& name,const std::string& algLib,const std::string& factoryName,
561                                                   bool algInitOnFile, const std::string& kind, Proc * procForTypes)
562 {
563   OptimizerLoop * ol = (kind == "base") ? new OptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes) :
564                                           new SalomeOptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes);
565   ol->edGetNbOfBranchesPort()->edInit(1);
566   return ol;
567 }
568
569 DataNode* RuntimeSALOME::createInDataNode(const std::string& kind,const std::string& name)
570 {
571   DataNode* node;
572   if(kind == "" )
573     {
574       node = new PresetNode(name);
575       return node;
576     }
577   else if(kind == "study" )
578     {
579       return new StudyInNode(name);
580     }
581   std::string msg="DataNode kind ("+kind+") unknown";
582   throw Exception(msg);
583 }
584
585 DataNode* RuntimeSALOME::createOutDataNode(const std::string& kind,const std::string& name)
586 {
587   if(kind == "" )
588     {
589       return new OutNode(name);
590     }
591   else if(kind == "study" )
592     {
593       return new StudyOutNode(name);
594     }
595
596   std::string msg="OutDataNode kind ("+kind+") unknown";
597   throw Exception(msg);
598 }
599
600 InlineFuncNode* RuntimeSALOME::createFuncNode(const std::string& kind,const std::string& name)
601 {
602   InlineFuncNode* node;
603   if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
604     {
605       node = new PyFuncNode(name);
606       return node;
607     }
608   if(kind == DistributedPythonNode::KIND)
609     return new DistributedPythonNode(name);
610   std::string msg="FuncNode kind ("+kind+") unknown";
611   throw Exception(msg);
612 }
613
614 InlineNode* RuntimeSALOME::createScriptNode(const std::string& kind,const std::string& name)
615 {
616   InlineNode* node;
617   if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
618     {
619       node = new PythonNode(name);
620       return node;
621     }
622   std::string msg="ScriptNode kind ("+kind+") unknown";
623   throw Exception(msg);
624 }
625
626 ServiceNode* RuntimeSALOME::createRefNode(const std::string& kind,const std::string& name)
627 {
628   ServiceNode* node;
629   if(kind == "" || kind == SalomeNode::KIND || kind == CORBANode::KIND)
630     {
631       node = new CORBANode(name);
632       return node;
633     }
634   else if(kind == XmlNode::KIND)
635     {
636       node = new XmlNode(name);
637       return node;
638     }
639   std::string msg="RefNode kind ("+kind+") unknown";
640   throw Exception(msg);
641 }
642
643 ServiceNode* RuntimeSALOME::createCompoNode(const std::string& kind,const std::string& name)
644 {
645   ServiceNode* node;
646   if(kind == "" || kind == SalomeNode::KIND )
647     {
648       node=new SalomeNode(name);
649       return node;
650     }
651   else if (kind == CppNode::KIND) 
652     {
653       node = new CppNode(name);
654       return node;
655     }
656   std::string msg="CompoNode kind ("+kind+") unknown";
657   throw Exception(msg);
658 }
659
660 ServiceInlineNode *RuntimeSALOME::createSInlineNode(const std::string& kind, const std::string& name)
661 {
662   if(kind == "" || kind == SalomeNode::KIND )
663     return new SalomePythonNode(name);
664   std::string msg="CompoNode kind ("+kind+") unknown";
665   throw Exception(msg);
666 }
667
668 ComponentInstance* RuntimeSALOME::createComponentInstance(const std::string& name,
669                                                           const std::string& kind)
670 {
671   ComponentInstance* compo;
672   if(kind == "" || kind == SalomeComponent::KIND) 
673     return new SalomeComponent(name);
674   else if(kind == CORBAComponent::KIND)
675     return new CORBAComponent(name);
676   else if(kind == SalomePythonComponent::KIND)
677     return new SalomePythonComponent(name);
678   else if (kind == CppComponent::KIND)
679     return new CppComponent(name);
680   else if (kind == SalomeHPComponent::KIND)
681     return new SalomeHPComponent(name);
682   std::string msg="Component Instance kind ("+kind+") unknown";
683   throw Exception(msg);
684 }
685
686 Container *RuntimeSALOME::createContainer(const std::string& kind)
687 {
688   if(kind == "" || kind == SalomeContainer::KIND)
689     return new SalomeContainer;
690   if(kind==SalomeHPContainer::KIND)
691     return new SalomeHPContainer;
692   else if (kind == CppContainer::KIND)
693     return new CppContainer;
694   std::string msg="Container kind ("+kind+") unknown";
695   throw Exception(msg);
696 }
697
698 InputPort * RuntimeSALOME::createInputPort(const std::string& name,
699                                            const std::string& impl,
700                                            Node * node,
701                                            TypeCode * type)
702 {
703   if(impl == CppNode::IMPL_NAME)
704     {
705       return new InputCppPort(name, node, type);
706     }
707   else if(impl == PythonNode::IMPL_NAME)
708     {
709       return new InputPyPort(name, node, type);
710     }
711   else if(impl == CORBANode::IMPL_NAME)
712     {
713       return new InputCorbaPort(name, node, type);
714     }
715   else if(impl == XmlNode::IMPL_NAME)
716     {
717       return new InputXmlPort(name, node, type);
718     }
719   else
720     {
721       stringstream msg;
722       msg << "Cannot create " << impl << " InputPort" ;
723       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
724       throw Exception(msg.str());
725     }
726 }
727
728 OutputPort * RuntimeSALOME::createOutputPort(const std::string& name,
729                                              const std::string& impl,
730                                              Node * node,
731                                              TypeCode * type)
732 {
733   if(impl == CppNode::IMPL_NAME)
734     {
735       return new OutputCppPort(name, node, type);
736     }
737   else if(impl == PythonNode::IMPL_NAME)
738     {
739       return new OutputPyPort(name, node, type);
740     }
741   else if(impl == CORBANode::IMPL_NAME)
742     {
743       return new OutputCorbaPort(name, node, type);
744     }
745   else if(impl == XmlNode::IMPL_NAME)
746     {
747       return new OutputXmlPort(name, node, type);
748     }
749   else
750     {
751       stringstream msg;
752       msg << "Cannot create " << impl << " OutputPort" ;
753       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
754       throw Exception(msg.str());
755     }
756 }
757
758 InputDataStreamPort* RuntimeSALOME::createInputDataStreamPort(const std::string& name,
759                                                               Node *node,TypeCode *type)
760 {
761   DEBTRACE("createInputDataStreamPort: " << name << " " << type->shortName());
762   if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
763     {
764       return new InputCalStreamPort(name,node,type);
765     }
766   else
767     {
768       return new InputDataStreamPort(name,node,type);
769     }
770 }
771
772 OutputDataStreamPort* RuntimeSALOME::createOutputDataStreamPort(const std::string& name,
773                                                                 Node *node,TypeCode *type)
774 {
775   DEBTRACE("createOutputDataStreamPort: " << name << " " << type->shortName());
776   if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
777     {
778       return new OutputCalStreamPort(name,node,type);
779     }
780   else
781     {
782       return new OutputDataStreamPort(name,node,type);
783     }
784 }
785
786 //! Main adapter function : adapt an InputPort to be able to connect it to an OutputPort with a possible different implementation 
787 /*!
788  *  \param source : InputPort to be adapted
789  *  \param impl : new implementation (C++, python, CORBA, XML, Neutral)
790  *  \param type : data type provided by the InputPort
791  *  \param init : indicates if the adapted InputPort will be used for initialization (value true) or not (value false)
792  * 
793  * \return : adapted InputPort
794  */
795 InputPort* RuntimeSALOME::adapt(InputPort* source,
796                                 const std::string& impl,
797                                 TypeCode * type,bool init)
798 {
799   string imp_source=source->getNode()->getImplementation();
800   if(imp_source == PythonNode::IMPL_NAME)
801     {
802       return adapt((InputPyPort*)source,impl,type,init);
803     }
804   else if(imp_source == CppNode::IMPL_NAME)
805     {
806       return adapt((InputCppPort*)source,impl,type,init);
807     }
808   else if(imp_source == CORBANode::IMPL_NAME)
809     {
810       return adapt((InputCorbaPort*)source,impl,type,init);
811     }
812   else if(imp_source == XmlNode::IMPL_NAME)
813     {
814       return adapt((InputXmlPort*)source,impl,type,init);
815     }
816   else if(imp_source == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
817     {
818       return adaptNeutral(source,impl,type,init);
819     }
820   else
821     {
822       stringstream msg;
823       msg << "Cannot adapt " << imp_source << " InputPort to " << impl;
824       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
825       throw ConversionException(msg.str());
826     }
827 }
828
829 //! Adapter function for InPropertyPort
830 /*!
831  *  \param source : InPropertyPort to be adapted
832  *  \param impl : new implementation (C++, python, CORBA, XML, Neutral)
833  *  \param type : data type provided by the InPropertyPort
834  *  \param init : indicates if the adapted InPropertyPort will be used for initialization (value true) or not (value false)
835  * 
836  * \return : adapted InputPort
837  */
838 InputPort* RuntimeSALOME::adapt(InPropertyPort* source,
839                                 const std::string& impl,
840                                 TypeCode * type,bool init)
841 {
842   return adaptNeutral((InputPort *)source,impl,type,init);
843 }
844
845 //! Adapt a Neutral input port to a Corba output port
846 /*!
847  *   \param inport : Neutral input port to adapt to Corba type type
848  *   \param type : output port type
849  *   \return an adaptated input port of type InputCorbaPort
850  */
851 InputPort* RuntimeSALOME::adaptNeutralToCorba(InputPort* inport,
852                       TypeCode * type)
853 {
854   // BEWARE : using the generic check
855   if(inport->edGetType()->isAdaptable(type))
856     {
857       //the output data is convertible to inport type
858       return new CorbaNeutral(inport);
859     }
860   //non convertible type
861   stringstream msg;
862   msg << "Cannot connect Corba output port with type: " << type->id() ;
863   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
864 #ifdef _DEVDEBUG_
865   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
866 #endif
867   throw ConversionException(msg.str());
868 }
869
870 //! Adapt a Neutral input port to a Python output port
871 /*!
872  *   \param inport : input port to adapt to Python type type
873  *   \param type : output port type
874  *   \return an adaptated input port of type InputPyPort
875  */
876 InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport,
877                       TypeCode * type)
878 {
879   // BEWARE : using the generic check
880   if(inport->edGetType()->isAdaptable(type))
881     {
882       //convertible type
883       return new PyNeutral(inport);
884     }
885   //last chance : an py output that is seq[objref] can be connected to a neutral input objref (P13268)
886   else if(type->kind()==Sequence && type->contentType()->kind()==Objref && inport->edGetType()->kind()==Objref)
887     {
888       return new PyNeutral(inport);
889     }
890   //non convertible type
891   stringstream msg;
892   msg << "Cannot connect Python output port with type: " << type->id() ;
893   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
894 #ifdef _DEVDEBUG_
895   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
896 #endif
897   throw ConversionException(msg.str());
898 }
899
900 //! Adapt a Neutral input port to a Xml output port 
901 /*!
902  *   \param inport : input port to adapt to Xml type type
903  *   \param type : output port type
904  *   \return an input port of type InputXmlPort
905  */
906 InputPort* RuntimeSALOME::adaptNeutralToXml(InputPort* inport,
907                       TypeCode * type)
908 {
909   // BEWARE : using the generic check
910   if(inport->edGetType()->isAdaptable(type))
911     {
912       //convertible type
913       return new XmlNeutral(inport);
914     }
915   //non convertible type
916   stringstream msg;
917   msg << "Cannot connect Xml output port with type: " << type->id() ;
918   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
919 #ifdef _DEVDEBUG_
920   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
921 #endif
922   throw ConversionException(msg.str());
923 }
924
925 //! Adapt a Neutral input port to a C++ output port 
926 /*!
927  *   \param inport : input port to adapt to C++ type type
928  *   \param type : output port type
929  *   \return an input port of type InputCppPort
930  */
931 InputPort* RuntimeSALOME::adaptNeutralToCpp(InputPort* inport,
932                       TypeCode * type)
933 {
934   DEBTRACE("RuntimeSALOME::adaptNeutralToCpp(InputPort* inport" );
935   if(isAdaptableNeutralCpp(type,inport->edGetType()))
936     {
937       //convertible type
938       return new CppNeutral(inport);
939     }
940   //non convertible type
941   stringstream msg;
942   msg << "Cannot connect Cpp output port with type: " << type->id() ;
943   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
944 #ifdef _DEVDEBUG_
945   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
946 #endif
947   throw ConversionException(msg.str());
948 }
949
950 //! Adapt a Neutral input port to connect it to an output port with a given implementation
951 /*!
952  *   \param source : Neutral input port to adapt to implementation impl and type type
953  *   \param impl : output port implementation (C++, Python, Corba, Xml or Neutral)
954  *   \param type : output port supported type
955  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
956  *   \return       the adaptated port
957  */
958 InputPort* RuntimeSALOME::adaptNeutral(InputPort* source,
959                                        const std::string& impl,
960                                        TypeCode * type,bool init)
961 {
962   if(impl == CppNode::IMPL_NAME)
963     {
964       return adaptNeutralToCpp(source,type);
965     }
966   else if(impl == PythonNode::IMPL_NAME)
967     {
968       return adaptNeutralToPython(source,type);
969     }
970   else if(impl == CORBANode::IMPL_NAME)
971     {
972       return adaptNeutralToCorba(source,type);
973     }
974   else if(impl == XmlNode::IMPL_NAME )
975     {
976       return adaptNeutralToXml(source,type);
977     }
978   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
979     {
980       if(init)
981         return new NeutralInit(source);
982       else
983         return new ProxyPort(source);
984     }
985   stringstream msg;
986   msg << "Cannot connect InputPort : unknown implementation " << impl;
987   msg << " (" <<__FILE__ << ":" <<__LINE__ << ")";
988   throw ConversionException(msg.str());
989 }
990
991 //! Adapt a XML input port to connect it to a CORBA output port 
992 /*!
993  *   \param inport : input port to adapt to CORBA type type
994  *   \param type : type supported by output port
995  *   \return an adaptator port of type InputCorbaPort 
996  */
997
998 InputPort* RuntimeSALOME::adaptXmlToCorba(InputXmlPort* inport,
999                                           TypeCode * type)
1000 {
1001   if(isAdaptableXmlCorba(type,inport->edGetType()))
1002     {
1003       //output type is convertible to input type
1004       return new CorbaXml(inport);
1005     }
1006   //output type is not convertible
1007   stringstream msg;
1008   msg << "Cannot connect Corba output port with type: " << type->id() ;
1009   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1010 #ifdef _DEVDEBUG_
1011   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1012 #endif
1013   throw ConversionException(msg.str());
1014 }
1015
1016 //! Adapt a XML input port to a Python output port
1017 /*!
1018  *   \param inport : input port to adapt to Python type type
1019  *   \param type : output port type
1020  *   \return an adaptated input port of type InputPyPort
1021  */
1022 InputPort* RuntimeSALOME::adaptXmlToPython(InputXmlPort* inport,
1023                       TypeCode * type)
1024 {
1025   if(inport->edGetType()->isAdaptable(type))
1026     {
1027       //the output data is convertible to inport type
1028       return new PyXml(inport);
1029     }
1030   //non convertible type
1031   stringstream msg;
1032   msg << "Cannot connect Python output port with type: " << type->id() ;
1033   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1034 #ifdef _DEVDEBUG_
1035   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1036 #endif
1037   throw ConversionException(msg.str());
1038 }
1039
1040 //! Adapt a XML input port to a C++ output port
1041 /*!
1042  *   \param inport : input port to adapt to C++ type type
1043  *   \param type : output port type
1044  *   \return an adaptated input port of type InputPyPort
1045  */
1046 InputPort* RuntimeSALOME::adaptXmlToCpp(InputXmlPort* inport,
1047                       TypeCode * type)
1048 {
1049   DEBTRACE("RuntimeSALOME::adaptXmlToCpp(InputPort* inport" );
1050   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1051   if(type->isAdaptable(inport->edGetType()))
1052     {
1053       //the output data is convertible to inport type
1054       return new CppXml(inport);
1055     }
1056   //non convertible type
1057   stringstream msg;
1058   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1059   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1060 #ifdef _DEVDEBUG_
1061   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1062 #endif
1063   throw ConversionException(msg.str());
1064 }
1065
1066 //! Adapt a XML input port to a Neutral output port
1067 /*!
1068  *   \param inport : input port to adapt to Neutral type type
1069  *   \param type : output port type
1070  *   \return an adaptated input port of type Neutralxxxx
1071  */
1072 InputPort* RuntimeSALOME::adaptXmlToNeutral(InputXmlPort* inport,
1073                       TypeCode * type)
1074 {
1075   if(inport->edGetType()->isAdaptable(type))
1076     {
1077       //the output data is convertible to inport type
1078       return new NeutralXml(inport);
1079     }
1080   //non convertible type
1081   stringstream msg;
1082   msg << "Cannot connect Xml InputPort to OutputNeutralPort : " ;
1083   msg << "(" <<__FILE__ << ":" <<__LINE__<< ")";
1084   throw ConversionException(msg.str());
1085 }
1086
1087 //! Adapt a XML input port to a Xml output port
1088 /*!
1089  *   \param inport : input port to adapt to Xml type type
1090  *   \param type : output port type
1091  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1092  *   \return an adaptated input port of type Xmlxxxx
1093  */
1094 InputPort* RuntimeSALOME::adaptXmlToXml(InputXmlPort* inport,
1095                       TypeCode * type,bool init)
1096 {
1097   if(init)
1098     return new ProxyPort(inport);
1099
1100   if(inport->edGetType()->isAdaptable(type))
1101     return new ProxyPort(inport);
1102
1103   stringstream msg;
1104   msg << "Cannot connect Xml output port with type: " << type->id() ;
1105   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1106 #ifdef _DEVDEBUG_
1107   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1108 #endif
1109   throw ConversionException(msg.str());
1110 }
1111
1112 //! Adapt an Xml input port to an output port which implementation is given by impl
1113 /*!
1114  *   \param source : input port to adapt to implementation impl and type type
1115  *   \param impl : output port implementation (C++, Python or Corba)
1116  *   \param type : output port supported type
1117  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1118  *   \return       the adaptated port
1119  */
1120
1121 InputPort* RuntimeSALOME::adapt(InputXmlPort* source,
1122                                 const std::string& impl,
1123                                 TypeCode * type,bool init)
1124 {
1125   if(impl == CORBANode::IMPL_NAME)
1126     {
1127       return adaptXmlToCorba(source,type);
1128     }
1129   else if(impl == PythonNode::IMPL_NAME)
1130     {
1131       return adaptXmlToPython(source,type);
1132     }
1133   else if(impl == CppNode::IMPL_NAME)
1134     {
1135       return adaptXmlToCpp(source,type);
1136     }
1137   else if(impl == XmlNode::IMPL_NAME )
1138     {
1139       return adaptXmlToXml(source,type,init);
1140     }
1141   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1142     {
1143       return adaptXmlToNeutral(source,type);
1144     }
1145   else
1146     {
1147       stringstream msg;
1148       msg << "Cannot connect InputXmlPort to " << impl << " implementation";
1149       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1150       throw ConversionException(msg.str());
1151     }
1152 }
1153
1154
1155 //! Adapt a CORBA input port to a CORBA output port 
1156 /*!
1157  *   \param inport : input port to adapt to CORBA outport data type
1158  *   \param type : outport data type 
1159  *   \return an adaptator port of type InputCORBAPort 
1160  */
1161 InputPort* RuntimeSALOME::adaptCorbaToCorba(InputCorbaPort* inport,
1162                                             TypeCode * type)
1163 {
1164   if(type->isA(inport->edGetType()))
1165     {
1166       //types are compatible : no conversion 
1167       //outport data type is more specific than inport required type
1168       //so the inport can be used safely 
1169       return new ProxyPort(inport);
1170     }
1171   else if(isAdaptableCorbaCorba(type,inport->edGetType()))
1172     {
1173       //ouport data can be converted to inport data type
1174       return new CorbaCorba(inport);
1175     }
1176   //outport data can not be converted
1177   stringstream msg;
1178   msg << "Cannot connect Corba output port with type: " << type->id() ;
1179   msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1180 #ifdef _DEVDEBUG_
1181   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1182 #endif
1183   throw ConversionException(msg.str());
1184 }
1185
1186 //! Adapt a CORBA input port to a Python output port 
1187 /*!
1188  *   \param inport : input port to adapt to Python type type
1189  *   \param type : outport data type 
1190  *   \return an adaptator port of type InputPyPort 
1191  */
1192
1193 InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport,
1194                                              TypeCode * type)
1195 {
1196   if(inport->edGetType()->kind() == Double)
1197     {
1198       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaDouble(inport);
1199     }
1200   else if(inport->edGetType()->kind() == Int)
1201     {
1202       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaInt(inport);
1203     }
1204   else if(inport->edGetType()->kind() == String)
1205     {
1206       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaString(inport);
1207     }
1208   else if(inport->edGetType()->kind() == Bool)
1209     {
1210       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaBool(inport);
1211     }
1212   else if(inport->edGetType()->kind() == Objref )
1213     {
1214       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1215         {
1216           return new PyCorbaObjref(inport);
1217         }
1218       else
1219         {
1220           stringstream msg;
1221           msg << "Cannot connect Python output port with type: " << type->id() ;
1222           msg << " to CORBA input port " << inport->getName() << " with incompatible objref type: " << inport->edGetType()->id();
1223           msg << " (" << __FILE__ << ":" <<__LINE__ << ")";
1224           throw ConversionException(msg.str());
1225         }
1226     }
1227   else if(inport->edGetType()->kind() == Sequence)
1228     {
1229       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1230         {
1231           return new PyCorbaSequence(inport);
1232         }
1233       else
1234         {
1235           stringstream msg;
1236           msg << "Cannot convert this sequence type " ;
1237           msg << __FILE__ << ":" <<__LINE__;
1238           throw ConversionException(msg.str());
1239         }
1240     }
1241   else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1242     {
1243       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1244         {
1245           return new PyCorbaStruct(inport);
1246         }
1247       else
1248         {
1249           stringstream msg;
1250           msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1251           msg << __FILE__ << ":" <<__LINE__;
1252           throw ConversionException(msg.str());
1253         }
1254     }
1255   // Adaptation not possible
1256   stringstream msg;
1257   msg << "Cannot connect Python output port with type: " << type->id() ;
1258   msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1259 #ifdef _DEVDEBUG_
1260   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1261 #endif
1262   throw ConversionException(msg.str());
1263 }
1264
1265 //! Adapt a CORBA input port to connect it to a XML output port 
1266 /*!
1267  *   \param inport : input port to adapt to Xml type type
1268  *   \param type : type supported by output port
1269  *   \return an adaptator port of type InputXmlPort 
1270  */
1271
1272 InputPort* RuntimeSALOME::adaptCorbaToXml(InputCorbaPort* inport,
1273                                           TypeCode * type)
1274 {
1275   // BEWARE : using the generic check
1276   if(inport->edGetType()->isAdaptable(type))
1277     {
1278       //output type is convertible to input type
1279       return new XmlCorba(inport);
1280     }
1281   //output type is not convertible
1282   stringstream msg;
1283   msg << "Cannot connect Xml output port with type: " << type->id() ;
1284   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1285 #ifdef _DEVDEBUG_
1286   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1287 #endif
1288   throw ConversionException(msg.str());
1289 }
1290
1291 //! Adapt a CORBA input port to a C++ output port 
1292 /*!
1293  *   \param inport : input port to adapt to C++ type type
1294  *   \param type : outport data type 
1295  *   \return an adaptator port of type InputCPPPort 
1296  */
1297
1298 InputPort* RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport,
1299                                           TypeCode * type)
1300 {
1301   DEBTRACE("RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport" );
1302   if(isAdaptableCorbaCpp(type,inport->edGetType()))
1303     {
1304       //output type is convertible to input type
1305       return new CppCorba(inport);
1306     }
1307   //output type is not convertible
1308   stringstream msg;
1309   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1310   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1311 #ifdef _DEVDEBUG_
1312   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1313 #endif
1314   throw ConversionException(msg.str());
1315 }
1316
1317 //! Adapt a CORBA input port to a neutral data 
1318 /*!
1319  *   \param inport : InputPort to adapt to Neutral type type
1320  *   \param type : outport data type 
1321  *   \return an adaptator port of type Neutralxxxx
1322  */
1323
1324 InputPort* RuntimeSALOME::adaptCorbaToNeutral(InputCorbaPort* inport,
1325                                               TypeCode * type)
1326 {
1327   if(inport->edGetType()->kind() == Double)
1328     {
1329       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaDouble(inport);
1330     }
1331   else if(inport->edGetType()->kind() == Int)
1332     {
1333       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaInt(inport);
1334     }
1335   else if(inport->edGetType()->kind() == String)
1336     {
1337       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaString(inport);
1338     }
1339   else if(inport->edGetType()->kind() == Bool)
1340     {
1341       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaBool(inport);
1342     }
1343   else if(inport->edGetType()->kind() == Objref)
1344     {
1345       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaObjref(inport);
1346     }
1347   else if(inport->edGetType()->kind() == Sequence)
1348     {
1349       if(isAdaptableCorbaNeutral(type,inport->edGetType()))
1350         return new NeutralCorbaSequence(inport);
1351       else
1352         {
1353           stringstream msg;
1354           msg << "Cannot convert this sequence type " ;
1355           msg << __FILE__ << ":" <<__LINE__;
1356           throw ConversionException(msg.str());
1357         }
1358     }
1359   else if(inport->edGetType()->kind() == Struct)
1360     {
1361       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaStruct(inport);
1362     }
1363
1364   // Adaptation not possible
1365   stringstream msg;
1366   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1367   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1368 #ifdef _DEVDEBUG_
1369   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1370 #endif
1371   throw ConversionException(msg.str());
1372 }
1373
1374 //! Adapt a CORBA input port to an output which implementation and type are given by impl and type
1375 /*!
1376  *   \param source : input port to adapt to implementation impl and type type
1377  *   \param impl : output port implementation (C++, Python or Corba)
1378  *   \param type : outport data type 
1379  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1380  *   \return an adaptator port which type depends on impl
1381  */
1382
1383 InputPort* RuntimeSALOME::adapt(InputCorbaPort* source,
1384                                 const std::string& impl,
1385                                 TypeCode * type,bool init)
1386 {
1387   if(impl == CppNode::IMPL_NAME)
1388     {
1389       return adaptCorbaToCpp(source,type);
1390     }
1391   else if(impl == PythonNode::IMPL_NAME)
1392     {
1393       return adaptCorbaToPython(source,type);
1394     }
1395   else if(impl == CORBANode::IMPL_NAME)
1396     {
1397       if(init)
1398         return adaptCorbaToCorba(source,type);
1399       else
1400         return adaptCorbaToCorba(source,type);
1401     }
1402   else if(impl == XmlNode::IMPL_NAME )
1403     {
1404       return adaptCorbaToXml(source,type);
1405     }
1406   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1407     {
1408       return adaptCorbaToNeutral(source,type);
1409     }
1410   else
1411     {
1412       stringstream msg;
1413       msg << "Cannot connect InputCorbaPort : unknown implementation " ;
1414       msg << __FILE__ << ":" <<__LINE__;
1415       throw ConversionException(msg.str());
1416     }
1417 }
1418
1419 //! Adapt a Python input port to a Python output port
1420 /*!
1421  * No need to make conversion or cast. 
1422  * Only check, it's possible.
1423  *   \param inport : InputPort to adapt to Python type type
1424  *   \param type : outport data type 
1425  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1426  *   \return an adaptator port of type InputPyPort 
1427  */
1428
1429 InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport,
1430                                               TypeCode * type,bool init)
1431 {
1432   if(init)
1433     return new PyInit(inport);
1434
1435   if(isAdaptablePyObjectPyObject(type,inport->edGetType()))
1436     {
1437       //output data is convertible to input type
1438       //With python, no need to convert. Conversion will be done automatically
1439       //by the interpreter
1440       return new ProxyPort(inport);
1441     }
1442   //output data is not convertible to input type
1443   stringstream msg;
1444   msg << "Cannot connect Python output port with type: " << type->id() ;
1445   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1446 #ifdef _DEVDEBUG_
1447   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1448 #endif
1449   throw ConversionException(msg.str());
1450 }
1451
1452 //! Adapt a Python input port to a C++ output port
1453 /*!
1454  *   \param inport : InputPort to adapt to C++ type type
1455  *   \param type : outport data type 
1456  *   \return an adaptator port of C++ type (InputCppPort)
1457  */
1458
1459 InputPort* RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport,
1460                                            TypeCode * type)
1461 {
1462   DEBTRACE("RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport" );
1463   if(isAdaptablePyObjectCpp(type,inport->edGetType()))
1464     {
1465       //output type is convertible to input type
1466       return new CppPy(inport);
1467     }
1468   //output type is not convertible
1469   stringstream msg;
1470   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1471   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1472 #ifdef _DEVDEBUG_
1473   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1474 #endif
1475   throw ConversionException(msg.str());
1476 }
1477
1478 //! Adapt a Python input port to a Neutral data port
1479 /*!
1480  *   \param inport : InputPort to adapt to Neutral type type
1481  *   \param type : outport data type 
1482  *   \return an adaptator port of Neutral type (Neutralxxxx)
1483  */
1484
1485 InputPort* RuntimeSALOME::adaptPythonToNeutral(InputPyPort* inport,
1486                                                TypeCode * type)
1487 {
1488   if(inport->edGetType()->kind() == Double)
1489     {
1490       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyDouble(inport);
1491     }
1492   else if(inport->edGetType()->kind() == Int)
1493     {
1494       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyInt(inport);
1495     }
1496   else if(inport->edGetType()->kind() == String)
1497     {
1498       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyString(inport);
1499     }
1500   else if(inport->edGetType()->kind() == Bool)
1501     {
1502       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyBool(inport);
1503     }
1504   else if(inport->edGetType()->kind() == Objref)
1505     {
1506       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyObjref(inport);
1507     }
1508   else if(inport->edGetType()->kind() == Sequence)
1509     {
1510       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))
1511         return new NeutralPySequence(inport);
1512       else
1513         {
1514           stringstream msg;
1515           msg << "Cannot convert this sequence type " ;
1516           msg << __FILE__ << ":" <<__LINE__;
1517           throw ConversionException(msg.str());
1518         }
1519     }
1520   else if(inport->edGetType()->kind() == Struct)
1521     {
1522       if(isAdaptablePyObjectNeutral(type,inport->edGetType())) return new NeutralPyStruct(inport);
1523     }
1524
1525   // Adaptation not possible
1526   stringstream msg;
1527   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1528   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1529 #ifdef _DEVDEBUG_
1530   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1531 #endif
1532   throw ConversionException(msg.str());
1533 }
1534
1535 //! Adapt a Python input port to a Corba output port
1536 /*!
1537  * Always convert the data
1538  *   \param inport : InputPort to adapt to Corba type type
1539  *   \param type : outport data type 
1540  *   \return an adaptator port of Corba type (InputCorbaPort)
1541  */
1542
1543 InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport,
1544                                              TypeCode * type)
1545 {
1546   if(inport->edGetType()->kind() == Double)
1547     {
1548       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyDouble(inport);
1549     }
1550   else if(inport->edGetType()->kind() == Int)
1551     {
1552       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyInt(inport);
1553     }
1554   else if(inport->edGetType()->kind() == String)
1555     {
1556       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyString(inport);
1557     }
1558   else if(inport->edGetType()->kind() == Bool)
1559     {
1560       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyBool(inport);
1561     }
1562   else if(inport->edGetType()->kind() == Objref)
1563     {
1564       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1565         {
1566           return new CorbaPyObjref(inport);
1567         }
1568       else
1569         {
1570           stringstream msg;
1571           msg << "Cannot connect InputCorbaPort : incompatible objref types " << type->id() << " " << inport->edGetType()->id();
1572           msg << " " << __FILE__ << ":" <<__LINE__;
1573           throw ConversionException(msg.str());
1574         }
1575     }
1576   else if(inport->edGetType()->kind() == Sequence)
1577     {
1578       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1579         {
1580           return new CorbaPySequence(inport);
1581         }
1582       else
1583         {
1584           stringstream msg;
1585           msg << "Cannot convert this sequence type " ;
1586           msg << __FILE__ << ":" <<__LINE__;
1587           throw ConversionException(msg.str());
1588         }
1589     }
1590   else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1591     {
1592       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1593         {
1594           return new CorbaPyStruct(inport);
1595         }
1596       else
1597         {
1598           stringstream msg;
1599           msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1600           msg << " " << __FILE__ << ":" <<__LINE__;
1601           throw ConversionException(msg.str());
1602         }
1603     }
1604   // Adaptation not possible
1605   stringstream msg;
1606   msg << "Cannot connect Corba output port with type: " << type->id() ;
1607   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1608 #ifdef _DEVDEBUG_
1609   msg << " ("__FILE__ << ":" << __LINE__ << ")";
1610 #endif
1611   throw ConversionException(msg.str());
1612 }
1613
1614 //! Adapt a Python input port to a Xml output port 
1615 /*!
1616  *   \param inport : input port to adapt to Xml type type
1617  *   \param type : output port type
1618  *   \return an input port of type InputXmlPort
1619  */
1620
1621 InputPort* RuntimeSALOME::adaptPythonToXml(InputPyPort* inport,
1622                                           TypeCode * type)
1623 {
1624   // BEWARE : using the generic check
1625   if(inport->edGetType()->isAdaptable(type))
1626     {
1627       //convertible type
1628       return new XmlPython(inport);
1629     }
1630   //non convertible type
1631   stringstream msg;
1632   msg << "Cannot connect Xml output port with type: " << type->id() ;
1633   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1634 #ifdef _DEVDEBUG_
1635   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1636 #endif
1637   throw ConversionException(msg.str());
1638 }
1639
1640 //! Adapt a Python input port to an output port with a given implementation
1641 /*!
1642  *   \param source : input port to adapt to implementation impl and type type
1643  *   \param impl : output port implementation (C++, Python or Corba)
1644  *   \param type : output port type
1645  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1646  *   \return     adaptated input port
1647  */
1648
1649 InputPort* RuntimeSALOME::adapt(InputPyPort* source,
1650                                 const std::string& impl,
1651                                 TypeCode * type,bool init)
1652 {
1653   if(impl == CppNode::IMPL_NAME)
1654     {
1655       return adaptPythonToCpp(source,type);
1656     }
1657   else if(impl == PythonNode::IMPL_NAME)
1658     {
1659       return adaptPythonToPython(source,type,init);
1660     }
1661   else if(impl == CORBANode::IMPL_NAME)
1662     {
1663       return adaptPythonToCorba(source,type);
1664     }
1665   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1666     {
1667       return adaptPythonToNeutral(source,type);
1668     }
1669   else if(impl == XmlNode::IMPL_NAME)
1670     {
1671       return adaptPythonToXml(source,type);
1672     }
1673   else
1674     {
1675       stringstream msg;
1676       msg << "Cannot connect InputPyPort : unknown implementation " << impl;
1677       msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1678       throw ConversionException(msg.str());
1679     }
1680 }
1681
1682
1683 //! Adapt a C++ input port to connect it to a CORBA output port
1684 /*!
1685  *   \param inport : input port to adapt to CORBA type type
1686  *   \param type : type supported by output port
1687  *   \return an adaptator port of type InputCorbaPort
1688  */
1689
1690 InputPort* RuntimeSALOME::adaptCppToCorba(InputCppPort* inport,
1691                                           TypeCode * type)
1692 {
1693   DEBTRACE("RuntimeSALOME::adaptCppToCorba(InputCppPort* inport)");
1694   if(isAdaptableCppCorba(type,inport->edGetType()))
1695     {
1696       //output type is convertible to input type
1697       return new CorbaCpp(inport);
1698     }
1699   //output type is not convertible
1700   stringstream msg;
1701   msg << "Cannot connect Corba output port with type: " << type->id() ;
1702   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1703 #ifdef _DEVDEBUG_
1704   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1705 #endif
1706   throw ConversionException(msg.str());
1707 }
1708
1709 //! Adapt a C++ input port to a Python output port
1710 /*!
1711  *   \param inport : input port to adapt to Python type type
1712  *   \param type : output port type
1713  *   \return an adaptated input port of type InputPyPort
1714  */
1715 InputPort* RuntimeSALOME::adaptCppToPython(InputCppPort* inport,
1716                       TypeCode * type)
1717 {
1718   DEBTRACE("RuntimeSALOME::adaptCppToPython(InputCppPort* inport)");
1719   if(isAdaptableCppPyObject(type,inport->edGetType()))
1720     {
1721       //output type is convertible to input type
1722       return new PyCpp(inport);
1723     }
1724   //output type is not convertible
1725   stringstream msg;
1726   msg << "Cannot connect Python output port with type: " << type->id() ;
1727   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1728 #ifdef _DEVDEBUG_
1729   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1730 #endif
1731   throw ConversionException(msg.str());
1732 }
1733
1734 //! Adapt a C++ input port to a C++ output port
1735 /*!
1736  *   \param inport : input port to adapt to C++ type type
1737  *   \param type : output port type
1738  *   \return an adaptated input port of type InputPyPort
1739  */
1740 InputPort* RuntimeSALOME::adaptCppToCpp(InputCppPort* inport,
1741                       TypeCode * type)
1742 {
1743   DEBTRACE("RuntimeSALOME::adaptCppToCpp(InputPort* inport" );
1744   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1745   if(type->isAdaptable(inport->edGetType()))
1746     {
1747       //the output data is convertible to inport type
1748       return new CppCpp(inport);
1749     }
1750   //non convertible type
1751   stringstream msg;
1752   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1753   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1754 #ifdef _DEVDEBUG_
1755   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1756 #endif
1757   throw ConversionException(msg.str());
1758 }
1759
1760 //! Adapt a C++ input port to a Neutral output port
1761 /*!
1762  *   \param inport : input port to adapt to C++ type type
1763  *   \param type : output port type
1764  *   \return an adaptated input port of type InputPyPort
1765  */
1766 InputPort* RuntimeSALOME::adaptCppToNeutral(InputCppPort* inport,
1767                       TypeCode * type)
1768 {
1769   DEBTRACE("RuntimeSALOME::adaptCppToNeutral(InputPort* inport" );
1770   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1771   if(type->isAdaptable(inport->edGetType()))
1772     {
1773       //the output data is convertible to inport type
1774       return new NeutralCpp(inport);
1775     }
1776   //non convertible type
1777   stringstream msg;
1778   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1779   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1780 #ifdef _DEVDEBUG_
1781   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1782 #endif
1783   throw ConversionException(msg.str());
1784 }
1785
1786 InputPort* RuntimeSALOME::adaptCppToXml(InputCppPort* inport,
1787                       TypeCode * type)
1788 {
1789   DEBTRACE("RuntimeSALOME::adaptCppToXml(InputCppPort* inport" );
1790   if(isAdaptableCppXml(type,inport->edGetType()))
1791     {
1792       //convertible type
1793       return new XmlCpp(inport);
1794     }
1795   //non convertible type
1796   stringstream msg;
1797   msg << "Cannot connect Xml output port with type: " << type->id() ;
1798   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1799 #ifdef _DEVDEBUG_
1800   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1801 #endif
1802    throw ConversionException(msg.str());
1803 }
1804
1805 //! Adapt a C++ input port to connect it to an output port with a given implementation
1806 /*!
1807  *   \param source : input port to adapt to implementation impl and type type
1808  *   \param impl : output port implementation (C++, Python or Corba)
1809  *   \param type : output port supported type
1810  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1811  *   \return       the adaptated port
1812  */
1813
1814 InputPort* RuntimeSALOME::adapt(InputCppPort* source,
1815                                 const std::string& impl,
1816                                 TypeCode * type,bool init)
1817 {
1818   DEBTRACE("RuntimeSALOME::adapt(InputCppPort* source)");
1819   if(impl == CORBANode::IMPL_NAME)
1820     {
1821       return adaptCppToCorba(source,type);
1822     }
1823   else if(impl == PythonNode::IMPL_NAME)
1824     {
1825       return adaptCppToPython(source,type);
1826     }
1827   else if(impl == XmlNode::IMPL_NAME)
1828     {
1829       return adaptCppToXml(source,type);
1830     }
1831   else if(impl == CppNode::IMPL_NAME)
1832     {
1833       return adaptCppToCpp(source, type);
1834     }
1835   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1836     {
1837       return adaptCppToNeutral(source, type);
1838     }
1839   else
1840     {
1841       stringstream msg;
1842       msg << "Cannot connect InputCppPort to " << impl << " implementation";
1843       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1844       throw ConversionException(msg.str());
1845     }
1846 }
1847
1848 // bool RuntimeSALOME::isCompatible(const OutputPort* outputPort, 
1849 //                               const InputPort*  inputPort)
1850 // {
1851 //   bool result=true;
1852 //   return result;
1853 // }
1854
1855 CORBA::ORB_ptr RuntimeSALOME::getOrb() const
1856 {
1857   return _orb;
1858 }
1859
1860 PyObject * RuntimeSALOME::getPyOrb() const
1861 {
1862   return _pyorb;
1863 }
1864
1865 PyObject * RuntimeSALOME::getBuiltins() const
1866 {
1867   return _bltins;
1868 }
1869
1870 DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory() const
1871 {
1872   return _dynFactory;
1873 }
1874
1875 PyObject * RuntimeSALOME::get_omnipy()
1876 {
1877   return _omnipy;
1878 }
1879
1880 omniORBpyAPI* RuntimeSALOME::getApi()
1881 {
1882   return _api;
1883 }
1884
1885 void* RuntimeSALOME::convertNeutral(TypeCode * type, Any *data)
1886 {
1887   if(data)
1888     return (void *)convertNeutralPyObject(type,data);
1889   else
1890     {
1891       Py_INCREF(Py_None);
1892       return (void *)Py_None;
1893     }
1894 }
1895
1896 std::string RuntimeSALOME::convertNeutralAsString(TypeCode * type, Any *data)
1897 {
1898   PyObject* ob;
1899   if(data)
1900     {
1901       // The call to PyGILState_Ensure was moved here because there was also
1902       // a crash when calling convertNeutralPyObject with a sequence of pyobj.
1903       // see also the comment below.
1904       PyGILState_STATE gstate = PyGILState_Ensure();
1905       ob=convertNeutralPyObject(type,data);
1906       std::string s=convertPyObjectToString(ob);
1907
1908       // Note (Renaud Barate, 8 jan 2013): With Python 2.7, this call to Py_DECREF causes a crash
1909       // (SIGSEGV) when ob is a sequence and the call is not protected with the global interpreter
1910       // lock. I thus added the call to PyGILState_Ensure / PyGILState_Release. It worked fine in
1911       // Python 2.6 without this call. If anyone finds the real reason of this bug and another fix,
1912       // feel free to change this code.
1913       //PyGILState_STATE gstate = PyGILState_Ensure();
1914       Py_DECREF(ob);
1915       PyGILState_Release(gstate);
1916       return s;
1917     }
1918   else
1919     {
1920       return "None";
1921     }
1922 }
1923
1924 std::string RuntimeSALOME::convertPyObjectToString(PyObject* ob)
1925 {
1926   return YACS::ENGINE::convertPyObjectToString(ob);
1927 }
1928
1929 PyObject* RuntimeSALOME::convertStringToPyObject(const std::string& s)
1930 {
1931   PyObject *mainmod;
1932   PyObject *globals;
1933   PyObject* ob;
1934   PyGILState_STATE gstate = PyGILState_Ensure();
1935   mainmod = PyImport_AddModule("__main__");
1936   globals = PyModule_GetDict(mainmod);
1937   PyObject* d = PyDict_New();
1938   //PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
1939   ob= PyRun_String( s.c_str(), Py_eval_input, globals, d);
1940   Py_DECREF(d);
1941   if(ob==NULL)
1942     {
1943       //exception
1944       std::string error;
1945       PyObject* new_stderr = newPyStdOut(error);
1946       PySys_SetObject((char *)"stderr", new_stderr);
1947       PyErr_Print();
1948       PySys_SetObject((char *)"stderr", PySys_GetObject((char *)"__stderr__"));
1949       Py_DECREF(new_stderr);
1950       PyGILState_Release(gstate);
1951       throw Exception(error);
1952     }
1953   PyGILState_Release(gstate);
1954   return ob;
1955 }