Add parametrized messaging and serialization to exceptions.
[shibboleth/cpp-xmltooling.git] / xmltooling / exceptions.h
1 /*\r
2  *  Copyright 2001-2006 Internet2\r
3  * \r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *     http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 /**\r
18  * @file exceptions.h\r
19  * \r
20  * Exception classes\r
21  */\r
22  \r
23 #if !defined(__xmltooling_exceptions_h__)\r
24 #define __xmltooling_exceptions_h__\r
25 \r
26 #include <map>\r
27 #include <string>\r
28 #include <vector>\r
29 #include <iostream>\r
30 #include <xmltooling/base.h>\r
31 \r
32 /**\r
33  * Declares a derived exception class\r
34  * \r
35  * @param name  the exception class\r
36  * @param base  the base class\r
37  */\r
38 #define DECL_XMLTOOLING_EXCEPTION(name,base) \\r
39     class XMLTOOL_EXCEPTIONAPI(XMLTOOL_API) name : public xmltooling::base { \\r
40     public: \\r
41         name(const char* msg=NULL, const xmltooling::params& p=xmltooling::params()) \\r
42             : xmltooling::base(msg,p) {} \\r
43         name(const char* msg, const xmltooling::namedparams& p) \\r
44             : xmltooling::base(msg,p) {} \\r
45         name(const std::string& msg, const xmltooling::params& p=xmltooling::params()) \\r
46             : xmltooling::base(msg,p) {} \\r
47         name(const std::string& msg, const xmltooling::namedparams& p) \\r
48             : xmltooling::base(msg,p) {} \\r
49         virtual ~name() {} \\r
50         virtual const char* getClassName() const { return "xmltooling::"#name; } \\r
51         void raise() const {throw *this;} \\r
52     }\r
53 \r
54 /**\r
55  * Declares a factory function for an exception class.\r
56  * \r
57  * @param name  the exception class name\r
58  */\r
59 #define DECL_EXCEPTION_FACTORY(name) \\r
60     xmltooling::XMLToolingException* name##Factory() \\r
61     { \\r
62         return new xmltooling::name(); \\r
63     }\r
64 \r
65 /**\r
66  * Registers a factory for an exception class.\r
67  * \r
68  * @param name  the exception class name\r
69  */\r
70 #define REGISTER_EXCEPTION_FACTORY(name) XMLToolingException::registerFactory("xmltooling::"#name,name##Factory)\r
71 \r
72 namespace xmltooling {\r
73     \r
74     /**\r
75      * Wrapper around a variable number of arguments.\r
76      */\r
77     class XMLTOOL_API params\r
78     {\r
79     public:\r
80         /**\r
81          * Initializes with zero parameters.\r
82          */\r
83         params() {}\r
84         \r
85         /**\r
86          * Initializes the parameter set.\r
87          * \r
88          * @param count     the number of parameters that follow\r
89          */\r
90         params(int count,...);\r
91         \r
92         /**\r
93          * Returns an immutable reference to the set of parameters.\r
94          * \r
95          * @return the parameter set\r
96          */\r
97         const std::vector<const char*>& get() const {return v;}\r
98         \r
99     protected:\r
100         std::vector<const char*> v;\r
101     };\r
102     \r
103     /**\r
104      * Wrapper around a variable number of name/value pairs.\r
105      */\r
106     class XMLTOOL_API namedparams : public params\r
107     {\r
108     public:\r
109         /**\r
110          * Initializes with zero parameters.\r
111          */\r
112         namedparams() {}\r
113 \r
114         /**\r
115          * Initializes the named parameter set.\r
116          * \r
117          * @param count     the number of name/value pairs that follow (must be even)\r
118          */\r
119         namedparams(int count,...);\r
120     };\r
121 \r
122     /**\r
123      * Base exception class, supports parametrized messages and XML serialization.\r
124      * Parameters are prefixed with a dollar sign ($) and can be positional ($1)\r
125      * or named ($info).\r
126      */\r
127     class XMLTOOL_EXCEPTIONAPI(XMLTOOL_API) XMLToolingException;\r
128     typedef XMLToolingException* ExceptionFactory();\r
129     \r
130     class XMLTOOL_EXCEPTIONAPI(XMLTOOL_API) XMLToolingException\r
131     {\r
132     public:\r
133         virtual ~XMLToolingException() {}\r
134 \r
135         /**\r
136          * Constructs an exception using a message and positional parameters.\r
137          * \r
138          * @param msg   error message\r
139          * @param p     an ordered set of positional parameter strings\r
140          */\r
141         XMLToolingException(const char* msg=NULL, const params& p=params());\r
142 \r
143         /**\r
144          * Constructs an exception using a message and named parameters.\r
145          * \r
146          * @param msg   error message\r
147          * @param p     a set of named parameter strings\r
148          */\r
149         XMLToolingException(const char* msg, const namedparams& p);\r
150 \r
151         /**\r
152          * Constructs an exception using a message and positional parameters.\r
153          * \r
154          * @param msg   error message\r
155          * @param p     an ordered set of positional parameter strings\r
156          */\r
157         XMLToolingException(const std::string& msg, const params& p=params());\r
158 \r
159         /**\r
160          * Constructs an exception using a message and named parameters.\r
161          * \r
162          * @param msg   error message\r
163          * @param p     a set of named parameter strings\r
164          */\r
165         XMLToolingException(const std::string& msg, const namedparams& p);\r
166 \r
167         /**\r
168          * Returns the error message, after processing any parameter references.\r
169          * \r
170          * @return  the processed message\r
171          */\r
172         const char* getMessage() const;\r
173 \r
174         /**\r
175          * Returns the error message, after processing any parameter references.\r
176          * \r
177          * @return  the processed message\r
178          */\r
179         const char* what() const {return getMessage();}\r
180 \r
181         /**\r
182          * Sets the error message.\r
183          * \r
184          * @param msg   the error message\r
185          */\r
186         void setMessage(const char* msg);\r
187 \r
188         /**\r
189          * Sets the error message.\r
190          * \r
191          * @param msg   the error message\r
192          */\r
193         void setMessage(const std::string& msg) {\r
194             setMessage(msg.c_str());\r
195         }\r
196 \r
197         /**\r
198          * Attach a set of positional parameters to the exception.\r
199          * \r
200          * @param p     an ordered set of named parameter strings\r
201          */\r
202         void addProperties(const params& p);\r
203         \r
204         /**\r
205          * Attach a set of named parameters to the exception.\r
206          * \r
207          * @param p     a set of named parameter strings\r
208          */\r
209         void addProperties(const namedparams& p);\r
210 \r
211         /**\r
212          * Attach a single positional parameter at the next available position.\r
213          * \r
214          * @param value the parameter value\r
215          */\r
216         void addProperty(const char* value) {\r
217             addProperties(params(1,value));\r
218         }\r
219 \r
220         /**\r
221          * Attach a single named parameter.\r
222          * \r
223          * @param name  the parameter name\r
224          * @param value the parameter value\r
225          */\r
226         void addProperty(const char* name, const char* value) {\r
227             addProperties(namedparams(1,name,value));\r
228         }\r
229 \r
230         /**\r
231          * Returns the parameter property with the designated position (based from one).\r
232          * \r
233          * @param index     position to access\r
234          * @return  the parameter property or NULL\r
235          */\r
236         const char* getProperty(unsigned int index) const;\r
237 \r
238         /**\r
239          * Returns the parameter property with the designated name.\r
240          * \r
241          * @param name     named parameter to access\r
242          * @return  the parameter property or NULL\r
243          */\r
244         const char* getProperty(const char* name) const;\r
245 \r
246         /**\r
247          * Raises an exception using itself.\r
248          * Used to raise an exception of a derived type.\r
249          */\r
250         virtual void raise() const {\r
251             throw *this;\r
252         }\r
253 \r
254         /**\r
255          * Returns a unique name for the exception class.\r
256          * \r
257          * @return class name\r
258          */\r
259         virtual const char* getClassName() const {\r
260             return "xmltooling::XMLToolingException";\r
261         }\r
262         \r
263         /**\r
264          * Returns a string containing a serialized representation of the exception.\r
265          * \r
266          * @return  the serialization\r
267          */\r
268         std::string toString() const;\r
269 \r
270     private:\r
271         std::string m_msg;\r
272         mutable std::string m_processedmsg;\r
273         std::map<std::string,std::string> m_params;\r
274 \r
275     public:\r
276         /**\r
277          * Builds an empty exception of the given type.\r
278          * \r
279          * @param exceptionClass    the name of the exception type to build\r
280          * @return an empty exception object\r
281          */\r
282         static XMLToolingException* getInstance(const char* exceptionClass);\r
283 \r
284         /**\r
285          * Builds an exception from a serialized input stream.\r
286          * \r
287          * @param in    input stream\r
288          * @return the exception object found in the stream\r
289          */\r
290         static XMLToolingException* fromStream(std::istream& in);\r
291         \r
292         /**\r
293          * Builds an exception from a serialized input buffer.\r
294          * \r
295          * @param s   input buffer\r
296          * @return the exception object found in the buffer\r
297          */\r
298         static XMLToolingException* fromString(const char* s);\r
299                 \r
300         /**\r
301          * Registers a factory to create exceptions of a given class name.\r
302          * \r
303          * @param exceptionClass    name of exception type\r
304          * @param factory           factory function to build exceptions with\r
305          */\r
306         static void registerFactory(const char* exceptionClass, ExceptionFactory* factory) {\r
307             m_factoryMap[exceptionClass] = factory;\r
308         }\r
309         \r
310         /**\r
311          * Unregisters the factory for a given class name.\r
312          * \r
313          * @param exceptionClass    name of exception type\r
314          */\r
315         static void deregisterFactory(const char* exceptionClass) {\r
316             m_factoryMap.erase(exceptionClass);\r
317         }\r
318 \r
319     private:\r
320         typedef std::map<std::string,ExceptionFactory*> ExceptionFactoryMap;\r
321         static ExceptionFactoryMap m_factoryMap;\r
322     };\r
323 \r
324     DECL_XMLTOOLING_EXCEPTION(XMLParserException,XMLToolingException);\r
325     DECL_XMLTOOLING_EXCEPTION(XMLObjectException,XMLToolingException);\r
326     DECL_XMLTOOLING_EXCEPTION(MarshallingException,XMLToolingException);\r
327     DECL_XMLTOOLING_EXCEPTION(UnmarshallingException,XMLToolingException);\r
328     DECL_XMLTOOLING_EXCEPTION(UnknownElementException,XMLToolingException);\r
329     DECL_XMLTOOLING_EXCEPTION(UnknownAttributeException,XMLToolingException);\r
330     DECL_XMLTOOLING_EXCEPTION(ValidationException,XMLToolingException);\r
331     DECL_XMLTOOLING_EXCEPTION(SignatureException,XMLToolingException);\r
332 \r
333 };\r
334 \r
335 #endif /* __xmltooling_exceptions_h__ */\r