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 m_unloadedPlugins = unloadedPlugins;
106 return m_brokenPlugins;
111 m_brokenPlugins = brokenPlugins;
116 for(boost::ptr_vector<PluginInfo>::const_iterator it = m_brokenPlugins.begin(); it != m_brokenPlugins.end(); ++it)
117 if(it->m_name == pluginName)
125 for(boost::ptr_vector<PluginInfo>::const_iterator it = m_unloadedPlugins.begin(); it != m_unloadedPlugins.end(); ++it)
126 if(it->m_name == pluginName)
134 return m_pluginsMap.find(pname) != m_pluginsMap.end();
142 boost::ptr_vector<PluginInfo> plugins;
145 if(m_unloadedPlugins.empty())
148 if(m_finders.empty())
155 const std::size_t nfinders = m_finders.size();
157 for(std::size_t i = 0; i < nfinders; ++i)
158 m_finders[i]->getPlugins(plugins);
164 plugins = m_unloadedPlugins;
167 load(plugins, start);
173 std::vector<AbstractPlugin*>::reverse_iterator it = m_plugins.rbegin();
175 while(it != m_plugins.rend())
177 std::auto_ptr<PluginInfo> pinfo(
new PluginInfo((*it)->getInfo()));
179 m_unloadedPlugins.push_back(pinfo.release());
180 it = m_plugins.rbegin();
184 assert(m_pluginCategoryMap.empty());
185 assert(m_plugins.empty());
186 assert(m_pluginsMap.empty());
192 m_unloadedPlugins.clear();
193 m_brokenPlugins.clear();
200 bool hasException =
false;
202 const std::size_t nplugins = plugins.size();
204 std::string exceptionPlugins;
206 for(std::size_t i = 0; i < nplugins; ++i)
217 exceptionPlugins +=
"\n" + pInfo.
m_name;
221 if(hasException || !m_brokenPlugins.empty())
222 throw Exception(
TE_TR(
"\n\nPlugins not loaded:" ) + exceptionPlugins);
227 if(isLoaded(pInfo.
m_name))
228 throw Exception((boost::format(
"Plugin %1% is already loaded") % pInfo.
m_name).str());
233 moveToBrokenList(pInfo);
234 throw Exception(
TE_TR(
"A required plugin is not loaded!"));
237 std::auto_ptr<AbstractPlugin> plugin;
249 if(engine.get() == 0)
250 throw Exception((boost::format(
"Could not determine plugin's language type for %1%!") % pInfo.
m_name).str());
252 plugin.reset(engine->load(pInfo));
254 if(plugin.get() == 0)
255 throw Exception((boost::format(
"Could not load plugin %1%!") % pInfo.
m_name).str());
257 catch(
const std::exception& e)
259 moveToBrokenList(pInfo);
260 Exception ee(e.what());
265 moveToBrokenList(pInfo);
277 for(std::size_t i = nmodules; i < nnmodules; ++i)
285 std::string plg_name = plugin->getInfo().m_name;
287 m_pluginCategoryMap[pInfo.
m_category].push_back(plugin.get());
288 m_plugins.push_back(plugin.get());
289 m_pluginsMap[plg_name] = plugin.release();
292 removeFromBrokenList(pInfo);
293 removeFromUnloadedList(pInfo);
295 updateDependents(plg_name);
297 catch(
const std::exception& e)
299 moveToBrokenList(pInfo);
300 Exception ee(e.what());
305 moveToBrokenList(pInfo);
312 load(getPlugin(pluginName));
317 std::map<std::string, AbstractPlugin*>::iterator it = m_pluginsMap.find(name);
319 if(it == m_pluginsMap.end())
320 throw Exception((boost::format(
"Plugin %1% is not loaded!") % name).str());
325 throw Exception((boost::format(
"Plugin %1% is NULL!") % name).str());
336 if(hasDependents(pluginName))
337 moveDependentsToBrokenList(pluginName);
347 if(engine.get() == 0)
348 throw Exception((boost::format(
"Could not determine plugin %1% language type!") % pluginName).str());
352 engine->unload(plugin);
354 m_unloadedPlugins.push_back(pInfo);
357 removeFromCategory(plugin, pluginCategory);
360 std::vector<AbstractPlugin*>::iterator it = std::find(m_plugins.begin(), m_plugins.end(), plugin);
362 if(it != m_plugins.end())
367 std::map<std::string, AbstractPlugin*>::iterator it = m_pluginsMap.find(pluginName);
369 if(it != m_pluginsMap.end())
370 m_pluginsMap.erase(it);
377 std::vector<AbstractPlugin*>::reverse_iterator it = m_plugins.rbegin();
379 while(it != m_plugins.rend())
381 if((*it)->isStarted())
390 return m_pluginsMap.size() + m_unloadedPlugins.size() + m_brokenPlugins.size();
395 const std::size_t size = plugins.size();
397 for(std::size_t i = 0; i < size; ++i)
398 if(!isLoaded(plugins[i]))
416 m_unloadedPlugins.push_back(plugin);
437 if(isUnloadedPlugin(plugin))
439 removeFromUnloadedList(info);
443 removeFromBrokenList(info);
448 std::vector<std::string> dependents;
450 const std::size_t nplugins = m_plugins.size();
452 for(std::size_t i = 0; i < nplugins; ++i)
454 if(pluginName == m_plugins[i]->getInfo().m_name)
457 const std::vector<std::string>& requiredPlugins = m_plugins[i]->getInfo().m_requiredPlugins;
459 const std::size_t size = requiredPlugins.size();
461 for(std::size_t j = 0; j < size; ++j)
464 if(pluginName == requiredPlugins[j])
466 dependents.push_back(m_plugins[i]->getInfo().m_name);
477 return getDependents(pluginName).empty() ?
false :
true;
483 std::map<std::string, AbstractPlugin*>::iterator it = m_pluginsMap.find(name);
485 if(it == m_pluginsMap.end())
486 throw Exception((boost::format(
TE_TR(
"Could not find the given plugin (%1%) in order to detach it from PluginManager!")) % name).str());
491 throw Exception((boost::format(
TE_TR(
"Could not detach a NULL plugin (%1%) from PluginManager!")) % name).str());
494 if(hasDependents(name))
495 moveDependentsToBrokenList(name);
502 std::vector<AbstractPlugin*>::iterator itv = std::find(m_plugins.begin(), m_plugins.end(), p);
504 if(itv == m_plugins.end())
505 throw Exception(
TE_TR(
"PluginManager has lost the synchronization between its internal indexes!"));
507 m_plugins.erase(itv);
509 m_pluginsMap.erase(name);
517 std::map<std::string, std::vector<AbstractPlugin*> >::const_iterator it = m_pluginCategoryMap.begin();
519 while(it != m_pluginCategoryMap.end())
521 categories.push_back(it->first);
529 std::map<std::string, std::vector<AbstractPlugin*> >::iterator it = m_pluginCategoryMap.find(name);
531 if(it == m_pluginCategoryMap.end())
533 std::vector<AbstractPlugin*> vec;
534 m_pluginCategoryMap.insert(std::map<std::string, std::vector<AbstractPlugin*> >::value_type(name, vec));
541 std::map<std::string, std::size_t> newPluginsMap;
543 const std::size_t nplugins = plugins.size();
545 for(std::size_t i = 0; i < nplugins; ++i)
546 newPluginsMap.insert(std::make_pair(plugins[i].m_name, i));
549 std::map<std::string, std::size_t>::const_iterator itend = newPluginsMap.end();
552 typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS> Graph;
553 typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
557 for(std::size_t i = 0; i < nplugins; ++i)
558 boost::add_vertex(dgraph);
560 for(std::size_t i = 0; i < nplugins; ++i)
562 const std::vector<std::string>& requiredPlugins = plugins[i].m_requiredPlugins;
564 const std::size_t nrequiredplugins = requiredPlugins.size();
566 for(std::size_t j = 0; j < nrequiredplugins; ++j)
568 std::map<std::string, std::size_t>::const_iterator it = newPluginsMap.find(requiredPlugins[j]);
573 boost::add_edge(it->second, i, dgraph);
579 std::vector<Vertex> toposortResult;
581 boost::topological_sort(dgraph, std::back_inserter(toposortResult));
584 boost::ptr_vector<PluginInfo> pluginsTemp;
586 for(std::vector<Vertex>::reverse_iterator it = toposortResult.rbegin(); it != toposortResult.rend(); ++it)
587 pluginsTemp.push_back(
new PluginInfo(plugins[*it]));
589 plugins = pluginsTemp;
594 std::map<std::string, std::vector<AbstractPlugin*> >::iterator it = m_pluginCategoryMap.find(category);
596 if(it == m_pluginCategoryMap.end())
599 std::vector<AbstractPlugin*>& plugins = it->second;
601 const std::size_t size = plugins.size();
603 for(std::size_t i = 0; i < size; ++i)
605 if(plugin == plugins[i])
607 plugins.erase(plugins.begin() + i);
610 m_pluginCategoryMap.erase(it);
619 removeFromUnloadedList(pInfo);
620 removeFromBrokenList(pInfo);
623 m_brokenPlugins.push_back(
new PluginInfo(pInfo));
628 for(boost::ptr_vector<PluginInfo>::iterator it = m_brokenPlugins.begin(); it != m_brokenPlugins.end(); ++it)
630 if(pInfo.
m_name == it->m_name)
632 m_brokenPlugins.erase(it);
640 for(boost::ptr_vector<PluginInfo>::iterator it = m_unloadedPlugins.begin(); it != m_unloadedPlugins.end(); ++it)
642 if(pInfo.
m_name == it->m_name)
644 m_unloadedPlugins.erase(it);
652 if(isBrokenPlugin(plugin))
655 std::vector<std::string> deps = getDependents(plugin);
659 std::vector<std::string>::iterator it;
661 for(it=deps.begin(); it!=deps.end(); ++it)
662 moveDependentsToBrokenList(*it,
true);
672 moveToBrokenList(info);
678 boost::ptr_vector<PluginInfo> deps = getBrokenPlugins();
682 boost::ptr_vector<PluginInfo>::iterator it;
683 std::vector<PluginInfo*> toUpdate;
685 for(it=deps.begin(); it!=deps.end(); ++it)
686 if(isLoaded((*it).m_requiredPlugins))
689 std::vector<PluginInfo*>::iterator it2;
690 for(it2=toUpdate.begin(); it2 != toUpdate.end(); ++it2)
692 removeFromBrokenList(*(*it2));
693 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.
void setUnloadedPlugins(boost::ptr_vector< te::plugin::PluginInfo > unloadedPlugins)
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.
void setBrokenPlugins(boost::ptr_vector< te::plugin::PluginInfo > brokenPlugins)
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.