Move catalog handling to parser API from config API.
[shibboleth/cpp-xmltooling.git] / xmltooling / util / ParserPool.h
1 /**
2  * Licensed to the University Corporation for Advanced Internet
3  * Development, Inc. (UCAID) under one or more contributor license
4  * agreements. See the NOTICE file distributed with this work for
5  * additional information regarding copyright ownership.
6  *
7  * UCAID licenses this file to you under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except
9  * in compliance with the License. You may obtain a copy of the
10  * License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17  * either express or implied. See the License for the specific
18  * language governing permissions and limitations under the License.
19  */
20
21 /**
22  * @file xmltooling/util/ParserPool.h
23  *
24  * A thread-safe pool of parsers that share characteristics.
25  */
26
27 #ifndef __xmltooling_pool_h__
28 #define __xmltooling_pool_h__
29
30 #include <xmltooling/unicode.h>
31
32 #include <map>
33 #include <memory>
34 #include <stack>
35 #include <string>
36 #include <istream>
37 #include <xercesc/dom/DOM.hpp>
38 #include <xercesc/sax/InputSource.hpp>
39 #include <xercesc/util/BinInputStream.hpp>
40 #include <xercesc/util/SecurityManager.hpp>
41 #include <xercesc/util/XMLURL.hpp>
42
43 #ifndef XMLTOOLING_NO_XMLSEC
44 # include <xsec/framework/XSECDefs.hpp>
45 #endif
46
47 #if defined (_MSC_VER)
48     #pragma warning( push )
49     #pragma warning( disable : 4250 4251 )
50 #endif
51
52 namespace xmltooling {
53
54     class XMLTOOL_API Mutex;
55
56     /**
57      * A thread-safe pool of DOMBuilders that share characteristics.
58      */
59     class XMLTOOL_API ParserPool :
60 #ifdef XMLTOOLING_XERCESC_COMPLIANT_DOMLS
61         public xercesc::DOMLSResourceResolver
62 #else
63         public xercesc::DOMEntityResolver
64 #endif
65     {
66         MAKE_NONCOPYABLE(ParserPool);
67     public:
68         /**
69          * Constructs a new pool
70          *
71          * @param namespaceAware    indicates whether parsers should be namespace-aware or not
72          * @param schemaAware       indicates whether parsers should be schema-validating or not
73          */
74         ParserPool(bool namespaceAware=true, bool schemaAware=false);
75         ~ParserPool();
76
77         /**
78          * Creates a new document using a parser from this pool.
79          *
80          * @return new XML document
81          *
82          */
83         xercesc::DOMDocument* newDocument();
84
85         /**
86          * Parses a document using a pooled parser with the proper settings
87          *
88          * @param domsrc An input source containing the content to be parsed
89          * @return The DOM document resulting from the parse
90          * @throws XMLParserException thrown if there was a problem reading, parsing, or validating the XML
91          */
92         xercesc::DOMDocument* parse(
93 #ifdef XMLTOOLING_XERCESC_COMPLIANT_DOMLS
94             xercesc::DOMLSInput& domsrc
95 #else
96             xercesc::DOMInputSource& domsrc
97 #endif
98             );
99
100         /**
101          * Parses a document using a pooled parser with the proper settings
102          *
103          * @param is An input stream containing the content to be parsed
104          * @return The DOM document resulting from the parse
105          * @throws XMLParserException thrown if there was a problem reading, parsing, or validating the XML
106          */
107         xercesc::DOMDocument* parse(std::istream& is);
108
109         /**
110          * Load OASIS catalog files to map schema namespace URIs to filenames.
111          *
112          * <p>This does not provide real catalog support; only the &lt;uri&gt; element
113          * is supported to map from a namespace URI to a relative path or file:// URI.
114          *
115          * <p>Multiple files can be specified using a platform-specific path delimiter.
116          *
117          * @param pathname  path to one or more catalog files
118          * @return true iff the catalogs were successfully processed
119          */
120         bool loadCatalogs(const char* pathnames);
121
122         /**
123          * Load an OASIS catalog file to map schema namespace URIs to filenames.
124          *
125          * <p>This does not provide real catalog support; only the &lt;uri&gt; element
126          * is supported to map from a namespace URI to a relative path or file:// URI.
127          *
128          * @param pathname  path to a catalog file
129          * @return true iff the catalog was successfully processed
130          */
131         bool loadCatalog(const char* pathnames);
132
133         /**
134          * Load an OASIS catalog file to map schema namespace URIs to filenames.
135          *
136          * This does not provide real catalog support; only the &lt;uri&gt; element
137          * is supported to map from a namespace URI to a relative path or file:// URI.
138          *
139          * @param pathname  path to a catalog file
140          * @return true iff the catalog was successfully processed
141          */
142         bool loadCatalog(const XMLCh* pathname);
143
144         /**
145          * Load a schema explicitly from a local file.
146          *
147          * Note that "successful processing" does not imply that the schema is valid,
148          * only that a reference to it was successfully registered with the pool.
149          *
150          * @param nsURI     XML namespace to load
151          * @param pathname  path to schema file
152          * @return true iff the schema was successfully processed
153          */
154         bool loadSchema(const XMLCh* nsURI, const XMLCh* pathname);
155
156         /**
157          * Supplies all external entities (primarily schemas) to the parser
158          */
159 #ifdef XMLTOOLING_XERCESC_COMPLIANT_DOMLS
160         xercesc::DOMLSInput* resolveResource(
161             const XMLCh *const resourceType,
162             const XMLCh *const namespaceUri,
163             const XMLCh *const publicId,
164             const XMLCh *const systemId,
165             const XMLCh *const baseURI
166             );
167 #else
168         xercesc::DOMInputSource* resolveEntity(
169             const XMLCh* const publicId, const XMLCh* const systemId, const XMLCh* const baseURI
170             );
171 #endif
172
173     private:
174 #ifdef XMLTOOLING_XERCESC_COMPLIANT_DOMLS
175         xercesc::DOMLSParser* createBuilder();
176         xercesc::DOMLSParser* checkoutBuilder();
177         void checkinBuilder(xercesc::DOMLSParser* builder);
178 #else
179         xercesc::DOMBuilder* createBuilder();
180         xercesc::DOMBuilder* checkoutBuilder();
181         void checkinBuilder(xercesc::DOMBuilder* builder);
182 #endif
183
184         xstring m_schemaLocations;
185         std::map<xstring,xstring> m_schemaLocMap;
186
187         bool m_namespaceAware,m_schemaAware;
188 #ifdef XMLTOOLING_XERCESC_COMPLIANT_DOMLS
189         std::stack<xercesc::DOMLSParser*> m_pool;
190 #else
191         std::stack<xercesc::DOMBuilder*> m_pool;
192 #endif
193         std::auto_ptr<Mutex> m_lock;
194         std::auto_ptr<xercesc::SecurityManager> m_security;
195     };
196
197     /**
198      * A parser source that wraps a C++ input stream
199      */
200     class XMLTOOL_API StreamInputSource : public xercesc::InputSource
201     {
202     MAKE_NONCOPYABLE(StreamInputSource);
203     public:
204         /**
205          * Constructs an input source around an input stream reference.
206          *
207          * @param is        reference to an input stream
208          * @param systemId  optional system identifier to attach to the stream
209          */
210         StreamInputSource(std::istream& is, const char* systemId=nullptr);
211         /// @cond off
212         xercesc::BinInputStream* makeStream() const;
213         /// @endcond
214
215         /**
216          * A Xerces input stream that wraps a C++ input stream
217          */
218         class XMLTOOL_API StreamBinInputStream : public xercesc::BinInputStream
219         {
220         public:
221             /**
222              * Constructs a Xerces input stream around a C++ input stream reference.
223              *
224              * @param is            reference to an input stream
225              */
226             StreamBinInputStream(std::istream& is);
227             /// @cond off
228 #ifdef XMLTOOLING_XERCESC_64BITSAFE
229             XMLFilePos curPos() const;
230             const XMLCh* getContentType() const;
231 #else
232             unsigned int curPos() const;
233 #endif
234             xsecsize_t readBytes(XMLByte* const toFill, const xsecsize_t maxToRead);
235             /// @endcond
236         private:
237             std::istream& m_is;
238             xsecsize_t m_pos;
239         };
240
241     private:
242         std::istream& m_is;
243     };
244
245     /**
246      * A URL-based parser source that supports a more advanced input stream.
247      */
248     class XMLTOOL_API URLInputSource : public xercesc::InputSource
249     {
250     MAKE_NONCOPYABLE(URLInputSource);
251     public:
252         /**
253          * Constructor.
254          *
255          * @param url       source of input
256          * @param systemId  optional system identifier to attach to the source
257          * @param cacheTag  optional pointer to string used for cache management
258          */
259         URLInputSource(const XMLCh* url, const char* systemId=nullptr, std::string* cacheTag=nullptr);
260
261         /**
262          * Constructor taking a DOM element supporting the following content:
263          *
264          * <dl>
265          *  <dt>uri | url</dt>
266          *  <dd>identifies the remote resource</dd>
267          *  <dt>verifyHost</dt>
268          *  <dd>true iff name of host should be matched against TLS/SSL certificate</dd>
269          *  <dt>TransportOption elements, like so:</dt>
270          *  <dd>&lt;TransportOption provider="CURL" option="150"&gt;0&lt;/TransportOption&gt;</dd>
271          * </dl>
272          *
273          * @param e         DOM to supply configuration
274          * @param systemId  optional system identifier to attach to the source
275          * @param cacheTag  optional pointer to string used for cache management
276          */
277         URLInputSource(const xercesc::DOMElement* e, const char* systemId=nullptr, std::string* cacheTag=nullptr);
278
279         /// @cond off
280         virtual xercesc::BinInputStream* makeStream() const;
281         /// @endcond
282
283         /** Element name used to signal a non-successful response when fetching a remote document. */
284         static const char asciiStatusCodeElementName[];
285
286         /** Element name used to signal a non-successful response when fetching a remote document. */
287         static const XMLCh utf16StatusCodeElementName[];
288     private:
289 #ifdef XMLTOOLING_LITE
290         xercesc::XMLURL m_url;
291 #else
292         std::string* m_cacheTag;
293         xmltooling::auto_ptr_char m_url;
294         const xercesc::DOMElement* m_root;
295 #endif
296     };
297 };
298
299 #if defined (_MSC_VER)
300     #pragma warning( pop )
301 #endif
302
303 #endif /* __xmltooling_pool_h__ */