1 /*------------------------------------------------------------------------------
2 Name: XmlBlasterException.cpp
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 Comment: Basic xmlBlaster exception.
6 ------------------------------------------------------------------------------*/
7 #include <util/XmlBlasterException.h>
8 #include <util/ErrorCode.h>
9 #include <stdexcept>
10 #include <util/lexical_cast.h>
11 #include <util/Global.h>
12
13
14 using namespace std;
15
16 namespace org { namespace xmlBlaster { namespace util {
17
18 XmlBlasterException::XmlBlasterException(const string &errorCodeStr,
19 const string &node,
20 const string &location,
21 const string &lang,
22 const string &message,
23 const string &versionInfo,
24 const string ×tampStr,
25 const string &stackTrace,
26 const string &embeddedMessage,
27 const string &transactionInfo)
28 : errorCodeStr_(errorCodeStr),
29 node_(node),
30 location_(location),
31 lang_(lang),
32 message_(message),
33 versionInfo_(versionInfo),
34 timestamp_(timestampStr),
35 stackTrace_(stackTrace),
36 embeddedMessage_(embeddedMessage),
37 transactionInfo_(transactionInfo)
38 {
39 if (embeddedMessage_ == "") {
40 embeddedMessage_ = "Original errorCode=" + errorCodeStr_;
41 }
42 if (stackTrace_.size() < 1 && isInternal()) stackTrace_ = getStackTrace();
43 }
44
45
46 XmlBlasterException::XmlBlasterException(const ErrorCode &errorCode,
47 const string &node,
48 const string &location,
49 const string &lang,
50 const string &versionInfo,
51 const string ×tampStr,
52 const string &stackTrace,
53 const string &embeddedMessage,
54 const string &transactionInfo)
55 : errorCodeStr_(errorCode.errorCode),
56 node_(node),
57 location_(location),
58 lang_(lang),
59 message_(errorCode.description),
60 versionInfo_(versionInfo),
61 timestamp_(timestampStr),
62 stackTrace_(stackTrace),
63 embeddedMessage_(embeddedMessage),
64 transactionInfo_(transactionInfo)
65 {
66 if (embeddedMessage_ == "") {
67 embeddedMessage_ = "Original errorCode=" + errorCodeStr_;
68 }
69 if (stackTrace_.size() < 1 && isInternal()) stackTrace_ = getStackTrace();
70 }
71
72
73 XmlBlasterException::XmlBlasterException(const ErrorCode &errorCode,
74 const string &node,
75 const string &embeddedMessage)
76 : errorCodeStr_(errorCode.errorCode),
77 node_(node),
78 location_(""),
79 lang_("en"),
80 message_(errorCode.description),
81 versionInfo_(Global::getReleaseId()),
82 timestamp_(""),
83 stackTrace_(""),
84 embeddedMessage_(embeddedMessage),
85 transactionInfo_("<transactioninfo/>")
86 {
87 if (embeddedMessage_ == "") {
88 embeddedMessage_ = "Original errorCode=" + errorCodeStr_;
89 }
90 if (stackTrace_.size() < 1 && isInternal()) stackTrace_ = getStackTrace();
91 }
92
93 XmlBlasterException::~XmlBlasterException() throw()
94 {
95 }
96
97 const char *XmlBlasterException::what() const throw()
98 {
99 str_ = toString();
100 return str_.c_str();
101 }
102
103 string XmlBlasterException::getErrorCodeStr() const
104 {
105 return errorCodeStr_;
106 }
107
108 string XmlBlasterException::getNode() const
109 {
110 return node_;
111 }
112
113 string XmlBlasterException::getLocation() const
114 {
115 return location_;
116 }
117
118 string XmlBlasterException::getLang() const
119 {
120 return lang_;
121 }
122
123 string XmlBlasterException::getMessage() const
124 {
125 string ret = errorCodeStr_ ;
126 ret += ", node=" + node_;
127 if (getLocation() != "") ret += ", location=" + getLocation();
128 if (getLang() != "en") ret += ", lang=" + getLang();
129 if (getVersionInfo() != "") ret += ", versionInfo=" + getVersionInfo();
130 if (timestamp_ != "") ret += ", timestamp=" + getTimestamp();
131 if (getStackTrace() != "") ret += ", stackTrace=" + getStackTrace();
132 if (getEmbeddedMessage() != "") ret += ", embeddedMessage=" + getEmbeddedMessage();
133 if (getTransactionInfo() != "" && getTransactionInfo() != "<transactioninfo/>")
134 ret += ", transactionInfo=" + getTransactionInfo();
135 ret += ", original message=" + message_;
136 return ret;
137 }
138
139 string XmlBlasterException::getRawMessage() const
140 {
141 return message_;
142 }
143
144 string XmlBlasterException::getVersionInfo() const
145 {
146 return versionInfo_;
147 }
148
149 string XmlBlasterException::getTimestamp() const
150 {
151 if (timestamp_ == "") {
152 timestamp_ = lexical_cast<std::string>(TimestampFactory::getInstance().getTimestamp());
153 }
154 return timestamp_;
155 }
156
157 string XmlBlasterException::getStackTraceStr() const
158 {
159 return stackTrace_;
160 }
161
162 string XmlBlasterException::getEmbeddedMessage() const
163 {
164 return embeddedMessage_;
165 }
166
167 string XmlBlasterException::getTransactionInfo() const
168 {
169 return transactionInfo_;
170 }
171
172 bool XmlBlasterException::isInternal() const
173 {
174 return (errorCodeStr_.find("internal") == 0);
175 }
176
177 bool XmlBlasterException::isResource() const
178 {
179 return (errorCodeStr_.find("resource") == 0);
180 }
181
182 bool XmlBlasterException::isCommunication() const
183 {
184 return (errorCodeStr_.find("communication") == 0);
185 }
186
187 bool XmlBlasterException::isUser() const
188 {
189 return (errorCodeStr_.find("user") == 0);
190 }
191
192 bool XmlBlasterException::isTransaction() const
193 {
194 return (errorCodeStr_.find("transaction") == 0);
195 }
196
197 /**
198 * Returns a stringified version of the exception
199 */
200 string XmlBlasterException::toString() const
201 {
202 return "errorCode=" + getErrorCodeStr() + " message=" + getRawMessage();
203 }
204
205 /**
206 * Parsing what toString() produced
207 */
208 XmlBlasterException XmlBlasterException::parseFromString(string fromString)
209 {
210 string errorCode = fromString;
211 string reason = fromString;
212 size_t start = fromString.find("errorCode=");
213 size_t end = fromString.find(" message=");
214 if (start != string::npos) {
215 if (end != string::npos) {
216 try {
217 errorCode = fromString.substr(start+(sizeof("errorCode=")/sizeof("e")), end);
218 }
219 catch(const out_of_range &/*e1*/) {
220 }
221 }
222 else {
223 try {
224 errorCode = fromString.substr(start+(sizeof("errorCode=")/sizeof("e")));
225 }
226 catch(out_of_range &/*e2*/) {
227 }
228 }
229 }
230 if (end != string::npos) {
231 try {
232 reason = fromString.substr(end+(sizeof(" message=")/sizeof("e")));
233 }
234 catch(out_of_range &/*e3*/) {
235 }
236 }
237 try {
238 return XmlBlasterException(errorCode, "XmlBlasterException", "en", reason);
239 }
240 catch (...) {
241 return XmlBlasterException(INTERNAL_ILLEGALARGUMENT.errorCode, "XmlBlasterException", "en", fromString);
242 }
243 }
244
245 /**
246 * Create a XML representation of the Exception.
247 * <pre>
248 * <exception errorCode='resource.outOfMemory'>
249 * <class>JavaClass</class>
250 * <message><![cdata[ bla bla ]]></message>
251 * </exception>
252 * </pre>
253 */
254 string XmlBlasterException::toXml() const
255 {
256 string buf = "<exception errorCode='" + getErrorCodeStr() + "'>\n";
257 if (getNode() != "") buf += " <node>" + getNode() + "</node>\n";
258 if (getLocation() != "") buf += " <location>" + getLocation() + "</location>\n";
259 if (getLang() != "en") buf += " <lang>" + getLang() + "</lang>\n";
260 if (getRawMessage() != "") buf += " <message><![CDATA[" + getRawMessage() + "]]></message>\n";
261 if (getVersionInfo() != "") buf += " <versionInfo>" + getVersionInfo() + "</versionInfo>\n";
262 buf += " <timestamp>" + getTimestamp() + "</timestamp>\n";
263 if (getStackTraceStr() != "") buf += " <stackTrace><![CDATA[" + getStackTraceStr() + "]]></stackTrace>\n";
264 if (getEmbeddedMessage() != "") buf += " <embeddedMessage><![CDATA[" + getEmbeddedMessage() + "]]></embeddedMessage>\n";
265 // buf += " <transactionInfo><![CDATA[" + getTransactionInfo() + "]]></transactionInfo>\n";
266 buf += "</exception>";
267 return buf;
268 }
269
270 #if defined(_ENABLE_STACK_TRACE_) && defined(__GNUC__)
271 string XmlBlasterException::getStackTrace(int maxNumOfLines)
272 {
273 void** arr = new void*[maxNumOfLines];
274 /*
275 > +Currently, the function name and offset can only be obtained on systems
276 > +that use the ELF binary format for programs and libraries.
277 Perhaps a reference to the addr2line program can be added here. It
278 can be used to retrieve symbols even if the -rdynamic flag wasn't
279 passed to the linker, and it should work on non-ELF targets as well.
280 o Under linux, gcc interprets it by setting the
281 "-export-dynamic" option for ld, which has that effect, according
282 to the linux ld manpage.
283
284 o Under IRIX it's ignored, and the program's happy as a clam.
285
286 o Under SunOS-4.1, gcc interprets it by setting the -dc -dp
287 options for ld, which again forces the allocation of the symbol
288 table in the code produced (see ld(1) on a Sun).
289 */
290 int bt = backtrace(arr, maxNumOfLines);
291 char** list = backtrace_symbols(arr, bt); // malloc the return pointer, the entries don't need to be freed
292 string ret;
293 for (int i=0; i<bt; i++) {
294 if (list[i] != NULL) ret += list[i] + string("\n");
295 }
296 free(list);
297 delete[] arr;
298 if (ret.size() < 1) {
299 ret = "Creation of stackTrace failed";
300 }
301 return ret;
302 }
303 #else
304 string XmlBlasterException::getStackTrace(int )
305 {
306 return ""; //no stack trace provided in this system";
307 }
308 #endif
309
310 }}} // namespaces
syntax highlighted by Code2HTML, v. 0.9.1