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