47 #include "../TaskContext.hpp" 48 #include "../Logger.hpp" 49 #include <boost/filesystem.hpp> 50 #include <boost/version.hpp> 51 #include "../os/StartStopManager.hpp" 52 #include "../os/MutexLock.hpp" 53 #include "../internal/GlobalService.hpp" 69 static const std::string
SO_EXT(
".dylib");
73 static const std::string
SO_EXT(
".dll");
80 static const std::string
SO_EXT(
".so");
109 if (!ext.empty() && (
'.' == ext[0]))
111 std::istringstream iss;
114 iss.str(ext.substr((
size_t)1));
115 iss >> std::dec >> std::noskipws >> i;
116 isExtensionVersion = !iss.fail() && iss.eof();
145 bool isLoadable =
false;
147 #if defined(__APPLE__) 149 #if BOOST_VERSION >= 104600 150 ext = filename.extension().string();
152 ext = filename.extension();
155 if (0 == ext.compare(
SO_EXT))
160 path name = filename.stem();
161 path ext = name.extension();
175 (filename.extension() ==
SO_EXT) &&
176 !filename.stem().empty();
184 static vector<string> splitPaths(
string const& str)
186 vector<string> paths;
189 string::size_type lastPos = str.find_first_not_of(
delimiters, 0);
191 string::size_type pos = str.find_first_of(
delimiters, lastPos);
193 while (string::npos != pos || string::npos != lastPos)
196 if ( !str.substr(lastPos, pos - lastPos).empty() )
197 paths.push_back(str.substr(lastPos, pos - lastPos));
199 lastPos = str.find_first_not_of(
delimiters, pos);
204 paths.push_back(
".");
208 static void removeDuplicates(
string& path_list)
210 vector<string> paths;
215 paths = splitPaths( path_list );
218 for(vector<string>::const_iterator it = paths.begin(); it != paths.end(); ++it)
232 path_list.swap(result);
241 static string makeShortFilename(
string const& str) {
243 if (str.substr(0,3) ==
"lib")
252 static RTT_UNUSED
bool hasEnding(
string const &fullString,
string const &ending)
254 if (fullString.length() > ending.length()) {
255 return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
273 char* paths = getenv(
"RTT_COMPONENT_PATH");
276 plugin_paths = paths;
278 if ( !default_plugin_path.empty() )
280 removeDuplicates( plugin_paths );
281 log(
Info) <<
"RTT_COMPONENT_PATH was set to: " << paths <<
" . Searching in: "<< plugin_paths<<
endlog();
284 removeDuplicates( plugin_paths );
285 log(
Info) <<
"No RTT_COMPONENT_PATH set. Using default: " << plugin_paths <<
endlog();
293 }
catch(std::exception& e) {
295 log(
Warning) <<
"Corrupted files found in '" << plugin_paths <<
"'. Fix or remove these plugins."<<
endlog();
329 return loadPluginsInternal( path_list,
"types",
"typekit");
334 return loadPluginInternal(name, path_list,
"types",
"typekit");
339 return loadPluginInternal(name, path_list,
"plugins",
"plugin");
344 return loadPluginsInternal( path_list,
"plugins",
"plugin");
349 for(vector<LoadedLib>::iterator it= loadedLibs.begin(); it != loadedLibs.end(); ++it) {
350 if (it->filename == servicename || it->plugname == servicename || it->shortname == servicename) {
352 log(
Info) <<
"Loading Service or Plugin " << servicename <<
" in TaskContext " << tc->
getName() <<
endlog();
354 return it->loadPlugin( tc );
355 }
catch(std::exception& e) {
356 log(
Error) <<
"Service or Plugin "<< servicename <<
" threw an exception during loading in " << tc->
getName() <<
endlog();
360 log(
Error) <<
"Service or Plugin "<< servicename <<
" threw an unknown exception during loading in " << tc->
getName() <<
endlog();
365 if (it->is_service) {
371 log(
Error) <<
"Service " << servicename <<
" cannot be loaded into the global service." <<
endlog();
374 }
catch(std::exception& e) {
375 log(
Error) <<
"Service "<< servicename <<
" threw an exception during loading in global service." <<
endlog();
379 log(
Error) <<
"Service "<< servicename <<
" threw an unknown exception during loading in global service. " <<
endlog();
383 log(
Error) <<
"Plugin "<< servicename <<
" was found, but it's not a Service." <<
endlog();
390 log(
Error) <<
"No such service or plugin: '"<< servicename <<
"'"<<
endlog();
398 path arg( path_list );
399 if (is_regular_file(arg)) {
400 #if BOOST_VERSION >= 104600 401 if ( loadInProcess(arg.string(), makeShortFilename(arg.filename().string()), kind,
true) ==
false)
403 if ( loadInProcess(arg.string(), makeShortFilename(arg.filename()), kind,
true) ==
false)
405 throw std::runtime_error(
"The plugin "+path_list+
" was found but could not be loaded !");
406 log(
Warning) <<
"You supplied a filename to 'loadPlugins(path)' or 'loadTypekits(path)'."<<
nlog();
407 log(
Warning) <<
"Please use 'loadLibrary(filename)' instead since the function you use will only scan directories in future releases."<<
endlog();
412 vector<string> paths;
413 if (path_list.empty())
416 paths = splitPaths( path_list );
418 bool all_good =
true, found =
false;
420 for (vector<string>::iterator it = paths.begin(); it != paths.end(); ++it)
423 path p = path(*it) / subdir;
426 log(
Info) <<
"Loading "<<kind<<
" libraries from directory " << p.string() <<
" ..."<<
endlog();
427 for (directory_iterator itr(p); itr != directory_iterator(); ++itr)
429 log(
Debug) <<
"Scanning file " << itr->path().string() <<
" ...";
433 #if BOOST_VERSION >= 104600 434 libname = itr->path().filename().string();
436 libname = itr->path().filename();
438 if(!isCompatiblePlugin(libname))
445 all_good = loadInProcess( itr->path().string(), makeShortFilename(libname), kind,
true) && all_good;
448 if (!is_regular_file(itr->status()))
459 throw std::runtime_error(
"Some found plugins could not be loaded !");
467 if (is_regular_file(arg)) {
468 #if BOOST_VERSION >= 104600 469 string subdir = arg.parent_path().filename().string();
471 string subdir = arg.parent_path().leaf();
475 if (subdir ==
"types") kind =
"typekit";
476 if (subdir ==
"plugins") kind =
"plugin";
477 if ( !kind.empty() ) {
478 #if BOOST_VERSION >= 104600 479 string libname = arg.filename().string();
481 string libname = arg.filename();
483 if(!isCompatiblePlugin(libname))
485 log(
Error) <<
"The " << kind <<
" " << name <<
" was found but is incompatible." <<
endlog();
489 #if BOOST_VERSION >= 104600 490 if ( loadInProcess(arg.string(), makeShortFilename(arg.filename().string()), kind,
true) ==
false)
492 if ( loadInProcess(arg.string(), makeShortFilename(arg.filename()), kind,
true) ==
false)
494 throw std::runtime_error(
"The plugin "+name+
" was found but could not be loaded !");
498 log(
Error) <<
"refusing to load " << name <<
" as I could not autodetect its type (name=" << name <<
", path=" << arg.string() <<
", subdir=" << subdir <<
")" <<
endlog();
504 if ( arg.is_complete() )
508 path dir = arg.parent_path();
509 #if BOOST_VERSION >= 104600 510 string file = arg.filename().string();
512 string file = arg.filename();
514 vector<string> paths = splitPaths(plugin_path);
515 vector<string> tryouts( paths.size() * 8 );
519 string subdir =
"plugins";
string kind =
"plugin";
521 for (vector<string>::iterator it = paths.begin(); it != paths.end(); ++it)
524 tryouts.push_back( p.string() );
525 if (is_regular_file( p ) && loadInProcess( p.string(), name, kind, true ) )
528 tryouts.push_back( p.string() );
529 if (is_regular_file( p ) && loadInProcess( p.string(), name, kind, true ) )
532 tryouts.push_back( p.string() );
533 if (is_regular_file( p ) && loadInProcess( p.string(), name, kind, true ) )
536 tryouts.push_back( p.string() );
537 if (is_regular_file( p ) && loadInProcess( p.string(), name, kind, true ) )
540 if (subdir ==
"types")
545 log(
Debug) <<
"No such "<< kind <<
" found in path: " << name <<
". Tried:"<<
endlog();
546 for(vector<string>::iterator it=tryouts.begin(); it != tryouts.end(); ++it)
556 if (name !=
"rtt" && loadLibrary(name)) {
557 log(
Warning) <<
"You supplied a filename as first argument to 'loadPlugin(name,path)' or 'loadTypekit(name,path)'."<<
nlog();
558 log(
Warning) <<
"Please use 'loadLibrary(filename)' instead since the function you use will only interprete 'name' as a directory name in future releases."<<
endlog();
562 if ( isLoadedInternal(name) ) {
563 log(
Debug) <<kind <<
" '"<< name <<
"' already loaded. Not reloading it." <<
endlog();
566 log(
Info) << kind <<
" '"<< name <<
"' not loaded before." <<
endlog();
569 string paths, trypaths;
570 if (path_list.empty())
580 vector<string> vpaths = splitPaths(paths);
582 bool path_found =
false;
583 string plugin_dir = name;
586 for(vector<string>::iterator it = vpaths.begin(); it != vpaths.end(); ++it) {
590 if (is_directory( p )) {
597 p = p / OROCOS_TARGET_NAME / plugin_dir;
599 if (is_directory( p )) {
609 paths.erase( paths.size() - 1 );
610 return loadPluginsInternal(paths,subdir,kind);
612 log(
Error) <<
"No such "<< kind <<
" found in path: " << name <<
". Looked for these directories: "<<
endlog();
613 if ( !paths.empty() )
614 log(
Error) <<
"Exist, but don't contain it: " << paths <<
endlog();
617 if ( !trypaths.empty() )
625 return isLoadedInternal(file);
631 std::vector<LoadedLib>::iterator lib = loadedLibs.begin();
632 while (lib != loadedLibs.end()) {
634 if ( lib->filename == p.filename() || lib->plugname == file || lib->shortname == file ) {
648 if ( isLoadedInternal(shortname) || isLoadedInternal(file) ) {
649 log(
Debug) <<
"plugin '"<< file <<
"' already loaded. Not reloading it." <<
endlog() ;
654 if(!isCompatiblePlugin(file))
657 log(
Error) <<
"could not load library '"<< p.string() <<
"': incompatible." <<
endlog();
666 log(
Error) <<
"could not load library '"<< p.string() <<
"': "<< e <<
endlog();
673 #if BOOST_VERSION >= 104600 674 string libname = p.filename().string();
676 string libname = p.filename();
679 LoadedLib loading_lib(libname,shortname,handle);
682 std::string(*pluginName)(void) = 0;
683 std::string(*targetName)(void) = 0;
685 if ((error =
dlerror()) == NULL) {
686 string plugname, targetname;
687 pluginName = (std::string(*)(void))(
dlsym(handle,
"getRTTPluginName") );
688 if ((error =
dlerror()) == NULL) {
689 plugname = (*pluginName)();
694 targetName = (std::string(*)(void))(
dlsym(handle,
"getRTTTargetName") );
695 if ((error =
dlerror()) == NULL) {
696 targetname = (*targetName)();
698 targetname = OROCOS_TARGET_NAME;
700 if ( targetname != OROCOS_TARGET_NAME ) {
701 log(
Error) <<
"Plugin "<< plugname <<
" reports to be compiled for OROCOS_TARGET "<< targetname
702 <<
" while we are running on target "<< OROCOS_TARGET_NAME <<
". Unloading."<<
endlog();
713 bool success =
false;
717 }
catch(std::exception& e) {
718 log(
Error) <<
"Loading "<< plugname <<
" threw an exception: "<< e.what() <<
endlog();
720 log(
Error) <<
"Unexpected exception in loadRTTPlugin !"<<
endlog();
724 log(
Error) <<
"Failed to load RTT Plugin '" <<plugname<<
"': plugin refused to load into this process. Unloading." <<
endlog();
728 if (kind ==
"typekit") {
729 log(
Info) <<
"Loaded RTT TypeKit/Transport '" + plugname +
"' from '" + shortname +
"'"<<
endlog();
734 log(
Info) <<
"Loaded RTT Service '" + plugname +
"' from '" + shortname +
"'"<<
endlog();
737 log(
Info) <<
"Loaded RTT Plugin '" + plugname +
"' from '" + shortname +
"'"<<
endlog();
740 loadedLibs.push_back(loading_lib);
752 vector<string> names;
753 for(vector<LoadedLib>::const_iterator it= loadedLibs.begin(); it != loadedLibs.end(); ++it) {
754 if ( it->is_service )
755 names.push_back( it->plugname );
762 vector<string> names;
763 for(vector<LoadedLib>::const_iterator it= loadedLibs.begin(); it != loadedLibs.end(); ++it) {
764 names.push_back( it->plugname );
771 vector<string> names;
772 for(vector<LoadedLib>::const_iterator it= loadedLibs.begin(); it != loadedLibs.end(); ++it) {
773 if ( it->is_typekit )
774 names.push_back( it->plugname );
786 plugin_path = newpath;
793 #if BOOST_VERSION >= 104600 794 string libname = p.filename().string();
796 string libname = p.filename();
801 #ifdef OROCOS_TARGET_WIN32 810 #endif // OROCOS_TARGET_WIN32
static Logger::LogFunction nlog()
void * dlsym(void *handle, const char *name)
static const std::string delimiters(":;")
RTT::ServicePtr(* createService)(void)
bool loadService(std::string const &servicename, TaskContext *tc)
bool loadPluginsInternal(std::string const &path_list, std::string const &subdir, std::string const &kind)
RTT_API bool isExtensionVersion(const std::string &ext)
bool isLoadedInternal(std::string name)
void * dlopen(const char *file, int mode)
boost::shared_ptr< Service > shared_ptr
bool(* loadPlugin)(RTT::TaskContext *)
bool loadTypekits(std::string const &path_list)
static boost::shared_ptr< PluginLoader > instance2
static const std::string SO_POSTFIX("")
bool loadTypekit(std::string const &name, std::string const &path_list)
std::vector< std::string > listTypekits() const
bool loadLibrary(std::string const &path)
int dlclose(void *handle)
char const * default_plugin_path
std::vector< std::string > listPlugins() const
bool loadPluginInternal(std::string const &name, std::string const &path_list, std::string const &subdir, std::string const &kind)
void setPluginPath(std::string const &newpath)
static const std::string FULL_PLUGINS_SUFFIX(string("-")+string(OROCOS_TARGET_NAME)+SO_POSTFIX+SO_EXT)
bool isLoaded(std::string name)
static boost::shared_ptr< PluginLoader > Instance()
std::vector< std::string > listServices() const
static const std::string default_delimiter(":")
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
bool isCompatiblePlugin(std::string const &filepath)
std::string getPluginPath() const
static RTT_UNUSED bool hasEnding(string const &fullString, string const &ending)
static const std::string SO_EXT(".so")
bool loadInProcess(std::string filename, std::string shortname, std::string kind, bool log_error)
RTT_API bool isLoadableLibrary(const path &filename)
bool loadPlugin(std::string const &name, std::string const &path_list)
static Logger::LogFunction endlog()
bool loadPlugins(std::string const &path_list)
static RTT_API Service::shared_ptr Instance()
virtual const std::string & getName() const
MutexLock is a scope based Monitor, protecting critical sections with a Mutex object through locking ...