pluginmanager.cc
Go to the documentation of this file.
00001 #include "pluginmanager.hh"
00002 #include "plugins.hh"
00003 #include "importer.hh"
00004 #include "exporter.hh"
00005 
00006 #include <boost/filesystem.hpp>
00007 #include <boost/version.hpp>
00008 #include <dlfcn.h>
00009 
00010 using namespace std;
00011 using namespace Typelib;
00012 using namespace boost::filesystem;
00013 
00014 namespace
00015 {
00016     using namespace std;
00017     
00018     template<typename Map, typename Object>
00019     bool add_plugin(Map& plugin_map, Object* object)
00020     { return (plugin_map.insert( make_pair(object->getName(), object) ).second); }
00021 
00022     template<typename Object>
00023     Object* get_plugin( map<string, Object*> const& plugin_map, string const& name)
00024     {
00025         typename map<string, Object*>::const_iterator it = plugin_map.find(name);
00026         if (it == plugin_map.end())
00027             throw PluginNotFound(name);
00028         return it->second;
00029     }
00030 
00031     template<typename Container>
00032     void clear(Container& container)
00033     {
00034         for (typename Container::iterator it = container.begin(); it != container.end(); ++it)
00035             delete it->second;
00036         container.clear();
00037     }
00038 }
00039 
00040 PluginManager::PluginManager()
00041 {
00042     // use the environment variable to override the load-path
00043     if (const char* pluginPath = getenv("TYPELIB_PLUGIN_PATH")) {
00044         // the delimiter inside the env-var
00045         const std::string delim(":");
00046         // make a copy of the env-var, which we can modify
00047         std::string s(pluginPath);
00048         // we need ":" at the end, to catch the last entry in the list
00049         if (s.find_last_of(delim) != s.length())
00050             s += ":";
00051         // pos of delim for initial loop
00052         size_t pos = s.find(delim);
00053         do {
00054             // use matched substr to lookup plugins in the directory
00055             loadPluginFromDirectory(s.substr(0,pos));
00056             // and remote the matched substr from the stored copy
00057             s.erase(0, pos + delim.length());
00058         // do all this until we reach the end of the stored copy
00059         } while ((pos = s.find(delim)) != std::string::npos);
00060     }
00061     // fall back to load plugins from compiled-in path
00062     else if (exists(TYPELIB_HARDCODED_PLUGIN_PATH)) {
00063         loadPluginFromDirectory(TYPELIB_HARDCODED_PLUGIN_PATH);
00064     } else {
00065         std::cerr << "typelib: neither env-var 'TYPELIB_PLUGIN_PATH' nor hardcoded path "
00066             << "'" << TYPELIB_HARDCODED_PLUGIN_PATH << "' point to existing directories. "
00067             << "you probably won't have any plugins\n";
00068     }
00069 }
00070 
00071 PluginManager::~PluginManager()
00072 {
00073     clear(m_importers);
00074     clear(m_exporters);
00075     for (std::vector<TypeDefinitionPlugin*>::iterator it = m_definition_plugins.begin();
00076             it != m_definition_plugins.end(); ++it)
00077         delete *it;
00078     m_definition_plugins.clear();
00079     //for (vector<void*>::iterator it = m_library_handles.begin(); it != m_library_handles.end(); ++it)
00080     //    dlclose(*it);
00081 }
00082 
00091 bool PluginManager::loadPluginFromDirectory(std::string const& directory)
00092 {
00093     path plugin_dir(directory);
00094     bool success = false;
00095 
00096     directory_iterator end_it;
00097     for (directory_iterator it(plugin_dir); it != end_it; ++it)
00098     {
00099         if (it->path().extension() == ".so" || it->path().extension() == ".dylib")
00100 #if BOOST_VERSION >= 104600
00101             success |= loadPlugin(it->path().string());
00102 #else
00103             success |= loadPlugin(it->path().file_string());
00104 #endif
00105     }
00106 
00107     if (!success)
00108         std::cerr << "typelib: can't load a plugin from directory '" << directory << "'" << endl;
00109 
00110     return success;
00111 }
00112 
00113 bool PluginManager::loadPlugin(std::string const& path)
00114 {
00115     void* libhandle = dlopen(path.c_str(), RTLD_LAZY);
00116     if (!libhandle)
00117     {
00118         cerr << "typelib: cannot load plugin " << path << ": " << dlerror() << endl;
00119         return false;
00120     }
00121 
00122     void* libentry  = dlsym(libhandle, "registerPlugins");
00123     if (!libentry)
00124     {
00125         cerr << "typelib: '" << path << "' does not seem to be a valid typelib plugin" << endl;
00126         return false;
00127     }
00128 
00129     PluginEntryPoint function = reinterpret_cast<PluginEntryPoint>(libentry);
00130     function(*this);
00131     m_library_handles.push_back(libhandle);
00132     return true;
00133 }
00134 
00135 bool PluginManager::add(ExportPlugin* plugin)
00136 { return add_plugin(m_exporters, plugin); }
00137 bool PluginManager::add(ImportPlugin* plugin)
00138 { return add_plugin(m_importers, plugin); }
00139 void PluginManager::add(TypeDefinitionPlugin* plugin)
00140 { return m_definition_plugins.push_back(plugin); }
00141 
00142 void PluginManager::registerPluginTypes(Registry& registry)
00143 {
00144     for (vector<TypeDefinitionPlugin*>::iterator it = m_definition_plugins.begin();
00145             it != m_definition_plugins.end(); ++it)
00146     {
00147         (*it)->registerTypes(registry);
00148     }
00149 }
00150 
00151 Importer* PluginManager::importer(std::string const& name) const
00152 { return get_plugin(m_importers, name)->create(); }
00153 Exporter* PluginManager::exporter(std::string const& name) const
00154 { return get_plugin(m_exporters, name)->create(); }
00155 
00156 
00157 std::string PluginManager::save(std::string const& kind, Registry const& registry)
00158 {
00159     utilmm::config_set config;
00160     return save(kind, config, registry);
00161 }
00162 
00163 std::string PluginManager::save(std::string const& kind, utilmm::config_set const& config, Registry const& registry)
00164 {
00165     ostringstream stream;
00166     save(kind, config, registry, stream);
00167     return stream.str();
00168 }
00169 void PluginManager::save(std::string const& kind, Registry const& registry, std::ostream& into)
00170 {
00171     utilmm::config_set config;
00172     save(kind, config, registry, into);
00173 }
00174 void PluginManager::save(std::string const& kind, utilmm::config_set const& config, Registry const& registry, std::ostream& into)
00175 {
00176     auto_ptr<Exporter> exporter(PluginManager::self()->exporter(kind));
00177     exporter->save(into, config, registry);
00178 }
00179 
00180 Registry* PluginManager::load(std::string const& kind, std::istream& stream)
00181 {
00182     utilmm::config_set config;
00183     return load(kind, stream, config);
00184 }
00185 void PluginManager::load(std::string const& kind, std::istream& stream, Registry& into )
00186 {
00187     utilmm::config_set config;
00188     return load(kind, stream, config, into);
00189 }
00190 Registry* PluginManager::load(std::string const& kind, std::string const& file)
00191 {
00192     utilmm::config_set config;
00193     return load(kind, file, config);
00194 }
00195 void PluginManager::load(std::string const& kind, std::string const& file, Registry& into)
00196 {
00197     utilmm::config_set config;
00198     return load(kind, file, config, into);
00199 }
00200 
00201 Registry* PluginManager::load(std::string const& kind, std::istream& stream, utilmm::config_set const& config )
00202 {
00203     auto_ptr<Registry> registry(new Registry);
00204     load(kind, stream, config, *registry.get());
00205     return registry.release();
00206 }
00207 void PluginManager::load(std::string const& kind, std::istream& stream, utilmm::config_set const& config
00208         , Registry& into )
00209 {
00210     std::auto_ptr<Importer> importer(PluginManager::self()->importer(kind));
00211     importer->load(stream, config, into);
00212 }
00213 Registry* PluginManager::load(std::string const& kind, std::string const& file, utilmm::config_set const& config)
00214 {
00215     auto_ptr<Registry> registry(new Registry);
00216     load(kind, file, config, *registry.get());
00217     return registry.release();
00218 }
00219 void PluginManager::load(std::string const& kind, std::string const& file, utilmm::config_set const& config
00220         , Registry& into)
00221 {
00222     auto_ptr<Importer> importer(PluginManager::self()->importer(kind));
00223     importer->load(file, config, into);
00224 }
00225 


typelib
Author(s): Sylvain Joyeux/sylvain.joyeux@m4x.org
autogenerated on Sat Jun 8 2019 18:49:22