+}
+
+//=============================================================================
+//! load a component implementation
+/*!
+* CORBA method
+* \param componentName component name
+* \param reason explains error when load fails
+* \return true if dlopen successfull or already done, false otherwise
+*/
+//=============================================================================
+bool
+Engines_Container_i::load_component_Library(const char* componentName, CORBA::String_out reason)
+{
+
+ //=================================================================
+ // --- C++ implementation section
+ //=================================================================
+ std::string retso;
+ if(load_component_CppImplementation(componentName,retso))
+ {
+ reason=CORBA::string_dup("");
+ return true;
+ }
+ else if(retso != "ImplementationNotFound")
+ {
+ reason=CORBA::string_dup(retso.c_str());
+ return false;
+ }
+
+ retso="Component ";
+ retso+=componentName;
+ retso+=": Can't find C++ implementation ";
+ retso+=std::string(LIB) + componentName + ENGINESO;
+
+ //=================================================================
+ // --- Python implementation section
+ //=================================================================
+ std::string retpy;
+ if(load_component_PythonImplementation(componentName,retpy))
+ {
+ reason=CORBA::string_dup("");
+ return true;
+ }
+ else if(retpy != "ImplementationNotFound")
+ {
+ reason=CORBA::string_dup(retpy.c_str());
+ return false;
+ }
+
+ retpy="Component ";
+ retpy+=componentName;
+ retpy+=": Can't find python implementation ";
+ retpy+=componentName;
+ retpy+="(.py)";
+
+ //=================================================================
+ // -- Executable implementation section
+ //=================================================================
+ std::string retex;
+ if(load_component_ExecutableImplementation(componentName,retex))
+ {
+ reason=CORBA::string_dup("");
+ return true;
+ }
+ else if(retex != "ImplementationNotFound")
+ {
+ reason=CORBA::string_dup(retex.c_str());
+ return false;
+ }
+
+ retex="Component ";
+ retex+=componentName;
+ retex+=": Can't find executable implementation ";
+ retex+=componentName;
+ retex+=".exe";
+
+ std::string ret="Component implementation not found: ";
+ ret += componentName ;
+ ret += '\n' ;
+ ret += retso+ '\n' ;
+ ret += retpy+ '\n' ;
+ ret += retex+ '\n' ;
+
+ std::cerr << ret << std::endl;
+ reason=CORBA::string_dup(ret.c_str());
+
+ return false;
+}
+
+//=============================================================================
+//! try to load a C++ component implementation
+/*!
+* C++ method:
+* \param componentName the name of the component (COMPONENT, for example)
+* \param reason explains error when load fails
+* \return true if loading is successfull or already done, false otherwise
+*/
+//=============================================================================
+bool
+Engines_Container_i::load_component_CppImplementation(const char* componentName, std::string& reason)
+{
+ std::string aCompName(componentName);
+ std::string impl_name = std::string(LIB) + aCompName + ENGINESO;
+ SCRUTE(impl_name);
+
+ _numInstanceMutex.lock(); // lock to be alone
+ // (see decInstanceCnt, finalize_removal))
+ if (_toRemove_map.count(impl_name) != 0) _toRemove_map.erase(impl_name);
+ if (_library_map.count(impl_name) != 0)
+ {
+ MESSAGE("Library " << impl_name << " already loaded");
+ _numInstanceMutex.unlock();
+ reason="";
+ return true;
+ }
+ _numInstanceMutex.unlock();
+
+#ifndef WIN32
+ void* handle;
+ handle = dlopen( impl_name.c_str() , RTLD_NOW | RTLD_GLOBAL ) ;
+ if ( !handle )
+ {
+ //not loadable. Try to find the lib file in LD_LIBRARY_PATH
+ std::string path;
+#ifdef __APPLE__
+ char* p=getenv("DYLD_LIBRARY_PATH");
+#else
+ char* p=getenv("LD_LIBRARY_PATH");
+#endif
+ if(p)path=p;
+ path=path+SEP+"/usr/lib"+SEP+"/lib";
+
+ std::string pth;
+ if(findpathof(path, pth, impl_name))
+ {
+ //found but not loadable
+ reason="Component ";
+ reason+=aCompName;
+ reason+=": C++ implementation found ";
+ reason+=pth;
+ reason+=" but it is not loadable. Error:\n";
+ reason+=dlerror();
+ std::cerr << reason << std::endl;
+ return false;
+ }
+ else
+ {
+ //not found
+ //continue with other implementation
+ reason="ImplementationNotFound";
+ return false;
+ }
+ }
+#else
+ HINSTANCE handle;
+ handle = LoadLibrary( impl_name.c_str() );
+ if ( !handle )
+ {
+ reason="ImplementationNotFound";
+ }
+#endif
+
+ if ( handle )
+ {
+ _numInstanceMutex.lock();
+ _library_map[impl_name] = handle;
+ _numInstanceMutex.unlock();
+ reason="";
+ return true;
+ }
+
+ return false;
+
+}
+//=============================================================================
+//! try to load a Python component implementation
+/*!
+* C++ method:
+* \param componentName name of the component
+* \param reason explains error when load fails
+* \return true if loading is successfull or already done, false otherwise
+*/
+//=============================================================================
+bool
+Engines_Container_i::load_component_PythonImplementation(const char* componentName, std::string& reason)
+{
+ std::string aCompName(componentName);
+
+ _numInstanceMutex.lock() ; // lock to be alone (stl container write)
+ if (_library_map.count(aCompName) != 0)
+ {
+ _numInstanceMutex.unlock() ;
+ reason="";
+ return true; // Python Component, already imported
+ }
+ _numInstanceMutex.unlock() ;
+
+ PyGILState_STATE gstate = PyGILState_Ensure();
+ PyObject *result = PyObject_CallMethod(_pyCont,
+ (char*)"import_component",
+ (char*)"s",componentName);
+
+ reason=PyString_AsString(result);
+ Py_XDECREF(result);
+ SCRUTE(reason);
+ PyGILState_Release(gstate);
+
+ if (reason=="")
+ {
+ //Python component has been loaded (import componentName)
+ _numInstanceMutex.lock() ; // lock to be alone (stl container write)
+ _library_map[aCompName] = (void *)_pyCont; // any non O value OK
+ _numInstanceMutex.unlock() ;
+ MESSAGE("import Python: "<< aCompName <<" OK");
+ return true;
+ }
+ else if(reason=="ImplementationNotFound")
+ {
+ //Python implementation has not been found. Continue with other implementation
+ reason="ImplementationNotFound";
+ }
+ else
+ {
+ //Python implementation has been found but loading has failed
+ std::cerr << reason << std::endl;
+ }
+ return false;
+
+}
+//=============================================================================
+//! try to load a Executable component implementation
+/*!
+* C++ method:
+* \param componentName name of the component
+* \param reason explains error when load fails
+* \return true if loading is successfull or already done, false otherwise
+*/
+//=============================================================================
+bool
+Engines_Container_i::load_component_ExecutableImplementation(const char* componentName, std::string& reason)
+{
+ std::string aCompName(componentName);
+ std::string executable=aCompName+".exe";
+
+ std::string path;
+ std::string pth;
+
+ char* p=getenv("PATH");
+ if(p)path=p;
+
+ if (findpathof(path, pth, executable))
+ {
+ if(checkifexecutable(pth))
+ {
+ _numInstanceMutex.lock() ; // lock to be alone (stl container write)
+ _library_map[executable] = (void *)1; // any non O value OK
+ _numInstanceMutex.unlock() ;
+ MESSAGE("import executable: "<< pth <<" OK");
+ reason="";
+ return true;
+ }
+ reason="Component ";
+ reason+=aCompName;
+ reason+=": implementation found ";
+ reason+=pth;
+ reason+=" but it is not executable";
+ std::cerr << reason << std::endl;
+ }
+ else
+ {
+ reason="ImplementationNotFound";
+ }
+ return false;
+}
+
+//=============================================================================
+//! Create a new component instance
+/*!
+* CORBA method: Creates a new servant instance of a component.
+* The servant registers itself to naming service and Registry.
+* \param genericRegisterName Name of the component instance to register
+* in Registry & Name Service (without _inst_n suffix)
+* \param studyId 0 for multiStudy instance,
+* study Id (>0) otherwise
+* \return a loaded component
+*/
+//=============================================================================
+Engines::EngineComponent_ptr
+Engines_Container_i::create_component_instance(const char*genericRegisterName,
+ CORBA::Long studyId)
+{
+ Engines::FieldsDict_var env = new Engines::FieldsDict;
+ char* reason;
+ Engines::EngineComponent_ptr compo =
+ create_component_instance_env(genericRegisterName, studyId, env, reason);
+ CORBA::string_free(reason);
+ return compo;
+}
+
+//=============================================================================
+//! Create a new component instance with environment variables specified
+/*!
+* CORBA method: Creates a new servant instance of a component.
+* The servant registers itself to naming service and Registry.
+* \param genericRegisterName Name of the component instance to register
+* in Registry & Name Service (without _inst_n suffix)
+* \param studyId 0 for multiStudy instance,
+* study Id (>0) otherwise
+* \param env dict of env variables
+* \param reason explains error when create_component_instance_env fails
+* \return a loaded component
+*/
+//=============================================================================
+Engines::EngineComponent_ptr
+Engines_Container_i::create_component_instance_env(const char*genericRegisterName,
+ CORBA::Long studyId,
+ const Engines::FieldsDict& env,
+ CORBA::String_out reason)
+{
+ if (studyId < 0)
+ {
+ INFOS("studyId must be > 0 for mono study instance, =0 for multiStudy");
+ reason=CORBA::string_dup("studyId must be > 0 for mono study instance, =0 for multiStudy");
+ return Engines::EngineComponent::_nil() ;
+ }
+
+ std::string error;
+ if (_library_map.count(genericRegisterName) != 0)
+ {
+ // It's a Python component
+ Engines::EngineComponent_ptr compo = createPythonInstance(genericRegisterName, studyId, error);
+ reason=CORBA::string_dup(error.c_str());
+ return compo;
+ }
+
+ std::string impl_name = std::string(LIB) + genericRegisterName + ENGINESO;
+ if (_library_map.count(impl_name) != 0)
+ {
+ // It's a C++ component
+ void* handle = _library_map[impl_name];
+ Engines::EngineComponent_ptr compo = createInstance(genericRegisterName, handle, studyId, error);
+ reason=CORBA::string_dup(error.c_str());
+ return compo;
+ }
+
+ impl_name = std::string(genericRegisterName) + ".exe";
+ if (_library_map.count(impl_name) != 0)
+ {
+ //It's an executable component
+ Engines::EngineComponent_ptr compo = createExecutableInstance(genericRegisterName, studyId, env, error);
+ reason=CORBA::string_dup(error.c_str());
+ return compo;
+ }
+
+ error="load_component_Library has probably not been called for component: ";
+ error += genericRegisterName;
+ INFOS(error);
+ reason=CORBA::string_dup(error.c_str());
+ return Engines::EngineComponent::_nil() ;
+}
+
+//=============================================================================
+//! Create a new component instance (Executable implementation)
+/*!
+* \param CompName Name of the component instance
+* \param studyId 0 for multiStudy instance,
+* study Id (>0) otherwise
+* \param env dict of env variables
+* \param reason explains error when creation fails
+* \return a loaded component
+*
+* This component is implemented in an executable with name genericRegisterName.exe
+* It must register itself in Naming Service. The container waits some time (10 s max)
+* it's registration.
+*/
+//=============================================================================
+Engines::EngineComponent_ptr
+Engines_Container_i::createExecutableInstance(std::string CompName, int studyId,
+ const Engines::FieldsDict& env,
+ std::string& reason)
+{
+ Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
+
+ _numInstanceMutex.lock() ; // lock on the instance number
+ _numInstance++ ;
+ int numInstance = _numInstance ;
+ _numInstanceMutex.unlock() ;
+
+ char aNumI[12];
+ sprintf( aNumI , "%d" , numInstance ) ;
+ std::string instanceName = CompName + "_inst_" + aNumI ;
+ std::string component_registerName = _containerName + "/" + instanceName;
+
+ //check if an entry exist in naming service
+ CORBA::Object_var nsobj = _NS->Resolve(component_registerName.c_str());
+ if ( !CORBA::is_nil(nsobj) )
+ {
+ // unregister the registered component
+ _NS->Destroy_Name(component_registerName.c_str());
+ //kill or shutdown it ???