Tweaked some APIs to conform better to eventual metadata
[shibboleth/sp.git] / shib / shib.h
1 /*
2  * The Shibboleth License, Version 1.
3  * Copyright (c) 2002
4  * University Corporation for Advanced Internet Development, Inc.
5  * All rights reserved
6  *
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution, if any, must include
17  * the following acknowledgment: "This product includes software developed by
18  * the University Corporation for Advanced Internet Development
19  * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
20  * may appear in the software itself, if and wherever such third-party
21  * acknowledgments normally appear.
22  *
23  * Neither the name of Shibboleth nor the names of its contributors, nor
24  * Internet2, nor the University Corporation for Advanced Internet Development,
25  * Inc., nor UCAID may be used to endorse or promote products derived from this
26  * software without specific prior written permission. For written permission,
27  * please contact shibboleth@shibboleth.org
28  *
29  * Products derived from this software may not be called Shibboleth, Internet2,
30  * UCAID, or the University Corporation for Advanced Internet Development, nor
31  * may Shibboleth appear in their name, without prior written permission of the
32  * University Corporation for Advanced Internet Development.
33  *
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36  * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
38  * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
39  * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
40  * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
41  * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
42  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
47  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  */
49
50
51 /* shib.h - Shibboleth header file
52
53    Scott Cantor
54    6/4/02
55
56    $History:$
57 */
58
59 #ifndef __shib_h__
60 #define __shib_h__
61
62 #include <saml/saml.h>
63 #include <shib/shib-threads.h>
64
65 #ifdef WIN32
66 # ifndef SHIB_EXPORTS
67 #  define SHIB_EXPORTS __declspec(dllimport)
68 # endif
69 #else
70 # define SHIB_EXPORTS
71 #endif
72
73 namespace shibboleth
74 {
75     #define DECLARE_SHIB_EXCEPTION(name,base) \
76         class SHIB_EXPORTS name : public saml::base \
77         { \
78         public: \
79             name(const char* msg) : saml::base(msg) {RTTI(name);} \
80             name(const std::string& msg) : saml::base(msg) {RTTI(name);} \
81             name(const saml::Iterator<saml::QName>& codes, const char* msg) : saml::base(codes,msg) {RTTI(name);} \
82             name(const saml::Iterator<saml::QName>& codes, const std::string& msg) : saml::base(codes, msg) {RTTI(name);} \
83             name(const saml::QName& code, const char* msg) : saml::base(code,msg) {RTTI(name);} \
84             name(const saml::QName& code, const std::string& msg) : saml::base(code, msg) {RTTI(name);} \
85             name(DOMElement* e) : saml::base(e) {RTTI(name);} \
86             name(std::istream& in) : saml::base(in) {RTTI(name);} \
87             virtual ~name() throw () {} \
88         }
89
90     DECLARE_SHIB_EXCEPTION(MetadataException,SAMLException);
91     DECLARE_SHIB_EXCEPTION(CredentialException,SAMLException);
92     DECLARE_SHIB_EXCEPTION(InvalidHandleException,RetryableProfileException);
93
94     // Manages pluggable implementations of interfaces
95     // Would prefer this to be a template, but the Windows STL isn't DLL-safe.
96
97     struct SHIB_EXPORTS IPlugIn
98     {
99         virtual ~IPlugIn() {}
100     };
101
102     class SHIB_EXPORTS PlugManager
103     {
104     public:
105         PlugManager() {}
106         ~PlugManager() {}
107
108         typedef IPlugIn* Factory(const DOMElement* source);
109         void regFactory(const char* type, Factory* factory);
110         void unregFactory(const char* type);
111         IPlugIn* newPlugin(const char* type, const DOMElement* source);
112
113     private:
114         typedef std::map<std::string, Factory*> FactoryMap;
115         FactoryMap m_map;
116     };
117
118     // Metadata abstract interfaces, inching toward SAML 2.0...
119     
120     struct SHIB_EXPORTS ILockable
121     {
122         virtual void lock()=0;
123         virtual void unlock()=0;
124         virtual ~ILockable() {}
125     };
126     
127     struct SHIB_EXPORTS IContactPerson
128     {
129         enum ContactType { technical, support, administrative, billing, other };
130         virtual ContactType getType() const=0;
131         virtual const char* getCompany() const=0;
132         virtual const char* getName() const=0;
133         virtual saml::Iterator<std::string> getEmails() const=0;
134         virtual saml::Iterator<std::string> getTelephones() const=0;
135         virtual const DOMElement* getElement() const=0;
136         virtual ~IContactPerson() {}
137     };
138
139     struct SHIB_EXPORTS IOrganization
140     {
141         virtual const char* getName(const char* lang) const=0;
142         virtual const char* getDisplayName(const char* lang) const=0;
143         virtual const char* getURL(const char* lang) const=0;
144         virtual const DOMElement* getElement() const=0;
145         virtual ~IOrganization() {}
146     };
147     
148     struct SHIB_EXPORTS IKeyDescriptor
149     {
150         enum KeyUse { encryption, signing };
151         virtual KeyUse getUse() const=0;
152         virtual const XMLCh* getEncryptionMethod() const=0;
153         virtual int getKeySize() const=0;
154         virtual DSIGKeyInfoList* getKeyInfo() const=0;
155         virtual const DOMElement* getElement() const=0;
156         virtual ~IKeyDescriptor() {}
157     };
158
159     struct SHIB_EXPORTS IEndpoint
160     {
161         virtual const XMLCh* getBinding() const=0;
162         virtual const XMLCh* getVersion() const=0;
163         virtual const XMLCh* getLocation() const=0;
164         virtual const XMLCh* getResponseLocation() const=0;
165         virtual const DOMElement* getElement() const=0;
166         virtual ~IEndpoint() {}
167     };
168
169     struct SHIB_EXPORTS IProvider;
170     struct SHIB_EXPORTS IProviderRole
171     {
172         virtual const IProvider* getProvider() const=0;
173         virtual saml::Iterator<const XMLCh*> getProtocolSupportEnumeration() const=0;
174         virtual bool hasSupport(const XMLCh* version) const=0;
175         virtual saml::Iterator<const IKeyDescriptor*> getKeyDescriptors() const=0;
176         virtual const IOrganization* getOrganization() const=0;
177         virtual saml::Iterator<const IContactPerson*> getContacts() const=0;
178         virtual saml::Iterator<const IEndpoint*> getDefaultEndpoints() const=0;
179         virtual const char* getErrorURL() const=0;
180         virtual const DOMElement* getElement() const=0;
181         virtual ~IProviderRole() {}
182     };
183        
184     struct SHIB_EXPORTS ISSOProviderRole : public virtual IProviderRole
185     {
186         virtual saml::Iterator<const IEndpoint*> getSingleLogoutServices() const=0;
187         virtual saml::Iterator<const IEndpoint*> getManageNameIdentifierServices() const=0;
188         virtual ~ISSOProviderRole() {}
189     };
190     
191     struct SHIB_EXPORTS IIDPProviderRole : public virtual ISSOProviderRole
192     {
193         virtual saml::Iterator<const IEndpoint*> getSingleSignOnServices() const=0;
194         virtual ~IIDPProviderRole() {}
195     };
196     
197     struct SHIB_EXPORTS ISPProviderRole : public virtual ISSOProviderRole
198     {
199         virtual bool getAuthnRequestsSigned() const=0;
200         virtual const IEndpoint* getDefaultAssertionConsumerServiceURL() const=0;
201         virtual const IEndpoint* getAssertionConsumerServiceURL(const XMLCh* id) const=0;
202         virtual ~ISPProviderRole() {}
203     };
204
205     struct SHIB_EXPORTS IPDPProviderRole : public virtual IProviderRole
206     {
207         virtual saml::Iterator<const IEndpoint*> getAuthorizationServices() const=0;
208         virtual ~IPDPProviderRole() {}
209     };
210
211     struct SHIB_EXPORTS IAttributeAuthorityRole : public virtual IProviderRole
212     {
213         virtual saml::Iterator<const IEndpoint*> getAttributeServices() const=0;
214         virtual ~IAttributeAuthorityRole() {}
215     };
216
217     struct SHIB_EXPORTS IAttributeRequestingService
218     {
219         virtual const XMLCh* getName(const XMLCh* lang) const=0;
220         virtual const XMLCh* getDescription(const XMLCh* lang) const=0;
221         virtual saml::Iterator<std::pair<const saml::SAMLAttributeDesignator*,bool> > getWantedAttributes() const=0;
222         virtual const DOMElement* getElement() const=0;
223         virtual ~IAttributeRequestingService() {}
224     };
225
226     struct SHIB_EXPORTS IAttributeRequesterRole : public virtual IProviderRole
227     {
228         virtual const IAttributeRequestingService* getDefaultAttributeRequestingService() const=0;
229         virtual const IAttributeRequestingService* getAttributeRequestingService(const XMLCh* id) const=0;
230         virtual saml::Iterator<const IAttributeRequestingService*> getAttributeRequestingServices() const=0;
231         virtual ~IAttributeRequesterRole() {}
232     };
233
234     struct SHIB_EXPORTS IProvider
235     {
236         virtual const XMLCh* getId() const=0;
237         virtual saml::Iterator<const XMLCh*> getGroups() const=0;
238         virtual const IOrganization* getOrganization() const=0;
239         virtual saml::Iterator<const IContactPerson*> getContacts() const=0;
240         virtual saml::Iterator<const IProviderRole*> getRoles() const=0;
241         virtual const DOMElement* getElement() const=0;
242         virtual saml::Iterator<std::pair<const XMLCh*,bool> > getSecurityDomains() const=0;
243         virtual ~IProvider() {}
244     };
245     
246     struct SHIB_EXPORTS IMetadata : public virtual ILockable, public virtual IPlugIn
247     {
248         virtual const IProvider* lookup(const XMLCh* providerId) const=0;
249         virtual ~IMetadata() {}
250     };
251
252     struct SHIB_EXPORTS IRevocation : public virtual ILockable, public virtual IPlugIn
253     {
254         virtual saml::Iterator<void*> getRevocationLists(const IProvider* provider, const IProviderRole* role=NULL) const=0;
255         virtual ~IRevocation() {}
256     };
257
258     // Trust interface hides *all* details of signature and SSL validation.
259     // Pluggable providers can fully override the Shibboleth trust model here.
260     
261     struct SHIB_EXPORTS ITrust : public virtual IPlugIn
262     {
263         virtual bool validate(
264             const saml::Iterator<IRevocation*>& revocations,
265             const IProviderRole* role, const saml::SAMLSignedObject& token,
266             const saml::Iterator<IMetadata*>& metadatas=EMPTY(IMetadata*)
267             )=0;
268         virtual bool attach(const saml::Iterator<IRevocation*>& revocations, const IProviderRole* role, void* ctx)=0;
269         virtual ~ITrust() {}
270     };
271     
272     struct SHIB_EXPORTS ICredResolver : public virtual IPlugIn
273     {
274         virtual void attach(void* ctx) const=0;
275         virtual XSECCryptoKey* getKey() const=0;
276         virtual saml::Iterator<XSECCryptoX509*> getCertificates() const=0;
277         virtual void dump(FILE* f) const=0;
278         virtual void dump() const { dump(stdout); }
279         virtual ~ICredResolver() {}
280     };
281
282     struct SHIB_EXPORTS ICredentials : public virtual ILockable, public virtual IPlugIn
283     {
284         virtual const ICredResolver* lookup(const char* id) const=0;
285         virtual ~ICredentials() {}
286     };
287     
288     struct SHIB_EXPORTS IAttributeRule
289     {
290         virtual const XMLCh* getName() const=0;
291         virtual const XMLCh* getNamespace() const=0;
292         virtual const char* getFactory() const=0;
293         virtual const char* getAlias() const=0;
294         virtual const char* getHeader() const=0;
295         virtual void apply(const IProvider* originSite, saml::SAMLAttribute& attribute) const=0;
296         virtual ~IAttributeRule() {}
297     };
298     
299     struct SHIB_EXPORTS IAAP : public virtual ILockable, public virtual IPlugIn
300     {
301         virtual const IAttributeRule* lookup(const XMLCh* attrName, const XMLCh* attrNamespace=NULL) const=0;
302         virtual const IAttributeRule* lookup(const char* alias) const=0;
303         virtual saml::Iterator<const IAttributeRule*> getAttributeRules() const=0;
304         virtual ~IAAP() {}
305     };
306
307 #ifdef SHIB_INSTANTIATE
308     template class SHIB_EXPORTS saml::Iterator<const IContactPerson*>;
309     template class SHIB_EXPORTS saml::Iterator<const IProviderRole*>;
310     template class SHIB_EXPORTS saml::Iterator<const IKeyDescriptor*>;
311     template class SHIB_EXPORTS saml::Iterator<const IEndpoint*>;
312     template class SHIB_EXPORTS saml::Iterator<const IAttributeRule*>;
313     template class SHIB_EXPORTS saml::Iterator<IMetadata*>;
314     template class SHIB_EXPORTS saml::ArrayIterator<IMetadata*>;
315     template class SHIB_EXPORTS saml::Iterator<ITrust*>;
316     template class SHIB_EXPORTS saml::ArrayIterator<ITrust*>;
317     template class SHIB_EXPORTS saml::Iterator<IRevocation*>;
318     template class SHIB_EXPORTS saml::ArrayIterator<IRevocation*>;
319     template class SHIB_EXPORTS saml::Iterator<ICredentials*>;
320     template class SHIB_EXPORTS saml::ArrayIterator<ICredentials*>;
321     template class SHIB_EXPORTS saml::Iterator<IAAP*>;
322     template class SHIB_EXPORTS saml::ArrayIterator<IAAP*>;
323 #endif
324
325     struct SHIB_EXPORTS Constants
326     {
327         static const XMLCh SHIB_ATTRIBUTE_NAMESPACE_URI[];
328         static const XMLCh SHIB_NAMEID_FORMAT_URI[];
329         static const XMLCh SHIB_NS[];
330         static const XMLCh InvalidHandle[];
331     };
332
333     // Glue classes between abstract metadata and concrete providers
334     
335     class SHIB_EXPORTS Locker
336     {
337     public:
338         Locker(ILockable* lockee) : m_lockee(lockee) {m_lockee->lock();}
339         ~Locker() {if (m_lockee) m_lockee->unlock();}
340         
341     private:
342         Locker(const Locker&);
343         void operator=(const Locker&);
344         ILockable* m_lockee;
345     };
346     
347     class SHIB_EXPORTS Metadata
348     {
349     public:
350         Metadata(const saml::Iterator<IMetadata*>& metadatas) : m_metadatas(metadatas), m_mapper(NULL) {}
351         ~Metadata();
352
353         const IProvider* lookup(const XMLCh* providerId);
354
355     private:
356         Metadata(const Metadata&);
357         void operator=(const Metadata&);
358         IMetadata* m_mapper;
359         const saml::Iterator<IMetadata*>& m_metadatas;
360     };
361
362     class SHIB_EXPORTS Revocation
363     {
364     public:
365         Revocation(const saml::Iterator<IRevocation*>& revocations) : m_revocations(revocations), m_mapper(NULL) {}
366         ~Revocation();
367
368         saml::Iterator<void*> getRevocationLists(const IProvider* provider, const IProviderRole* role=NULL);
369
370     private:
371         Revocation(const Revocation&);
372         void operator=(const Revocation&);
373         IRevocation* m_mapper;
374         const saml::Iterator<IRevocation*>& m_revocations;
375     };
376
377     class SHIB_EXPORTS Trust
378     {
379     public:
380         Trust(const saml::Iterator<ITrust*>& trusts) : m_trusts(trusts) {}
381         ~Trust() {}
382
383         bool validate(
384             const saml::Iterator<IRevocation*>& revocations,
385             const IProviderRole* role, const saml::SAMLSignedObject& token,
386             const saml::Iterator<IMetadata*>& metadatas=EMPTY(IMetadata*)
387             ) const;
388         bool attach(const saml::Iterator<IRevocation*>& revocations, const IProviderRole* role, void* ctx) const;
389         
390     private:
391         Trust(const Trust&);
392         void operator=(const Trust&);
393         const saml::Iterator<ITrust*>& m_trusts;
394     };
395     
396     class SHIB_EXPORTS Credentials
397     {
398     public:
399         Credentials(const saml::Iterator<ICredentials*>& creds) : m_creds(creds), m_mapper(NULL) {}
400         ~Credentials();
401
402         const ICredResolver* lookup(const char* id);
403
404     private:
405         Credentials(const Credentials&);
406         void operator=(const Credentials&);
407         ICredentials* m_mapper;
408         const saml::Iterator<ICredentials*>& m_creds;
409     };
410
411     class SHIB_EXPORTS AAP
412     {
413     public:
414         AAP(const saml::Iterator<IAAP*>& aaps, const XMLCh* attrName, const XMLCh* attrNamespace=NULL);
415         AAP(const saml::Iterator<IAAP*>& aaps, const char* alias);
416         ~AAP();
417         bool fail() const {return m_mapper==NULL;}
418         const IAttributeRule* operator->() const {return m_rule;}
419         operator const IAttributeRule*() const {return m_rule;}
420         
421         static void apply(const saml::Iterator<IAAP*>& aaps, const IProvider* originSite, saml::SAMLAssertion& assertion);
422         
423     private:
424         AAP(const AAP&);
425         void operator=(const AAP&);
426         IAAP* m_mapper;
427         const IAttributeRule* m_rule;
428     };
429
430     // Wrapper classes around the POST profile and SAML binding
431
432     class SHIB_EXPORTS ShibPOSTProfile
433     {
434     public:
435         ShibPOSTProfile(
436             const saml::Iterator<IMetadata*>& metadatas=EMPTY(IMetadata*),
437             const saml::Iterator<IRevocation*>& revocations=EMPTY(IRevocation*),
438             const saml::Iterator<ITrust*>& trusts=EMPTY(ITrust*),
439             const saml::Iterator<ICredentials*>& creds=EMPTY(ICredentials*)
440             );
441         virtual ~ShibPOSTProfile() {}
442
443         virtual const saml::SAMLAssertion* getSSOAssertion(
444             const saml::SAMLResponse& r, const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*)
445             );
446         virtual const saml::SAMLAuthenticationStatement* getSSOStatement(const saml::SAMLAssertion& a);
447         virtual saml::SAMLResponse* accept(
448             const XMLByte* buf,
449             const XMLCh* recipient,
450             int ttlSeconds,
451             const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*),
452             XMLCh** pproviderId=NULL
453             );
454         virtual saml::SAMLResponse* prepare(
455             const IIDPProviderRole* role,
456             const char* credResolverId,
457             const XMLCh* recipient,
458             const XMLCh* authMethod,
459             time_t authInstant,
460             const XMLCh* name,
461             const XMLCh* format=Constants::SHIB_NAMEID_FORMAT_URI,
462             const XMLCh* nameQualifier=NULL,
463             const XMLCh* subjectIP=NULL,
464             const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*),
465             const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings=EMPTY(saml::SAMLAuthorityBinding*)
466             );
467         virtual bool checkReplayCache(const saml::SAMLAssertion& a);
468         virtual const XMLCh* getProviderId(const saml::SAMLResponse& r);
469
470     protected:
471         const saml::Iterator<IMetadata*>& m_metadatas;
472         const saml::Iterator<IRevocation*>& m_revocations;
473         const saml::Iterator<ITrust*>& m_trusts;
474         const saml::Iterator<ICredentials*>& m_creds;
475     };
476
477     class SHIB_EXPORTS ShibBinding
478     {
479     public:
480         ShibBinding(
481             const saml::Iterator<IRevocation*>& revocations,
482             const saml::Iterator<ITrust*>& trusts,
483             const saml::Iterator<ICredentials*>& creds
484             ) : m_revocations(revocations), m_trusts(trusts), m_creds(creds),
485                 m_credResolverId(NULL), m_AA(NULL), m_binding(NULL) {}
486         virtual ~ShibBinding() {delete m_binding;}
487
488         saml::SAMLResponse* send(
489             saml::SAMLRequest& req,
490             const IAttributeAuthorityRole* AA,
491             const char* credResolverId=NULL,
492             const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*),
493             const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings=EMPTY(saml::SAMLAuthorityBinding*),
494             saml::SAMLConfig::SAMLBindingConfig& conf=saml::SAMLConfig::getConfig().binding_defaults
495             );
496
497     private:
498         friend bool ssl_ctx_callback(void* ssl_ctx, void* userptr);
499         const saml::Iterator<IRevocation*>& m_revocations;
500         const saml::Iterator<ITrust*>& m_trusts;
501         const saml::Iterator<ICredentials*>& m_creds;
502         const char* m_credResolverId;
503         const IAttributeAuthorityRole* m_AA;
504         saml::SAMLBinding* m_binding;
505     };
506
507     class SHIB_EXPORTS ShibConfig
508     {
509     public:
510         ShibConfig() {}
511         virtual ~ShibConfig() {}
512
513         // global per-process setup and shutdown of Shibboleth runtime
514         virtual bool init();
515         virtual void term();
516
517         // enables runtime and clients to access configuration
518         static ShibConfig& getConfig();
519
520         // allows pluggable implementations of metadata and configuration data
521         PlugManager m_plugMgr;
522     };
523
524     /* Helper classes for implementing reloadable XML-based config files
525        The ILockable interface will usually be inherited twice, once as
526        part of the external interface to clients and once as an implementation
527        detail of the reloading class below.
528      */
529     
530     class SHIB_EXPORTS ReloadableXMLFileImpl
531     {
532     public:
533         ReloadableXMLFileImpl(const char* pathname);
534         ReloadableXMLFileImpl(const DOMElement* pathname);
535         virtual ~ReloadableXMLFileImpl();
536         
537     protected:
538         DOMDocument* m_doc;
539         const DOMElement* m_root;
540     };
541
542     class SHIB_EXPORTS ReloadableXMLFile : protected virtual ILockable
543     {
544     public:
545         ReloadableXMLFile(const DOMElement* e);
546         ~ReloadableXMLFile() { delete m_lock; delete m_impl; }
547
548         virtual void lock();
549         virtual void unlock() { if (m_lock) m_lock->unlock(); }
550
551         ReloadableXMLFileImpl* getImplementation() const;
552
553     protected:
554         virtual ReloadableXMLFileImpl* newImplementation(const char* pathname, bool first=true) const=0;
555         virtual ReloadableXMLFileImpl* newImplementation(const DOMElement* e, bool first=true) const=0;
556         mutable ReloadableXMLFileImpl* m_impl;
557         
558     private:
559         const DOMElement* m_root;
560         std::string m_source;
561         time_t m_filestamp;
562         RWLock* m_lock;
563     };
564 }
565
566 #endif