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 utilmm;
00013 using namespace boost::filesystem;
00014
00015 namespace
00016 {
00017 using namespace std;
00018
00019 template<typename Map, typename Object>
00020 bool add_plugin(Map& plugin_map, Object* object)
00021 { return (plugin_map.insert( make_pair(object->getName(), object) ).second); }
00022
00023 template<typename Object>
00024 Object* get_plugin( map<string, Object*> const& plugin_map, string const& name)
00025 {
00026 typename map<string, Object*>::const_iterator it = plugin_map.find(name);
00027 if (it == plugin_map.end())
00028 throw PluginNotFound();
00029 return it->second;
00030 }
00031
00032 template<typename Container>
00033 void clear(Container& container)
00034 {
00035 for (typename Container::iterator it = container.begin(); it != container.end(); ++it)
00036 delete it->second;
00037 container.clear();
00038 }
00039 }
00040
00041 PluginManager::PluginManager()
00042 {
00043
00044 if (! exists(TYPELIB_PLUGIN_PATH))
00045 return;
00046 path plugin_dir(TYPELIB_PLUGIN_PATH);
00047
00048 directory_iterator end_it;
00049 for (directory_iterator it(plugin_dir); it != end_it; ++it)
00050 {
00051 if (it->path().extension() == ".so")
00052 #if BOOST_VERSION >= 104600
00053 loadPlugin(it->path().string());
00054 #else
00055 loadPlugin(it->path().file_string());
00056 #endif
00057 }
00058 }
00059
00060 PluginManager::~PluginManager()
00061 {
00062 clear(m_importers);
00063 clear(m_exporters);
00064 for (std::vector<TypeDefinitionPlugin*>::iterator it = m_definition_plugins.begin();
00065 it != m_definition_plugins.end(); ++it)
00066 delete *it;
00067 m_definition_plugins.clear();
00068
00069
00070 }
00071
00072 bool PluginManager::loadPlugin(std::string const& path)
00073 {
00074 void* libhandle = dlopen(path.c_str(), RTLD_LAZY);
00075 if (!libhandle)
00076 {
00077 cerr << "typelib: cannot load plugin " << path << ": " << dlerror() << endl;
00078 return false;
00079 }
00080
00081 void* libentry = dlsym(libhandle, "registerPlugins");
00082 if (!libentry)
00083 {
00084 cerr << "typelib: " << libentry << " does not seem to be a valid typelib plugin" << endl;
00085 return false;
00086 }
00087
00088 PluginEntryPoint function = reinterpret_cast<PluginEntryPoint>(libentry);
00089 function(*this);
00090 m_library_handles.push_back(libhandle);
00091 return true;
00092 }
00093
00094 bool PluginManager::add(ExportPlugin* plugin)
00095 { return add_plugin(m_exporters, plugin); }
00096 bool PluginManager::add(ImportPlugin* plugin)
00097 { return add_plugin(m_importers, plugin); }
00098 void PluginManager::add(TypeDefinitionPlugin* plugin)
00099 { return m_definition_plugins.push_back(plugin); }
00100
00101 void PluginManager::registerPluginTypes(Registry& registry)
00102 {
00103 for (vector<TypeDefinitionPlugin*>::iterator it = m_definition_plugins.begin();
00104 it != m_definition_plugins.end(); ++it)
00105 {
00106 (*it)->registerTypes(registry);
00107 }
00108 }
00109
00110 Importer* PluginManager::importer(std::string const& name) const
00111 { return get_plugin(m_importers, name)->create(); }
00112 Exporter* PluginManager::exporter(std::string const& name) const
00113 { return get_plugin(m_exporters, name)->create(); }
00114
00115
00116 std::string PluginManager::save(std::string const& kind, Registry const& registry)
00117 {
00118 utilmm::config_set config;
00119 return save(kind, config, registry);
00120 }
00121
00122 std::string PluginManager::save(std::string const& kind, utilmm::config_set const& config, Registry const& registry)
00123 {
00124 ostringstream stream;
00125 save(kind, config, registry, stream);
00126 return stream.str();
00127 }
00128 void PluginManager::save(std::string const& kind, Registry const& registry, std::ostream& into)
00129 {
00130 utilmm::config_set config;
00131 save(kind, config, registry, into);
00132 }
00133 void PluginManager::save(std::string const& kind, utilmm::config_set const& config, Registry const& registry, std::ostream& into)
00134 {
00135 auto_ptr<Exporter> exporter(PluginManager::self()->exporter(kind));
00136 exporter->save(into, config, registry);
00137 }
00138
00139 Registry* PluginManager::load(std::string const& kind, std::istream& stream)
00140 {
00141 utilmm::config_set config;
00142 return load(kind, stream, config);
00143 }
00144 void PluginManager::load(std::string const& kind, std::istream& stream, Registry& into )
00145 {
00146 utilmm::config_set config;
00147 return load(kind, stream, config, into);
00148 }
00149 Registry* PluginManager::load(std::string const& kind, std::string const& file)
00150 {
00151 utilmm::config_set config;
00152 return load(kind, file, config);
00153 }
00154 void PluginManager::load(std::string const& kind, std::string const& file, Registry& into)
00155 {
00156 utilmm::config_set config;
00157 return load(kind, file, config, into);
00158 }
00159
00160 Registry* PluginManager::load(std::string const& kind, std::istream& stream, utilmm::config_set const& config )
00161 {
00162 auto_ptr<Registry> registry(new Registry);
00163 load(kind, stream, config, *registry.get());
00164 return registry.release();
00165 }
00166 void PluginManager::load(std::string const& kind, std::istream& stream, utilmm::config_set const& config
00167 , Registry& into )
00168 {
00169 std::auto_ptr<Importer> importer(PluginManager::self()->importer(kind));
00170 importer->load(stream, config, into);
00171 }
00172 Registry* PluginManager::load(std::string const& kind, std::string const& file, utilmm::config_set const& config)
00173 {
00174 auto_ptr<Registry> registry(new Registry);
00175 load(kind, file, config, *registry.get());
00176 return registry.release();
00177 }
00178 void PluginManager::load(std::string const& kind, std::string const& file, utilmm::config_set const& config
00179 , Registry& into)
00180 {
00181 auto_ptr<Importer> importer(PluginManager::self()->importer(kind));
00182 importer->load(file, config, into);
00183 }
00184