src/terralib/core/plugin/Utils.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
3 
4  This file is part of the TerraLib - a Framework for building GIS enabled
5  applications.
6 
7  TerraLib is free software: you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as published by
9  the Free Software Foundation, either version 3 of the License,
10  or (at your option) any later version.
11 
12  TerraLib is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with TerraLib. See COPYING. If not, write to
19  TerraLib Team at <terralib-team@terralib.org>.
20  */
21 
22 /*!
23  \file terralib/core/plugin/Utils.cpp
24 
25  \brief General utilities for plugins.
26 
27  \author Gilberto Ribeiro de Queiroz
28  \author Matheus Cavassan Zaglia
29  */
30 
31 // TerraLib
32 #include "Utils.h"
33 #include "../filesystem/FileSystem.h"
34 #include "../encoding/CharEncoding.h"
35 #include "../translator/Translator.h"
36 #include "CppPluginEngine.h"
37 #include "Exception.h"
38 #include "Finders.h"
39 #include "PluginEngineManager.h"
40 #include "PluginManager.h"
41 
42 // Boost
43 #include <boost/algorithm/string/join.hpp>
44 #include <boost/format.hpp>
45 #include <boost/graph/adjacency_list.hpp>
46 #include <boost/graph/topological_sort.hpp>
47 
48 static bool g_plugin_module_initialized(false);
49 
51 {
53  return;
54 
55  std::unique_ptr<te::core::AbstractPluginEngine> cppengine(
57 
58  te::core::PluginEngineManager::instance().insert(std::move(cppengine));
59 
61 }
62 
64 {
66  return;
67 
69 
71 }
72 
73 std::vector<te::core::PluginInfo> te::core::plugin::TopologicalSort(
74  const std::vector<te::core::PluginInfo>& v_pInfo)
75 {
76  std::map<std::string, std::size_t> plugins_map;
77 
78  const std::size_t nplugins = v_pInfo.size();
79 
80  for(std::size_t i = 0; i != nplugins; ++i)
81  plugins_map.insert(std::make_pair(v_pInfo[i].name, i));
82 
83  std::map<std::string, std::size_t>::const_iterator it_end = plugins_map.end();
84 
85  typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS>
86  Graph;
87  typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
88 
89  Graph dgraph; // The dependency graph must be a DAG
90 
91  for(std::size_t i = 0; i < nplugins; ++i)
92  boost::add_vertex(dgraph);
93 
94  for(std::size_t i = 0; i != nplugins; ++i)
95  {
96  const std::vector<std::string>& required_plugins = v_pInfo[i].dependencies;
97 
98  const std::size_t num_required_plugins = required_plugins.size();
99 
100  for(std::size_t j = 0; j != num_required_plugins; ++j)
101  {
102  std::map<std::string, std::size_t>::const_iterator it =
103  plugins_map.find(required_plugins[j]);
104 
105  if(it != it_end)
106  {
107  // if plugin A (it->second) is required for plugin B (i) then there must
108  // be a directed edge from A to B (A must come first then B!)
109  boost::add_edge(it->second, i, dgraph);
110  }
111  }
112  }
113 
114  std::vector<Vertex> toposortResult;
115 
116  try
117  {
118  boost::topological_sort(dgraph, std::back_inserter(toposortResult));
119  }
120  catch(const boost::not_a_dag& e)
121  {
122  boost::format err_msg(
123  TE_TR("The plugins cannot be sorted due to the following error: %1%"));
124 
126  << ErrorDescription((err_msg % e.what()).str());
127  }
128 
129  std::vector<te::core::PluginInfo> sortedPlugins;
130 
131  for(auto it = toposortResult.rbegin(); it != toposortResult.rend(); ++it)
132  sortedPlugins.push_back(v_pInfo[*it]);
133 
134  assert(sortedPlugins.size() == v_pInfo.size());
135 
136  return sortedPlugins;
137 }
138 
140 {
142 
143  std::vector<te::core::PluginInfo> v_pInfo = te::core::DefaultPluginFinder();
144 
145  v_pInfo = te::core::plugin::TopologicalSort(v_pInfo);
146 
147  std::vector<std::string> failToLoad;
148 
149  for(const te::core::PluginInfo& pinfo : v_pInfo)
150  {
151  try
152  {
154  te::core::PluginManager::instance().load(pinfo.name, start);
155  }
156  catch(...)
157  {
158  failToLoad.push_back(pinfo.name);
159  }
160  }
161  if(failToLoad.size() > 0)
162  {
163  boost::format err_msg(
164  TE_TR("Could not load the following plugins:\n\n%1%"));
165 
167  (err_msg % boost::algorithm::join(failToLoad, "\n")).str());
168  }
169 }
170 
172 {
173  std::vector<te::core::PluginInfo> pVec =
175 
176  for(auto plugin = pVec.rbegin(); plugin != pVec.rend(); ++plugin)
177  {
178  te::core::PluginManager::instance().stop(plugin->name);
180  }
181 }
182 
183 void te::core::plugin::UnloadPlugin(const std::string& plugin_name)
184 {
185  const te::core::PluginInfo& pInfo =
187 
188  for(auto dependent : pInfo.dependencies)
189  UnloadPlugin(dependent);
190 
191  if(te::core::PluginManager::instance().isUnloaded(plugin_name))
192  return;
193 
196 }
TECOREEXPORT void FinalizePluginSystem()
void insert(std::unique_ptr< AbstractPluginEngine > engine)
Register a new plugin engine.
TECOREEXPORT std::vector< PluginInfo > TopologicalSort(const std::vector< PluginInfo > &v_pinfo)
An exception indicating an error when loading a plugin.
void stop(const std::string &plugin_name)
Stop a loaded plugin.
A singleton that can be used to register plugin engines.
void insert(const PluginInfo &pinfo)
Adds plugin with its plugin information to the list of unloaded plugins.
Basic information about a plugin.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
void load(const std::string &plugin_name, const bool start=true)
It tries to load the informed plugin.
void clear()
Unregister every plugin engine.
boost::error_info< struct tag_error_description, std::string > ErrorDescription
The base type for error report messages.
static PluginManager & instance()
Access the singleton.
General utilities for plugins.
TECOREEXPORT void UnloadPlugin(const std::string &plugin_name)
TECOREEXPORT void LoadAll(bool start=true)
std::vector< std::string > dependencies
The list of required plugins in order to launch the plugin.
const PluginInfo & getPluginInfo(const std::string &name) const
Return information about a plugin identified by the given name.
An exception indicating an error when two or more plugins have cyclic dependecy.
A plugin engine for plugins written in C++.
TECOREEXPORT std::vector< PluginInfo > DefaultPluginFinder()
Definition: Finders.cpp:74
static bool g_plugin_module_initialized(false)
TECOREEXPORT void InitializePluginSystem()
General utilities for searching for plugins.
void clear()
Stop and unload all plugins, then clear the internal list of plugins.
std::vector< PluginInfo > getLoadedPlugins() const
Return the list of plugins that are loaded.
void unload(const std::string &plugin_name)
Try to unload a given plugin.
static PluginEngineManager & instance()
Access the singleton.