Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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 ++ ()
00123 {
00124 ++_it;
00125 return *this;
00126 }
00127 Iterator operator ++ (int)
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;
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
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
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;
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 }
00446
00447
00448 #endif // Foundation_ClassLoader_INCLUDED