machine/WarePluginsManager.hpp
Go to the documentation of this file.
00001 /*
00002 
00003   This file is part of OpenFLUID software
00004   Copyright(c) 2007, INRA - Montpellier SupAgro
00005 
00006 
00007  == GNU General Public License Usage ==
00008 
00009   OpenFLUID is free software: you can redistribute it and/or modify
00010   it under the terms of the GNU General Public License as published by
00011   the Free Software Foundation, either version 3 of the License, or
00012   (at your option) any later version.
00013 
00014   OpenFLUID is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017   GNU General Public License for more details.
00018 
00019   You should have received a copy of the GNU General Public License
00020   along with OpenFLUID. If not, see <http://www.gnu.org/licenses/>.
00021 
00022 
00023  == Other Usage ==
00024 
00025   Other Usage means a use of OpenFLUID that is inconsistent with the GPL
00026   license, and requires a written agreement between You and INRA.
00027   Licensees for Other Usage of OpenFLUID may use this file in accordance
00028   with the terms contained in the written agreement between You and INRA.
00029   
00030 */
00031 
00032 
00033 /**
00034   \file WarePluginsManager.hpp
00035   \brief Header of ...
00036 
00037   \author Jean-Christophe FABRE <fabrejc@supagro.inra.fr>
00038  */
00039 
00040 
00041 #ifndef __WAREPLUGINSMANAGER_HPP__
00042 #define __WAREPLUGINSMANAGER_HPP__
00043 
00044 #include <vector>
00045 #include <map>
00046 #include <string>
00047 
00048 #include <QLibrary>
00049 #include <QFileInfo>
00050 
00051 #include <openfluid/ware/PluggableWare.hpp>
00052 #include <openfluid/dllexport.hpp>
00053 #include <openfluid/config.hpp>
00054 
00055 
00056 namespace openfluid { namespace machine {
00057 
00058 
00059 typedef std::string (*GetWareABIVersionProc)();
00060 
00061 
00062 // =====================================================================
00063 // =====================================================================
00064 
00065 
00066 /**
00067   Management class for pluggable ware
00068   @tparam S class defining the container for ware signature only
00069   @tparam M class defining the container for ware signature and body
00070   @tparam SP procedure definition for instantiation of the signature
00071   @tparam BP procedure definition for instantiation of the body
00072 */
00073 template<class S, class M, typename SP, typename BP>
00074 class DLLEXPORT WarePluginsManager
00075 {
00076   private:
00077 
00078     QLibrary* loadWare(const std::string& FullFilePath)
00079     {
00080       std::string PluginFileName = QFileInfo(QString::fromStdString(FullFilePath)).fileName().toStdString();
00081 
00082       if (m_LoadedPlugins.find(PluginFileName) == m_LoadedPlugins.end())
00083       {
00084         m_LoadedPlugins[PluginFileName] = new QLibrary(QString::fromStdString(FullFilePath));
00085       }
00086 
00087       return m_LoadedPlugins[PluginFileName];
00088     }
00089 
00090 
00091     // =====================================================================
00092     // =====================================================================
00093 
00094 
00095     M* buildWareContainerWithSignatureOnly(const std::string& ID)
00096     {
00097 
00098       std::string PluginFilename = ID+getPluginFilenameSuffix()+openfluid::config::PLUGINS_EXT;
00099       std::string PluginFullPath = getPluginFullPath(PluginFilename);
00100       M* Plug = NULL;
00101 
00102       QLibrary* PlugLib = loadWare(PluginFullPath);
00103 
00104       // library loading
00105       if (PlugLib)
00106       {
00107         Plug = new M();
00108         Plug->FileFullPath = PluginFullPath;
00109 
00110         GetWareABIVersionProc ABIVersionProc = (GetWareABIVersionProc)PlugLib->resolve(WAREABIVERSION_PROC_NAME);
00111 
00112         if (ABIVersionProc)
00113         {
00114           Plug->Verified = (openfluid::tools::CompareVersions(openfluid::config::FULL_VERSION,ABIVersionProc(),false) == 0);
00115         }
00116         else Plug->Verified = false;
00117 
00118 
00119         if (Plug->Verified)
00120         {
00121           BP BodyProc = (BP)PlugLib->resolve(WAREBODY_PROC_NAME);
00122           SP SignatureProc = (SP)PlugLib->resolve(WARESIGNATURE_PROC_NAME);
00123 
00124           // checks if the handle procs exist
00125           if (SignatureProc && BodyProc)
00126           {
00127             Plug->Signature = SignatureProc();
00128 
00129             if (Plug->Signature == NULL)
00130               throw openfluid::base::FrameworkException("WarePluginsManager::buildWareContainerWithSignatureOnly","Signature from plugin file " + PluginFilename + " cannot be instanciated");
00131 
00132             Plug->Verified = (Plug->Signature->ID == ID);
00133 
00134             Plug->Body = 0;
00135           }
00136           else throw openfluid::base::FrameworkException("WarePluginsManager::buildWareContainerWithSignatureOnly","Format error in plugin file " + PluginFilename);
00137         }
00138         else throw openfluid::base::FrameworkException("WarePluginsManager::buildWareContainerWithSignatureOnly","Compatibility version mismatch for plugin file " + PluginFilename);
00139       }
00140       else throw openfluid::base::FrameworkException("WarePluginsManager::buildWareContainerWithSignatureOnly","Unable to load plugin from file " + PluginFilename);
00141 
00142       return Plug;
00143     }
00144 
00145 
00146     // =====================================================================
00147     // =====================================================================
00148 
00149 
00150     S* getWareSignature(const std::string& PluginFilename)
00151     {
00152       std::string PluginFullPath = getPluginFullPath(PluginFilename);
00153       S* Plug = NULL;
00154 
00155       QLibrary* PlugLib = loadWare(PluginFullPath);
00156 
00157       // library loading
00158       if (PlugLib)
00159       {
00160         Plug = new M();
00161         Plug->FileFullPath = PluginFullPath;
00162 
00163         GetWareABIVersionProc ABIVersionProc = (GetWareABIVersionProc)PlugLib->resolve(WAREABIVERSION_PROC_NAME);
00164 
00165         if (ABIVersionProc)
00166         {
00167           Plug->Verified = (openfluid::tools::CompareVersions(openfluid::config::FULL_VERSION,ABIVersionProc(),false) == 0);
00168         }
00169         else Plug->Verified = false;
00170 
00171 
00172         if (Plug->Verified)
00173         {
00174           BP BodyProc = (BP)PlugLib->resolve(WAREBODY_PROC_NAME);
00175           SP SignatureProc = (SP)PlugLib->resolve(WARESIGNATURE_PROC_NAME);
00176 
00177           // checks if the handle procs exist
00178           if (SignatureProc && BodyProc)
00179           {
00180             Plug->Signature = SignatureProc();
00181 
00182             if (Plug->Signature == NULL)
00183               throw openfluid::base::FrameworkException("WarePluginsManager::getWareSignature","Signature from plugin file " + PluginFilename + " cannot be instanciated");
00184 
00185             Plug->Verified = QString::fromStdString(PluginFilename).startsWith(QString::fromStdString(Plug->Signature->ID));
00186           }
00187           else throw openfluid::base::FrameworkException("WarePluginsManager::getWareSignature","Format error in plugin file " + PluginFilename);
00188         }
00189       }
00190       else throw openfluid::base::FrameworkException("WarePluginsManager::getWareSignature","Unable to find plugin file " + PluginFilename);
00191 
00192       return Plug;
00193     }
00194 
00195 
00196     // =====================================================================
00197     // =====================================================================
00198 
00199 
00200   protected:
00201 
00202     std::map<std::string,QLibrary*> m_LoadedPlugins;
00203 
00204 
00205     WarePluginsManager()
00206     {
00207 
00208     }
00209 
00210 
00211     // =====================================================================
00212     // =====================================================================
00213 
00214 
00215   public:
00216 
00217     virtual ~WarePluginsManager()
00218     {
00219 
00220     }
00221 
00222 
00223     // =====================================================================
00224     // =====================================================================
00225 
00226 
00227     virtual std::string getPluginFullPath(const std::string& Filename) = 0;
00228 
00229 
00230     // =====================================================================
00231     // =====================================================================
00232 
00233 
00234     virtual std::vector<std::string> getPluginsSearchPaths() = 0;
00235 
00236 
00237     // =====================================================================
00238     // =====================================================================
00239 
00240 
00241     virtual std::string getPluginFilenameSuffix() = 0;
00242 
00243 
00244     // =====================================================================
00245     // =====================================================================
00246 
00247 
00248     /**
00249       Lists available wares
00250     */
00251     std::vector<S*> getAvailableWaresSignatures(const std::string Pattern = "")
00252     {
00253       std::vector<S*> PluginsContainers;
00254       std::vector<std::string> PluginsPaths = getPluginsSearchPaths();
00255       std::vector<std::string> PluginFiles;
00256       std::vector<std::string> TmpFiles;
00257       unsigned int i,j;
00258 
00259 
00260       for (i=0;i<PluginsPaths.size();i++)
00261       {
00262         TmpFiles = openfluid::tools::GetFilesBySuffixAndExt(PluginsPaths[i],getPluginFilenameSuffix(),openfluid::config::PLUGINS_EXT,false,true);
00263         for (j=0;j<TmpFiles.size();j++) PluginFiles.push_back(TmpFiles[j]);
00264       }
00265 
00266 
00267       S* CurrentPlug;
00268 
00269       for (i=0;i<PluginFiles.size();i++)
00270       {
00271         CurrentPlug = getWareSignature(PluginFiles[i]);
00272 
00273         if (CurrentPlug != NULL && CurrentPlug->Verified)
00274         {
00275           if (Pattern != "")
00276           {
00277             if (openfluid::tools::WildcardMatching(Pattern,CurrentPlug->Signature->ID))
00278               PluginsContainers.push_back(CurrentPlug);
00279           }
00280           else PluginsContainers.push_back(CurrentPlug);
00281         }
00282       }
00283 
00284       return PluginsContainers;
00285     }
00286 
00287 
00288     // =====================================================================
00289     // =====================================================================
00290 
00291 
00292     M* loadWareSignatureOnly(const std::string& ID)
00293     {
00294       M* Plug = buildWareContainerWithSignatureOnly(ID);
00295 
00296       if (Plug != NULL && Plug->Verified) return Plug;
00297 
00298       return NULL;
00299     }
00300 
00301 
00302     // =====================================================================
00303     // =====================================================================
00304 
00305 
00306     void completeSignatureWithWareBody(M* Item)
00307     {
00308       std::string PluginFullPath = Item->FileFullPath;
00309 
00310       QLibrary* PlugLib = loadWare(PluginFullPath);
00311 
00312       // library loading
00313       if (PlugLib)
00314       {
00315         BP BodyProc = (BP)PlugLib->resolve(WAREBODY_PROC_NAME);
00316 
00317         // checks if the handle proc exists
00318         if(BodyProc)
00319         {
00320           Item->Body = BodyProc();
00321 
00322           if (Item->Body == NULL)
00323             throw openfluid::base::FrameworkException("WarePluginsManager::completeSignatureWithWareBody","Ware from plugin file " + PluginFullPath + " cannot be instanciated");
00324 
00325         }
00326         else throw openfluid::base::FrameworkException("completeSignatureWithWareBody","Format error in plugin file " + PluginFullPath);
00327       }
00328       else throw openfluid::base::FrameworkException("completeSignatureWithWareBody","Unable to find plugin file " + PluginFullPath);
00329     }
00330 
00331 
00332     // =====================================================================
00333     // =====================================================================
00334 
00335 
00336     void unloadAllWares()
00337     {
00338       std::map<std::string,QLibrary*>::iterator it;
00339 
00340       for (it=m_LoadedPlugins.begin();it != m_LoadedPlugins.end(); ++it)
00341       {
00342         it->second->unload();
00343         delete (it->second);
00344       }
00345 
00346       m_LoadedPlugins.clear();
00347     }
00348 
00349 };
00350 
00351 
00352 
00353 } } //namespaces
00354 
00355 
00356 
00357 
00358 #endif /* __WAREPLUGINSMANAGER_HPP__ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines