67baa8259a7e11021f3f22690968feeb17eb4976
[shibboleth/cpp-xmltooling.git] / xmltooling / exceptions.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/exceptions.h
19  * 
20  * Exception classes.
21  */
22  
23 #ifndef __xmltooling_exceptions_h__
24 #define __xmltooling_exceptions_h__
25
26 #include <xmltooling/base.h>
27
28 #include <map>
29 #include <string>
30 #include <vector>
31 #include <iostream>
32
33 /**
34  * Declares a derived exception class
35  * 
36  * @param name      the exception class
37  * @param linkage   linkage specification for class
38  * @param ns        the exception class C++ namespace
39  * @param base      the base class
40  * @param desc      documentation comment for class
41  */
42 #define DECL_XMLTOOLING_EXCEPTION(name,linkage,ns,base,desc) \
43     XMLTOOLING_DOXYGEN(desc) \
44     class linkage name : public base { \
45     public: \
46         XMLTOOLING_DOXYGEN(Constructor) \
47         name(const char* msg=nullptr, const xmltooling::params& p=xmltooling::params()) : base(msg,p) {} \
48         XMLTOOLING_DOXYGEN(Constructor) \
49         name(const char* msg, const xmltooling::namedparams& p) : base(msg,p) {} \
50         XMLTOOLING_DOXYGEN(Constructor) \
51         name(const std::string& msg, const xmltooling::params& p=xmltooling::params()) : base(msg,p) {} \
52         XMLTOOLING_DOXYGEN(Constructor) \
53         name(const std::string& msg, const xmltooling::namedparams& p) : base(msg,p) {} \
54         virtual ~name() throw () {} \
55         virtual const char* getClassName() const { return #ns"::"#name; } \
56         void raise() const {throw *this;} \
57     }
58
59 /**
60  * Declares a factory function for an exception class.
61  * 
62  * @param name  the exception class name
63  * @param ns    the exception class C++ namespace
64  */
65 #define DECL_XMLTOOLING_EXCEPTION_FACTORY(name,ns) \
66     xmltooling::XMLToolingException* name##Factory() \
67     { \
68         return new ns::name(); \
69     }
70
71 /**
72  * Registers a factory for an exception class.
73  * 
74  * @param name      the exception class name
75  * @param ns        the exception class C++ namespace
76  */
77 #define REGISTER_XMLTOOLING_EXCEPTION_FACTORY(name,ns) XMLToolingException::registerFactory(#ns"::"#name,name##Factory)
78
79 #if defined (_MSC_VER)
80     #pragma warning( push )
81     #pragma warning( disable : 4250 4251 )
82 #endif
83
84 namespace xmltooling {
85     
86     /**
87      * Wrapper around a variable number of arguments.
88      */
89     class XMLTOOL_API params
90     {
91     public:
92         /**
93          * Initializes with zero parameters.
94          */
95         params() {}
96         
97         /**
98          * Initializes the parameter set.
99          * 
100          * @param count     the number of parameters that follow
101          */
102         params(int count,...);
103         
104         /**
105          * Returns an immutable reference to the set of parameters.
106          * 
107          * @return the parameter set
108          */
109         const std::vector<const char*>& get() const {return v;}
110         
111     protected:
112         /** Contains the parameters being passed. */
113         std::vector<const char*> v;
114     };
115     
116     /**
117      * Wrapper around a variable number of name/value pairs.
118      */
119     class XMLTOOL_API namedparams : public params
120     {
121     public:
122         /**
123          * Initializes with zero parameters.
124          */
125         namedparams() {}
126
127         /**
128          * Initializes the named parameter set.
129          * 
130          * @param count     the number of name/value pairs that follow (must be even)
131          */
132         namedparams(int count,...);
133     };
134
135     /**
136      * Base exception class, supports parametrized messages and XML serialization.
137      * Parameters are prefixed with a dollar sign ($) and can be positional ($1)
138      * or named ($info).
139      */
140     class XMLTOOL_EXCEPTIONAPI(XMLTOOL_API) XMLToolingException : public std::exception
141     {
142     public:
143         virtual ~XMLToolingException() throw () {}
144
145         /**
146          * Constructs an exception using a message and positional parameters.
147          * 
148          * @param msg   error message
149          * @param p     an ordered set of positional parameter strings
150          */
151         XMLToolingException(const char* msg=nullptr, const params& p=params());
152
153         /**
154          * Constructs an exception using a message and named parameters.
155          * 
156          * @param msg   error message
157          * @param p     a set of named parameter strings
158          */
159         XMLToolingException(const char* msg, const namedparams& p);
160
161         /**
162          * Constructs an exception using a message and positional parameters.
163          * 
164          * @param msg   error message
165          * @param p     an ordered set of positional parameter strings
166          */
167         XMLToolingException(const std::string& msg, const params& p=params());
168
169         /**
170          * Constructs an exception using a message and named parameters.
171          * 
172          * @param msg   error message
173          * @param p     a set of named parameter strings
174          */
175         XMLToolingException(const std::string& msg, const namedparams& p);
176
177         /**
178          * Returns the error message, after processing any parameter references.
179          * 
180          * @return  the processed message
181          */
182         const char* getMessage() const;
183
184         /**
185          * Returns the error message, after processing any parameter references.
186          * 
187          * @return  the processed message
188          */
189         const char* what() const throw () {return getMessage();}
190
191         /**
192          * Sets the error message.
193          * 
194          * @param msg   the error message
195          */
196         void setMessage(const char* msg);
197
198         /**
199          * Sets the error message.
200          * 
201          * @param msg   the error message
202          */
203         void setMessage(const std::string& msg) {
204             setMessage(msg.c_str());
205         }
206
207         /**
208          * Attach a set of positional parameters to the exception.
209          * 
210          * @param p     an ordered set of named parameter strings
211          */
212         void addProperties(const params& p);
213         
214         /**
215          * Attach a set of named parameters to the exception.
216          * 
217          * @param p     a set of named parameter strings
218          */
219         void addProperties(const namedparams& p);
220
221         /**
222          * Attach a single positional parameter at the next available position.
223          * 
224          * @param value the parameter value
225          */
226         void addProperty(const char* value) {
227             addProperties(params(1,value));
228         }
229
230         /**
231          * Attach a single named parameter.
232          * 
233          * @param name  the parameter name
234          * @param value the parameter value
235          */
236         void addProperty(const char* name, const char* value) {
237             addProperties(namedparams(1,name,value));
238         }
239
240         /**
241          * Returns the parameter property with the designated position (based from one).
242          * 
243          * @param index     position to access
244          * @return  the parameter property or nullptr
245          */
246         const char* getProperty(unsigned int index) const;
247
248         /**
249          * Returns the parameter property with the designated name.
250          * 
251          * @param name     named parameter to access
252          * @return  the parameter property or nullptr
253          */
254         const char* getProperty(const char* name) const;
255
256         /**
257          * Raises an exception using itself.
258          * Used to raise an exception of a derived type.
259          */
260         virtual void raise() const {
261             throw *this;
262         }
263
264         /**
265          * Returns a unique name for the exception class.
266          * 
267          * @return class name
268          */
269         virtual const char* getClassName() const {
270             return "xmltooling::XMLToolingException";
271         }
272         
273         /**
274          * Returns a string containing a serialized representation of the exception.
275          * 
276          * @return  the serialization
277          */
278         std::string toString() const;
279
280         /**
281          * Returns a set of query string name/value pairs, URL-encoded, representing the
282          * exception's type, message, and parameters.
283          *
284          * @return  the query string representation
285          */
286         std::string toQueryString() const;
287
288     private:
289         std::string m_msg;
290         mutable std::string m_processedmsg;
291         std::map<std::string,std::string> m_params;
292
293     public:
294         /**
295          * Builds an empty exception of the given type.
296          * 
297          * @param exceptionClass    the name of the exception type to build
298          * @return an empty exception object
299          */
300         static XMLToolingException* getInstance(const char* exceptionClass);
301
302         /**
303          * Builds an exception from a serialized input stream.
304          * 
305          * @param in    input stream
306          * @return the exception object found in the stream
307          */
308         static XMLToolingException* fromStream(std::istream& in);
309         
310         /**
311          * Builds an exception from a serialized input buffer.
312          * 
313          * @param s   input buffer
314          * @return the exception object found in the buffer
315          */
316         static XMLToolingException* fromString(const char* s);
317                 
318         /** A factory function that returns an empty exception object of a given type. */
319         typedef XMLToolingException* ExceptionFactory();
320         
321         /**
322          * Registers a factory to create exceptions of a given class name.
323          * 
324          * @param exceptionClass    name of exception type
325          * @param factory           factory function to build exceptions with
326          */
327         static void registerFactory(const char* exceptionClass, ExceptionFactory* factory) {
328             m_factoryMap[exceptionClass] = factory;
329         }
330         
331         /**
332          * Unregisters the factory for a given class name.
333          * 
334          * @param exceptionClass    name of exception type
335          */
336         static void deregisterFactory(const char* exceptionClass) {
337             m_factoryMap.erase(exceptionClass);
338         }
339
340         /**
341          * Unregisters all factories.
342          */
343         static void deregisterFactories() {
344             m_factoryMap.clear();
345         }
346
347     private:
348         typedef std::map<std::string,ExceptionFactory*> ExceptionFactoryMap;
349         static ExceptionFactoryMap m_factoryMap;
350     };
351
352     DECL_XMLTOOLING_EXCEPTION(XMLParserException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions related to XML parsing);
353     DECL_XMLTOOLING_EXCEPTION(XMLObjectException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions in basic object usage);
354     DECL_XMLTOOLING_EXCEPTION(MarshallingException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions during object marshalling);
355     DECL_XMLTOOLING_EXCEPTION(UnmarshallingException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions during object unmarshalling);
356     DECL_XMLTOOLING_EXCEPTION(UnknownElementException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions due to processing of unknown element content);
357     DECL_XMLTOOLING_EXCEPTION(UnknownAttributeException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions due to processing of unknown attributes);
358     DECL_XMLTOOLING_EXCEPTION(UnknownExtensionException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions from use of an unrecognized extension/plugin);
359     DECL_XMLTOOLING_EXCEPTION(ValidationException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions during object validation);
360     DECL_XMLTOOLING_EXCEPTION(IOException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions related to physical input/output errors);
361
362 #ifndef XMLTOOLING_NO_XMLSEC
363     DECL_XMLTOOLING_EXCEPTION(XMLSecurityException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions related to the XML security layer);
364 #endif
365 };
366
367 #if defined (_MSC_VER)
368     #pragma warning( pop )
369 #endif
370
371 #endif /* __xmltooling_exceptions_h__ */