Salome HOME
Merge Python 3 porting.
[modules/yacs.git] / src / runtime / RuntimeSALOME.cxx
1 // Copyright (C) 2006-2016  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("SalomeContainerToolsSpreadOverTheResDecorator::getParameters : 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("SalomeContainerToolsSpreadOverTheResDecorator::getParameters : 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("SalomeContainerToolsSpreadOverTheResDecorator::getParameters : 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   {
469     Engines::ResourceList *rl(0);
470     Engines::IntegerList *il(0);
471     resManager->ListAllAvailableResources(rl,il);
472     int sz(rl->length());
473     if(il->length()!=sz)
474       throw Exception("SalomeContainerToolsSpreadOverTheResDecorator::getParameters : Internal error ! Invalid size !");
475     ret.resize(sz);
476     for(int i=0;i<sz;i++)
477       {
478         std::string s((*rl)[i]);
479         ret[i]=std::pair<std::string,int>(s,(*il)[i]);
480       }
481     delete rl;
482     delete il;
483   }
484   return ret;
485 }
486
487 std::string RuntimeSALOME::getVersion() const
488 {
489 #ifdef YACS_DEVELOPMENT
490   return CORBA::string_dup(YACS_VERSION_STR"dev");
491 #else
492   return CORBA::string_dup(YACS_VERSION_STR);
493 #endif
494 }
495
496 Proc* RuntimeSALOME::createProc(const std::string& name)
497 {
498   return new SalomeProc(name);
499 }
500
501 TypeCode * RuntimeSALOME::createInterfaceTc(const std::string& id, const std::string& name,
502                                             std::list<TypeCodeObjref *> ltc)
503 {
504   std::string myName;
505   if(id == "") myName = "IDL:" + name + ":1.0";
506   else myName = id;
507   return TypeCode::interfaceTc(myName.c_str(),name.c_str(),ltc);
508 }
509
510 TypeCode * RuntimeSALOME::createSequenceTc(const std::string& id,
511                                            const std::string& name,
512                                            TypeCode *content)
513 {
514   return TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
515 };
516
517 TypeCodeStruct * RuntimeSALOME::createStructTc(const std::string& id, const std::string& name)
518 {
519   std::string myName;
520   if(id == "") myName = "IDL:" + name + ":1.0";
521   else myName = id;
522   return (TypeCodeStruct *)TypeCode::structTc(myName.c_str(),name.c_str());
523 }
524
525 Bloc* RuntimeSALOME::createBloc(const std::string& name)
526 {
527   return new Bloc(name);
528 }
529
530 WhileLoop* RuntimeSALOME::createWhileLoop(const std::string& name)
531 {
532   return new WhileLoop(name);
533 }
534
535 ForLoop* RuntimeSALOME::createForLoop(const std::string& name)
536 {
537   return new ForLoop(name);
538 }
539
540 OptimizerLoop* RuntimeSALOME::createOptimizerLoop(const std::string& name,const std::string& algLib,const std::string& factoryName,
541                                                   bool algInitOnFile, const std::string& kind, Proc * procForTypes)
542 {
543   OptimizerLoop * ol = (kind == "base") ? new OptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes) :
544                                           new SalomeOptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes);
545   ol->edGetNbOfBranchesPort()->edInit(1);
546   return ol;
547 }
548
549 DataNode* RuntimeSALOME::createInDataNode(const std::string& kind,const std::string& name)
550 {
551   DataNode* node;
552   if(kind == "" )
553     {
554       node = new PresetNode(name);
555       return node;
556     }
557   else if(kind == "study" )
558     {
559       return new StudyInNode(name);
560     }
561   std::string msg="DataNode kind ("+kind+") unknown";
562   throw Exception(msg);
563 }
564
565 DataNode* RuntimeSALOME::createOutDataNode(const std::string& kind,const std::string& name)
566 {
567   if(kind == "" )
568     {
569       return new OutNode(name);
570     }
571   else if(kind == "study" )
572     {
573       return new StudyOutNode(name);
574     }
575
576   std::string msg="OutDataNode kind ("+kind+") unknown";
577   throw Exception(msg);
578 }
579
580 InlineFuncNode* RuntimeSALOME::createFuncNode(const std::string& kind,const std::string& name)
581 {
582   InlineFuncNode* node;
583   if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
584     {
585       node = new PyFuncNode(name);
586       return node;
587     }
588   if(kind == DistributedPythonNode::KIND)
589     return new DistributedPythonNode(name);
590   std::string msg="FuncNode kind ("+kind+") unknown";
591   throw Exception(msg);
592 }
593
594 InlineNode* RuntimeSALOME::createScriptNode(const std::string& kind,const std::string& name)
595 {
596   InlineNode* node;
597   if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
598     {
599       node = new PythonNode(name);
600       return node;
601     }
602   std::string msg="ScriptNode kind ("+kind+") unknown";
603   throw Exception(msg);
604 }
605
606 ServiceNode* RuntimeSALOME::createRefNode(const std::string& kind,const std::string& name)
607 {
608   ServiceNode* node;
609   if(kind == "" || kind == SalomeNode::KIND || kind == CORBANode::KIND)
610     {
611       node = new CORBANode(name);
612       return node;
613     }
614   else if(kind == XmlNode::KIND)
615     {
616       node = new XmlNode(name);
617       return node;
618     }
619   std::string msg="RefNode kind ("+kind+") unknown";
620   throw Exception(msg);
621 }
622
623 ServiceNode* RuntimeSALOME::createCompoNode(const std::string& kind,const std::string& name)
624 {
625   ServiceNode* node;
626   if(kind == "" || kind == SalomeNode::KIND )
627     {
628       node=new SalomeNode(name);
629       return node;
630     }
631   else if (kind == CppNode::KIND) 
632     {
633       node = new CppNode(name);
634       return node;
635     }
636   std::string msg="CompoNode kind ("+kind+") unknown";
637   throw Exception(msg);
638 }
639
640 ServiceInlineNode *RuntimeSALOME::createSInlineNode(const std::string& kind, const std::string& name)
641 {
642   if(kind == "" || kind == SalomeNode::KIND )
643     return new SalomePythonNode(name);
644   std::string msg="CompoNode kind ("+kind+") unknown";
645   throw Exception(msg);
646 }
647
648 ComponentInstance* RuntimeSALOME::createComponentInstance(const std::string& name,
649                                                           const std::string& kind)
650 {
651   ComponentInstance* compo;
652   if(kind == "" || kind == SalomeComponent::KIND) 
653     return new SalomeComponent(name);
654   else if(kind == CORBAComponent::KIND)
655     return new CORBAComponent(name);
656   else if(kind == SalomePythonComponent::KIND)
657     return new SalomePythonComponent(name);
658   else if (kind == CppComponent::KIND)
659     return new CppComponent(name);
660   else if (kind == SalomeHPComponent::KIND)
661     return new SalomeHPComponent(name);
662   std::string msg="Component Instance kind ("+kind+") unknown";
663   throw Exception(msg);
664 }
665
666 Container *RuntimeSALOME::createContainer(const std::string& kind)
667 {
668   if(kind == "" || kind == SalomeContainer::KIND)
669     return new SalomeContainer;
670   if(kind==SalomeHPContainer::KIND)
671     return new SalomeHPContainer;
672   else if (kind == CppContainer::KIND)
673     return new CppContainer;
674   std::string msg="Container kind ("+kind+") unknown";
675   throw Exception(msg);
676 }
677
678 InputPort * RuntimeSALOME::createInputPort(const std::string& name,
679                                            const std::string& impl,
680                                            Node * node,
681                                            TypeCode * type)
682 {
683   if(impl == CppNode::IMPL_NAME)
684     {
685       return new InputCppPort(name, node, type);
686     }
687   else if(impl == PythonNode::IMPL_NAME)
688     {
689       return new InputPyPort(name, node, type);
690     }
691   else if(impl == CORBANode::IMPL_NAME)
692     {
693       return new InputCorbaPort(name, node, type);
694     }
695   else if(impl == XmlNode::IMPL_NAME)
696     {
697       return new InputXmlPort(name, node, type);
698     }
699   else
700     {
701       stringstream msg;
702       msg << "Cannot create " << impl << " InputPort" ;
703       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
704       throw Exception(msg.str());
705     }
706 }
707
708 OutputPort * RuntimeSALOME::createOutputPort(const std::string& name,
709                                              const std::string& impl,
710                                              Node * node,
711                                              TypeCode * type)
712 {
713   if(impl == CppNode::IMPL_NAME)
714     {
715       return new OutputCppPort(name, node, type);
716     }
717   else if(impl == PythonNode::IMPL_NAME)
718     {
719       return new OutputPyPort(name, node, type);
720     }
721   else if(impl == CORBANode::IMPL_NAME)
722     {
723       return new OutputCorbaPort(name, node, type);
724     }
725   else if(impl == XmlNode::IMPL_NAME)
726     {
727       return new OutputXmlPort(name, node, type);
728     }
729   else
730     {
731       stringstream msg;
732       msg << "Cannot create " << impl << " OutputPort" ;
733       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
734       throw Exception(msg.str());
735     }
736 }
737
738 InputDataStreamPort* RuntimeSALOME::createInputDataStreamPort(const std::string& name,
739                                                               Node *node,TypeCode *type)
740 {
741   DEBTRACE("createInputDataStreamPort: " << name << " " << type->shortName());
742   if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
743     {
744       return new InputCalStreamPort(name,node,type);
745     }
746   else
747     {
748       return new InputDataStreamPort(name,node,type);
749     }
750 }
751
752 OutputDataStreamPort* RuntimeSALOME::createOutputDataStreamPort(const std::string& name,
753                                                                 Node *node,TypeCode *type)
754 {
755   DEBTRACE("createOutputDataStreamPort: " << name << " " << type->shortName());
756   if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
757     {
758       return new OutputCalStreamPort(name,node,type);
759     }
760   else
761     {
762       return new OutputDataStreamPort(name,node,type);
763     }
764 }
765
766 //! Main adapter function : adapt an InputPort to be able to connect it to an OutputPort with a possible different implementation 
767 /*!
768  *  \param source : InputPort to be adapted
769  *  \param impl : new implementation (C++, python, CORBA, XML, Neutral)
770  *  \param type : data type provided by the InputPort
771  *  \param init : indicates if the adapted InputPort will be used for initialization (value true) or not (value false)
772  * 
773  * \return : adapted InputPort
774  */
775 InputPort* RuntimeSALOME::adapt(InputPort* source,
776                                 const std::string& impl,
777                                 TypeCode * type,bool init) throw (ConversionException)
778 {
779   string imp_source=source->getNode()->getImplementation();
780   if(imp_source == PythonNode::IMPL_NAME)
781     {
782       return adapt((InputPyPort*)source,impl,type,init);
783     }
784   else if(imp_source == CppNode::IMPL_NAME)
785     {
786       return adapt((InputCppPort*)source,impl,type,init);
787     }
788   else if(imp_source == CORBANode::IMPL_NAME)
789     {
790       return adapt((InputCorbaPort*)source,impl,type,init);
791     }
792   else if(imp_source == XmlNode::IMPL_NAME)
793     {
794       return adapt((InputXmlPort*)source,impl,type,init);
795     }
796   else if(imp_source == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
797     {
798       return adaptNeutral(source,impl,type,init);
799     }
800   else
801     {
802       stringstream msg;
803       msg << "Cannot adapt " << imp_source << " InputPort to " << impl;
804       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
805       throw ConversionException(msg.str());
806     }
807 }
808
809 //! Adapter function for InPropertyPort
810 /*!
811  *  \param source : InPropertyPort to be adapted
812  *  \param impl : new implementation (C++, python, CORBA, XML, Neutral)
813  *  \param type : data type provided by the InPropertyPort
814  *  \param init : indicates if the adapted InPropertyPort will be used for initialization (value true) or not (value false)
815  * 
816  * \return : adapted InputPort
817  */
818 InputPort* RuntimeSALOME::adapt(InPropertyPort* source,
819                                 const std::string& impl,
820                                 TypeCode * type,bool init) throw (ConversionException)
821 {
822   return adaptNeutral((InputPort *)source,impl,type,init);
823 }
824
825 //! Adapt a Neutral input port to a Corba output port
826 /*!
827  *   \param inport : Neutral input port to adapt to Corba type type
828  *   \param type : output port type
829  *   \return an adaptated input port of type InputCorbaPort
830  */
831 InputPort* RuntimeSALOME::adaptNeutralToCorba(InputPort* inport,
832                       TypeCode * type) throw (ConversionException)
833 {
834   // BEWARE : using the generic check
835   if(inport->edGetType()->isAdaptable(type))
836     {
837       //the output data is convertible to inport type
838       return new CorbaNeutral(inport);
839     }
840   //non convertible type
841   stringstream msg;
842   msg << "Cannot connect Corba output port with type: " << type->id() ;
843   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
844 #ifdef _DEVDEBUG_
845   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
846 #endif
847   throw ConversionException(msg.str());
848 }
849
850 //! Adapt a Neutral input port to a Python output port
851 /*!
852  *   \param inport : input port to adapt to Python type type
853  *   \param type : output port type
854  *   \return an adaptated input port of type InputPyPort
855  */
856 InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport,
857                       TypeCode * type) throw (ConversionException)
858 {
859   // BEWARE : using the generic check
860   if(inport->edGetType()->isAdaptable(type))
861     {
862       //convertible type
863       return new PyNeutral(inport);
864     }
865   //last chance : an py output that is seq[objref] can be connected to a neutral input objref (P13268)
866   else if(type->kind()==Sequence && type->contentType()->kind()==Objref && inport->edGetType()->kind()==Objref)
867     {
868       return new PyNeutral(inport);
869     }
870   //non convertible type
871   stringstream msg;
872   msg << "Cannot connect Python output port with type: " << type->id() ;
873   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
874 #ifdef _DEVDEBUG_
875   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
876 #endif
877   throw ConversionException(msg.str());
878 }
879
880 //! Adapt a Neutral input port to a Xml output port 
881 /*!
882  *   \param inport : input port to adapt to Xml type type
883  *   \param type : output port type
884  *   \return an input port of type InputXmlPort
885  */
886 InputPort* RuntimeSALOME::adaptNeutralToXml(InputPort* inport,
887                       TypeCode * type) throw (ConversionException)
888 {
889   // BEWARE : using the generic check
890   if(inport->edGetType()->isAdaptable(type))
891     {
892       //convertible type
893       return new XmlNeutral(inport);
894     }
895   //non convertible type
896   stringstream msg;
897   msg << "Cannot connect Xml output port with type: " << type->id() ;
898   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
899 #ifdef _DEVDEBUG_
900   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
901 #endif
902   throw ConversionException(msg.str());
903 }
904
905 //! Adapt a Neutral input port to a C++ output port 
906 /*!
907  *   \param inport : input port to adapt to C++ type type
908  *   \param type : output port type
909  *   \return an input port of type InputCppPort
910  */
911 InputPort* RuntimeSALOME::adaptNeutralToCpp(InputPort* inport,
912                       TypeCode * type) throw (ConversionException)
913 {
914   DEBTRACE("RuntimeSALOME::adaptNeutralToCpp(InputPort* inport" );
915   if(isAdaptableNeutralCpp(type,inport->edGetType()))
916     {
917       //convertible type
918       return new CppNeutral(inport);
919     }
920   //non convertible type
921   stringstream msg;
922   msg << "Cannot connect Cpp output port with type: " << type->id() ;
923   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
924 #ifdef _DEVDEBUG_
925   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
926 #endif
927   throw ConversionException(msg.str());
928 }
929
930 //! Adapt a Neutral input port to connect it to an output port with a given implementation
931 /*!
932  *   \param source : Neutral input port to adapt to implementation impl and type type
933  *   \param impl : output port implementation (C++, Python, Corba, Xml or Neutral)
934  *   \param type : output port supported type
935  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
936  *   \return       the adaptated port
937  */
938 InputPort* RuntimeSALOME::adaptNeutral(InputPort* source,
939                                        const std::string& impl,
940                                        TypeCode * type,bool init) throw (ConversionException)
941 {
942   if(impl == CppNode::IMPL_NAME)
943     {
944       return adaptNeutralToCpp(source,type);
945     }
946   else if(impl == PythonNode::IMPL_NAME)
947     {
948       return adaptNeutralToPython(source,type);
949     }
950   else if(impl == CORBANode::IMPL_NAME)
951     {
952       return adaptNeutralToCorba(source,type);
953     }
954   else if(impl == XmlNode::IMPL_NAME )
955     {
956       return adaptNeutralToXml(source,type);
957     }
958   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
959     {
960       if(init)
961         return new NeutralInit(source);
962       else
963         return new ProxyPort(source);
964     }
965   stringstream msg;
966   msg << "Cannot connect InputPort : unknown implementation " << impl;
967   msg << " (" <<__FILE__ << ":" <<__LINE__ << ")";
968   throw ConversionException(msg.str());
969 }
970
971 //! Adapt a XML input port to connect it to a CORBA output port 
972 /*!
973  *   \param inport : input port to adapt to CORBA type type
974  *   \param type : type supported by output port
975  *   \return an adaptator port of type InputCorbaPort 
976  */
977
978 InputPort* RuntimeSALOME::adaptXmlToCorba(InputXmlPort* inport,
979                                           TypeCode * type) throw (ConversionException)
980 {
981   if(isAdaptableXmlCorba(type,inport->edGetType()))
982     {
983       //output type is convertible to input type
984       return new CorbaXml(inport);
985     }
986   //output type is not convertible
987   stringstream msg;
988   msg << "Cannot connect Corba output port with type: " << type->id() ;
989   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
990 #ifdef _DEVDEBUG_
991   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
992 #endif
993   throw ConversionException(msg.str());
994 }
995
996 //! Adapt a XML input port to a Python output port
997 /*!
998  *   \param inport : input port to adapt to Python type type
999  *   \param type : output port type
1000  *   \return an adaptated input port of type InputPyPort
1001  */
1002 InputPort* RuntimeSALOME::adaptXmlToPython(InputXmlPort* inport,
1003                       TypeCode * type) throw (ConversionException)
1004 {
1005   if(inport->edGetType()->isAdaptable(type))
1006     {
1007       //the output data is convertible to inport type
1008       return new PyXml(inport);
1009     }
1010   //non convertible type
1011   stringstream msg;
1012   msg << "Cannot connect Python output port with type: " << type->id() ;
1013   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1014 #ifdef _DEVDEBUG_
1015   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1016 #endif
1017   throw ConversionException(msg.str());
1018 }
1019
1020 //! Adapt a XML input port to a C++ output port
1021 /*!
1022  *   \param inport : input port to adapt to C++ type type
1023  *   \param type : output port type
1024  *   \return an adaptated input port of type InputPyPort
1025  */
1026 InputPort* RuntimeSALOME::adaptXmlToCpp(InputXmlPort* inport,
1027                       TypeCode * type) throw (ConversionException)
1028 {
1029   DEBTRACE("RuntimeSALOME::adaptXmlToCpp(InputPort* inport" );
1030   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1031   if(type->isAdaptable(inport->edGetType()))
1032     {
1033       //the output data is convertible to inport type
1034       return new CppXml(inport);
1035     }
1036   //non convertible type
1037   stringstream msg;
1038   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1039   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1040 #ifdef _DEVDEBUG_
1041   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1042 #endif
1043   throw ConversionException(msg.str());
1044 }
1045
1046 //! Adapt a XML input port to a Neutral output port
1047 /*!
1048  *   \param inport : input port to adapt to Neutral type type
1049  *   \param type : output port type
1050  *   \return an adaptated input port of type Neutralxxxx
1051  */
1052 InputPort* RuntimeSALOME::adaptXmlToNeutral(InputXmlPort* inport,
1053                       TypeCode * type) throw (ConversionException)
1054 {
1055   if(inport->edGetType()->isAdaptable(type))
1056     {
1057       //the output data is convertible to inport type
1058       return new NeutralXml(inport);
1059     }
1060   //non convertible type
1061   stringstream msg;
1062   msg << "Cannot connect Xml InputPort to OutputNeutralPort : " ;
1063   msg << "(" <<__FILE__ << ":" <<__LINE__<< ")";
1064   throw ConversionException(msg.str());
1065 }
1066
1067 //! Adapt a XML input port to a Xml output port
1068 /*!
1069  *   \param inport : input port to adapt to Xml type type
1070  *   \param type : output port type
1071  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1072  *   \return an adaptated input port of type Xmlxxxx
1073  */
1074 InputPort* RuntimeSALOME::adaptXmlToXml(InputXmlPort* inport,
1075                       TypeCode * type,bool init) throw (ConversionException)
1076 {
1077   if(init)
1078     return new ProxyPort(inport);
1079
1080   if(inport->edGetType()->isAdaptable(type))
1081     return new ProxyPort(inport);
1082
1083   stringstream msg;
1084   msg << "Cannot connect Xml output port with type: " << type->id() ;
1085   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1086 #ifdef _DEVDEBUG_
1087   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1088 #endif
1089   throw ConversionException(msg.str());
1090 }
1091
1092 //! Adapt an Xml input port to an output port which implementation is given by impl
1093 /*!
1094  *   \param source : input port to adapt to implementation impl and type type
1095  *   \param impl : output port implementation (C++, Python or Corba)
1096  *   \param type : output port supported type
1097  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1098  *   \return       the adaptated port
1099  */
1100
1101 InputPort* RuntimeSALOME::adapt(InputXmlPort* source,
1102                                 const std::string& impl,
1103                                 TypeCode * type,bool init) throw (ConversionException)
1104 {
1105   if(impl == CORBANode::IMPL_NAME)
1106     {
1107       return adaptXmlToCorba(source,type);
1108     }
1109   else if(impl == PythonNode::IMPL_NAME)
1110     {
1111       return adaptXmlToPython(source,type);
1112     }
1113   else if(impl == CppNode::IMPL_NAME)
1114     {
1115       return adaptXmlToCpp(source,type);
1116     }
1117   else if(impl == XmlNode::IMPL_NAME )
1118     {
1119       return adaptXmlToXml(source,type,init);
1120     }
1121   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1122     {
1123       return adaptXmlToNeutral(source,type);
1124     }
1125   else
1126     {
1127       stringstream msg;
1128       msg << "Cannot connect InputXmlPort to " << impl << " implementation";
1129       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1130       throw ConversionException(msg.str());
1131     }
1132 }
1133
1134
1135 //! Adapt a CORBA input port to a CORBA output port 
1136 /*!
1137  *   \param inport : input port to adapt to CORBA outport data type
1138  *   \param type : outport data type 
1139  *   \return an adaptator port of type InputCORBAPort 
1140  */
1141 InputPort* RuntimeSALOME::adaptCorbaToCorba(InputCorbaPort* inport,
1142                                             TypeCode * type) throw (ConversionException)
1143 {
1144   if(type->isA(inport->edGetType()))
1145     {
1146       //types are compatible : no conversion 
1147       //outport data type is more specific than inport required type
1148       //so the inport can be used safely 
1149       return new ProxyPort(inport);
1150     }
1151   else if(isAdaptableCorbaCorba(type,inport->edGetType()))
1152     {
1153       //ouport data can be converted to inport data type
1154       return new CorbaCorba(inport);
1155     }
1156   //outport data can not be converted
1157   stringstream msg;
1158   msg << "Cannot connect Corba output port with type: " << type->id() ;
1159   msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1160 #ifdef _DEVDEBUG_
1161   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1162 #endif
1163   throw ConversionException(msg.str());
1164 }
1165
1166 //! Adapt a CORBA input port to a Python output port 
1167 /*!
1168  *   \param inport : input port to adapt to Python type type
1169  *   \param type : outport data type 
1170  *   \return an adaptator port of type InputPyPort 
1171  */
1172
1173 InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport,
1174                                              TypeCode * type) throw (ConversionException)
1175 {
1176   if(inport->edGetType()->kind() == Double)
1177     {
1178       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaDouble(inport);
1179     }
1180   else if(inport->edGetType()->kind() == Int)
1181     {
1182       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaInt(inport);
1183     }
1184   else if(inport->edGetType()->kind() == String)
1185     {
1186       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaString(inport);
1187     }
1188   else if(inport->edGetType()->kind() == Bool)
1189     {
1190       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaBool(inport);
1191     }
1192   else if(inport->edGetType()->kind() == Objref )
1193     {
1194       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1195         {
1196           return new PyCorbaObjref(inport);
1197         }
1198       else
1199         {
1200           stringstream msg;
1201           msg << "Cannot connect Python output port with type: " << type->id() ;
1202           msg << " to CORBA input port " << inport->getName() << " with incompatible objref type: " << inport->edGetType()->id();
1203           msg << " (" << __FILE__ << ":" <<__LINE__ << ")";
1204           throw ConversionException(msg.str());
1205         }
1206     }
1207   else if(inport->edGetType()->kind() == Sequence)
1208     {
1209       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1210         {
1211           return new PyCorbaSequence(inport);
1212         }
1213       else
1214         {
1215           stringstream msg;
1216           msg << "Cannot convert this sequence type " ;
1217           msg << __FILE__ << ":" <<__LINE__;
1218           throw ConversionException(msg.str());
1219         }
1220     }
1221   else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1222     {
1223       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1224         {
1225           return new PyCorbaStruct(inport);
1226         }
1227       else
1228         {
1229           stringstream msg;
1230           msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1231           msg << __FILE__ << ":" <<__LINE__;
1232           throw ConversionException(msg.str());
1233         }
1234     }
1235   // Adaptation not possible
1236   stringstream msg;
1237   msg << "Cannot connect Python output port with type: " << type->id() ;
1238   msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1239 #ifdef _DEVDEBUG_
1240   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1241 #endif
1242   throw ConversionException(msg.str());
1243 }
1244
1245 //! Adapt a CORBA input port to connect it to a XML output port 
1246 /*!
1247  *   \param inport : input port to adapt to Xml type type
1248  *   \param type : type supported by output port
1249  *   \return an adaptator port of type InputXmlPort 
1250  */
1251
1252 InputPort* RuntimeSALOME::adaptCorbaToXml(InputCorbaPort* inport,
1253                                           TypeCode * type) throw (ConversionException)
1254 {
1255   // BEWARE : using the generic check
1256   if(inport->edGetType()->isAdaptable(type))
1257     {
1258       //output type is convertible to input type
1259       return new XmlCorba(inport);
1260     }
1261   //output type is not convertible
1262   stringstream msg;
1263   msg << "Cannot connect Xml output port with type: " << type->id() ;
1264   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1265 #ifdef _DEVDEBUG_
1266   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1267 #endif
1268   throw ConversionException(msg.str());
1269 }
1270
1271 //! Adapt a CORBA input port to a C++ output port 
1272 /*!
1273  *   \param inport : input port to adapt to C++ type type
1274  *   \param type : outport data type 
1275  *   \return an adaptator port of type InputCPPPort 
1276  */
1277
1278 InputPort* RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport,
1279                                           TypeCode * type) throw (ConversionException)
1280 {
1281   DEBTRACE("RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport" );
1282   if(isAdaptableCorbaCpp(type,inport->edGetType()))
1283     {
1284       //output type is convertible to input type
1285       return new CppCorba(inport);
1286     }
1287   //output type is not convertible
1288   stringstream msg;
1289   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1290   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1291 #ifdef _DEVDEBUG_
1292   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1293 #endif
1294   throw ConversionException(msg.str());
1295 }
1296
1297 //! Adapt a CORBA input port to a neutral data 
1298 /*!
1299  *   \param inport : InputPort to adapt to Neutral type type
1300  *   \param type : outport data type 
1301  *   \return an adaptator port of type Neutralxxxx
1302  */
1303
1304 InputPort* RuntimeSALOME::adaptCorbaToNeutral(InputCorbaPort* inport,
1305                                               TypeCode * type) throw (ConversionException)
1306 {
1307   if(inport->edGetType()->kind() == Double)
1308     {
1309       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaDouble(inport);
1310     }
1311   else if(inport->edGetType()->kind() == Int)
1312     {
1313       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaInt(inport);
1314     }
1315   else if(inport->edGetType()->kind() == String)
1316     {
1317       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaString(inport);
1318     }
1319   else if(inport->edGetType()->kind() == Bool)
1320     {
1321       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaBool(inport);
1322     }
1323   else if(inport->edGetType()->kind() == Objref)
1324     {
1325       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaObjref(inport);
1326     }
1327   else if(inport->edGetType()->kind() == Sequence)
1328     {
1329       if(isAdaptableCorbaNeutral(type,inport->edGetType()))
1330         return new NeutralCorbaSequence(inport);
1331       else
1332         {
1333           stringstream msg;
1334           msg << "Cannot convert this sequence type " ;
1335           msg << __FILE__ << ":" <<__LINE__;
1336           throw ConversionException(msg.str());
1337         }
1338     }
1339   else if(inport->edGetType()->kind() == Struct)
1340     {
1341       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaStruct(inport);
1342     }
1343
1344   // Adaptation not possible
1345   stringstream msg;
1346   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1347   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1348 #ifdef _DEVDEBUG_
1349   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1350 #endif
1351   throw ConversionException(msg.str());
1352 }
1353
1354 //! Adapt a CORBA input port to an output which implementation and type are given by impl and type
1355 /*!
1356  *   \param source : input port to adapt to implementation impl and type type
1357  *   \param impl : output port implementation (C++, Python or Corba)
1358  *   \param type : outport data type 
1359  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1360  *   \return an adaptator port which type depends on impl
1361  */
1362
1363 InputPort* RuntimeSALOME::adapt(InputCorbaPort* source,
1364                                 const std::string& impl,
1365                                 TypeCode * type,bool init) throw (ConversionException)
1366 {
1367   if(impl == CppNode::IMPL_NAME)
1368     {
1369       return adaptCorbaToCpp(source,type);
1370     }
1371   else if(impl == PythonNode::IMPL_NAME)
1372     {
1373       return adaptCorbaToPython(source,type);
1374     }
1375   else if(impl == CORBANode::IMPL_NAME)
1376     {
1377       if(init)
1378         return adaptCorbaToCorba(source,type);
1379       else
1380         return adaptCorbaToCorba(source,type);
1381     }
1382   else if(impl == XmlNode::IMPL_NAME )
1383     {
1384       return adaptCorbaToXml(source,type);
1385     }
1386   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1387     {
1388       return adaptCorbaToNeutral(source,type);
1389     }
1390   else
1391     {
1392       stringstream msg;
1393       msg << "Cannot connect InputCorbaPort : unknown implementation " ;
1394       msg << __FILE__ << ":" <<__LINE__;
1395       throw ConversionException(msg.str());
1396     }
1397 }
1398
1399 //! Adapt a Python input port to a Python output port
1400 /*!
1401  * No need to make conversion or cast. 
1402  * Only check, it's possible.
1403  *   \param inport : InputPort to adapt to Python type type
1404  *   \param type : outport data type 
1405  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1406  *   \return an adaptator port of type InputPyPort 
1407  */
1408
1409 InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport,
1410                                               TypeCode * type,bool init) throw (ConversionException)
1411 {
1412   if(init)
1413     return new PyInit(inport);
1414
1415   if(isAdaptablePyObjectPyObject(type,inport->edGetType()))
1416     {
1417       //output data is convertible to input type
1418       //With python, no need to convert. Conversion will be done automatically
1419       //by the interpreter
1420       return new ProxyPort(inport);
1421     }
1422   //output data is not convertible to input type
1423   stringstream msg;
1424   msg << "Cannot connect Python output port with type: " << type->id() ;
1425   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1426 #ifdef _DEVDEBUG_
1427   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1428 #endif
1429   throw ConversionException(msg.str());
1430 }
1431
1432 //! Adapt a Python input port to a C++ output port
1433 /*!
1434  *   \param inport : InputPort to adapt to C++ type type
1435  *   \param type : outport data type 
1436  *   \return an adaptator port of C++ type (InputCppPort)
1437  */
1438
1439 InputPort* RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport,
1440                                            TypeCode * type) throw (ConversionException)
1441 {
1442   DEBTRACE("RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport" );
1443   if(isAdaptablePyObjectCpp(type,inport->edGetType()))
1444     {
1445       //output type is convertible to input type
1446       return new CppPy(inport);
1447     }
1448   //output type is not convertible
1449   stringstream msg;
1450   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1451   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1452 #ifdef _DEVDEBUG_
1453   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1454 #endif
1455   throw ConversionException(msg.str());
1456 }
1457
1458 //! Adapt a Python input port to a Neutral data port
1459 /*!
1460  *   \param inport : InputPort to adapt to Neutral type type
1461  *   \param type : outport data type 
1462  *   \return an adaptator port of Neutral type (Neutralxxxx)
1463  */
1464
1465 InputPort* RuntimeSALOME::adaptPythonToNeutral(InputPyPort* inport,
1466                                                TypeCode * type) throw (ConversionException)
1467 {
1468   if(inport->edGetType()->kind() == Double)
1469     {
1470       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyDouble(inport);
1471     }
1472   else if(inport->edGetType()->kind() == Int)
1473     {
1474       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyInt(inport);
1475     }
1476   else if(inport->edGetType()->kind() == String)
1477     {
1478       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyString(inport);
1479     }
1480   else if(inport->edGetType()->kind() == Bool)
1481     {
1482       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyBool(inport);
1483     }
1484   else if(inport->edGetType()->kind() == Objref)
1485     {
1486       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyObjref(inport);
1487     }
1488   else if(inport->edGetType()->kind() == Sequence)
1489     {
1490       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))
1491         return new NeutralPySequence(inport);
1492       else
1493         {
1494           stringstream msg;
1495           msg << "Cannot convert this sequence type " ;
1496           msg << __FILE__ << ":" <<__LINE__;
1497           throw ConversionException(msg.str());
1498         }
1499     }
1500   else if(inport->edGetType()->kind() == Struct)
1501     {
1502       if(isAdaptablePyObjectNeutral(type,inport->edGetType())) return new NeutralPyStruct(inport);
1503     }
1504
1505   // Adaptation not possible
1506   stringstream msg;
1507   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1508   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1509 #ifdef _DEVDEBUG_
1510   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1511 #endif
1512   throw ConversionException(msg.str());
1513 }
1514
1515 //! Adapt a Python input port to a Corba output port
1516 /*!
1517  * Always convert the data
1518  *   \param inport : InputPort to adapt to Corba type type
1519  *   \param type : outport data type 
1520  *   \return an adaptator port of Corba type (InputCorbaPort)
1521  */
1522
1523 InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport,
1524                                              TypeCode * type) throw (ConversionException)
1525 {
1526   if(inport->edGetType()->kind() == Double)
1527     {
1528       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyDouble(inport);
1529     }
1530   else if(inport->edGetType()->kind() == Int)
1531     {
1532       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyInt(inport);
1533     }
1534   else if(inport->edGetType()->kind() == String)
1535     {
1536       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyString(inport);
1537     }
1538   else if(inport->edGetType()->kind() == Bool)
1539     {
1540       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyBool(inport);
1541     }
1542   else if(inport->edGetType()->kind() == Objref)
1543     {
1544       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1545         {
1546           return new CorbaPyObjref(inport);
1547         }
1548       else
1549         {
1550           stringstream msg;
1551           msg << "Cannot connect InputCorbaPort : incompatible objref types " << type->id() << " " << inport->edGetType()->id();
1552           msg << " " << __FILE__ << ":" <<__LINE__;
1553           throw ConversionException(msg.str());
1554         }
1555     }
1556   else if(inport->edGetType()->kind() == Sequence)
1557     {
1558       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1559         {
1560           return new CorbaPySequence(inport);
1561         }
1562       else
1563         {
1564           stringstream msg;
1565           msg << "Cannot convert this sequence type " ;
1566           msg << __FILE__ << ":" <<__LINE__;
1567           throw ConversionException(msg.str());
1568         }
1569     }
1570   else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1571     {
1572       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1573         {
1574           return new CorbaPyStruct(inport);
1575         }
1576       else
1577         {
1578           stringstream msg;
1579           msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1580           msg << " " << __FILE__ << ":" <<__LINE__;
1581           throw ConversionException(msg.str());
1582         }
1583     }
1584   // Adaptation not possible
1585   stringstream msg;
1586   msg << "Cannot connect Corba output port with type: " << type->id() ;
1587   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1588 #ifdef _DEVDEBUG_
1589   msg << " ("__FILE__ << ":" << __LINE__ << ")";
1590 #endif
1591   throw ConversionException(msg.str());
1592 }
1593
1594 //! Adapt a Python input port to a Xml output port 
1595 /*!
1596  *   \param inport : input port to adapt to Xml type type
1597  *   \param type : output port type
1598  *   \return an input port of type InputXmlPort
1599  */
1600
1601 InputPort* RuntimeSALOME::adaptPythonToXml(InputPyPort* inport,
1602                                           TypeCode * type) throw (ConversionException)
1603 {
1604   // BEWARE : using the generic check
1605   if(inport->edGetType()->isAdaptable(type))
1606     {
1607       //convertible type
1608       return new XmlPython(inport);
1609     }
1610   //non convertible type
1611   stringstream msg;
1612   msg << "Cannot connect Xml output port with type: " << type->id() ;
1613   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1614 #ifdef _DEVDEBUG_
1615   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1616 #endif
1617   throw ConversionException(msg.str());
1618 }
1619
1620 //! Adapt a Python input port to an output port with a given implementation
1621 /*!
1622  *   \param source : input port to adapt to implementation impl and type type
1623  *   \param impl : output port implementation (C++, Python or Corba)
1624  *   \param type : output port type
1625  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1626  *   \return     adaptated input port
1627  */
1628
1629 InputPort* RuntimeSALOME::adapt(InputPyPort* source,
1630                                 const std::string& impl,
1631                                 TypeCode * type,bool init) throw (ConversionException)
1632 {
1633   if(impl == CppNode::IMPL_NAME)
1634     {
1635       return adaptPythonToCpp(source,type);
1636     }
1637   else if(impl == PythonNode::IMPL_NAME)
1638     {
1639       return adaptPythonToPython(source,type,init);
1640     }
1641   else if(impl == CORBANode::IMPL_NAME)
1642     {
1643       return adaptPythonToCorba(source,type);
1644     }
1645   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1646     {
1647       return adaptPythonToNeutral(source,type);
1648     }
1649   else if(impl == XmlNode::IMPL_NAME)
1650     {
1651       return adaptPythonToXml(source,type);
1652     }
1653   else
1654     {
1655       stringstream msg;
1656       msg << "Cannot connect InputPyPort : unknown implementation " << impl;
1657       msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1658       throw ConversionException(msg.str());
1659     }
1660 }
1661
1662
1663 //! Adapt a C++ input port to connect it to a CORBA output port
1664 /*!
1665  *   \param inport : input port to adapt to CORBA type type
1666  *   \param type : type supported by output port
1667  *   \return an adaptator port of type InputCorbaPort
1668  */
1669
1670 InputPort* RuntimeSALOME::adaptCppToCorba(InputCppPort* inport,
1671                                           TypeCode * type) throw (ConversionException)
1672 {
1673   DEBTRACE("RuntimeSALOME::adaptCppToCorba(InputCppPort* inport)");
1674   if(isAdaptableCppCorba(type,inport->edGetType()))
1675     {
1676       //output type is convertible to input type
1677       return new CorbaCpp(inport);
1678     }
1679   //output type is not convertible
1680   stringstream msg;
1681   msg << "Cannot connect Corba output port with type: " << type->id() ;
1682   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1683 #ifdef _DEVDEBUG_
1684   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1685 #endif
1686   throw ConversionException(msg.str());
1687 }
1688
1689 //! Adapt a C++ input port to a Python output port
1690 /*!
1691  *   \param inport : input port to adapt to Python type type
1692  *   \param type : output port type
1693  *   \return an adaptated input port of type InputPyPort
1694  */
1695 InputPort* RuntimeSALOME::adaptCppToPython(InputCppPort* inport,
1696                       TypeCode * type) throw (ConversionException)
1697 {
1698   DEBTRACE("RuntimeSALOME::adaptCppToPython(InputCppPort* inport)");
1699   if(isAdaptableCppPyObject(type,inport->edGetType()))
1700     {
1701       //output type is convertible to input type
1702       return new PyCpp(inport);
1703     }
1704   //output type is not convertible
1705   stringstream msg;
1706   msg << "Cannot connect Python output port with type: " << type->id() ;
1707   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1708 #ifdef _DEVDEBUG_
1709   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1710 #endif
1711   throw ConversionException(msg.str());
1712 }
1713
1714 //! Adapt a C++ input port to a C++ output port
1715 /*!
1716  *   \param inport : input port to adapt to C++ type type
1717  *   \param type : output port type
1718  *   \return an adaptated input port of type InputPyPort
1719  */
1720 InputPort* RuntimeSALOME::adaptCppToCpp(InputCppPort* inport,
1721                       TypeCode * type) throw (ConversionException)
1722 {
1723   DEBTRACE("RuntimeSALOME::adaptCppToCpp(InputPort* inport" );
1724   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1725   if(type->isAdaptable(inport->edGetType()))
1726     {
1727       //the output data is convertible to inport type
1728       return new CppCpp(inport);
1729     }
1730   //non convertible type
1731   stringstream msg;
1732   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1733   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1734 #ifdef _DEVDEBUG_
1735   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1736 #endif
1737   throw ConversionException(msg.str());
1738 }
1739
1740 //! Adapt a C++ input port to a Neutral output port
1741 /*!
1742  *   \param inport : input port to adapt to C++ type type
1743  *   \param type : output port type
1744  *   \return an adaptated input port of type InputPyPort
1745  */
1746 InputPort* RuntimeSALOME::adaptCppToNeutral(InputCppPort* inport,
1747                       TypeCode * type) throw (ConversionException)
1748 {
1749   DEBTRACE("RuntimeSALOME::adaptCppToNeutral(InputPort* inport" );
1750   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1751   if(type->isAdaptable(inport->edGetType()))
1752     {
1753       //the output data is convertible to inport type
1754       return new NeutralCpp(inport);
1755     }
1756   //non convertible type
1757   stringstream msg;
1758   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1759   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1760 #ifdef _DEVDEBUG_
1761   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1762 #endif
1763   throw ConversionException(msg.str());
1764 }
1765
1766 InputPort* RuntimeSALOME::adaptCppToXml(InputCppPort* inport,
1767                       TypeCode * type) throw (ConversionException)
1768 {
1769   DEBTRACE("RuntimeSALOME::adaptCppToXml(InputCppPort* inport" );
1770   if(isAdaptableCppXml(type,inport->edGetType()))
1771     {
1772       //convertible type
1773       return new XmlCpp(inport);
1774     }
1775   //non convertible type
1776   stringstream msg;
1777   msg << "Cannot connect Xml output port with type: " << type->id() ;
1778   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1779 #ifdef _DEVDEBUG_
1780   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1781 #endif
1782    throw ConversionException(msg.str());
1783 }
1784
1785 //! Adapt a C++ input port to connect it to an output port with a given implementation
1786 /*!
1787  *   \param source : input port to adapt to implementation impl and type type
1788  *   \param impl : output port implementation (C++, Python or Corba)
1789  *   \param type : output port supported type
1790  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1791  *   \return       the adaptated port
1792  */
1793
1794 InputPort* RuntimeSALOME::adapt(InputCppPort* source,
1795                                 const std::string& impl,
1796                                 TypeCode * type,bool init) throw (ConversionException)
1797 {
1798   DEBTRACE("RuntimeSALOME::adapt(InputCppPort* source)");
1799   if(impl == CORBANode::IMPL_NAME)
1800     {
1801       return adaptCppToCorba(source,type);
1802     }
1803   else if(impl == PythonNode::IMPL_NAME)
1804     {
1805       return adaptCppToPython(source,type);
1806     }
1807   else if(impl == XmlNode::IMPL_NAME)
1808     {
1809       return adaptCppToXml(source,type);
1810     }
1811   else if(impl == CppNode::IMPL_NAME)
1812     {
1813       return adaptCppToCpp(source, type);
1814     }
1815   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1816     {
1817       return adaptCppToNeutral(source, type);
1818     }
1819   else
1820     {
1821       stringstream msg;
1822       msg << "Cannot connect InputCppPort to " << impl << " implementation";
1823       msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1824       throw ConversionException(msg.str());
1825     }
1826 }
1827
1828 // bool RuntimeSALOME::isCompatible(const OutputPort* outputPort, 
1829 //                               const InputPort*  inputPort)
1830 // {
1831 //   bool result=true;
1832 //   return result;
1833 // }
1834
1835 CORBA::ORB_ptr RuntimeSALOME::getOrb() const
1836 {
1837   return _orb;
1838 }
1839
1840 PyObject * RuntimeSALOME::getPyOrb() const
1841 {
1842   return _pyorb;
1843 }
1844
1845 PyObject * RuntimeSALOME::getBuiltins() const
1846 {
1847   return _bltins;
1848 }
1849
1850 DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory() const
1851 {
1852   return _dynFactory;
1853 }
1854
1855 PyObject * RuntimeSALOME::get_omnipy()
1856 {
1857   return _omnipy;
1858 }
1859
1860 omniORBpyAPI* RuntimeSALOME::getApi()
1861 {
1862   return _api;
1863 }
1864
1865 void* RuntimeSALOME::convertNeutral(TypeCode * type, Any *data)
1866 {
1867   if(data)
1868     return (void *)convertNeutralPyObject(type,data);
1869   else
1870     {
1871       Py_INCREF(Py_None);
1872       return (void *)Py_None;
1873     }
1874 }
1875
1876 std::string RuntimeSALOME::convertNeutralAsString(TypeCode * type, Any *data)
1877 {
1878   PyObject* ob;
1879   if(data)
1880     {
1881       // The call to PyGILState_Ensure was moved here because there was also
1882       // a crash when calling convertNeutralPyObject with a sequence of pyobj.
1883       // see also the comment below.
1884       PyGILState_STATE gstate = PyGILState_Ensure();
1885       ob=convertNeutralPyObject(type,data);
1886       std::string s=convertPyObjectToString(ob);
1887
1888       // Note (Renaud Barate, 8 jan 2013): With Python 2.7, this call to Py_DECREF causes a crash
1889       // (SIGSEGV) when ob is a sequence and the call is not protected with the global interpreter
1890       // lock. I thus added the call to PyGILState_Ensure / PyGILState_Release. It worked fine in
1891       // Python 2.6 without this call. If anyone finds the real reason of this bug and another fix,
1892       // feel free to change this code.
1893       //PyGILState_STATE gstate = PyGILState_Ensure();
1894       Py_DECREF(ob);
1895       PyGILState_Release(gstate);
1896       return s;
1897     }
1898   else
1899     {
1900       return "None";
1901     }
1902 }
1903
1904 std::string RuntimeSALOME::convertPyObjectToString(PyObject* ob)
1905 {
1906   return YACS::ENGINE::convertPyObjectToString(ob);
1907 }
1908
1909 PyObject* RuntimeSALOME::convertStringToPyObject(const std::string& s)
1910 {
1911   PyObject *mainmod;
1912   PyObject *globals;
1913   PyObject* ob;
1914   PyGILState_STATE gstate = PyGILState_Ensure();
1915   mainmod = PyImport_AddModule("__main__");
1916   globals = PyModule_GetDict(mainmod);
1917   PyObject* d = PyDict_New();
1918   //PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
1919   ob= PyRun_String( s.c_str(), Py_eval_input, globals, d);
1920   Py_DECREF(d);
1921   if(ob==NULL)
1922     {
1923       //exception
1924       std::string error;
1925       PyObject* new_stderr = newPyStdOut(error);
1926       PySys_SetObject((char *)"stderr", new_stderr);
1927       PyErr_Print();
1928       PySys_SetObject((char *)"stderr", PySys_GetObject((char *)"__stderr__"));
1929       Py_DECREF(new_stderr);
1930       PyGILState_Release(gstate);
1931       throw Exception(error);
1932     }
1933   PyGILState_Release(gstate);
1934   return ob;
1935 }