Code_TYMPAN  4.4.0
Industrial site acoustic simulation
TYPluginManager.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012> <EDF-R&D> <FRANCE>
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  */
15 
16 #include "Tympan/core/logging.h"
17 #include "Tympan/core/exceptions.h"
19 #include "TYPluginManager.h"
20 
21 #if TY_COMPILER == TY_COMPILER_MSVC
22  #define WIN32_LEAN_AND_MEAN
23  #include <windows.h>
24 #else
25 extern "C"
26 {
27  #include <dlfcn.h>
28 }
29 #endif
30 
31 // Initialise a NULL.
33 
35 
37 {
38  unloadPlugins();
39 }
40 
42 {
43  bool ret = _pInstance ? true : false;
44  _pInstance = this;
45  return ret;
46 }
47 
49 {
50  if (!_pInstance)
51  {
53  }
54 
55  return _pInstance;
56 }
57 
58 QFileInfoList TYPluginManager::getPluginFileList(const QDir& directory) const
59 {
60  // Get all available plug-ins.
61  QStringList filters;
62  filters.append("*.dll");
63  filters.append("*.so");
64  QFileInfoList file_list = directory.entryInfoList(filters, QDir::Files, QDir::Name);
65  return file_list;
66 }
67 
68 void TYPluginManager::createPlugins(const QFileInfoList& file_list)
69 {
70  QFileInfoList::const_iterator itfile;
71  for (itfile = file_list.begin(); itfile != file_list.end(); ++itfile)
72  {
73  TYPluginData* plugin_data = new TYPluginData();
74  plugin_data->filename = itfile->absoluteFilePath();
75 
76  OMessageManager::get()->debug("Trying to dynamically load '%s'.\n",
77  itfile->absoluteFilePath().toUtf8().data());
78 
79  plugin_data->pluginDllInstance =
80  (LIB_HANDLE)LIB_LOAD(itfile->absoluteFilePath().toLocal8Bit().data());
81 
82  if (plugin_data->pluginDllInstance)
83  {
84  // Retrieve methods via pointers to member functions of a plugin.
85  plugin_data->startPlugin =
86  (TYPGStartPlugin)LIB_GETSYM(plugin_data->pluginDllInstance, "startPlugin");
87  plugin_data->getPlugin = (TYPGGetPlugin)LIB_GETSYM(plugin_data->pluginDllInstance, "getPlugin");
88  plugin_data->stopPlugin =
89  (TYPGStopPlugin)LIB_GETSYM(plugin_data->pluginDllInstance, "stopPlugin");
90  }
91  else
92  {
93  OMessageManager::get()->info("Unable to load the library file '%s'.",
94  itfile->absoluteFilePath().toUtf8().data());
95  // Do not attempt to unload a library not loaded
96  delete plugin_data;
97  continue;
98  }
99 
100  // Check all pointers to methods.
101  if (!plugin_data->startPlugin || !plugin_data->getPlugin || !plugin_data->stopPlugin)
102  {
103  OMessageManager::get()->info("Unable to get methods from the plugin '%s'.",
104  itfile->absoluteFilePath().toUtf8().data());
105  LIB_UNLOAD(plugin_data->pluginDllInstance);
106  delete plugin_data;
107  continue;
108  }
109 
110  // Start the plugin and add it to the list '_plugins'. True if success.
111  bool success = startPlugin(plugin_data);
112  if (!success)
113  {
114  OMessageManager::get()->info("Unable to start the plugin from the file '%s'.",
115  itfile->absoluteFilePath().toUtf8().data());
116  LIB_UNLOAD(plugin_data->pluginDllInstance);
117  delete plugin_data;
118  continue;
119  }
120  }
121 }
122 
124 {
125  // Start the plugin.
126  plugin_data->startPlugin();
127  // If already exists in the list, stop and unload it.
128  if (exist(plugin_data->getPlugin()->getUUID()))
129  {
130  plugin_data->stopPlugin();
131  return false;
132  }
133  else
134  {
135  _plugins.push_back(plugin_data);
136  return true;
137  }
138 }
139 
140 bool TYPluginManager::loadPlugins(const QString& directory)
141 {
142  // Get the folder where there are plug-ins (aka solvers).
143  QString dirPath = QDir::toNativeSeparators(directory);
144  QDir dir(dirPath);
145 
146  // Check if the folder exists.
147  if (!dir.exists())
148  {
149  OMessageManager::get()->info("The directory of plugins '%s' does not exist.",
150  dir.absolutePath().toUtf8().data());
151  return false;
152  }
153 
154  QFileInfoList plugin_file_list = getPluginFileList(dir);
155 
156  // Load methods related to a plugin, check them and add the related plugin
157  // to the list.
158  createPlugins(plugin_file_list);
159 
160  // Check if there is unless the default plugin.
161  if (!exist(OGenID(QString(DEFAULT_SOLVER_UUID))))
162  {
163  OMessageManager::get()->info("WARNING: Default solver is not present !");
164  }
165 
166  if (_plugins.size() == 0)
167  {
168  OMessageManager::get()->info("No plugins found.");
169  return false;
170  }
171 
172  return true;
173 }
174 
176 {
177  // On decharge la memoire
178  for (TYPluginList::iterator it = _plugins.begin(); it != _plugins.end(); ++it)
179  {
180  (*it)->stopPlugin();
181  LIB_UNLOAD((*it)->pluginDllInstance);
182  delete (*it);
183  }
184 
185  // On vide la liste
186  _plugins.clear();
187 }
188 
190 {
191  Plugin* plugin = getPlugin(uuid);
192  if (plugin != nullptr)
193  return plugin->getSolver();
194  return nullptr;
195 }
196 
198 {
199  for (TYPluginList::const_iterator it = _plugins.begin(); it != _plugins.end(); ++it)
200  if ((*it)->getPlugin()->getUUID() == uuid)
201  {
202  return (*it)->getPlugin();
203  }
204 
205  return nullptr;
206 }
207 
208 void TYPluginManager::getInfos(pluginInfos* pInfos, const OGenID& uuid) const
209 {
210  Plugin* plugin = getPlugin(uuid);
211  if (plugin)
212  {
213  plugin->getInfos(pInfos);
214  }
215 }
216 
217 QString TYPluginManager::getInfo(const QString& info, const OGenID& uuid) const
218 {
219  pluginInfos* pInfos = new pluginInfos();
220  getInfos(pInfos, uuid);
221  if (info == "author")
222  {
223  return pInfos->_author;
224  }
225  else if (info == "version")
226  {
227  return pInfos->_version;
228  }
229  else if (info == "description")
230  {
231  return pInfos->_description;
232  }
233  else // name
234  {
235  return pInfos->_name;
236  }
237 }
238 
240 {
241  return _plugins;
242 }
243 
245 {
246  // Si on trouve l'uuid, on retourne vrai
247  for (TYPluginList::iterator it = _plugins.begin(); it != _plugins.end(); ++it)
248  if ((*it)->getPlugin()->getUUID() == uuid)
249  {
250  return true;
251  }
252 
253  // Sinon, on retourne faux
254  return false;
255 }
256 
257 bool TYPluginManager::exist(const QString& solverName)
258 {
259  // Si on trouve l'uuid, on retourne vrai
260  for (TYPluginList::iterator it = _plugins.begin(); it != _plugins.end(); ++it)
261  if ((*it)->getPlugin()->getName() == solverName)
262  {
263  return true;
264  }
265 
266  // Sinon, on retourne faux
267  return false;
268 }
269 
270 OGenID TYPluginManager::solverID(const QString& solverName)
271 {
272  for (TYPluginList::iterator it = _plugins.begin(); it != _plugins.end(); ++it)
273  {
274  if ((*it)->getPlugin()->getName() == solverName)
275  {
276  return (*it)->getPlugin()->getUUID();
277  }
278  }
279  throw tympan::invalid_data("Unknown solver name") << tympan_source_loc;
280 }
281 
282 namespace tympan
283 {
284 void load_solvers(const char* path)
285 {
286  LPTYPluginManager plugin_manager = TYPluginManager::get();
287  plugin_manager->unloadPlugins();
288  plugin_manager->loadPlugins(path);
289 }
290 
292 {
293  LPTYPluginManager plugin_manager = TYPluginManager::get();
294  if (plugin_manager->getPluginList().empty())
295  {
296  throw tympan::invalid_data("The solvers are not loaded") << tympan_source_loc;
297  }
298  Plugin* plugin = plugin_manager->getPlugin(uuid);
299  pluginInfos* pInfos = new pluginInfos();
300  plugin->getInfos(pInfos);
302  mm->info("***************************************************************");
303  mm->info(" CHARGEMENT DE LA DLL");
304  mm->info("");
305  mm->info("Nom : %s", pInfos->_name.toLatin1().data());
306  mm->info("Version : %s", pInfos->_version.toLatin1().data());
307  mm->info("Description : %s", pInfos->_description.toLatin1().data());
308  mm->info("Auteur : %s", pInfos->_author.toLatin1().data());
309  mm->info("");
310  mm->info("***************************************************************");
311  delete pInfos;
312  return plugin->getSolver();
313 }
314 
315 OGenID solver_id(std::string name)
316 {
317  LPTYPluginManager plugin_manager = TYPluginManager::get();
318  if (plugin_manager->getPluginList().empty())
319  {
320  throw tympan::invalid_data("The solvers are not loaded") << tympan_source_loc;
321  }
322  return plugin_manager->solverID(QString::fromStdString(name));
323 }
324 } /* namespace tympan */
Plugin * plugin
Le plugin associe au solver 9613.
Definition: plugin.cpp:23
#define DEFAULT_SOLVER_UUID
#define LIB_LOAD(a)
void(* TYPGStopPlugin)()
#define LIB_GETSYM(a, b)
#define LIB_UNLOAD(a)
void(* TYPGStartPlugin)()
#define LIB_HANDLE
Plugin *(* TYPGGetPlugin)()
const char * name
Definition: idgen.h:28
virtual void debug(const char *message,...)
Definition: logging.cpp:151
static OMessageManager * get()
Definition: logging.cpp:108
virtual void info(const char *message,...)
Definition: logging.cpp:143
Definition: plugin.h:48
void getInfos(pluginInfos *pInfos)
Definition: plugin.h:99
SolverInterface * getSolver() const
Definition: plugin.h:119
Interface class for solvers.
Definition: interfaces.h:33
bool exist(const OGenID &uuid)
OGenID solverID(const QString &solverName)
bool loadPlugins(const QString &directory)
Load, check, create and start plugins.
static LPTYPluginManager _pInstance
QString getInfo(const QString &info, const OGenID &uuid) const
Retourne une info spécifique du solveur.
TYPluginList & getPluginList()
void createPlugins(const QFileInfoList &file_list)
Create TYPluginData related to library files to load.
std::list< TYPluginData * > TYPluginList
bool startPlugin(TYPluginData *plugin_data)
Check the loaded plugin.
Plugin * getPlugin(const OGenID &uuid) const
SolverInterface * getSolver(const OGenID &uuid) const
QFileInfoList getPluginFileList(const QDir &directory) const
Get the list of dynamic library files to load.
void getInfos(pluginInfos *pInfos, const OGenID &uuid) const
TYPluginList _plugins
static LPTYPluginManager get()
Utilities to handle exceptions and to pretty-print value.
#define tympan_source_loc
This macro build a source_loc object to be attached to a tympan::Exception.
Definition: exceptions.h:76
OGenID solver_id(std::string name)
Return the id of the solver named name (a previous call to tympan::load_solvers() is.
SolverInterface * select_solver(OGenID uuid)
Select a solver amongst the loaded solvers (a previous call to tympan::load_solvers() is.
void load_solvers(const char *path)
Load the solver plugins found in path
TYPGStopPlugin stopPlugin
QString filename
TYPGGetPlugin getPlugin
TYPGStartPlugin startPlugin
LIB_HANDLE pluginDllInstance
QString _author
Definition: plugin.h:42
QString _version
Definition: plugin.h:43
QString _name
Definition: plugin.h:41
QString _description
Definition: plugin.h:44
The base exception class for errors due to invalid data.
Definition: exceptions.h:60