All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
WarePluginsManager.hpp
Go to the documentation of this file.
1 /*
2 
3  This file is part of OpenFLUID software
4  Copyright(c) 2007, INRA - Montpellier SupAgro
5 
6 
7  == GNU General Public License Usage ==
8 
9  OpenFLUID is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  OpenFLUID is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with OpenFLUID. If not, see <http://www.gnu.org/licenses/>.
21 
22 
23  == Other Usage ==
24 
25  Other Usage means a use of OpenFLUID that is inconsistent with the GPL
26  license, and requires a written agreement between You and INRA.
27  Licensees for Other Usage of OpenFLUID may use this file in accordance
28  with the terms contained in the written agreement between You and INRA.
29 
30 */
31 
32 
33 /**
34  @file WarePluginsManager.hpp
35 
36  @author Jean-Christophe FABRE <jean-christophe.fabre@supagro.inra.fr>
37  */
38 
39 
40 #ifndef __OPENFLUID_MACHINE_WAREPLUGINSMANAGER_HPP__
41 #define __OPENFLUID_MACHINE_WAREPLUGINSMANAGER_HPP__
42 
43 #include <vector>
44 #include <map>
45 #include <string>
46 
47 #include <QLibrary>
48 #include <QFileInfo>
49 
52 #include <openfluid/dllexport.hpp>
53 #include <openfluid/config.hpp>
54 
55 
56 namespace openfluid { namespace machine {
57 
58 
59 typedef std::string (*GetWareABIVersionProc)();
60 
61 typedef std::string (*GetWareLinkUIDProc)();
62 
63 
64 // =====================================================================
65 // =====================================================================
66 
67 
68 /**
69  Management class for pluggable ware
70  @tparam S class defining the container for ware signature only
71  @tparam M class defining the container for ware signature and body
72  @tparam SP procedure definition for instantiation of the signature
73  @tparam BP procedure definition for instantiation of the body
74 */
75 template<class S, class M, typename SP, typename BP>
77 {
78  private:
79 
80  QLibrary* loadWare(const std::string& FullFilePath)
81  {
82  std::string PluginFileName = QFileInfo(QString::fromStdString(FullFilePath)).fileName().toStdString();
83 
84  if (m_LoadedPlugins.find(PluginFileName) == m_LoadedPlugins.end())
85  {
86  m_LoadedPlugins[PluginFileName] = new QLibrary(QString::fromStdString(FullFilePath));
87  }
88 
89  return m_LoadedPlugins[PluginFileName];
90  }
91 
92 
93  // =====================================================================
94  // =====================================================================
95 
96 
97  M* buildWareContainerWithSignatureOnly(const std::string& ID)
98  {
99 
100  std::string PluginFilename = ID+getPluginFilenameSuffix()+openfluid::config::PLUGINS_EXT;
101  std::string PluginFullPath = getPluginFullPath(PluginFilename);
102  M* Plug = NULL;
103 
104  QLibrary* PlugLib = loadWare(PluginFullPath);
105 
106  // library loading
107  if (PlugLib && PlugLib->load())
108  {
109  Plug = new M();
110  Plug->FileFullPath = PluginFullPath;
111 
112  GetWareABIVersionProc ABIVersionProc = (GetWareABIVersionProc)PlugLib->resolve(WAREABIVERSION_PROC_NAME);
113 
114  if (ABIVersionProc)
115  {
116  Plug->Verified =
117  (openfluid::tools::compareVersions(openfluid::config::FULL_VERSION,ABIVersionProc(),false) == 0);
118  }
119  else Plug->Verified = false;
120 
121 
122  if (Plug->Verified)
123  {
124  BP BodyProc = (BP)PlugLib->resolve(WAREBODY_PROC_NAME);
125  SP SignatureProc = (SP)PlugLib->resolve(WARESIGNATURE_PROC_NAME);
126 
127  // checks if the handle procs exist
128  if (SignatureProc && BodyProc)
129  {
130  Plug->Signature = SignatureProc();
131 
132  if (Plug->Signature == NULL)
133  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION,
134  "Signature from plugin file " + PluginFilename +
135  " cannot be instanciated");
136 
137  Plug->Verified = (Plug->Signature->ID == ID);
138 
139  Plug->Body = 0;
140 
141  GetWareLinkUIDProc LinkUIDProc = (GetWareLinkUIDProc)PlugLib->resolve(WARELINKUID_PROC_NAME);
142 
143  if (LinkUIDProc)
144  Plug->LinkUID = LinkUIDProc();
145  }
146  else
147  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION,
148  "Format error in plugin file " + PluginFilename);
149  }
150  else
151  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION,
152  "Compatibility version mismatch for plugin file " + PluginFilename);
153  }
154  else
155  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION,
156  "Unable to load plugin from file " + PluginFilename);
157 
158  return Plug;
159  }
160 
161 
162  // =====================================================================
163  // =====================================================================
164 
165 
166  S* getWareSignature(const std::string& PluginFilename)
167  {
168  std::string PluginFullPath = getPluginFullPath(PluginFilename);
169  S* Plug = NULL;
170 
173  .addInfos({{"pluginfullpath",PluginFullPath},{"pluginfilename",PluginFilename}});
174 
175  // library loading
176  QLibrary* PlugLib = loadWare(PluginFullPath);
177 
178 
179  if (PlugLib)
180  {
181  if (PlugLib->load())
182  {
183  Plug = new M();
184  Plug->FileFullPath = PluginFullPath;
185 
186  GetWareABIVersionProc ABIVersionProc = (GetWareABIVersionProc)PlugLib->resolve(WAREABIVERSION_PROC_NAME);
187 
188  if (ABIVersionProc)
189  {
190  Plug->Verified =
191  (openfluid::tools::compareVersions(openfluid::config::FULL_VERSION,ABIVersionProc(),false) == 0);
192  }
193  else Plug->Verified = false;
194 
195 
196  if (Plug->Verified)
197  {
198  BP BodyProc = (BP)PlugLib->resolve(WAREBODY_PROC_NAME);
199  SP SignatureProc = (SP)PlugLib->resolve(WARESIGNATURE_PROC_NAME);
200 
201  // checks if the handle procs exist
202  if (SignatureProc && BodyProc)
203  {
204  try
205  {
206  Plug->Signature = SignatureProc();
207  }
209  {
211  }
212 
213  if (Plug->Signature == NULL)
214  throw openfluid::base::FrameworkException(ECtxt,"Signature cannot be instanciated from plugin file");
215 
216  Plug->Verified =
217  QString::fromStdString(PluginFilename).startsWith(QString::fromStdString(Plug->Signature->ID));
218 
219  GetWareLinkUIDProc LinkUIDProc = (GetWareLinkUIDProc)PlugLib->resolve(WARELINKUID_PROC_NAME);
220 
221  if (LinkUIDProc)
222  Plug->LinkUID = LinkUIDProc();
223  }
224  else
225  throw openfluid::base::FrameworkException(ECtxt,"Format error in plugin file");
226  }
227  }
228  else
229  {
230  throw openfluid::base::FrameworkException(ECtxt,PlugLib->errorString().toStdString());
231  }
232  }
233  else
234  throw openfluid::base::FrameworkException(ECtxt,"Unable to find plugin file");
235 
236  return Plug;
237  }
238 
239 
240  // =====================================================================
241  // =====================================================================
242 
243 
244  protected:
245 
246  std::map<std::string,QLibrary*> m_LoadedPlugins;
247 
248 
250  {
251 
252  }
253 
254 
255  // =====================================================================
256  // =====================================================================
257 
258 
259  public:
260 
262  {
263  public:
264  std::vector<S*> AvailablePlugins;
265 
266  std::map<std::string,std::string> ErroredFiles;
267  };
268 
269 
271  {
272 
273  }
274 
275 
276  // =====================================================================
277  // =====================================================================
278 
279 
280  virtual std::string getPluginFullPath(const std::string& Filename) const = 0;
281 
282 
283  // =====================================================================
284  // =====================================================================
285 
286 
287  virtual std::vector<std::string> getPluginsSearchPaths() const = 0;
288 
289 
290  // =====================================================================
291  // =====================================================================
292 
293 
294  virtual std::string getPluginFilenameSuffix() const = 0;
295 
296 
297  // =====================================================================
298  // =====================================================================
299 
300 
301  /**
302  Lists available wares
303  */
304  PluginsSearchResults getAvailableWaresSignatures(const std::string& Pattern = "")
305  {
306  PluginsSearchResults SearchResults;
307  std::vector<std::string> PluginsPaths = getPluginsSearchPaths();
308  std::vector<std::string> PluginFiles;
309  std::vector<std::string> TmpFiles;
310  unsigned int i,j;
311 
312 
313  for (i=0;i<PluginsPaths.size();i++)
314  {
315  TmpFiles = openfluid::tools::findFilesBySuffixAndExtension(PluginsPaths[i],
316  getPluginFilenameSuffix(),
317  openfluid::config::PLUGINS_EXT,false,true);
318  for (j=0;j<TmpFiles.size();j++)
319  PluginFiles.push_back(TmpFiles[j]);
320  }
321 
322 
323  S* CurrentPlug = NULL;
324 
325  for (i=0;i<PluginFiles.size();i++)
326  {
327  try
328  {
329  CurrentPlug = getWareSignature(PluginFiles[i]);
330  }
332  {
333  SearchResults.ErroredFiles[E.getContext().at("pluginfullpath")] = E.getMessage();
334  }
335 
336  if (CurrentPlug != NULL && CurrentPlug->Verified)
337  {
338  if (Pattern != "")
339  {
340  if (openfluid::tools::matchWithWildcard(Pattern,CurrentPlug->Signature->ID))
341  SearchResults.AvailablePlugins.push_back(CurrentPlug);
342  }
343  else SearchResults.AvailablePlugins.push_back(CurrentPlug);
344  }
345  }
346 
347  return SearchResults;
348  }
349 
350 
351  // =====================================================================
352  // =====================================================================
353 
354 
355  M* loadWareSignatureOnly(const std::string& ID)
356  {
357  M* Plug = buildWareContainerWithSignatureOnly(ID);
358 
359  if (Plug != NULL && Plug->Verified) return Plug;
360 
361  return NULL;
362  }
363 
364 
365  // =====================================================================
366  // =====================================================================
367 
368 
370  {
371  std::string PluginFullPath = Item->FileFullPath;
372 
373  QLibrary* PlugLib = loadWare(PluginFullPath);
374 
375  // library loading
376  if (PlugLib && PlugLib->load())
377  {
378  BP BodyProc = (BP)PlugLib->resolve(WAREBODY_PROC_NAME);
379 
380  // checks if the handle proc exists
381  if(BodyProc)
382  {
383  Item->Body = BodyProc();
384 
385  if (Item->Body == NULL)
386  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION,
387  "Ware from plugin file " + PluginFullPath +
388  " cannot be instanciated");
389 
390  }
391  else throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION,
392  "Format error in plugin file " + PluginFullPath);
393  }
394  else throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION,
395  "Unable to find plugin file " + PluginFullPath);
396  }
397 
398 
399  // =====================================================================
400  // =====================================================================
401 
402 
404  {
405  std::map<std::string,QLibrary*>::iterator it;
406 
407  for (it=m_LoadedPlugins.begin();it != m_LoadedPlugins.end(); ++it)
408  {
409  it->second->unload();
410  delete (it->second);
411  }
412 
413  m_LoadedPlugins.clear();
414  }
415 
416 };
417 
418 
419 
420 } } //namespaces
421 
422 
423 
424 
425 #endif /* __OPENFLUID_MACHINE_WAREPLUGINSMANAGER_HPP__ */
WarePluginsManager()
Definition: WarePluginsManager.hpp:249
static ExceptionContext computeContext()
Definition: FrameworkException.hpp:89
std::map< std::string, std::string > ErroredFiles
Definition: WarePluginsManager.hpp:266
bool OPENFLUID_API matchWithWildcard(const std::string &Pattern, const std::string &Str)
#define WAREBODY_PROC_NAME
Definition: PluggableWare.hpp:57
std::map< std::string, QLibrary * > m_LoadedPlugins
Definition: WarePluginsManager.hpp:246
#define WAREABIVERSION_PROC_NAME
Definition: PluggableWare.hpp:69
M * loadWareSignatureOnly(const std::string &ID)
Definition: WarePluginsManager.hpp:355
std::vector< S * > AvailablePlugins
Definition: WarePluginsManager.hpp:264
PluginsSearchResults getAvailableWaresSignatures(const std::string &Pattern="")
Definition: WarePluginsManager.hpp:304
#define WARESIGNATURE_PROC_NAME
Definition: PluggableWare.hpp:63
Definition: FrameworkException.hpp:50
ExceptionContext & addInfos(const std::map< std::string, std::string > &Infos)
Definition: ExceptionContext.hpp:69
const std::string getMessage() const
Definition: Exception.hpp:97
std::string(* GetWareABIVersionProc)()
Definition: WarePluginsManager.hpp:59
Definition: ExceptionContext.hpp:53
void completeSignatureWithWareBody(M *Item)
Definition: WarePluginsManager.hpp:369
#define WARELINKUID_PROC_NAME
Definition: PluggableWare.hpp:76
void unloadAllWares()
Definition: WarePluginsManager.hpp:403
Definition: WarePluginsManager.hpp:76
std::string(* GetWareLinkUIDProc)()
Definition: WarePluginsManager.hpp:61
#define OPENFLUID_API
Definition: dllexport.hpp:87
int OPENFLUID_API compareVersions(const std::string &VersionA, const std::string &VersionB, bool Strict=true)
std::vector< std::string > OPENFLUID_API findFilesBySuffixAndExtension(const std::string &Path, const std::string &Suffix, const std::string &Ext, bool WithPath=false, bool ExtIncludeDot=false)
virtual ~WarePluginsManager()
Definition: WarePluginsManager.hpp:270
const ExceptionContext getContext() const
Definition: Exception.hpp:115