Redesigned APIs, factored out pluggable bits, new wrapper classes for SAML.
[shibboleth/cpp-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(UnsupportedProtocolException,SAMLException);
91     DECLARE_SHIB_EXCEPTION(MetadataException,SAMLException);
92     DECLARE_SHIB_EXCEPTION(CredentialException,SAMLException);
93
94     // Metadata abstract interfaces, inching toward SAML 2.0...
95     
96     struct SHIB_EXPORTS ILockable
97     {
98         virtual void lock()=0;
99         virtual void unlock()=0;
100         virtual ~ILockable() {}
101     };
102     
103     struct SHIB_EXPORTS IContactPerson
104     {
105         enum ContactType { technical, support, administrative, billing, other };
106         virtual ContactType getType() const=0;
107         virtual const char* getCompany() const=0;
108         virtual const char* getName() const=0;
109         virtual saml::Iterator<std::string> getEmails() const=0;
110         virtual saml::Iterator<std::string> getTelephones() const=0;
111         virtual const DOMElement* getElement() const=0;
112         virtual ~IContactPerson() {}
113     };
114
115     struct SHIB_EXPORTS IOrganization
116     {
117         virtual const char* getName(const char* lang) const=0;
118         virtual const char* getDisplayName(const char* lang) const=0;
119         virtual const char* getURL(const char* lang) const=0;
120         virtual const DOMElement* getElement() const=0;
121         virtual ~IOrganization() {}
122     };
123     
124     struct SHIB_EXPORTS IKeyDescriptor
125     {
126         enum KeyUse { encryption, signing };
127         virtual KeyUse getUse() const=0;
128         virtual const XMLCh* getEncryptionMethod() const=0;
129         virtual int getKeySize() const=0;
130         virtual DSIGKeyInfoList* getKeyInfo() const=0;
131         virtual const DOMElement* getElement() const=0;
132         virtual ~IKeyDescriptor() {}
133     };
134
135     struct SHIB_EXPORTS IProvider;
136     struct SHIB_EXPORTS IProviderRole
137     {
138         virtual const IProvider* getProvider() const=0;
139         virtual saml::Iterator<const XMLCh*> getProtocolSupportEnumeration() const=0;
140         virtual saml::Iterator<const IKeyDescriptor*> getKeyDescriptors() const=0;
141         virtual const IOrganization* getOrganization() const=0;
142         virtual saml::Iterator<const IContactPerson*> getContacts() const=0;
143         virtual const XMLCh* getSOAPEndpoint() const=0;
144         virtual const XMLCh* getURLEndpoint() const=0;
145         virtual const char* getErrorURL() const=0;
146         virtual const DOMElement* getElement() const=0;
147         virtual ~IProviderRole() {}
148     };
149     
150     struct SHIB_EXPORTS IEndpoint
151     {
152         virtual const XMLCh* getBinding() const=0;
153         virtual const XMLCh* getVersion() const=0;
154         virtual const XMLCh* getLocation() const=0;
155         virtual ~IEndpoint() {}
156     };
157     
158     struct SHIB_EXPORTS ISSOProviderRole : public virtual IProviderRole
159     {
160         virtual saml::Iterator<const IEndpoint*> getSingleLogoutServices() const=0;
161         virtual const XMLCh* getSingleLogoutServiceReturnURL() const=0;
162         virtual saml::Iterator<const IEndpoint*> getFederationTerminationServices() const=0;
163         virtual const XMLCh* getFederationTerminationServiceReturnURL() const=0;
164         virtual saml::Iterator<const IEndpoint*> getRegisterNameIdentifierServices() const=0;
165         virtual const XMLCh* getRegisterNameIdentifierServiceReturnURL() const=0;
166         virtual ~ISSOProviderRole() {}
167     };
168     
169     struct SHIB_EXPORTS IIDPProviderRole : public virtual ISSOProviderRole
170     {
171         virtual saml::Iterator<const IEndpoint*> getSingleSignOnServices() const=0;
172         virtual ~IIDPProviderRole() {}
173     };
174     
175     struct SHIB_EXPORTS ISPProviderRole : public virtual ISSOProviderRole
176     {
177         virtual bool getAuthnRequestsSigned() const=0;
178         virtual const IEndpoint* getDefaultAssertionConsumerServiceURL() const=0;
179         virtual const IEndpoint* getAssertionConsumerServiceURL(const XMLCh* id) const=0;
180         virtual ~ISPProviderRole() {}
181     };
182
183     struct SHIB_EXPORTS IPDPProviderRole : public virtual IProviderRole
184     {
185         virtual saml::Iterator<const IEndpoint*> getAuthorizationServices() const=0;
186         virtual ~IPDPProviderRole() {}
187     };
188
189     struct SHIB_EXPORTS IAttributeAuthorityRole : public virtual IProviderRole
190     {
191         virtual saml::Iterator<const IEndpoint*> getAttributeServices() const=0;
192         virtual ~IAttributeAuthorityRole() {}
193     };
194
195     struct SHIB_EXPORTS IAttributeConsumingService
196     {
197         virtual const XMLCh* getName(const XMLCh* lang) const=0;
198         virtual const XMLCh* getDescription(const XMLCh* lang) const=0;
199         virtual saml::Iterator<std::pair<const saml::SAMLAttributeDesignator*,bool> > getWantedAttributes() const=0;
200         virtual const DOMElement* getElement() const=0;
201         virtual ~IAttributeConsumingService() {}
202     };
203
204     struct SHIB_EXPORTS IAttributeConsumerRole : public virtual IProviderRole
205     {
206         virtual const IAttributeConsumingService* getDefaultAttributeConsumingService() const=0;
207         virtual const IAttributeConsumingService* getAttributeConsumingService(const XMLCh* id) const=0;
208         virtual saml::Iterator<const IAttributeConsumingService*> getAttributeConsumingServices() const=0;
209         virtual ~IAttributeConsumerRole() {}
210     };
211
212     struct SHIB_EXPORTS IProvider
213     {
214         virtual const XMLCh* getId() const=0;
215         virtual saml::Iterator<const XMLCh*> getGroups() const=0;
216         virtual const IOrganization* getOrganization() const=0;
217         virtual saml::Iterator<const IContactPerson*> getContacts() const=0;
218         virtual saml::Iterator<const IProviderRole*> getRoles() const=0;
219         virtual const DOMElement* getElement() const=0;
220         virtual saml::Iterator<std::pair<const XMLCh*,bool> > getSecurityDomains() const=0;
221         virtual ~IProvider() {}
222     };
223     
224     struct SHIB_EXPORTS IMetadata : public virtual ILockable
225     {
226         virtual const IProvider* lookup(const XMLCh* providerId) const=0;
227         virtual ~IMetadata() {}
228     };
229
230     struct SHIB_EXPORTS IRevocation : public virtual ILockable
231     {
232         virtual saml::Iterator<void*> getRevocationLists(const IProvider* provider, const IProviderRole* role=NULL) const=0;
233         virtual ~IRevocation() {}
234     };
235
236     // Trust interface hides *all* details of signature and SSL validation.
237     // Pluggable providers can fully override the Shibboleth trust model here.
238     
239     struct SHIB_EXPORTS ITrust : public virtual ILockable
240     {
241         virtual bool validate(
242             const saml::Iterator<IRevocation*>& revocations,
243             const IProviderRole* role, const saml::SAMLSignedObject& token,
244             const saml::Iterator<IMetadata*>& metadatas=EMPTY(IMetadata*)
245             ) const=0;
246         virtual bool attach(const saml::Iterator<IRevocation*>& revocations, const IProviderRole* role, void* ctx) const=0;
247         virtual ~ITrust() {}
248     };
249     
250     struct SHIB_EXPORTS ICredResolver
251     {
252         virtual void attach(void* ctx) const=0;
253         virtual XSECCryptoKey* getKey() const=0;
254         virtual saml::Iterator<XSECCryptoX509*> getCertificates() const=0;
255         virtual void dump(FILE* f) const=0;
256         virtual void dump() const { dump(stdout); }
257         virtual ~ICredResolver() {}
258     };
259
260     struct SHIB_EXPORTS ICredentials : public virtual ILockable
261     {
262         virtual const ICredResolver* lookup(const char* id) const=0;
263         virtual ~ICredentials() {}
264     };
265     
266     struct SHIB_EXPORTS IAttributeRule
267     {
268         virtual const XMLCh* getName() const=0;
269         virtual const XMLCh* getNamespace() const=0;
270         virtual const char* getFactory() const=0;
271         virtual const char* getAlias() const=0;
272         virtual const char* getHeader() const=0;
273         virtual void apply(const IProvider* originSite, saml::SAMLAttribute& attribute) const=0;
274         virtual ~IAttributeRule() {}
275     };
276     
277     struct SHIB_EXPORTS IAAP : public virtual ILockable
278     {
279         virtual const IAttributeRule* lookup(const XMLCh* attrName, const XMLCh* attrNamespace=NULL) const=0;
280         virtual const IAttributeRule* lookup(const char* alias) const=0;
281         virtual saml::Iterator<const IAttributeRule*> getAttributeRules() const=0;
282         virtual ~IAAP() {}
283     };
284
285 #ifdef SHIB_INSTANTIATE
286     template class SHIB_EXPORTS saml::Iterator<const IContactPerson*>;
287     template class SHIB_EXPORTS saml::Iterator<const IProviderRole*>;
288     template class SHIB_EXPORTS saml::Iterator<const IKeyDescriptor*>;
289     template class SHIB_EXPORTS saml::Iterator<const IEndpoint*>;
290     template class SHIB_EXPORTS saml::Iterator<const IAttributeRule*>;
291     template class SHIB_EXPORTS saml::Iterator<IMetadata*>;
292     template class SHIB_EXPORTS saml::ArrayIterator<IMetadata*>;
293     template class SHIB_EXPORTS saml::Iterator<ITrust*>;
294     template class SHIB_EXPORTS saml::ArrayIterator<ITrust*>;
295     template class SHIB_EXPORTS saml::Iterator<IRevocation*>;
296     template class SHIB_EXPORTS saml::ArrayIterator<IRevocation*>;
297     template class SHIB_EXPORTS saml::Iterator<ICredentials*>;
298     template class SHIB_EXPORTS saml::ArrayIterator<ICredentials*>;
299     template class SHIB_EXPORTS saml::Iterator<IAAP*>;
300     template class SHIB_EXPORTS saml::ArrayIterator<IAAP*>;
301 #endif
302
303     struct SHIB_EXPORTS Constants
304     {
305         static const XMLCh SHIB_ATTRIBUTE_NAMESPACE_URI[];
306         static const XMLCh SHIB_NAMEID_FORMAT_URI[];
307         static const XMLCh SHIB_NS[];
308     };
309
310     // Glue classes between abstract metadata and concrete providers
311     
312     class SHIB_EXPORTS Metadata
313     {
314     public:
315         Metadata(const saml::Iterator<IMetadata*>& metadatas) : m_metadatas(metadatas), m_mapper(NULL) {}
316         ~Metadata();
317
318         const IProvider* lookup(const XMLCh* providerId);
319
320     private:
321         Metadata(const Metadata&);
322         void operator=(const Metadata&);
323         IMetadata* m_mapper;
324         const saml::Iterator<IMetadata*>& m_metadatas;
325     };
326
327     class SHIB_EXPORTS Revocation
328     {
329     public:
330         Revocation(const saml::Iterator<IRevocation*>& revocations) : m_revocations(revocations), m_mapper(NULL) {}
331         ~Revocation();
332
333         saml::Iterator<void*> getRevocationLists(const IProvider* provider, const IProviderRole* role=NULL);
334
335     private:
336         Revocation(const Revocation&);
337         void operator=(const Revocation&);
338         IRevocation* m_mapper;
339         const saml::Iterator<IRevocation*>& m_revocations;
340     };
341
342     class SHIB_EXPORTS Trust
343     {
344     public:
345         Trust(const saml::Iterator<ITrust*>& trusts) : m_trusts(trusts) {}
346         ~Trust() {}
347
348         bool validate(
349             const saml::Iterator<IRevocation*>& revocations,
350             const IProviderRole* role, const saml::SAMLSignedObject& token,
351             const saml::Iterator<IMetadata*>& metadatas=EMPTY(IMetadata*)
352             ) const;
353         bool attach(const saml::Iterator<IRevocation*>& revocations, const IProviderRole* role, void* ctx) const;
354         
355     private:
356         Trust(const Trust&);
357         void operator=(const Trust&);
358         const saml::Iterator<ITrust*>& m_trusts;
359     };
360     
361     class SHIB_EXPORTS Credentials
362     {
363     public:
364         Credentials(const saml::Iterator<ICredentials*>& creds) : m_creds(creds), m_mapper(NULL) {}
365         ~Credentials();
366
367         const ICredResolver* lookup(const char* id);
368
369     private:
370         Credentials(const Credentials&);
371         void operator=(const Credentials&);
372         ICredentials* m_mapper;
373         const saml::Iterator<ICredentials*>& m_creds;
374     };
375
376     class SHIB_EXPORTS AAP
377     {
378     public:
379         AAP(const saml::Iterator<IAAP*>& aaps, const XMLCh* attrName, const XMLCh* attrNamespace=NULL);
380         AAP(const saml::Iterator<IAAP*>& aaps, const char* alias);
381         ~AAP();
382         bool fail() const {return m_mapper==NULL;}
383         const IAttributeRule* operator->() const {return m_rule;}
384         operator const IAttributeRule*() const {return m_rule;}
385         
386         static void apply(const saml::Iterator<IAAP*>& aaps, const IProvider* originSite, saml::SAMLAssertion& assertion);
387         
388     private:
389         AAP(const AAP&);
390         void operator=(const AAP&);
391         IAAP* m_mapper;
392         const IAttributeRule* m_rule;
393     };
394
395     // Wrapper classes around the POST profile and SAML binding
396
397     class SHIB_EXPORTS ShibPOSTProfile
398     {
399     public:
400         ShibPOSTProfile(
401             const saml::Iterator<IMetadata*>& metadatas=EMPTY(IMetadata*),
402             const saml::Iterator<IRevocation*>& revocations=EMPTY(IRevocation*),
403             const saml::Iterator<ITrust*>& trusts=EMPTY(ITrust*),
404             const saml::Iterator<ICredentials*>& creds=EMPTY(ICredentials*)
405             );
406         virtual ~ShibPOSTProfile() {}
407
408         virtual const saml::SAMLAssertion* getSSOAssertion(
409             const saml::SAMLResponse& r, const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*)
410             );
411         virtual const saml::SAMLAuthenticationStatement* getSSOStatement(const saml::SAMLAssertion& a);
412         virtual saml::SAMLResponse* accept(
413             const XMLByte* buf,
414             const XMLCh* recipient,
415             int ttlSeconds,
416             const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*),
417             XMLCh** pproviderId=NULL
418             );
419         virtual saml::SAMLResponse* prepare(
420             const IIDPProviderRole* role,
421             const char* credResolverId,
422             const XMLCh* recipient,
423             const XMLCh* authMethod,
424             time_t authInstant,
425             const XMLCh* name,
426             const XMLCh* format=Constants::SHIB_NAMEID_FORMAT_URI,
427             const XMLCh* nameQualifier=NULL,
428             const XMLCh* subjectIP=NULL,
429             const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*),
430             const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings=EMPTY(saml::SAMLAuthorityBinding*)
431             );
432         virtual bool checkReplayCache(const saml::SAMLAssertion& a);
433         virtual const XMLCh* getProviderId(const saml::SAMLResponse& r);
434
435     protected:
436         const saml::Iterator<IMetadata*>& m_metadatas;
437         const saml::Iterator<IRevocation*>& m_revocations;
438         const saml::Iterator<ITrust*>& m_trusts;
439         const saml::Iterator<ICredentials*>& m_creds;
440     };
441
442     class SHIB_EXPORTS ShibBinding
443     {
444     public:
445         ShibBinding(
446             const saml::Iterator<IRevocation*>& revocations,
447             const saml::Iterator<ITrust*>& trusts,
448             const saml::Iterator<ICredentials*>& creds
449             ) : m_revocations(revocations), m_trusts(trusts), m_creds(creds),
450                 m_credResolverId(NULL), m_AA(NULL), m_binding(NULL) {}
451         virtual ~ShibBinding() {delete m_binding;}
452
453         saml::SAMLResponse* send(
454             saml::SAMLRequest& req,
455             const IProvider* provider,
456             const char* credResolverId=NULL,
457             const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings=EMPTY(saml::SAMLAuthorityBinding*),
458             saml::SAMLConfig::SAMLBindingConfig& conf=saml::SAMLConfig::getConfig().binding_defaults
459             );
460
461     private:
462         friend bool ssl_ctx_callback(void* ssl_ctx, void* userptr);
463         const saml::Iterator<IRevocation*>& m_revocations;
464         const saml::Iterator<ITrust*>& m_trusts;
465         const saml::Iterator<ICredentials*>& m_creds;
466         const char* m_credResolverId;
467         const IAttributeAuthorityRole* m_AA;
468         saml::SAMLBinding* m_binding;
469     };
470
471     extern "C" {
472         typedef IMetadata* MetadataFactory(const DOMElement* source);
473         typedef IRevocation* RevocationFactory(const DOMElement* source);
474         typedef ITrust* TrustFactory(const DOMElement* source);
475         typedef ICredentials* CredentialsFactory(const DOMElement* source);
476         typedef IAAP* AAPFactory(const DOMElement* source);
477         typedef ICredResolver* CredResolverFactory(const DOMElement* source);
478     }
479     
480     class SHIB_EXPORTS ShibConfig
481     {
482     public:
483         ShibConfig() {}
484         virtual ~ShibConfig();
485
486         // global per-process setup and shutdown of Shibboleth runtime
487         virtual bool init()=0;
488         virtual void term()=0;
489
490         // enables runtime and clients to access configuration
491         static ShibConfig& getConfig();
492
493         // allows pluggable implementations of metadata and configuration data
494         virtual void regFactory(const char* type, MetadataFactory* factory)=0;
495         virtual void regFactory(const char* type, RevocationFactory* factory)=0;
496         virtual void regFactory(const char* type, TrustFactory* factory)=0;
497         virtual void regFactory(const char* type, CredentialsFactory* factory)=0;
498         virtual void regFactory(const char* type, AAPFactory* factory)=0;
499         virtual void regFactory(const char* type, CredResolverFactory* factory)=0;
500         virtual void unregFactory(const char* type)=0;
501         
502         // build a specific metadata lookup object
503         virtual IMetadata* newMetadata(const char* type, const DOMElement* source) const=0;
504         virtual IRevocation* newRevocation(const char* type, const DOMElement* source) const=0;
505         virtual ITrust* newTrust(const char* type, const DOMElement* source) const=0;
506         virtual ICredentials* newCredentials(const char* type, const DOMElement* source) const=0;
507         virtual IAAP* newAAP(const char* type, const DOMElement* source) const=0;
508         virtual ICredResolver* newCredResolver(const char* type, const DOMElement* source) const=0;
509     };
510
511     /* Helper classes for implementing reloadable XML-based config files
512        The ILockable interface will usually be inherited twice, once as
513        part of the external interface to clients and once as an implementation
514        detail of the reloading class below.
515      */
516     
517     class SHIB_EXPORTS ReloadableXMLFileImpl
518     {
519     public:
520         ReloadableXMLFileImpl(const char* pathname);
521         ReloadableXMLFileImpl(const DOMElement* pathname);
522         virtual ~ReloadableXMLFileImpl();
523         
524     protected:
525         DOMDocument* m_doc;
526         const DOMElement* m_root;
527     };
528
529     class SHIB_EXPORTS ReloadableXMLFile : protected virtual ILockable
530     {
531     public:
532         ReloadableXMLFile(const DOMElement* e);
533         ~ReloadableXMLFile() { delete m_lock; delete m_impl; }
534
535         virtual void lock();
536         virtual void unlock() { if (m_lock) m_lock->unlock(); }
537
538         ReloadableXMLFileImpl* getImplementation() const;
539
540     protected:
541         virtual ReloadableXMLFileImpl* newImplementation(const char* pathname) const=0;
542         virtual ReloadableXMLFileImpl* newImplementation(const DOMElement* e) const=0;
543         
544     private:
545         const DOMElement* m_root;
546         std::string m_source;
547         time_t m_filestamp;
548         RWLock* m_lock;
549         mutable ReloadableXMLFileImpl* m_impl;
550     };
551 }
552
553 #endif