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
00043 if (const char* pluginPath = getenv("TYPELIB_PLUGIN_PATH")) {
00044
00045 const std::string delim(":");
00046
00047 std::string s(pluginPath);
00048
00049 if (s.find_last_of(delim) != s.length())
00050 s += ":";
00051
00052 size_t pos = s.find(delim);
00053 do {
00054
00055 loadPluginFromDirectory(s.substr(0,pos));
00056
00057 s.erase(0, pos + delim.length());
00058
00059 } while ((pos = s.find(delim)) != std::string::npos);
00060 }
00061
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
00080
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