00001 #include "ComponentLoader.hpp"
00002 #include <rtt/TaskContext.hpp>
00003 #include <rtt/Logger.hpp>
00004 #include <boost/filesystem.hpp>
00005 #include <boost/version.hpp>
00006 #include <rtt/os/StartStopManager.hpp>
00007 #include <rtt/plugin/PluginLoader.hpp>
00008 #include <rtt/types/TypekitRepository.hpp>
00009
00010 #ifdef HAS_ROSLIB
00011 #include <rospack/rospack.h>
00012 #endif
00013
00014 #ifndef _WIN32
00015 # include <dlfcn.h>
00016 #endif
00017
00018 using namespace RTT;
00019 using namespace RTT::detail;
00020 using namespace std;
00021 using namespace boost::filesystem;
00022
00023 namespace RTT
00024 {
00025
00026
00027 FactoryMap* ComponentFactories::Factories = 0;
00028 }
00029
00030
00031 #ifdef __APPLE__
00032 static const std::string SO_EXT(".dylib");
00033 static const std::string SO_POSTFIX("");
00034 #else
00035 # ifdef _WIN32
00036 static const std::string SO_EXT(".dll");
00037 # ifdef _DEBUG
00038 static const std::string SO_POSTFIX("d");
00039 # else
00040 static const std::string SO_POSTFIX("");
00041 # endif // _DEBUG
00042 # else
00043 static const std::string SO_EXT(".so");
00044 static const std::string SO_POSTFIX("");
00045 # endif
00046 #endif
00047
00048
00049 static const std::string FULL_COMPONENT_SUFFIX(string("-") + string(OROCOS_TARGET_NAME) + SO_POSTFIX + SO_EXT);
00050
00051
00052 # ifdef _WIN32
00053 static const std::string delimiters(";");
00054 static const char default_delimiter(';');
00055 # else
00056 static const std::string delimiters(":;");
00057 static const char default_delimiter(':');
00058 # endif
00059
00068 static bool isExtensionVersion(const std::string& ext)
00069 {
00070 bool isExtensionVersion = false;
00071
00072 if (!ext.empty() && ('.' == ext[0]))
00073 {
00074 std::istringstream iss;
00075 int i;
00076
00077 iss.str(ext.substr((size_t)1));
00078 iss >> std::dec >> std::noskipws >> i;
00079 isExtensionVersion = !iss.fail() && iss.eof();
00080 }
00081
00082 return isExtensionVersion;
00083 }
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 static bool isLoadableLibrary(const path& filename)
00107 {
00108 bool isLoadable = false;
00109
00110 #if defined(__APPLE__)
00111 std::string ext;
00112 #if BOOST_VERSION >= 104600
00113 ext = filename.extension().string();
00114 #else
00115 ext = filename.extension();
00116 #endif
00117
00118 if (0 == ext.compare(SO_EXT))
00119 {
00120
00121
00122
00123 path name = filename.stem();
00124 path ext = name.extension();
00125 isLoadable =
00126
00127 !name.empty() &&
00128
00129 (ext.empty() || !isExtensionVersion(ext.string()));
00130 }
00131
00132
00133 #else
00134
00135
00136
00137 isLoadable =
00138 (filename.extension() == SO_EXT) &&
00139 !filename.stem().empty();
00140 #endif
00141
00142 return isLoadable;
00143 }
00144
00145 namespace RTT {
00146 extern char const* default_comp_path_build;
00147 }
00148
00149 namespace {
00153 int loadComponents()
00154 {
00155 std::string default_comp_path = ::default_comp_path_build;
00156
00157 char* paths = getenv("RTT_COMPONENT_PATH");
00158 string component_paths;
00159 if (paths) {
00160 component_paths = paths;
00161
00162 if ( !default_comp_path.empty() )
00163 component_paths = component_paths + default_delimiter + default_comp_path;
00164 log(Info) <<"RTT_COMPONENT_PATH was set to: " << paths << " . Searching in: "<< component_paths<< endlog();
00165 } else {
00166 component_paths = default_comp_path;
00167 log(Info) <<"No RTT_COMPONENT_PATH set. Using default: " << component_paths <<endlog();
00168 }
00169
00170 ComponentLoader::Instance()->setComponentPath(component_paths);
00171 return 0;
00172 }
00173
00174 os::InitFunction component_loader( &loadComponents );
00175
00176 void unloadComponents()
00177 {
00178 ComponentLoader::Release();
00179 }
00180
00181 os::CleanupFunction component_unloader( &unloadComponents );
00182 }
00183
00184 static boost::shared_ptr<ComponentLoader> instance2;
00185
00186 namespace {
00187
00188
00189 static vector<string> splitPaths(string const& str)
00190 {
00191 vector<string> paths;
00192
00193
00194 string::size_type lastPos = str.find_first_not_of(delimiters, 0);
00195
00196 string::size_type pos = str.find_first_of(delimiters, lastPos);
00197
00198 while (string::npos != pos || string::npos != lastPos)
00199 {
00200
00201 if ( !str.substr(lastPos, pos - lastPos).empty() )
00202 paths.push_back(str.substr(lastPos, pos - lastPos));
00203
00204 lastPos = str.find_first_not_of(delimiters, pos);
00205
00206 pos = str.find_first_of(delimiters, lastPos);
00207 }
00208 if ( paths.empty() )
00209 paths.push_back(".");
00210 return paths;
00211 }
00212
00219 static string makeShortFilename(string const& str) {
00220 string ret = str;
00221 if (str.substr(0,3) == "lib")
00222 ret = str.substr(3);
00223 if (ret.rfind(FULL_COMPONENT_SUFFIX) != string::npos)
00224 ret = ret.substr(0, ret.rfind(FULL_COMPONENT_SUFFIX) );
00225 return ret;
00226 }
00227
00228 }
00229
00230 static bool hasEnding(string const &fullString, string const &ending)
00231 {
00232 if (fullString.length() > ending.length()) {
00233 return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
00234 } else {
00235 return false;
00236 }
00237 }
00238
00239 boost::shared_ptr<ComponentLoader> ComponentLoader::Instance() {
00240 if (!instance2)
00241 instance2.reset( new ComponentLoader() );
00242 return instance2;
00243 }
00244
00245 void ComponentLoader::Release() {
00246 instance2.reset();
00247 }
00248
00249
00250
00251 bool ComponentLoader::import( std::string const& path_list )
00252 {
00253 if (path_list.empty() ) {
00254 log(Error) << "import paths: No paths were given for loading ( path_list = '' )."<<endlog();
00255 return false;
00256 }
00257
00258
00259 vector<string> paths;
00260 paths = splitPaths( path_list );
00261
00262 bool all_good = true, found = false;
00263
00264 for (vector<string>::iterator it = paths.begin(); it != paths.end(); ++it)
00265 {
00266
00267 path p = path(*it);
00268 if (is_directory(p))
00269 {
00270 log(Info) << "Importing directory " << p.string() << " ..."<<endlog();
00271 for (directory_iterator itr(p); itr != directory_iterator(); ++itr)
00272 {
00273 log(Debug) << "Scanning file " << itr->path().string() << " ...";
00274 if (is_regular_file(itr->status()) && isLoadableLibrary(itr->path()) ) {
00275 found = true;
00276 std::string libname;
00277 #if BOOST_VERSION >= 104600
00278 libname = itr->path().filename().string();
00279 #else
00280 libname = itr->path().filename();
00281 #endif
00282 if(!isCompatibleComponent(libname))
00283 {
00284 log(Debug) << "not a compatible component: ignored."<<endlog();
00285 }
00286 else
00287 {
00288 found = true;
00289 all_good = loadInProcess( itr->path().string(), makeShortFilename(libname ), true) && all_good;
00290 }
00291 } else {
00292 if (!is_regular_file(itr->status()))
00293 log(Debug) << "not a regular file: ignored."<<endlog();
00294 else
00295 log(Debug) << "not a " + SO_EXT + " library: ignored."<<endlog();
00296 }
00297 }
00298 log(Debug) << "Looking for plugins or typekits in directory " << p.string() << " ..."<<endlog();
00299 try {
00300 found = PluginLoader::Instance()->loadTypekits( p.string() ) || found;
00301 found = PluginLoader::Instance()->loadPlugins( p.string() ) || found;
00302 } catch (std::exception& e) {
00303 all_good = false;
00304 log(Error) << e.what() <<endlog();
00305 }
00306 }
00307 else {
00308
00309 log(Debug) << "No such directory: " << p<< endlog();
00310 }
00311 #if 0
00312
00313 p = path(*it) / OROCOS_TARGET_NAME;
00314 if (is_directory(p))
00315 {
00316 log(Info) << "Importing component libraries from directory " << p.string() << " ..."<<endlog();
00317 for (directory_iterator itr(p); itr != directory_iterator(); ++itr)
00318 {
00319 log(Debug) << "Scanning file " << itr->path().string() << " ...";
00320 if (is_regular_file(itr->status()) && isLoadableLibrary(itr->path()) ) {
00321 found = true;
00322 #if BOOST_VERSION >= 104600
00323 all_good = loadInProcess( itr->path().string(), makeShortFilename(itr->path().filename().string() ), true) && all_good;
00324 #else
00325 all_good = loadInProcess( itr->path().string(), makeShortFilename(itr->path().filename() ), true) && all_good;
00326 #endif
00327 }else {
00328 if (!is_regular_file(itr->status()))
00329 log(Debug) << "not a regular file: ignored."<<endlog();
00330 else
00331 log(Debug) << "not a " + SO_EXT + " library: ignored."<<endlog();
00332 }
00333 }
00334 log(Info) << "Importing plugins and typekits from directory " << p.string() << " ..."<<endlog();
00335 try {
00336 found = PluginLoader::Instance()->loadTypekits( p.string() ) || found;
00337 found = PluginLoader::Instance()->loadPlugins( p.string() ) || found;
00338 } catch (std::exception& e) {
00339 all_good = false;
00340 log(Error) << e.what() <<endlog();
00341 }
00342 }
00343 #endif
00344 }
00345 if (!all_good)
00346 throw std::runtime_error("Some found plugins could not be loaded !");
00347 return found;
00348 }
00349
00350
00351
00352 bool ComponentLoader::import( std::string const& package, std::string const& path_list )
00353 {
00354
00355 path arg( package );
00356 if (is_regular_file(arg) && isLoadableLibrary(arg)) {
00357 #if BOOST_VERSION >= 104600
00358 return loadInProcess(arg.string(), makeShortFilename( arg.filename().string() ), true);
00359 #else
00360 return loadInProcess(arg.string(), makeShortFilename( arg.filename() ), true);
00361 #endif
00362 }
00363
00364
00365 if ( arg.is_complete() ) {
00366
00367 bool ret = import(package);
00368
00369 if ( arg.parent_path().leaf() != OROCOS_TARGET_NAME )
00370 ret = import( (arg / OROCOS_TARGET_NAME).string() ) || ret;
00371
00372 if (ret)
00373 return true;
00374
00375 log(Error) << "Could not import absolute path '"<<package << "': nothing found."<<endlog();
00376 return false;
00377 }
00378
00379 if ( isImported(package) ) {
00380 log(Info) <<"Component package '"<< package <<"' already imported." <<endlog();
00381 return true;
00382 }
00383
00384
00385
00386
00387 if ( importRosPackage(package) )
00388 return true;
00389
00390
00391 return importInstalledPackage(package, path_list);
00392 }
00393
00394 bool ComponentLoader::importRosPackage(std::string const& package)
00395 {
00396
00397 #ifdef HAS_ROSLIB
00398 using namespace rospack;
00399 try {
00400 bool found = false;
00401 Rospack rpack;
00402 rpack.setQuiet(true);
00403 char* rpp = getenv("ROS_PACKAGE_PATH");
00404 vector<string> paths;
00405 if (rpp)
00406 paths = splitPaths(rpp);
00407 string ppath;
00408 rpack.crawl(paths,false);
00409 rpack.find(package, ppath);
00410 if ( !ppath.empty() ) {
00411 path rospath = path(ppath) / "lib" / "orocos";
00412 path rospath_target = rospath / OROCOS_TARGET_NAME;
00413
00414 vector<string> rospackresult;
00415 rpack.setQuiet(false);
00416 bool valid = rpack.deps(package, false, rospackresult);
00417 if (!valid) {
00418 log(Error) <<"The ROS package '"<< package <<"' in '"<< ppath << "' caused trouble. Bailing out."<<endlog();
00419 return false;
00420 }
00421
00422 for(vector<string>::iterator it = rospackresult.begin(); it != rospackresult.end(); ++it) {
00423 if ( isImported(*it) ) {
00424 log(Debug) <<"Package dependency '"<< *it <<"' already imported." <<endlog();
00425 continue;
00426 }
00427 if ( rpack.find( *it, ppath ) == false )
00428 throw *it;
00429 path deppath = path(ppath) / "lib" / "orocos";
00430 path deppath_target = path(deppath) / OROCOS_TARGET_NAME;
00431
00432 if ( is_directory( deppath_target ) ) {
00433 log(Debug) << "Ignoring files under " << deppath.string() << " since " << deppath_target.string() << " was found."<<endlog();
00434 found = true;
00435 if ( import( deppath_target.string() ) ) {
00436 loadedPackages.push_back( *it );
00437 }
00438 }
00439 else if ( is_directory( deppath ) ) {
00440 found = true;
00441 if ( import( deppath.string() ) ) {
00442 loadedPackages.push_back( *it );
00443 }
00444 }
00445 }
00446
00447 if ( is_directory( rospath_target ) ) {
00448 log(Debug) << "Ignoring files under " << rospath.string() << " since " << rospath_target.string() << " was found."<<endlog();
00449 found = true;
00450 if ( import( rospath_target.string() ) ) {
00451 loadedPackages.push_back( package );
00452 }
00453 } else if ( is_directory( rospath ) ) {
00454 found = true;
00455 if ( import( rospath.string() ) ) {
00456 loadedPackages.push_back( package );
00457 }
00458 }
00459
00460 if (!found) {
00461 log(Debug) <<"The ROS package '"<< package <<"' in '"<< ppath << "' nor its dependencies contained a lib/orocos directory. I'll look in the RTT_COMPONENT_PATH next."<<endlog();
00462 }
00463 return found;
00464 } else
00465 log(Info) << "Not a ros package: " << package << endlog();
00466 } catch(std::string arg) {
00467 log(Info) << "While processing the dependencies of " << package << ": not a ros package: " << arg << endlog();
00468 }
00469 #endif
00470 return false;
00471 }
00472
00473 bool ComponentLoader::importInstalledPackage(std::string const& package, std::string const& path_list)
00474 {
00475 string paths;
00476 string trypaths;
00477 vector<string> tryouts;
00478 if (path_list.empty())
00479 paths = component_path + default_delimiter + ".";
00480 else
00481 paths = path_list;
00482
00483 bool path_found = false;
00484
00485
00486
00487 vector<string> vpaths;
00488 vpaths = splitPaths(paths);
00489 trypaths = paths;
00490 paths.clear();
00491
00492 path p( package );
00493 if (is_directory( p )) {
00494 path_found = true;
00495
00496 paths += p.string() + default_delimiter + (p / OROCOS_TARGET_NAME).string() + default_delimiter;
00497 if ( p.is_complete() ) {
00498
00499
00500
00501 }
00502 }
00503
00504 for(vector<string>::iterator it = vpaths.begin(); it != vpaths.end(); ++it) {
00505 p = *it;
00506 p = p / package;
00507
00508 if (is_directory( p )) {
00509 path_found = true;
00510 paths += p.string() + default_delimiter ;
00511 } else
00512 tryouts.push_back( p.string() );
00513 p = *it;
00514 p = p / OROCOS_TARGET_NAME / package;
00515
00516 if (is_directory( p )) {
00517 path_found = true;
00518 paths += p.string() + default_delimiter ;
00519 } else
00520 tryouts.push_back( p.string() );
00521 }
00522 if ( path_found )
00523 paths.erase( paths.size() - 1 );
00524
00525
00526 if (path_found) {
00527 if ( import(paths) ) {
00528 loadedPackages.push_back( package );
00529 return true;
00530 } else {
00531 log(Error) << "Failed to import components, types or plugins from package or directory '"<< package <<"' found in:"<< endlog();
00532 log(Error) << paths << endlog();
00533 return false;
00534 }
00535 }
00536 log(Error) << "No such package or directory found in search path: " << package << ". Search path is: "<< endlog();
00537 log(Error) << trypaths << endlog();
00538 for(vector<string>::iterator it=tryouts.begin(); it != tryouts.end(); ++it)
00539 log(Error) << *it << endlog();
00540 return false;
00541 }
00542
00543 bool ComponentLoader::reloadLibrary(std::string const& name)
00544 {
00545 path arg = name;
00546
00547 #if BOOST_VERSION >= 104600
00548 if (is_regular_file( arg ) && reloadInProcess( arg.string(), makeShortFilename( arg.filename().string() ) ) )
00549 #else
00550 if (is_regular_file( arg ) && reloadInProcess( arg.string(), makeShortFilename( arg.filename() ) ) )
00551 #endif
00552 return true;
00553
00554 return false;
00555 }
00556
00557 bool ComponentLoader::loadLibrary( std::string const& name )
00558 {
00559 path arg = name;
00560
00561 #if BOOST_VERSION >= 104600
00562 if (is_regular_file( arg ) && loadInProcess( arg.string(), makeShortFilename( arg.filename().string() ), true ) )
00563 #else
00564 if (is_regular_file( arg ) && loadInProcess( arg.string(), makeShortFilename( arg.filename() ), true ) )
00565 #endif
00566 return true;
00567
00568 if ( arg.is_complete() )
00569 return false;
00570
00571
00572 vector<string> paths = splitPaths( component_path );
00573 vector<string> tryouts( paths.size() * 4 );
00574 tryouts.clear();
00575 path dir = arg.parent_path();
00576 #if BOOST_VERSION >= 104600
00577 string file = arg.filename().string();
00578 #else
00579 string file = arg.filename();
00580 #endif
00581
00582 for (vector<string>::iterator it = paths.begin(); it != paths.end(); ++it)
00583 {
00584 path p = path(*it) / dir / (file + FULL_COMPONENT_SUFFIX);
00585 tryouts.push_back( p.string() );
00586 if (is_regular_file( p ) && loadInProcess( p.string(), makeShortFilename(file), true ) )
00587 return true;
00588 p = path(*it) / dir / ("lib" + file + FULL_COMPONENT_SUFFIX);
00589 tryouts.push_back( p.string() );
00590 if (is_regular_file( p ) && loadInProcess( p.string(), makeShortFilename(file), true ) )
00591 return true;
00592 p = path(*it) / OROCOS_TARGET_NAME / dir / (file + FULL_COMPONENT_SUFFIX);
00593 tryouts.push_back( p.string() );
00594 if (is_regular_file( p ) && loadInProcess( p.string(), makeShortFilename(file), true ) )
00595 return true;
00596 p = path(*it) / OROCOS_TARGET_NAME / dir / ("lib" + file + FULL_COMPONENT_SUFFIX);
00597 tryouts.push_back( p.string() );
00598 if (is_regular_file( p ) && loadInProcess( p.string(), makeShortFilename(file), true ) )
00599 return true;
00600 }
00601 log(Debug) << "No such library found in path: " << name << ". Tried:"<< endlog();
00602 for(vector<string>::iterator it=tryouts.begin(); it != tryouts.end(); ++it)
00603 log(Debug) << *it << endlog();
00604 return false;
00605 }
00606
00607 bool ComponentLoader::isImported(string type_name)
00608 {
00609 if (ComponentFactories::Instance().find(type_name) != ComponentFactories::Instance().end() )
00610 return true;
00611 if (find(loadedPackages.begin(), loadedPackages.end(), type_name) != loadedPackages.end())
00612 return true;
00613
00614
00615 if ( type_name == "ocl" && TypekitRepository::hasTypekit("OCLTypekit")) {
00616 return true;
00617 }
00618 return false;
00619 }
00620
00621 bool ComponentLoader::reloadInProcess(string file, string libname)
00622 {
00623 path p(file);
00624
00625
00626
00627
00628
00629 std::vector<LoadedLib>::iterator lib = loadedLibs.begin();
00630 while (lib != loadedLibs.end()) {
00631
00632 if ( lib->filename == file) {
00633 log(Info) <<"Component library "<< lib->filename <<" already loaded... " ;
00634
00635 bool can_unload = true;
00636 CompList::iterator cit;
00637 for( std::vector<std::string>::iterator ctype = lib->components_type.begin(); ctype != lib->components_type.end() && can_unload; ++ctype) {
00638 for ( cit = comps.begin(); cit != comps.end(); ++cit) {
00639 if( (*ctype) == cit->second.type ) {
00640
00641 log(Info) << "can NOT reload library because of the instance " << cit->second.type <<"::"<<cit->second.instance->getName() <<endlog();
00642 can_unload = false;
00643 }
00644 }
00645 }
00646 if( can_unload ) {
00647 log(Info) << "try to RELOAD"<<endlog();
00648 dlclose(lib->handle);
00649
00650 std::vector<LoadedLib>::iterator lib_un = lib;
00651 loadedLibs.erase(lib_un);
00652 return loadInProcess(file, libname, true);
00653 }
00654 else
00655 return false;
00656 }
00657 else lib++;
00658 }
00659 log(Error) << "Can't reload Component library "<< file << " since it was not loaded or is not a component library." <<endlog();
00660 return false;
00661 }
00662
00663
00664 bool ComponentLoader::loadInProcess(string file, string libname, bool log_error) {
00665 path p(file);
00666 char* error;
00667 void* handle;
00668 bool success=false;
00669
00670
00671 if(!isCompatibleComponent(file))
00672 {
00673 if(log_error)
00674 log(Error) << "Could not load library '"<< p.string() <<"': incompatible." <<endlog();
00675 return false;
00676 }
00677
00678 handle = dlopen ( p.string().c_str(), RTLD_NOW);
00679
00680 if (!handle) {
00681 if ( log_error ) {
00682 log(Error) << "Could not load library '"<< p.string() <<"':"<<endlog();
00683 log(Error) << dlerror() << endlog();
00684 }
00685 return false;
00686 }
00687
00688
00689 log(Debug)<<"Succesfully loaded "<<libname<<endlog();
00690 LoadedLib loading_lib(file, libname, handle);
00691 dlerror();
00692
00693
00694 FactoryMap* (*getfactory)(void) = 0;
00695 vector<string> (*getcomponenttypes)(void) = 0;
00696 FactoryMap* fmap = 0;
00697 getfactory = (FactoryMap*(*)(void))( dlsym(handle, "getComponentFactoryMap") );
00698 if ((error = dlerror()) == NULL) {
00699
00700 fmap = (*getfactory)();
00701 ComponentFactories::Instance().insert( fmap->begin(), fmap->end() );
00702 log(Info) << "Loaded multi component library '"<< file <<"'"<<endlog();
00703 getcomponenttypes = (vector<string>(*)(void))(dlsym(handle, "getComponentTypeNames"));
00704 if ((error = dlerror()) == NULL) {
00705 log(Debug) << "Components:";
00706 vector<string> ctypes = getcomponenttypes();
00707 for (vector<string>::iterator it = ctypes.begin(); it != ctypes.end(); ++it)
00708 log(Debug) <<" "<< *it;
00709 log(Debug) << endlog();
00710 }
00711 loadedLibs.push_back(loading_lib);
00712 success = true;
00713 }
00714
00715
00716 dlerror();
00717
00718 RTT::TaskContext* (*factory)(std::string) = 0;
00719 std::string(*tname)(void) = 0;
00720 factory = (RTT::TaskContext*(*)(std::string))(dlsym(handle, "createComponent") );
00721 string create_error;
00722 error = dlerror();
00723 if (error) create_error = error;
00724 tname = (std::string(*)(void))(dlsym(handle, "getComponentType") );
00725 string gettype_error;
00726 error = dlerror();
00727 if (error) gettype_error = error;
00728 if ( factory && tname ) {
00729 std::string cname = (*tname)();
00730 if ( ComponentFactories::Instance().count(cname) == 1 ) {
00731 log(Warning) << "Component type name "<<cname<<" already used: overriding."<<endlog();
00732 }
00733 ComponentFactories::Instance()[cname] = factory;
00734 log(Info) << "Loaded component type '"<< cname <<"'"<<endlog();
00735 loading_lib.components_type.push_back( cname );
00736 loadedLibs.push_back(loading_lib);
00737 success = true;
00738 }
00739
00740 if (success) return true;
00741
00742 log(Error) <<"Unloading "<< loading_lib.filename <<": not a valid component library:" <<endlog();
00743 if (!create_error.empty())
00744 log(Error) << " " << create_error << endlog();
00745 if (!gettype_error.empty())
00746 log(Error) << " " << gettype_error << endlog();
00747 dlclose(handle);
00748 return false;
00749 }
00750
00751 std::vector<std::string> ComponentLoader::listComponentTypes() const {
00752 vector<string> names;
00753 FactoryMap::iterator it;
00754 for( it = ComponentFactories::Instance().begin(); it != ComponentFactories::Instance().end(); ++it) {
00755 names.push_back( it->first );
00756 }
00757 return names;
00758 }
00759
00760 std::string ComponentLoader::getComponentPath() const {
00761 string ret = component_path;
00762
00763 if ( ret.length() && ret[ ret.length() -1 ] != default_delimiter )
00764 ret += default_delimiter;
00765 return ret;
00766 }
00767
00768 void ComponentLoader::setComponentPath( std::string const& newpath ) {
00769 component_path = newpath;
00770 }
00771
00772
00773 RTT::TaskContext *ComponentLoader::loadComponent(const std::string & name, const std::string & type)
00774 {
00775 TaskContext* instance = 0;
00776 RTT::TaskContext* (*factory)(std::string name) = 0;
00777 log(Debug) << "Trying to create component "<< name <<" of type "<< type << endlog();
00778
00779
00780 if ( ComponentFactories::Instance().count(type) == 1 ) {
00781 factory = ComponentFactories::Instance()[ type ];
00782 if (factory == 0 ) {
00783 log(Error) <<"Found empty factory for Component type "<<type<<endlog();
00784 return 0;
00785 }
00786 }
00787
00788 if ( factory ) {
00789 log(Debug) <<"Found factory for Component type "<<type<<endlog();
00790 } else {
00791 log(Error) << "Unable to create Orocos Component '"<<type<<"': unknown component type." <<endlog();
00792 return 0;
00793 }
00794
00795 comps[name].type = type;
00796
00797 try {
00798 comps[name].instance = instance = (*factory)(name);
00799 } catch(...) {
00800 log(Error) <<"The constructor of component type "<<type<<" threw an exception!"<<endlog();
00801 }
00802
00803 if ( instance == 0 ) {
00804 log(Error) <<"Failed to load component with name "<<name<<": refused to be created."<<endlog();
00805 }
00806 return instance;
00807 }
00808
00809 bool ComponentLoader::unloadComponent( RTT::TaskContext* tc ) {
00810 if (!tc)
00811 return false;
00812 CompList::iterator it;
00813 it = comps.find( tc->getName() );
00814
00815 if ( it != comps.end() ) {
00816 delete tc;
00817 comps.erase(it);
00818 return true;
00819 }
00820 log(Error) <<"Refusing to unload a component I didn't load myself."<<endlog();
00821 return false;
00822 }
00823
00824 std::vector<std::string> ComponentLoader::listComponents() const
00825 {
00826 vector<string> names( comps.size() );
00827 for(map<string,ComponentData>::const_iterator it = comps.begin(); it != comps.end(); ++it)
00828 names.push_back( it->first );
00829 return names;
00830 }
00831
00832 bool ComponentLoader::isCompatibleComponent(std::string const& filepath)
00833 {
00834 path p(filepath);
00835
00836 #if BOOST_VERSION >= 104600
00837 string libname = p.filename().string();
00838 #else
00839 string libname = p.filename();
00840 #endif
00841
00842
00843
00844 #ifdef _WIN32
00845
00846
00847
00848 if(!hasEnding(libname, FULL_COMPONENT_SUFFIX))
00849 {
00850
00851 return false;
00852 }
00853 #endif // _WIN32
00854
00855
00856
00857
00858
00859 return true;
00860 }
00861
00862 const FactoryMap& ComponentLoader::getFactories() const
00863 {
00864 return ComponentFactories::Instance();
00865 }
00866
00867 void ComponentLoader::addFactory(std::string const& name, ComponentLoaderSignature factory)
00868 {
00869 ComponentFactories::Instance()[name] = factory;
00870 }