source: XMLIO_V2/external/include/Poco/ClassLoader.h @ 80

Last change on this file since 80 was 80, checked in by ymipsl, 14 years ago

ajout lib externe

  • Property svn:eol-style set to native
File size: 10.8 KB
Line 
1//
2// ClassLoader.h
3//
4// $Id: //poco/1.3/Foundation/include/Poco/ClassLoader.h#2 $
5//
6// Library: Foundation
7// Package: SharedLibrary
8// Module:  ClassLoader
9//
10// Definition of the ClassLoader class.
11//
12// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
13// and Contributors.
14//
15// Permission is hereby granted, free of charge, to any person or organization
16// obtaining a copy of the software and accompanying documentation covered by
17// this license (the "Software") to use, reproduce, display, distribute,
18// execute, and transmit the Software, and to prepare derivative works of the
19// Software, and to permit third-parties to whom the Software is furnished to
20// do so, all subject to the following:
21//
22// The copyright notices in the Software and this entire statement, including
23// the above license grant, this restriction and the following disclaimer,
24// must be included in all copies of the Software, in whole or in part, and
25// all derivative works of the Software, unless such copies or derivative
26// works are solely in the form of machine-executable object code generated by
27// a source language processor.
28//
29// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
32// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
33// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
34// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
35// DEALINGS IN THE SOFTWARE.
36//
37
38
39#ifndef Foundation_ClassLoader_INCLUDED
40#define Foundation_ClassLoader_INCLUDED
41
42
43#include "Poco/Foundation.h"
44#include "Poco/MetaObject.h"
45#include "Poco/Manifest.h"
46#include "Poco/SharedLibrary.h"
47#include "Poco/Mutex.h"
48#include "Poco/Exception.h"
49#include <map>
50
51
52namespace Poco {
53
54
55template <class Base>
56class ClassLoader
57        /// The ClassLoader loads C++ classes from shared libraries
58        /// at runtime. It must be instantiated with a root class
59        /// of the loadable classes.
60        /// For a class to be loadable from a library, the library
61        /// must provide a Manifest of all the classes it contains.
62        /// The Manifest for a shared library can be easily built
63        /// with the help of the macros in the header file
64        /// "Foundation/ClassLibrary.h".
65        ///
66        /// Starting with POCO release 1.3, a class library can
67        /// export multiple manifests. In addition to the default
68        /// (unnamed) manifest, multiple named manifests can
69        /// be exported, each having a different base class.
70        ///
71        /// There is one important restriction: one instance of
72        /// ClassLoader can only load one manifest from a class
73        /// library.
74{
75public:
76        typedef AbstractMetaObject<Base> Meta;
77        typedef Manifest<Base> Manif;
78        typedef void (*InitializeLibraryFunc)();
79        typedef void (*UninitializeLibraryFunc)();
80        typedef bool (*BuildManifestFunc)(ManifestBase*);
81
82        struct LibraryInfo
83        {
84                SharedLibrary* pLibrary;
85                const Manif*   pManifest;
86                int            refCount;
87        };
88        typedef std::map<std::string, LibraryInfo> LibraryMap;
89
90        class Iterator
91                /// The ClassLoader's very own iterator class.
92        {
93        public:
94                typedef std::pair<std::string, const Manif*> Pair;
95
96                Iterator(const typename LibraryMap::const_iterator& it)
97                {
98                        _it = it;
99                }
100                Iterator(const Iterator& it)
101                {
102                        _it = it._it;
103                }
104                ~Iterator()
105                {
106                }
107                Iterator& operator = (const Iterator& it)
108                {
109                        _it = it._it;
110                        return *this;
111                }
112                inline bool operator == (const Iterator& it) const
113                {
114                        return _it == it._it;
115                }
116                inline bool operator != (const Iterator& it) const
117                {
118                        return _it != it._it;
119                }
120                Iterator& operator ++ () // prefix
121                {
122                        ++_it;
123                        return *this;
124                }
125                Iterator operator ++ (int) // postfix
126                {
127                        Iterator result(_it);
128                        ++_it;
129                        return result;
130                }
131                inline const Pair* operator * () const
132                {
133                        _pair.first  = _it->first;
134                        _pair.second = _it->second.pManifest;
135                        return &_pair;
136                }
137                inline const Pair* operator -> () const
138                {
139                        _pair.first  = _it->first;
140                        _pair.second = _it->second.pManifest;
141                        return &_pair;
142                }
143
144        private:
145                typename LibraryMap::const_iterator _it;
146                mutable Pair _pair;
147        };
148
149        ClassLoader()
150                /// Creates the ClassLoader.
151        {
152        }
153
154        virtual ~ClassLoader()
155                /// Destroys the ClassLoader.
156        {
157                for (typename LibraryMap::const_iterator it = _map.begin(); it != _map.end(); ++it)
158                {
159                        delete it->second.pLibrary;
160                        delete it->second.pManifest;
161                }
162        }
163
164        void loadLibrary(const std::string& path, const std::string& manifest)
165                /// Loads a library from the given path, using the given manifest.
166                /// Does nothing if the library is already loaded.
167                /// Throws a LibraryLoadException if the library
168                /// cannot be loaded or does not have a Manifest.
169                /// If the library exports a function named "pocoInitializeLibrary",
170                /// this function is executed.
171                /// If called multiple times for the same library,
172                /// the number of calls to unloadLibrary() must be the same
173                /// for the library to become unloaded.
174        {
175                FastMutex::ScopedLock lock(_mutex);
176
177                typename LibraryMap::iterator it = _map.find(path);
178                if (it == _map.end())
179                {
180                        LibraryInfo li;
181                        li.pLibrary  = new SharedLibrary(path);
182                        li.pManifest = new Manif();
183                        li.refCount  = 1;
184                        try
185                        {
186                                std::string pocoBuildManifestSymbol("pocoBuildManifest");
187                                pocoBuildManifestSymbol.append(manifest);
188                                if (li.pLibrary->hasSymbol("pocoInitializeLibrary"))
189                                {
190                                        InitializeLibraryFunc initializeLibrary = (InitializeLibraryFunc) li.pLibrary->getSymbol("pocoInitializeLibrary");
191                                        initializeLibrary();
192                                }
193                                if (li.pLibrary->hasSymbol(pocoBuildManifestSymbol))
194                                {
195                                        BuildManifestFunc buildManifest = (BuildManifestFunc) li.pLibrary->getSymbol(pocoBuildManifestSymbol);
196                                        if (buildManifest(const_cast<Manif*>(li.pManifest)))
197                                                _map[path] = li;
198                                        else
199                                                throw LibraryLoadException(std::string("Manifest class mismatch in ") + path, manifest);
200                                }
201                                else throw LibraryLoadException(std::string("No manifest in ") + path, manifest);
202                        }
203                        catch (...)
204                        {
205                                delete li.pLibrary;
206                                delete li.pManifest;
207                                throw;
208                        }
209                }
210                else
211                {
212                        ++it->second.refCount;
213                }
214        }
215
216        void loadLibrary(const std::string& path)
217                /// Loads a library from the given path. Does nothing
218                /// if the library is already loaded.
219                /// Throws a LibraryLoadException if the library
220                /// cannot be loaded or does not have a Manifest.
221                /// If the library exports a function named "pocoInitializeLibrary",
222                /// this function is executed.
223                /// If called multiple times for the same library,
224                /// the number of calls to unloadLibrary() must be the same
225                /// for the library to become unloaded.
226                ///
227                /// Equivalent to loadLibrary(path, "").
228        {
229                loadLibrary(path, "");
230        }
231               
232        void unloadLibrary(const std::string& path)
233                /// Unloads the given library.
234                /// Be extremely cautious when unloading shared libraries.
235                /// If objects from the library are still referenced somewhere,
236                /// a total crash is very likely.
237                /// If the library exports a function named "pocoUninitializeLibrary",
238                /// this function is executed before it is unloaded.
239                /// If loadLibrary() has been called multiple times for the same
240                /// library, the number of calls to unloadLibrary() must be the same
241                /// for the library to become unloaded.
242        {
243                FastMutex::ScopedLock lock(_mutex);
244
245                typename LibraryMap::iterator it = _map.find(path);
246                if (it != _map.end())
247                {
248                        if (--it->second.refCount == 0)
249                        {
250                                if (it->second.pLibrary->hasSymbol("pocoUninitializeLibrary"))
251                                {
252                                        UninitializeLibraryFunc uninitializeLibrary = (UninitializeLibraryFunc) it->second.pLibrary->getSymbol("pocoUninitializeLibrary");
253                                        uninitializeLibrary();
254                                }
255                                delete it->second.pManifest;
256                                it->second.pLibrary->unload();
257                                delete it->second.pLibrary;
258                                _map.erase(it);
259                        }
260                }
261                else throw NotFoundException(path);
262        }
263
264        const Meta* findClass(const std::string& className) const
265                /// Returns a pointer to the MetaObject for the given
266                /// class, or a null pointer if the class is not known.
267        {
268                FastMutex::ScopedLock lock(_mutex);
269
270                for (typename LibraryMap::const_iterator it = _map.begin(); it != _map.end(); ++it)
271                {
272                        const Manif* pManif = it->second.pManifest;
273                        typename Manif::Iterator itm = pManif->find(className);
274                        if (itm != pManif->end())
275                                return *itm;
276                }
277                return 0;
278        }
279       
280        const Meta& classFor(const std::string& className) const
281                /// Returns a reference to the MetaObject for the given
282                /// class. Throws a NotFoundException if the class
283                /// is not known.
284        {
285                const Meta* pMeta = findClass(className);
286                if (pMeta)
287                        return *pMeta;
288                else
289                        throw NotFoundException(className);
290        }
291       
292        Base* create(const std::string& className) const
293                /// Creates an instance of the given class.
294                /// Throws a NotFoundException if the class
295                /// is not known.
296        {
297                return classFor(className).create();
298        }
299       
300        Base& instance(const std::string& className) const
301                /// Returns a reference to the sole instance of
302                /// the given class. The class must be a singleton,
303                /// otherwise an InvalidAccessException will be thrown.
304                /// Throws a NotFoundException if the class
305                /// is not known.
306        {
307                return classFor(className).instance();
308        }
309       
310        bool canCreate(const std::string& className) const
311                /// Returns true if create() can create new instances
312                /// of the class.
313        {
314                return classFor(className).canCreate();
315        }
316
317        void destroy(const std::string& className, Base* pObject) const
318                /// Destroys the object pObject points to.
319                /// Does nothing if object is not found.
320        {
321                classFor(className).destroy(pObject);
322        }
323
324        bool isAutoDelete(const std::string& className, Base* pObject) const
325                /// Returns true if the object is automatically
326                /// deleted by its meta object.
327        {
328                return classFor(className).isAutoDelete(pObject);
329        }
330       
331        const Manif* findManifest(const std::string& path) const
332                /// Returns a pointer to the Manifest for the given
333                /// library, or a null pointer if the library has not been loaded.
334        {
335                FastMutex::ScopedLock lock(_mutex);
336
337                typename LibraryMap::const_iterator it = _map.find(path);
338                if (it != _map.end())
339                        return it->second.pManifest;
340                else
341                        return 0;
342        }
343       
344        const Manif& manifestFor(const std::string& path) const
345                /// Returns a reference to the Manifest for the given library
346                /// Throws a NotFoundException if the library has not been loaded.
347        {
348                const Manif* pManif = findManifest(path);
349                if (pManif)
350                        return *pManif;
351                else
352                        throw NotFoundException(path);
353        }
354
355        bool isLibraryLoaded(const std::string& path) const
356                /// Returns true if the library with the given name
357                /// has already been loaded.
358        {
359                return findManifest(path) != 0;
360        }
361
362        Iterator begin() const
363        {
364                FastMutex::ScopedLock lock(_mutex);
365
366                return Iterator(_map.begin());
367        }
368
369        Iterator end() const
370        {
371                FastMutex::ScopedLock lock(_mutex);
372
373                return Iterator(_map.end());
374        }
375
376private:
377        LibraryMap _map;
378        mutable FastMutex _mutex;
379};
380
381
382} // namespace Poco
383
384
385#endif // Foundation_ClassLoader_INCLUDED
Note: See TracBrowser for help on using the repository browser.