StreamBase C++ API  7.5.4dev
Exceptions.hpp
1 //
2 // Copyright (c) 2004-2015 Cloud Software Group, Inc. All rights reserved.
3 //
4 
5 #ifndef STREAMBASE_EXCEPTIONS_H
6 #define STREAMBASE_EXCEPTIONS_H
7 
8 #include "StreamBase.hpp"
9 #include <string>
10 #include <exception>
11 #include <NMSTL/ptr.hpp>
12 #include "Errors.hpp"
13 
14 SB_INTERNAL_FWD(XMLExceptionBuilder);
15 SB_INTERNAL_FWD(Errors);
16 SB_INTERNAL_FWD(StackTrace);
17 
18 SB_NAMESPACE_BEGIN;
19 
20 #include "ExceptionCodes.hpp"
21 
22 #define SB_Throw(x) do { \
23  x.file(__FILE__).line(__LINE__).function(__FUNCTION__).throwMyself(); \
24  NMSTL_ASSERT_UNREACHABLE(); \
25 } while(0)
26 
27 // ________________________________________________________________________
28 /// The base class for all StreamBaseExceptions. Currently defined exceptions
29 /// include
30 ///
31 /// - StreamBaseNoSuchEntityException: requested an entity which doesn't exist
32 /// - StreamBaseBadXmlException: non-well-formed (i.e., unparseable) XML
33 /// - StreamBaseBadEntityException: semantically invalid entity description (e.g., box doesn't have a type)
34 /// - StreamBaseTypingException: typechecking failed
35 /// - StreamBaseIllegalArgumentException: miscellaneous illegal argument provided
36 ///
37 /// An StreamBaseException should never be thrown directly; use the
38 /// Throw macro instead.
39 class StreamBaseException : public std::exception {
40  public:
41  /// Constructor.
42  ///
43  /// @param code see ExceptionsCodes.hpp; use SB_NEW_MESSAGE_CODE if in doubt
44  /// @param message the exception message
45  /// @param error_type the class of error, for server runtime error handling
46  /// @param type the type of the exception
47  StreamBaseException(std::string code, std::string message,
48  sb_internal::Errors::Type error_type = sb_internal::Errors::UNKNOWNTYPE,
49  std::string type = "StreamBaseException");
50 
51  /// Constructor.
52  ///
53  /// @param code see ExceptionsCodes.hpp; use SB_NEW_MESSAGE_CODE if in doubt
54  /// @param message the exception message
55  /// @param c an exception that is the "cause" of this exception
56  /// @param error_type the class of error, for server runtime error handling
57  /// @param type the type of the exception
58  StreamBaseException(std::string code, std::string message, StreamBaseException& c,
59  sb_internal::Errors::Type error_type = sb_internal::Errors::UNKNOWNTYPE,
60  std::string type = "StreamBaseException");
61 
62 #ifndef DOXYGEN_SKIP
63  /// Create a StreamBaseException from a given xmlstring. Xmlstring must start with
64  /// the <exception> node as produced by asXmlString
65  static StreamBaseException fromXmlString(const std::string &xmlstring, NMSTL::ptr<StreamBaseException> cause = NMSTL::ptr<StreamBaseException>());
66 #endif
67 
68  /// Destructor.
69  virtual ~StreamBaseException() throw();
70 
71  /// Returns the message as a C string. The string is owned by this
72  /// object, so the pointer becomes invalid upon destruction of the
73  /// StreamBaseException.
74  virtual const char *what() const throw() { return _message.c_str(); }
75 
76 #ifndef DOXYGEN_SKIP
77  /// Returns the message.
78  std::string getMessage() const { return _message; }
79  std::string getSummary() const { return _summary.empty() ? _message : _summary; }
80 
81  /// Returns the source file line number, function in which the exception was
82  /// thrown (or an empty string if unknown).
83  std::string getFile() const { return _file; }
84  unsigned int getLine() const { return _line; }
85  std::string getFunction() const { return _function; }
86 
87  /// Returns the type of the exception (e.g., "StreamBaseException" or
88  /// "StreamBaseNoSuchEntityException").
89  std::string getType() const { return _type; }
90 
91  /// Returns the Errors::Type of the exception FATAL, NON_FATAL, MEM, etc..
92  ///
93  sb_internal::Errors::Type getErrorType() const { return _error_type; }
94 
95  /// Returns a description containing all known information about the message.
96  std::string as_string() const;
97 
98  /// Returns a stack trace describing where the exception was
99  /// thrown. Uses external programs; may be very slow.
100  std::string getStackTrace() const;
101 
102  // Find exception in chain that matches type. Return NULL
103  StreamBaseException *findByType(const std::string type);
104  // Return deepest exception in chain
105  StreamBaseException& getDeepest();
106 
107  // Return exception chain as a string, for various contexts
108  virtual std::string asXmlStringSingle() const;
109  virtual std::string asXmlString() const; // return chain as XML tree, for wire
110  virtual std::string chainAsString() const; // return chain, as printable string
111  virtual std::string linkAsString() const; // return single link of chain, as string
112  virtual std::string getChainOfMessages() const; // chain all exception messages together
113 
114  std::string getCode() const { return _code; }
115  StreamBaseException& getCause() const { return *_cause; }
116  bool hasCause() const { return _cause; } // does this exception have a cause?
117 
118  const std::string getParam(const std::string name) const;
119  // some convenience param getters
120  const std::string getBoxParam() const;
121  const std::string getBoxName() const;
122  const std::string getFieldName() const;
123 
124  StreamBaseException& param(const std::string name, const std::string val);
125  StreamBaseException& param(const std::string name, int val);
126  StreamBaseException& code(std::string val);
127  StreamBaseException& code(int val);
128  StreamBaseException& file(const char *val);
129  StreamBaseException& file(std::string val);
130  StreamBaseException& line(int val);
131  StreamBaseException& function(const char *val);
132  StreamBaseException& function(std::string val);
133  StreamBaseException& type(std::string val);
134  StreamBaseException& message(std::string val);
135  StreamBaseException& cause(const StreamBaseException& val);
136 
137  StreamBaseException& summary(std::string val);
138 
139  // some convenience param setters
140  StreamBaseException& boxparam(std::string name);
141  StreamBaseException& boxname(std::string name);
142  StreamBaseException& fieldname(std::string name);
143 
144  virtual void throwMyself();
145 #endif
146 
147  protected:
148  virtual std::string causeAsXmlString() const; // create an xmlstring for the cause
149  private:
150  struct StackTraceHolder {
151  NMSTL::ptr<sb_internal::StackTrace> _trace;
152  StackTraceHolder(const NMSTL::ptr<sb_internal::StackTrace>&);
153  StackTraceHolder(const StackTraceHolder&);
154  StackTraceHolder& operator = (const StackTraceHolder&);
155  ~StackTraceHolder();
156  };
157 
158  std::string _message;
159  std::string _file;
160  unsigned int _line;
161  std::string _function;
162  std::string _type;
163  StackTraceHolder _trace;
164  sb_internal::Errors::Type _error_type;
165  std::map<std::string,std::string> _params;
166  std::string _code;
167  std::string _summary;
168  NMSTL::ptr<StreamBaseException> _cause;
169  std::string _xmlNodeLocation;
170  friend class sb_internal::XMLExceptionBuilder;
171 };
172 
173 #ifdef DOXYGEN_SKIP
174 #define STREAMBASE_EXCEPTION_SUBTYPE(cl, parent, error_type) class cl : public parent {};
175 #else
176 
177 #define STREAMBASE_EXCEPTION_SUBTYPE(cl, parent, error_type) \
178 class cl : public parent { \
179  public: \
180  cl(std::string code, std::string message, sb_internal::Errors::Type a_error_type=error_type, const char *type=#cl) : \
181  parent(code, message, a_error_type, type ? type : #cl) {} \
182  cl(std::string code, std::string message, StreamBaseException& c, sb_internal::Errors::Type a_error_type=error_type, const char *type=#cl) : \
183  parent(code, message, c, a_error_type, type ? type : #cl) {} \
184  void throwMyself() { throw(*this); }; \
185 }
186 
187 #endif // DOXYGEN_SKIP
188 
189 #define STREAMBASE_EXCEPTION_TYPE(cl, error_type) \
190  STREAMBASE_EXCEPTION_SUBTYPE(cl, StreamBaseException, error_type)
191 
192 
193 /// Requested an entity which doesn't exist.
194 STREAMBASE_EXCEPTION_TYPE(StreamBaseNoSuchEntityException, sb_internal::Errors::NON_FATAL_ERROR);
195 
196 /// Non-well-formed XML.
197 STREAMBASE_EXCEPTION_TYPE(StreamBaseBadXmlException, sb_internal::Errors::XML_ERROR);
198 
199 /// Semantically invalid XML (e.g., box doesn't have a type).
200 STREAMBASE_EXCEPTION_TYPE(StreamBaseBadEntityException, sb_internal::Errors::NON_FATAL_ERROR);
201 
202 /// Typechecking failed.
203 STREAMBASE_EXCEPTION_TYPE(StreamBaseTypingException, sb_internal::Errors::TYPECHECK_ERROR);
204 
205 /// Miscellaneous illegal argument.
206 STREAMBASE_EXCEPTION_TYPE(StreamBaseIllegalArgumentException, sb_internal::Errors::XMLRPC_ERROR);
207 
208 /// A feature is not implemented.
209 STREAMBASE_EXCEPTION_TYPE(StreamBaseNotImplementedException, sb_internal::Errors::NON_FATAL_ERROR);
210 
211 /// A feature is not supported.
212 STREAMBASE_EXCEPTION_TYPE(StreamBaseNotSupportedException, sb_internal::Errors::NON_FATAL_ERROR);
213 
214 /// A network (TCP/IP) error was encountered.
215 STREAMBASE_EXCEPTION_TYPE(StreamBaseNetworkException, sb_internal::Errors::XMLRPC_ERROR);
216 
217 /// A network timeout error was encountered.
218 STREAMBASE_EXCEPTION_TYPE(StreamBaseTimeoutException, sb_internal::Errors::NETWORK_ERROR);
219 
220 /// A dequeued result was not available in the time allowed
221 STREAMBASE_EXCEPTION_TYPE(StreamBaseDequeueTimeoutException, sb_internal::Errors::NETWORK_ERROR);
222 
223 /// Illegal Argument
224 STREAMBASE_EXCEPTION_TYPE(IllegalArgumentException, sb_internal::Errors::NON_FATAL_ERROR);
225 
226 /// Null value encountered
227 STREAMBASE_EXCEPTION_TYPE(NullValueException, sb_internal::Errors::NON_FATAL_ERROR);
228 
229 /// An XML/RPC error has occurred.
231  public:
232  StreamBaseXmlRpcFault(int fault_code, std::string fault_string);
233  StreamBaseXmlRpcFault(std::string code, std::string message,
234  sb_internal::Errors::Type error_type = sb_internal::Errors::UNKNOWNTYPE,
235  std::string type = "StreamBaseXmlRpcFault");
236 
237  StreamBaseXmlRpcFault(std::string code, std::string message, StreamBaseException& c,
238  sb_internal::Errors::Type error_type = sb_internal::Errors::UNKNOWNTYPE,
239  std::string type = "StreamBaseXmlRpcFault");
240 
241 #ifndef DOXYGEN_SKIP
242  //const StreamBaseXmlRpcFault& throwMyself() { throw(*this); return *this; }
243  void throwMyself() { throw(*this); }
244 #endif
245 };
246 
247 /// An Exception which contains a list of cause exceptions
249  private:
250  std::vector<StreamBaseException> causes;
251  protected:
252  virtual std::string causeAsXmlString() const; // create an xmlstring for the cause
253  public:
254  StreamBaseListException(std::string code, std::string message, const std::vector<StreamBaseException>& causes,
255  sb_internal::Errors::Type error_type = sb_internal::Errors::UNKNOWNTYPE,
256  std::string type = "StreamBaseListException");
257 
258  virtual ~StreamBaseListException() throw();
259 
260  const std::vector<StreamBaseException> &getCauses() const { return causes; }
261  std::string getChainOfMessages() const; // chain all exception messages together
262  std::string chainAsString() const;
263 
264 #ifndef DOXYGEN_SKIP
265  void throwMyself() { throw(*this); }
266 #endif
267 };
268 SB_NAMESPACE_END;
269 #endif
270