ClassLoader.h
Go to the documentation of this file.
00001 //
00002 // ClassLoader.h
00003 //
00004 // $Id: //poco/1.3/Foundation/include/Poco/ClassLoader.h#2 $
00005 //
00006 // Library: Foundation
00007 // Package: SharedLibrary
00008 // Module:  ClassLoader
00009 //
00010 // Definition of the ClassLoader class.
00011 //
00012 // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
00013 // and Contributors.
00014 //
00015 // Permission is hereby granted, free of charge, to any person or organization
00016 // obtaining a copy of the software and accompanying documentation covered by
00017 // this license (the "Software") to use, reproduce, display, distribute,
00018 // execute, and transmit the Software, and to prepare derivative works of the
00019 // Software, and to permit third-parties to whom the Software is furnished to
00020 // do so, all subject to the following:
00021 // 
00022 // The copyright notices in the Software and this entire statement, including
00023 // the above license grant, this restriction and the following disclaimer,
00024 // must be included in all copies of the Software, in whole or in part, and
00025 // all derivative works of the Software, unless such copies or derivative
00026 // works are solely in the form of machine-executable object code generated by
00027 // a source language processor.
00028 // 
00029 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00030 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00031 // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
00032 // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
00033 // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
00034 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00035 // DEALINGS IN THE SOFTWARE.
00036 //
00037 
00038 
00039 #ifndef Foundation_ClassLoader_INCLUDED
00040 #define Foundation_ClassLoader_INCLUDED
00041 
00042 
00043 #include "Poco/Foundation.h"
00044 #include "Poco/MetaObject.h"
00045 #include "Poco/Manifest.h"
00046 #include "Poco/SharedLibrary.h"
00047 #include "Poco/Mutex.h"
00048 #include "Poco/Exception.h"
00049 #include <map>
00050 #include <vector>
00051 
00052 namespace Poco {
00053 
00054 
00055 template <class Base>
00056 class ClassLoader
00074 {
00075 public:
00076         typedef AbstractMetaObject<Base> Meta;
00077         typedef Manifest<Base> Manif;
00078         typedef void (*InitializeLibraryFunc)();
00079         typedef void (*UninitializeLibraryFunc)();
00080         typedef bool (*BuildManifestFunc)(ManifestBase*);
00081 
00082         typedef std::pair<const Manif*, std::string> manifest_pair;
00083 
00084         struct LibraryInfo
00085         {
00086                 SharedLibrary* pLibrary;
00087                 std::vector< manifest_pair >   vpManifest;
00088                 int            refCount;
00089         };
00090         typedef std::map<std::string, LibraryInfo> LibraryMap;
00091 
00092         class Iterator
00094         {
00095         public:
00096                 typedef std::pair<std::string, std::vector<manifest_pair> > Pair;
00097 
00098                 Iterator(const typename LibraryMap::const_iterator& it)
00099                 {
00100                         _it = it;
00101                 }
00102                 Iterator(const Iterator& it)
00103                 {
00104                         _it = it._it;
00105                 }
00106                 ~Iterator()
00107                 {
00108                 }
00109                 Iterator& operator = (const Iterator& it)
00110                 {
00111                         _it = it._it;
00112                         return *this;
00113                 }
00114                 inline bool operator == (const Iterator& it) const
00115                 {
00116                         return _it == it._it;
00117                 }
00118                 inline bool operator != (const Iterator& it) const
00119                 {
00120                         return _it != it._it;
00121                 }
00122                 Iterator& operator ++ () // prefix
00123                 {
00124                         ++_it;
00125                         return *this;
00126                 }
00127                 Iterator operator ++ (int) // postfix
00128                 {
00129                         Iterator result(_it);
00130                         ++_it;
00131                         return result;
00132                 }
00133                 inline const Pair* operator * () const
00134                 {
00135                         _pair.first  = _it->first;
00136                         _pair.second = _it->second.vpManifest;
00137                         return &_pair;
00138                 }
00139                 inline const Pair* operator -> () const
00140                 {
00141                         _pair.first  = _it->first;
00142                         _pair.second = _it->second.vpManifest;
00143                         return &_pair;
00144                 }
00145 
00146         private:
00147                 typename LibraryMap::const_iterator _it;
00148                 mutable Pair _pair;
00149         };
00150 
00151         ClassLoader()
00153         {
00154         }
00155 
00156         virtual ~ClassLoader()
00158         {
00159                 for (typename LibraryMap::const_iterator it = _map.begin(); it != _map.end(); ++it)
00160                 {
00161                         delete it->second.pLibrary;
00162                         for (unsigned int i = 0 ; i < it->second.vpManifest.size(); i++)
00163                         {
00164                           delete it->second.vpManifest[i].first;
00165                         }
00166                 }
00167         }
00168 
00169         void loadLibrary(const std::string& path, const std::string& manifest)
00179         {
00180                 FastMutex::ScopedLock lock(_mutex);
00181 
00182                 typename LibraryMap::iterator it = _map.find(path);
00183                 if (it == _map.end())
00184                 {
00185                         LibraryInfo li;
00186                         li.pLibrary  = new SharedLibrary(path);
00187                         li.vpManifest.push_back( manifest_pair(new Manif(), manifest));
00188                         li.refCount  = 1;
00189                         try
00190                         {
00191                                 std::string pocoBuildManifestSymbol("pocoBuildManifest");
00192                                 pocoBuildManifestSymbol.append(manifest);
00193                                 if (li.pLibrary->hasSymbol("pocoInitializeLibrary"))
00194                                 {
00195                                         InitializeLibraryFunc initializeLibrary = (InitializeLibraryFunc) li.pLibrary->getSymbol("pocoInitializeLibrary");
00196                                         initializeLibrary();
00197                                 }
00198                                 if (li.pLibrary->hasSymbol(pocoBuildManifestSymbol))
00199                                 {
00200                                         BuildManifestFunc buildManifest = (BuildManifestFunc) li.pLibrary->getSymbol(pocoBuildManifestSymbol);
00201                                         if (buildManifest(const_cast<Manif*>(li.vpManifest.back().first))){
00202                                                 _map[path] = li;
00203                                         }
00204                                         else
00205                                                 throw LibraryLoadException(std::string("Manifest class mismatch in ") + path, manifest);
00206                                 }
00207                                 else throw LibraryLoadException(std::string("No manifest in ") + path, manifest);
00208                         }
00209                         catch (...)
00210                         {
00211                                 delete li.pLibrary;
00212                                 delete li.vpManifest.back().first; //known only one long
00213                                 li.vpManifest.pop_back();
00214                                 _map.erase(path);
00215                                 throw;
00216                         }
00217                 }
00218                 else
00219                 {
00220                   bool found = false;
00221                   for (unsigned int i = 0; i < it->second.vpManifest.size(); i++)
00222                   {
00223                     if (manifest == it->second.vpManifest[i].second)
00224                     {
00225                       found = true;
00226                       break;
00227                     }
00228                   }
00229                   if ( !found)
00230                   {
00231                     //\TODO make this a function call for cut and paste from above
00232                     try
00233                         {
00234                                 std::string pocoBuildManifestSymbol("pocoBuildManifest");
00235                                 pocoBuildManifestSymbol.append(manifest);
00236                                 if (it->second.pLibrary->hasSymbol("pocoInitializeLibrary"))
00237                                 {
00238                                         InitializeLibraryFunc initializeLibrary = (InitializeLibraryFunc) it->second.pLibrary->getSymbol("pocoInitializeLibrary");
00239                                         initializeLibrary();
00240                                 }
00241                                 if (it->second.pLibrary->hasSymbol(pocoBuildManifestSymbol))
00242                                 {
00243                                         BuildManifestFunc buildManifest = (BuildManifestFunc) it->second.pLibrary->getSymbol(pocoBuildManifestSymbol);
00244                                         if (it->second.vpManifest.empty() || !buildManifest(const_cast<Manif*>(it->second.vpManifest.back().first))){   
00245                                                 throw LibraryLoadException(std::string("Manifest class mismatch in ") + path, manifest);
00246                                         }
00247                                 }
00248                                 else throw LibraryLoadException(std::string("No manifest in ") + path, manifest);
00249                         }
00250                         catch (LibraryLoadException& ex)
00251                         {
00252                           // don't delete here for there are other manifests using it delete it->second.pLibrary;
00253                                 typename std::vector< manifest_pair >::iterator man_it = it->second.vpManifest.begin();
00254                                 for(;man_it != it->second.vpManifest.end(); ++man_it){
00255                                         if(man_it->second == manifest){
00256                                                 delete man_it->first; //only last one
00257                                                 it->second.vpManifest.erase(man_it);
00258                                                 break;
00259                                         }
00260                                 }
00261                                 throw;
00262                         }
00263                   }
00264                   
00265                         ++it->second.refCount;
00266                 }
00267         }
00268 
00269         void loadLibrary(const std::string& path)
00281         {
00282                 loadLibrary(path, "");
00283         }
00284                 
00285         void unloadLibrary(const std::string& path)
00295         {
00296                 FastMutex::ScopedLock lock(_mutex);
00297 
00298                 typename LibraryMap::iterator it = _map.find(path);
00299                 if (it != _map.end())
00300                 {
00301                         if (--it->second.refCount == 0)
00302                         {
00303                                 if (it->second.pLibrary->hasSymbol("pocoUninitializeLibrary"))
00304                                 {
00305                                         UninitializeLibraryFunc uninitializeLibrary = (UninitializeLibraryFunc) it->second.pLibrary->getSymbol("pocoUninitializeLibrary");
00306                                         uninitializeLibrary();
00307                                 }
00308 
00309 
00310                                 for (unsigned int i = 0 ; i < it->second.vpManifest.size(); i++)
00311                                 {
00312                                   delete it->second.vpManifest[i].first;
00313                                 }
00314                                 
00315                                 it->second.pLibrary->unload();
00316                                 delete it->second.pLibrary;
00317                                 _map.erase(it);
00318                         }
00319                 }
00320                 else throw NotFoundException(path);
00321         }
00322 
00323         const Meta* findClass(const std::string& className) const
00326         {
00327                 FastMutex::ScopedLock lock(_mutex);
00328 
00329                 for (typename LibraryMap::const_iterator it = _map.begin(); it != _map.end(); ++it)
00330                 {
00331                   for (unsigned int i = 0 ; i < it->second.vpManifest.size(); i++)
00332                   {
00333                   
00334                         const Manif* pManif = it->second.vpManifest[i].first;
00335                         typename Manif::Iterator itm = pManif->find(className);
00336                         if (itm != pManif->end())
00337                                 return *itm;
00338                   }
00339                 }
00340                 return 0;
00341         }
00342         
00343         const Meta& classFor(const std::string& className) const
00347         {
00348                 const Meta* pMeta = findClass(className);
00349                 if (pMeta)
00350                         return *pMeta;
00351                 else
00352                         throw NotFoundException(className);
00353         }
00354         
00355         Base* create(const std::string& className) const
00359         {
00360                 return classFor(className).create();
00361         }
00362         
00363         Base& instance(const std::string& className) const
00369         {
00370                 return classFor(className).instance();
00371         }
00372         
00373         bool canCreate(const std::string& className) const
00376         {
00377                 return classFor(className).canCreate();
00378         }
00379 
00380         void destroy(const std::string& className, Base* pObject) const
00383         {
00384                 classFor(className).destroy(pObject);
00385         }
00386 
00387         bool isAutoDelete(const std::string& className, Base* pObject) const
00390         {
00391                 return classFor(className).isAutoDelete(pObject);
00392         }
00393         
00394         std::vector<manifest_pair> findManifest(const std::string& path) const
00397         {
00398                 FastMutex::ScopedLock lock(_mutex);
00399 
00400                 typename LibraryMap::const_iterator it = _map.find(path);
00401                 if (it != _map.end())
00402                         return it->second.vpManifest;
00403                 else
00404                         return 0;
00405         }
00406         
00407         const Manif& manifestFor(const std::string& path) const
00410         {
00411                 const Manif* pManif = findManifest(path);
00412                 if (pManif)
00413                         return *pManif;
00414                 else
00415                         throw NotFoundException(path);
00416         }
00417 
00418         bool isLibraryLoaded(const std::string& path) const
00421         {
00422                 return findManifest(path) != 0;
00423         }
00424 
00425         Iterator begin() const
00426         {
00427                 FastMutex::ScopedLock lock(_mutex);
00428 
00429                 return Iterator(_map.begin());
00430         }
00431 
00432         Iterator end() const
00433         {
00434                 FastMutex::ScopedLock lock(_mutex);
00435 
00436                 return Iterator(_map.end());
00437         }
00438 
00439 private:
00440         LibraryMap _map;
00441         mutable FastMutex _mutex;
00442 };
00443 
00444 
00445 } // namespace Poco
00446 
00447 
00448 #endif // Foundation_ClassLoader_INCLUDED


pluginlib
Author(s): Tully Foote and Eitan Marder-Eppstein
autogenerated on Sat Dec 28 2013 17:20:19