27 #include "../common/STLUtils.h"
28 #include "../common/TerraLib.h"
29 #include "../common/Translator.h"
44 #include <boost/graph/adjacency_list.hpp>
45 #include <boost/graph/properties.hpp>
46 #include <boost/graph/exception.hpp>
47 #include <boost/graph/topological_sort.hpp>
48 #include <boost/format.hpp>
49 #include <boost/filesystem.hpp>
51 std::vector<std::string>
54 std::vector<std::string> plugins;
57 for(std::vector<AbstractPlugin*>::const_iterator it =
m_plugins.begin(); it !=
m_plugins.end(); ++it)
58 plugins.push_back((*it)->getInfo().m_name);
62 plugins.push_back(it->m_name);
66 plugins.push_back(it->m_name);
75 std::map<std::string, AbstractPlugin*>::const_iterator it = m_pluginsMap.find(name);
77 if(it != m_pluginsMap.end())
78 return it->second->getInfo();
82 for(boost::ptr_vector<PluginInfo>::const_iterator it = m_unloadedPlugins.begin(); it != m_unloadedPlugins.end(); ++it)
83 if(it->m_name == name)
87 for(boost::ptr_vector<PluginInfo>::const_iterator it = m_brokenPlugins.begin(); it != m_brokenPlugins.end(); ++it)
88 if(it->m_name == name)
91 throw Exception((boost::format(
"Could not find plugin %1%") % name).str());
96 return m_unloadedPlugins;
101 return m_brokenPlugins;
106 for(boost::ptr_vector<PluginInfo>::const_iterator it = m_brokenPlugins.begin(); it != m_brokenPlugins.end(); ++it)
107 if(it->m_name == pluginName)
115 for(boost::ptr_vector<PluginInfo>::const_iterator it = m_unloadedPlugins.begin(); it != m_unloadedPlugins.end(); ++it)
116 if(it->m_name == pluginName)
124 return m_pluginsMap.find(pname) != m_pluginsMap.end();
132 boost::ptr_vector<PluginInfo> plugins;
135 if(m_unloadedPlugins.empty())
138 if(m_finders.empty())
145 const std::size_t nfinders = m_finders.size();
147 for(std::size_t i = 0; i < nfinders; ++i)
148 m_finders[i]->getPlugins(plugins);
154 plugins = m_unloadedPlugins;
157 load(plugins, start);
163 std::vector<AbstractPlugin*>::reverse_iterator it = m_plugins.rbegin();
165 while(it != m_plugins.rend())
167 std::auto_ptr<PluginInfo> pinfo(
new PluginInfo((*it)->getInfo()));
169 m_unloadedPlugins.push_back(pinfo.release());
170 it = m_plugins.rbegin();
174 assert(m_pluginCategoryMap.empty());
175 assert(m_plugins.empty());
176 assert(m_pluginsMap.empty());
182 m_unloadedPlugins.clear();
183 m_brokenPlugins.clear();
190 bool hasException =
false;
192 const std::size_t nplugins = plugins.size();
194 std::string exceptionPlugins;
196 for(std::size_t i = 0; i < nplugins; ++i)
207 exceptionPlugins +=
"\n" + pInfo.
m_name;
211 if(hasException || !m_brokenPlugins.empty())
212 throw Exception(
TE_TR(
"\n\nPlugins not loaded:" ) + exceptionPlugins);
217 if(isLoaded(pInfo.
m_name))
218 throw Exception((boost::format(
"Plugin %1% is already loaded") % pInfo.
m_name).str());
223 moveToBrokenList(pInfo);
224 throw Exception(
TE_TR(
"A required plugin is not loaded!"));
227 std::auto_ptr<AbstractPlugin> plugin;
239 if(engine.get() == 0)
240 throw Exception((boost::format(
"Could not determine plugin's language type for %1%!") % pInfo.
m_name).str());
242 plugin.reset(engine->load(pInfo));
244 if(plugin.get() == 0)
245 throw Exception((boost::format(
"Could not load plugin %1%!") % pInfo.
m_name).str());
247 catch(
const std::exception& e)
249 moveToBrokenList(pInfo);
250 Exception ee(e.what());
255 moveToBrokenList(pInfo);
267 for(std::size_t i = nmodules; i < nnmodules; ++i)
275 std::string plg_name = plugin->getInfo().m_name;
277 m_pluginCategoryMap[pInfo.
m_category].push_back(plugin.get());
278 m_plugins.push_back(plugin.get());
279 m_pluginsMap[plg_name] = plugin.release();
282 removeFromBrokenList(pInfo);
283 removeFromUnloadedList(pInfo);
285 updateDependents(plg_name);
287 catch(
const std::exception& e)
289 moveToBrokenList(pInfo);
290 Exception ee(e.what());
295 moveToBrokenList(pInfo);
302 load(getPlugin(pluginName));
307 std::map<std::string, AbstractPlugin*>::iterator it = m_pluginsMap.find(name);
309 if(it == m_pluginsMap.end())
310 throw Exception((boost::format(
"Plugin %1% is not loaded!") % name).str());
315 throw Exception((boost::format(
"Plugin %1% is NULL!") % name).str());
326 if(hasDependents(pluginName))
327 moveDependentsToBrokenList(pluginName);
337 if(engine.get() == 0)
338 throw Exception((boost::format(
"Could not determine plugin %1% language type!") % pluginName).str());
342 engine->unload(plugin);
344 m_unloadedPlugins.push_back(pInfo);
347 removeFromCategory(plugin, pluginCategory);
350 std::vector<AbstractPlugin*>::iterator it = std::find(m_plugins.begin(), m_plugins.end(), plugin);
352 if(it != m_plugins.end())
357 std::map<std::string, AbstractPlugin*>::iterator it = m_pluginsMap.find(pluginName);
359 if(it != m_pluginsMap.end())
360 m_pluginsMap.erase(it);
367 std::vector<AbstractPlugin*>::reverse_iterator it = m_plugins.rbegin();
369 while(it != m_plugins.rend())
371 if((*it)->isStarted())
380 return m_pluginsMap.size() + m_unloadedPlugins.size() + m_brokenPlugins.size();
385 const std::size_t size = plugins.size();
387 for(std::size_t i = 0; i < size; ++i)
388 if(!isLoaded(plugins[i]))
406 m_unloadedPlugins.push_back(plugin);
427 if(isUnloadedPlugin(plugin))
429 removeFromUnloadedList(info);
433 removeFromBrokenList(info);
438 std::vector<std::string> dependents;
440 const std::size_t nplugins = m_plugins.size();
442 for(std::size_t i = 0; i < nplugins; ++i)
444 if(pluginName == m_plugins[i]->getInfo().m_name)
447 const std::vector<std::string>& requiredPlugins = m_plugins[i]->getInfo().m_requiredPlugins;
449 const std::size_t size = requiredPlugins.size();
451 for(std::size_t j = 0; j < size; ++j)
454 if(pluginName == requiredPlugins[j])
456 dependents.push_back(m_plugins[i]->getInfo().m_name);
467 return getDependents(pluginName).empty() ?
false :
true;
473 std::map<std::string, AbstractPlugin*>::iterator it = m_pluginsMap.find(name);
475 if(it == m_pluginsMap.end())
476 throw Exception((boost::format(
TE_TR(
"Could not find the given plugin (%1%) in order to detach it from PluginManager!")) % name).str());
481 throw Exception((boost::format(
TE_TR(
"Could not detach a NULL plugin (%1%) from PluginManager!")) % name).str());
484 if(hasDependents(name))
485 moveDependentsToBrokenList(name);
492 std::vector<AbstractPlugin*>::iterator itv = std::find(m_plugins.begin(), m_plugins.end(), p);
494 if(itv == m_plugins.end())
495 throw Exception(
TE_TR(
"PluginManager has lost the synchronization between its internal indexes!"));
497 m_plugins.erase(itv);
499 m_pluginsMap.erase(name);
507 std::map<std::string, std::vector<AbstractPlugin*> >::const_iterator it = m_pluginCategoryMap.begin();
509 while(it != m_pluginCategoryMap.end())
511 categories.push_back(it->first);
519 std::map<std::string, std::vector<AbstractPlugin*> >::iterator it = m_pluginCategoryMap.find(name);
521 if(it == m_pluginCategoryMap.end())
523 std::vector<AbstractPlugin*> vec;
524 m_pluginCategoryMap.insert(std::map<std::string, std::vector<AbstractPlugin*> >::value_type(name, vec));
531 std::map<std::string, std::size_t> newPluginsMap;
533 const std::size_t nplugins = plugins.size();
535 for(std::size_t i = 0; i < nplugins; ++i)
536 newPluginsMap.insert(std::make_pair(plugins[i].m_name, i));
539 std::map<std::string, std::size_t>::const_iterator itend = newPluginsMap.end();
542 typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS> Graph;
543 typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
547 for(std::size_t i = 0; i < nplugins; ++i)
548 boost::add_vertex(dgraph);
550 for(std::size_t i = 0; i < nplugins; ++i)
552 const std::vector<std::string>& requiredPlugins = plugins[i].m_requiredPlugins;
554 const std::size_t nrequiredplugins = requiredPlugins.size();
556 for(std::size_t j = 0; j < nrequiredplugins; ++j)
558 std::map<std::string, std::size_t>::const_iterator it = newPluginsMap.find(requiredPlugins[j]);
563 boost::add_edge(it->second, i, dgraph);
569 std::vector<Vertex> toposortResult;
571 boost::topological_sort(dgraph, std::back_inserter(toposortResult));
574 boost::ptr_vector<PluginInfo> pluginsTemp;
576 for(std::vector<Vertex>::reverse_iterator it = toposortResult.rbegin(); it != toposortResult.rend(); ++it)
577 pluginsTemp.push_back(
new PluginInfo(plugins[*it]));
579 plugins = pluginsTemp;
584 std::map<std::string, std::vector<AbstractPlugin*> >::iterator it = m_pluginCategoryMap.find(category);
586 if(it == m_pluginCategoryMap.end())
589 std::vector<AbstractPlugin*>& plugins = it->second;
591 const std::size_t size = plugins.size();
593 for(std::size_t i = 0; i < size; ++i)
595 if(plugin == plugins[i])
597 plugins.erase(plugins.begin() + i);
600 m_pluginCategoryMap.erase(it);
609 removeFromUnloadedList(pInfo);
610 removeFromBrokenList(pInfo);
613 m_brokenPlugins.push_back(
new PluginInfo(pInfo));
618 for(boost::ptr_vector<PluginInfo>::iterator it = m_brokenPlugins.begin(); it != m_brokenPlugins.end(); ++it)
620 if(pInfo.
m_name == it->m_name)
622 m_brokenPlugins.erase(it);
630 for(boost::ptr_vector<PluginInfo>::iterator it = m_unloadedPlugins.begin(); it != m_unloadedPlugins.end(); ++it)
632 if(pInfo.
m_name == it->m_name)
634 m_unloadedPlugins.erase(it);
642 if(isBrokenPlugin(plugin))
645 std::vector<std::string> deps = getDependents(plugin);
649 std::vector<std::string>::iterator it;
651 for(it=deps.begin(); it!=deps.end(); ++it)
652 moveDependentsToBrokenList(*it,
true);
662 moveToBrokenList(info);
668 boost::ptr_vector<PluginInfo> deps = getBrokenPlugins();
672 boost::ptr_vector<PluginInfo>::iterator it;
673 std::vector<PluginInfo*> toUpdate;
675 for(it=deps.begin(); it!=deps.end(); ++it)
676 if(isLoaded((*it).m_requiredPlugins))
679 std::vector<PluginInfo*>::iterator it2;
680 for(it2=toUpdate.begin(); it2 != toUpdate.end(); ++it2)
682 removeFromBrokenList(*(*it2));
683 m_unloadedPlugins.push_back(*it2);
This is the abstract factory for plugin engines.
void moveDependentsToBrokenList(const std::string &plugin, const bool &unloadPlugin=false)
void moveToBrokenList(const PluginInfo &pInfo)
std::string m_name
The plugin name: an internal value used to identify the plugin in the system. Must be a unique value...
virtual const PluginInfo & getInfo() const =0
It return the information associated to the plugin.
void shutdownAll()
It try to shutdown all plugins.
std::vector< std::string > m_requiredPlugins
The list of required plugins in order to lunch the plugin.
void remove(const std::string &plugin)
PluginManager()
It creates a new plugin.
An abstract class for TerraLib Plugins.
A plugin finder that search for plugins in some special directories defined by compile time macros...
void addCategory(const std::string &name)
Add a new category type.
virtual bool isStarted() const =0
It tells if the plugin was started or not.
void removeFromCategory(AbstractPlugin *plugin, const std::string &category)
It removes the given plugin from the category and then updates the internal category index...
void unloadAll()
It try to unload all plugins.
bool hasDependents(const std::string &pluginName) const
If there is a plugin that depends on the informed plugin it returns true, otherwise, if no plugin depends on it, return false.
void add(const PluginInfo &plugin)
Adds plug-in to unload list.
boost::ptr_vector< PluginInfo > m_brokenPlugins
The list of plugins that could not be loaded.
std::vector< AbstractPlugin * > m_plugins
The list of managed plugins: this will be need to unload accordinly the plugins!
~PluginManager()
Singleton destructor.
void updateDependents(const std::string &plugin)
The AbstractFinder class allows applications to extend how PluginManager can search for plugins...
#define TE_TR(message)
It marks a string in order to get translated.
void load(boost::ptr_vector< PluginInfo > &plugins, const bool start=true)
It tries to load all informed plugins.
void removeFromUnloadedList(const PluginInfo &pInfo)
boost::ptr_vector< PluginInfo > m_unloadedPlugins
The list of plugins that are not loaded.
An abstract class for TerraLib Plugins.
std::string m_engine
The type of plugin execution engine: C++, JAVA.
std::size_t getNumRegModules() const
It returns the number of registered modules.
static TerraLib & getInstance()
It returns a reference to the singleton instance.
void removeFromBrokenList(const PluginInfo &pInfo)
An abstract class for plugin engines.
const boost::ptr_vector< PluginInfo > & getUnloadedPlugins() const
It returns the list of plugins that are not loaded.
virtual void shutdown()=0
This method will be called by TerraLib to shutdown plugin's functionality.
void clear()
Unload all plugins and them clear the internal list.
void sort(boost::ptr_vector< PluginInfo > &plugins) const
It sorts the plugins according to their dependency.
void getCategories(std::vector< std::string > &categories) const
Get plugins category types.
std::vector< std::string > getPlugins() const
It returns the list of plugins managed by PluginManager.
AbstractPlugin * detach(const std::string &pluginName)
It detaches the given plugin from the list of loaded plugins.
bool isUnloadedPlugin(const std::string &pluginName) const
It returns true if the plugin is in the not-loaded list of plugins.
static AbstractPluginEngine * make(const std::string &factoryKey)
It creates an object with the appropriated factory.
void initialize()
It initializes the TerraLib Platform.
A plugin finder that search for plugins in some special directories defined by compile time macros...
const boost::ptr_vector< PluginInfo > & getBrokenPlugins() const
It returns the list of plugins that could not be loaded.
std::size_t getNumPlugins() const
It returns the number of plugins kept in the manager.
const PluginInfo & getPlugin(const std::string &name) const
It returns the plugin identified by the given name.
void loadAll(const bool start=true)
It loads all the plugins in the not-loaded list or searchs for installed plugin with installed finder...
A singleton for managing plugins.
bool isBrokenPlugin(const std::string &pluginName) const
It returns true if the plugin is in the broken list of plugins.
bool isLoaded(const std::string &pname) const
It returns true if the plugin is loaded otherwise returns false.
std::vector< std::string > getDependents(const std::string &pluginName) const
It searches for all plugins that depends on the given plugin.
The basic information about a plugin.
The basic information about a plugin.
void getPlugins(boost::ptr_vector< PluginInfo > &plugins)
This method searches for installed plugins and output the plugins information in the PluginInfo vecto...
void FreeContents(boost::unordered_map< K, V * > &m)
This function can be applied to a map of pointers. It will delete each pointer in the map...
std::string m_category
The plugin category.
void unload(const std::string &name)
It tries to unload a given plugin.