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