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>
54 for(std::vector<AbstractPlugin*>::const_iterator it =
m_plugins.begin(); it !=
m_plugins.end(); ++it)
55 plugins.push_back((*it)->getInfo().m_name);
59 plugins.push_back(it->m_name);
63 plugins.push_back(it->m_name);
70 std::map<std::string, AbstractPlugin*>::const_iterator it = m_pluginsMap.find(name);
72 if(it != m_pluginsMap.end())
73 return it->second->getInfo();
77 for(boost::ptr_vector<PluginInfo>::const_iterator it = m_unloadedPlugins.begin(); it != m_unloadedPlugins.end(); ++it)
78 if(it->m_name == name)
82 for(boost::ptr_vector<PluginInfo>::const_iterator it = m_brokenPlugins.begin(); it != m_brokenPlugins.end(); ++it)
83 if(it->m_name == name)
86 throw Exception((boost::format(
"Could not find plugin %1%") % name).str());
91 return m_unloadedPlugins;
96 return m_brokenPlugins;
101 for(boost::ptr_vector<PluginInfo>::const_iterator it = m_brokenPlugins.begin(); it != m_brokenPlugins.end(); ++it)
102 if(it->m_name == pluginName)
110 for(boost::ptr_vector<PluginInfo>::const_iterator it = m_unloadedPlugins.begin(); it != m_unloadedPlugins.end(); ++it)
111 if(it->m_name == pluginName)
119 return m_pluginsMap.find(pname) != m_pluginsMap.end();
127 boost::ptr_vector<PluginInfo> plugins;
130 if(m_unloadedPlugins.empty())
133 if(m_finders.empty())
140 const std::size_t nfinders = m_finders.size();
142 for(std::size_t i = 0; i < nfinders; ++i)
143 m_finders[i]->getPlugins(plugins);
149 plugins = m_unloadedPlugins;
152 load(plugins, start);
158 std::vector<AbstractPlugin*>::reverse_iterator it = m_plugins.rbegin();
160 while(it != m_plugins.rend())
162 std::auto_ptr<PluginInfo> pinfo(
new PluginInfo((*it)->getInfo()));
164 m_unloadedPlugins.push_back(pinfo.release());
165 it = m_plugins.rbegin();
169 assert(m_pluginCategoryMap.empty());
170 assert(m_plugins.empty());
171 assert(m_pluginsMap.empty());
177 m_unloadedPlugins.clear();
178 m_brokenPlugins.clear();
185 bool hasException =
false;
187 const std::size_t nplugins = plugins.size();
189 std::string exceptionPlugins;
191 for(std::size_t i = 0; i < nplugins; ++i)
202 exceptionPlugins +=
"\n" + pInfo.
m_name;
206 if(hasException || !m_brokenPlugins.empty())
207 throw Exception(
TR_PLUGIN(
"\n\nPlugins not loaded:" ) + exceptionPlugins);
216 if( internalPInfo.
m_folder.empty() ||
217 (!boost::filesystem::is_directory(internalPInfo.
m_folder)) )
219 boost::ptr_vector<PluginInfo> pluginsInfos;
221 if(m_finders.empty())
226 for( boost::ptr_vector<PluginInfo>::size_type pIdx = 0; pIdx <
227 pluginsInfos.size() ; ++pIdx )
229 if( pluginsInfos[ pIdx ].m_name == internalPInfo.
m_name )
231 internalPInfo.
m_folder = pluginsInfos[ pIdx ].m_folder;
238 const std::size_t nfinders = m_finders.size();
240 for(std::size_t i = 0; i < nfinders; ++i)
242 pluginsInfos.clear();
244 m_finders[i]->getPlugins(pluginsInfos);
246 for( boost::ptr_vector<PluginInfo>::size_type pIdx = 0; pIdx <
247 pluginsInfos.size() ; ++pIdx )
249 if( pluginsInfos[ pIdx ].m_name == internalPInfo.
m_name )
251 internalPInfo.
m_folder = pluginsInfos[ pIdx ].m_folder;
262 if(isLoaded(internalPInfo.
m_name))
263 throw Exception((boost::format(
"Plugin %1% is already loaded") % internalPInfo.
m_name).str());
268 moveToBrokenList(internalPInfo);
269 throw Exception(
TR_PLUGIN(
"A required plugin is not loaded!"));
272 std::auto_ptr<AbstractPlugin> plugin;
284 if(engine.get() == 0)
285 throw Exception((boost::format(
"Could not determine plugin's language type for %1%!") % internalPInfo.
m_name).str());
287 plugin.reset(engine->load(internalPInfo));
289 if(plugin.get() == 0)
290 throw Exception((boost::format(
"Could not load plugin %1%!") % internalPInfo.
m_name).str());
292 catch(
const std::exception& e)
294 moveToBrokenList(internalPInfo);
295 Exception ee(e.what());
300 moveToBrokenList(internalPInfo);
312 for(std::size_t i = nmodules; i < nnmodules; ++i)
320 std::string plg_name = plugin->getInfo().m_name;
322 m_pluginCategoryMap[internalPInfo.
m_category].push_back(plugin.get());
323 m_plugins.push_back(plugin.get());
324 m_pluginsMap[plg_name] = plugin.release();
327 removeFromBrokenList(internalPInfo);
328 removeFromUnloadedList(internalPInfo);
330 updateDependents(plg_name);
332 catch(
const std::exception& e)
334 moveToBrokenList(internalPInfo);
335 Exception ee(e.what());
340 moveToBrokenList(internalPInfo);
347 load(getPlugin(pluginName));
352 std::map<std::string, AbstractPlugin*>::iterator it = m_pluginsMap.find(name);
354 if(it == m_pluginsMap.end())
355 throw Exception((boost::format(
"Plugin %1% is not loaded!") % name).str());
360 throw Exception((boost::format(
"Plugin %1% is NULL!") % name).str());
371 if(hasDependents(pluginName))
372 moveDependentsToBrokenList(pluginName);
382 if(engine.get() == 0)
383 throw Exception((boost::format(
"Could not determine plugin %1% language type!") % pluginName).str());
387 engine->unload(plugin);
389 m_unloadedPlugins.push_back(pInfo);
392 removeFromCategory(plugin, pluginCategory);
395 std::vector<AbstractPlugin*>::iterator it = std::find(m_plugins.begin(), m_plugins.end(), plugin);
397 if(it != m_plugins.end())
402 std::map<std::string, AbstractPlugin*>::iterator it = m_pluginsMap.find(pluginName);
404 if(it != m_pluginsMap.end())
405 m_pluginsMap.erase(it);
412 std::vector<AbstractPlugin*>::reverse_iterator it = m_plugins.rbegin();
414 while(it != m_plugins.rend())
416 if((*it)->isStarted())
425 return m_pluginsMap.size() + m_unloadedPlugins.size() + m_brokenPlugins.size();
430 const std::size_t size = plugins.size();
432 for(std::size_t i = 0; i < size; ++i)
433 if(!isLoaded(plugins[i]))
451 m_unloadedPlugins.push_back(plugin);
472 if(isUnloadedPlugin(plugin))
474 removeFromUnloadedList(info);
478 removeFromBrokenList(info);
483 std::vector<std::string> dependents;
485 const std::size_t nplugins = m_plugins.size();
487 for(std::size_t i = 0; i < nplugins; ++i)
489 if(pluginName == m_plugins[i]->getInfo().m_name)
492 const std::vector<std::string>& requiredPlugins = m_plugins[i]->getInfo().m_requiredPlugins;
494 const std::size_t size = requiredPlugins.size();
496 for(std::size_t j = 0; j < size; ++j)
499 if(pluginName == requiredPlugins[j])
501 dependents.push_back(m_plugins[i]->getInfo().m_name);
512 return getDependents(pluginName).empty() ?
false :
true;
518 std::map<std::string, AbstractPlugin*>::iterator it = m_pluginsMap.find(name);
520 if(it == m_pluginsMap.end())
521 throw Exception((boost::format(
TR_PLUGIN(
"Could not find the given plugin (%1%) in order to detach it from PluginManager!")) % name).str());
526 throw Exception((boost::format(
TR_PLUGIN(
"Could not detach a NULL plugin (%1%) from PluginManager!")) % name).str());
529 if(hasDependents(name))
530 moveDependentsToBrokenList(name);
537 std::vector<AbstractPlugin*>::iterator itv = std::find(m_plugins.begin(), m_plugins.end(), p);
539 if(itv == m_plugins.end())
540 throw Exception(
TR_PLUGIN(
"PluginManager has lost the synchronization between its internal indexes!"));
542 m_plugins.erase(itv);
544 m_pluginsMap.erase(name);
552 std::map<std::string, std::vector<AbstractPlugin*> >::const_iterator it = m_pluginCategoryMap.begin();
554 while(it != m_pluginCategoryMap.end())
556 categories.push_back(it->first);
564 std::map<std::string, std::vector<AbstractPlugin*> >::iterator it = m_pluginCategoryMap.find(name);
566 if(it == m_pluginCategoryMap.end())
568 std::vector<AbstractPlugin*> vec;
569 m_pluginCategoryMap.insert(std::map<std::string, std::vector<AbstractPlugin*> >::value_type(name, vec));
576 std::map<std::string, std::size_t> newPluginsMap;
578 const std::size_t nplugins = plugins.size();
580 for(std::size_t i = 0; i < nplugins; ++i)
581 newPluginsMap.insert(std::make_pair(plugins[i].m_name, i));
584 std::map<std::string, std::size_t>::const_iterator itend = newPluginsMap.end();
587 typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS> Graph;
588 typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
592 for(std::size_t i = 0; i < nplugins; ++i)
593 boost::add_vertex(dgraph);
595 for(std::size_t i = 0; i < nplugins; ++i)
597 const std::vector<std::string>& requiredPlugins = plugins[i].m_requiredPlugins;
599 const std::size_t nrequiredplugins = requiredPlugins.size();
601 for(std::size_t j = 0; j < nrequiredplugins; ++j)
603 std::map<std::string, std::size_t>::const_iterator it = newPluginsMap.find(requiredPlugins[j]);
608 boost::add_edge(it->second, i, dgraph);
614 std::vector<Vertex> toposortResult;
616 boost::topological_sort(dgraph, std::back_inserter(toposortResult));
619 boost::ptr_vector<PluginInfo> pluginsTemp;
621 for(std::vector<Vertex>::reverse_iterator it = toposortResult.rbegin(); it != toposortResult.rend(); ++it)
622 pluginsTemp.push_back(
new PluginInfo(plugins[*it]));
624 plugins = pluginsTemp;
629 std::map<std::string, std::vector<AbstractPlugin*> >::iterator it = m_pluginCategoryMap.find(category);
631 if(it == m_pluginCategoryMap.end())
634 std::vector<AbstractPlugin*>& plugins = it->second;
636 const std::size_t size = plugins.size();
638 for(std::size_t i = 0; i < size; ++i)
640 if(plugin == plugins[i])
642 plugins.erase(plugins.begin() + i);
645 m_pluginCategoryMap.erase(it);
654 removeFromUnloadedList(pInfo);
655 removeFromBrokenList(pInfo);
658 m_brokenPlugins.push_back(
new PluginInfo(pInfo));
663 for(boost::ptr_vector<PluginInfo>::iterator it = m_brokenPlugins.begin(); it != m_brokenPlugins.end(); ++it)
665 if(pInfo.
m_name == it->m_name)
667 m_brokenPlugins.erase(it);
675 for(boost::ptr_vector<PluginInfo>::iterator it = m_unloadedPlugins.begin(); it != m_unloadedPlugins.end(); ++it)
677 if(pInfo.
m_name == it->m_name)
679 m_unloadedPlugins.erase(it);
687 if(isBrokenPlugin(plugin))
690 std::vector<std::string> deps = getDependents(plugin);
694 std::vector<std::string>::iterator it;
696 for(it=deps.begin(); it!=deps.end(); ++it)
697 moveDependentsToBrokenList(*it,
true);
707 moveToBrokenList(info);
713 boost::ptr_vector<PluginInfo> deps = getBrokenPlugins();
717 boost::ptr_vector<PluginInfo>::iterator it;
718 std::vector<PluginInfo*> toUpdate;
720 for(it=deps.begin(); it!=deps.end(); ++it)
721 if(isLoaded((*it).m_requiredPlugins))
724 std::vector<PluginInfo*>::iterator it2;
725 for(it2=toUpdate.begin(); it2 != toUpdate.end(); ++it2)
727 removeFromBrokenList(*(*it2));
728 m_unloadedPlugins.push_back(*it2);
void updateDependents(const std::string &plugin)
boost::ptr_vector< PluginInfo > m_brokenPlugins
The list of plugins that could not be loaded.
const boost::ptr_vector< PluginInfo > & getUnloadedPlugins() const
It returns the list of plugins that are not loaded.
The basic information about a plugin.
void unloadAll()
It try to unload all plugins.
void removeFromUnloadedList(const PluginInfo &pInfo)
The basic information about a plugin.
An abstract class for TerraLib Plugins.
A plugin finder that search for plugins in some special directories defined by compile time macros...
std::vector< std::string > m_requiredPlugins
The list of required plugins in order to lunch the plugin.
#define TR_PLUGIN(message)
It marks a string in order to get translated. This is a special mark used in the Plugin module of Ter...
An abstract class for TerraLib Plugins.
boost::ptr_vector< PluginInfo > m_unloadedPlugins
The list of plugins that are not loaded.
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...
void unload(const std::string &name)
It tries to unload a given plugin.
virtual bool isStarted() const =0
It tells if the plugin was started or not.
void load(boost::ptr_vector< PluginInfo > &plugins, const bool start=true)
It tries to load all informed 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 remove(const std::string &plugin)
static AbstractPluginEngine * make(const std::string &factoryKey)
It creates an object with the appropriated factory.
std::size_t getNumRegModules() const
It returns the number of registered modules.
const boost::ptr_vector< PluginInfo > & getBrokenPlugins() const
It returns the list of plugins that could not be loaded.
void shutdownAll()
It try to shutdown all plugins.
void getPlugins(std::vector< std::string > &plugins) 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.
void sort(boost::ptr_vector< PluginInfo > &plugins) const
It sorts the plugins according to their dependency.
void clear()
Unload all plugins and them clear the internal list.
A plugin finder that search for plugins in some special directories defined by compile time macros...
A singleton for managing plugins.
void loadAll(const bool start=true)
It loads all the plugins in the not-loaded list or searchs for installed plugin with installed finder...
void moveToBrokenList(const PluginInfo &pInfo)
This is the abstract factory for plugin engines.
void addCategory(const std::string &name)
Add a new category type.
std::vector< AbstractPlugin * > m_plugins
The list of managed plugins: this will be need to unload accordinly the plugins!
void removeFromCategory(AbstractPlugin *plugin, const std::string &category)
It removes the given plugin from the category and then updates the internal category index...
std::vector< std::string > getDependents(const std::string &pluginName) const
It searches for all plugins that depends on the given plugin.
void moveDependentsToBrokenList(const std::string &plugin, const bool &unloadPlugin=false)
PluginManager()
It creates a new plugin.
virtual const PluginInfo & getInfo() const =0
It return the information associated to the plugin.
bool isBrokenPlugin(const std::string &pluginName) const
It returns true if the plugin is in the broken list of plugins.
void getCategories(std::vector< std::string > &categories) const
Get plugins category types.
void removeFromBrokenList(const PluginInfo &pInfo)
std::string m_engine
The type of plugin execution engine: C++, JAVA.
void add(const PluginInfo &plugin)
Adds plug-in to unload list.
static TerraLib & getInstance()
It returns a reference to the singleton instance.
std::string m_name
The plugin name: an internal value used to identify the plugin in the system. Must be a unique value...
std::size_t getNumPlugins() const
It returns the number of plugins kept in the manager.
The AbstractFinder class allows applications to extend how PluginManager can search for plugins...
std::string m_folder
The plugin folder (where the plugin is installed).
virtual void shutdown()=0
This method will be called by TerraLib to shutdown plugin's functionality.
void getPlugins(boost::ptr_vector< PluginInfo > &plugins)
This method searches for installed plugins and output the plugins information in the PluginInfo vecto...
std::string m_category
The plugin category.
An abstract class for plugin engines.
bool isLoaded(const std::string &pname) const
It returns true if the plugin is loaded otherwise returns false.
const PluginInfo & getPlugin(const std::string &name) const
It returns the plugin identified by the given name.
void initialize()
It initializes the TerraLib Platform.
~PluginManager()
Singleton destructor.
bool isUnloadedPlugin(const std::string &pluginName) const
It returns true if the plugin is in the not-loaded list of plugins.