https://issues.shibboleth.net/jira/browse/CPPXT-58
[shibboleth/cpp-xmltooling.git] / xmltooling / util / ReloadableXMLFile.h
1 /*
2  *  Copyright 2001-2010 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * @file xmltooling/util/ReloadableXMLFile.h
19  * 
20  * Base class for file-based XML configuration.
21  */
22
23 #ifndef __xmltooling_reloadable_h__
24 #define __xmltooling_reloadable_h__
25
26 #include <xmltooling/logging.h>
27 #include <xmltooling/Lockable.h>
28
29 #include <ctime>
30 #include <string>
31 #include <xercesc/dom/DOM.hpp>
32
33 #ifndef XMLTOOLING_LITE
34     namespace xmlsignature {
35         class XMLTOOL_API Signature;
36     };
37 #endif
38
39 namespace xmltooling {
40
41     class XMLTOOL_API CondWait;
42     class XMLTOOL_API RWLock;
43     class XMLTOOL_API Thread;
44
45 #ifndef XMLTOOLING_LITE
46     class XMLTOOL_API CredentialResolver;
47     class XMLTOOL_API SignatureTrustEngine;
48 #endif
49
50     /**
51      * Base class for file-based XML configuration.
52      */
53     class XMLTOOL_API ReloadableXMLFile : protected virtual Lockable
54     {
55     MAKE_NONCOPYABLE(ReloadableXMLFile);
56     protected:
57         /**
58          * Constructor taking a DOM element supporting the following content:
59          * 
60          * <dl>
61          *  <dt>file | filename | path | pathname</dt>
62          *  <dd>identifies a local file</dd>
63          *  <dt>uri | url</dt>
64          *  <dd>identifies a remote resource</dd>
65          *  <dt>validate</dt>
66          *  <dd>use a validating parser</dd>
67          *  <dt>reloadChanges</dt>
68          *  <dd>enables monitoring of local file for changes</dd>
69          *  <dt>reloadInterval</dt>
70          *  <dd>enables periodic refresh of remote file</dd>
71          *  <dt>backingFilePath</dt>
72          *  <dd>location for backup of remote resource</dd>
73          *  <dt>id</dt>
74          *  <dd>identifies the plugin instance for logging purposes</dd>
75          *  <dt>certificate</dt>
76          *  <dd>requires XML be signed with an enveloped signature verifiable with specified key</dd>
77          *  <dt>signerName</dt>
78          *  <dd>requires XML be signed with an enveloped signature verifiable with &lt;TrustEngine&gt;
79          *      by certificate containing this name</dd>
80          *  <dt>&lt;CredentialResolver&gt;</dt>
81          *  <dd>requires XML be signed with an enveloped signature verifiable with specified key</dd>
82          *  <dt>&lt;TrustEngine&gt;</dt>
83          *  <dd>requires XML be signed with an enveloped signature verifiable with specified TrustEngine</dd>
84          * </dl>
85          * 
86          * @param e     DOM to supply configuration
87          * @param log   logging object to use
88          */
89         ReloadableXMLFile(const xercesc::DOMElement* e, logging::Category& log);
90     
91         virtual ~ReloadableXMLFile();
92
93         /**
94          * Loads configuration material.
95          * 
96          * <p>This method is called to load configuration material
97          * initially and any time a change is detected. The base version
98          * performs basic parsing duties and returns the result.
99          *
100          * <p>This method is not called with the object locked, so actual
101          * modification of implementation state requires explicit locking within
102          * the method override.
103          * 
104          * @return a pair consisting of a flag indicating whether to take ownership of
105          *      the document, and the root element of the tree to load
106          */
107         virtual std::pair<bool,xercesc::DOMElement*> background_load();
108
109         /**
110          * Basic load/parse of configuration material.
111          * 
112          * <p>The base version performs basic parsing duties and returns the result.
113          * Subclasses should override the new background_load() method and perform
114          * their own locking in conjunction with use of this method.
115          *
116          * <p>Subclasses that continue to override this method will function, but
117          * a write lock will be acquired and held for the entire operation.
118          * 
119          * @return a pair consisting of a flag indicating whether to take ownership of
120          *      the document, and the root element of the tree to load
121          */
122         virtual std::pair<bool,xercesc::DOMElement*> load();
123
124         /**
125          * Accesses a lock interface protecting use of backup file associated with the
126          * object.
127          *
128          * <p>The lock is <strong>NOT</strong> acquired automatically.
129          *
130          * @return  pointer to a lock interface, or nullptr if unnecessary
131          */
132         virtual Lockable* getBackupLock();
133
134         /**
135          * Shuts down reload thread, should be called from subclass destructor.
136          */
137         void shutdown();
138
139         /** Root of the original DOM element passed into constructor. */
140         const xercesc::DOMElement* m_root;
141         
142         /** Indicates whether resources is local or remote. */
143         bool m_local;
144         
145         /** Use a validating parser when parsing XML. */
146         bool m_validate;
147         
148         /** Resource location, may be a local path or a URI. */
149         std::string m_source;
150
151         /** Path to backup copy for remote resource. */
152         std::string m_backing;
153
154         /**
155          * Before load, indicates whether the backup is handled by the base class,
156          * after load, will be true iff it started false and a backup needs to be done.
157          */
158         bool m_backupIndicator;
159
160         /** Last modification of local resource. */
161         time_t m_filestamp;
162
163         /** Time in seconds to wait before trying for new copy of remote resource. */
164         time_t m_reloadInterval;
165
166         /** Caching tag associated with remote resource. */
167         std::string m_cacheTag;
168
169         /** Shared lock for guarding reloads. */
170         RWLock* m_lock;
171         
172         /** Logging object. */
173         logging::Category& m_log;
174
175         /** Plugin identifier. */
176         std::string m_id;
177
178 #ifndef XMLTOOLING_LITE
179         /** CredentialResolver for signature verification. */
180         CredentialResolver* m_credResolver;
181
182         /** TrustEngine for signature verification. */
183         SignatureTrustEngine* m_trust;
184
185         /** Name of signer for signature verification. */
186         std::string m_signerName;
187 #endif
188
189     public:
190         Lockable* lock();
191         void unlock();
192
193     private:
194         std::pair<bool,xercesc::DOMElement*> load(bool backup);
195 #ifndef XMLTOOLING_LITE
196         void validateSignature(xmlsignature::Signature& sigObj) const;
197 #endif
198         // Used to manage background reload/refresh.
199         bool m_shutdown;
200         CondWait* m_reload_wait;
201         Thread* m_reload_thread;
202         static void* reload_fn(void*);
203     };
204
205 };
206
207 #endif /* __xmltooling_reloadable_h__ */