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