00001 /*------------------------------------------------------------------------------ 00002 Name: XmlBlasterException.cpp 00003 Project: xmlBlaster.org 00004 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file 00005 Comment: Basic xmlBlaster exception. 00006 ------------------------------------------------------------------------------*/ 00007 #include <util/XmlBlasterException.h> 00008 #include <util/ErrorCode.h> 00009 #include <stdexcept> 00010 #include <util/lexical_cast.h> 00011 #include <util/Global.h> 00012 00013 00014 using namespace std; 00015 00016 namespace org { namespace xmlBlaster { namespace util { 00017 00018 XmlBlasterException::XmlBlasterException(const string &errorCodeStr, 00019 const string &node, 00020 const string &location, 00021 const string &lang, 00022 const string &message, 00023 const string &versionInfo, 00024 const string ×tampStr, 00025 const string &stackTrace, 00026 const string &embeddedMessage, 00027 const string &transactionInfo) 00028 : errorCodeStr_(errorCodeStr), 00029 node_(node), 00030 location_(location), 00031 lang_(lang), 00032 message_(message), 00033 versionInfo_(versionInfo), 00034 timestamp_(timestampStr), 00035 stackTrace_(stackTrace), 00036 embeddedMessage_(embeddedMessage), 00037 transactionInfo_(transactionInfo) 00038 { 00039 if (embeddedMessage_ == "") { 00040 embeddedMessage_ = "Original errorCode=" + errorCodeStr_; 00041 } 00042 if (stackTrace_.size() < 1 && isInternal()) stackTrace_ = getStackTrace(); 00043 } 00044 00045 00046 XmlBlasterException::XmlBlasterException(const ErrorCode &errorCode, 00047 const string &node, 00048 const string &location, 00049 const string &lang, 00050 const string &versionInfo, 00051 const string ×tampStr, 00052 const string &stackTrace, 00053 const string &embeddedMessage, 00054 const string &transactionInfo) 00055 : errorCodeStr_(errorCode.errorCode), 00056 node_(node), 00057 location_(location), 00058 lang_(lang), 00059 message_(errorCode.description), 00060 versionInfo_(versionInfo), 00061 timestamp_(timestampStr), 00062 stackTrace_(stackTrace), 00063 embeddedMessage_(embeddedMessage), 00064 transactionInfo_(transactionInfo) 00065 { 00066 if (embeddedMessage_ == "") { 00067 embeddedMessage_ = "Original errorCode=" + errorCodeStr_; 00068 } 00069 if (stackTrace_.size() < 1 && isInternal()) stackTrace_ = getStackTrace(); 00070 } 00071 00072 00073 XmlBlasterException::XmlBlasterException(const ErrorCode &errorCode, 00074 const string &node, 00075 const string &embeddedMessage) 00076 : errorCodeStr_(errorCode.errorCode), 00077 node_(node), 00078 location_(""), 00079 lang_("en"), 00080 message_(errorCode.description), 00081 versionInfo_(Global::getReleaseId()), 00082 timestamp_(""), 00083 stackTrace_(""), 00084 embeddedMessage_(embeddedMessage), 00085 transactionInfo_("<transactioninfo/>") 00086 { 00087 if (embeddedMessage_ == "") { 00088 embeddedMessage_ = "Original errorCode=" + errorCodeStr_; 00089 } 00090 if (stackTrace_.size() < 1 && isInternal()) stackTrace_ = getStackTrace(); 00091 } 00092 00093 XmlBlasterException::~XmlBlasterException() throw() 00094 { 00095 } 00096 00097 const char *XmlBlasterException::what() const throw() 00098 { 00099 str_ = toString(); 00100 return str_.c_str(); 00101 } 00102 00103 string XmlBlasterException::getErrorCodeStr() const 00104 { 00105 return errorCodeStr_; 00106 } 00107 00108 string XmlBlasterException::getNode() const 00109 { 00110 return node_; 00111 } 00112 00113 string XmlBlasterException::getLocation() const 00114 { 00115 return location_; 00116 } 00117 00118 string XmlBlasterException::getLang() const 00119 { 00120 return lang_; 00121 } 00122 00123 string XmlBlasterException::getMessage() const 00124 { 00125 string ret = errorCodeStr_ ; 00126 ret += ", node=" + node_; 00127 if (getLocation() != "") ret += ", location=" + getLocation(); 00128 if (getLang() != "en") ret += ", lang=" + getLang(); 00129 if (getVersionInfo() != "") ret += ", versionInfo=" + getVersionInfo(); 00130 if (timestamp_ != "") ret += ", timestamp=" + getTimestamp(); 00131 if (getStackTrace() != "") ret += ", stackTrace=" + getStackTrace(); 00132 if (getEmbeddedMessage() != "") ret += ", embeddedMessage=" + getEmbeddedMessage(); 00133 if (getTransactionInfo() != "" && getTransactionInfo() != "<transactioninfo/>") 00134 ret += ", transactionInfo=" + getTransactionInfo(); 00135 ret += ", original message=" + message_; 00136 return ret; 00137 } 00138 00139 string XmlBlasterException::getRawMessage() const 00140 { 00141 return message_; 00142 } 00143 00144 string XmlBlasterException::getVersionInfo() const 00145 { 00146 return versionInfo_; 00147 } 00148 00149 string XmlBlasterException::getTimestamp() const 00150 { 00151 if (timestamp_ == "") { 00152 timestamp_ = lexical_cast<std::string>(TimestampFactory::getInstance().getTimestamp()); 00153 } 00154 return timestamp_; 00155 } 00156 00157 string XmlBlasterException::getStackTraceStr() const 00158 { 00159 return stackTrace_; 00160 } 00161 00162 string XmlBlasterException::getEmbeddedMessage() const 00163 { 00164 return embeddedMessage_; 00165 } 00166 00167 string XmlBlasterException::getTransactionInfo() const 00168 { 00169 return transactionInfo_; 00170 } 00171 00172 bool XmlBlasterException::isInternal() const 00173 { 00174 return (errorCodeStr_.find("internal") == 0); 00175 } 00176 00177 bool XmlBlasterException::isResource() const 00178 { 00179 return (errorCodeStr_.find("resource") == 0); 00180 } 00181 00182 bool XmlBlasterException::isCommunication() const 00183 { 00184 return (errorCodeStr_.find("communication") == 0); 00185 } 00186 00187 bool XmlBlasterException::isUser() const 00188 { 00189 return (errorCodeStr_.find("user") == 0); 00190 } 00191 00192 bool XmlBlasterException::isTransaction() const 00193 { 00194 return (errorCodeStr_.find("transaction") == 0); 00195 } 00196 00200 string XmlBlasterException::toString() const 00201 { 00202 return "errorCode=" + getErrorCodeStr() + " message=" + getRawMessage(); 00203 } 00204 00208 XmlBlasterException XmlBlasterException::parseFromString(string fromString) 00209 { 00210 string errorCode = fromString; 00211 string reason = fromString; 00212 size_t start = fromString.find("errorCode="); 00213 size_t end = fromString.find(" message="); 00214 if (start != string::npos) { 00215 if (end != string::npos) { 00216 try { 00217 errorCode = fromString.substr(start+(sizeof("errorCode=")/sizeof("e")), end); 00218 } 00219 catch(const out_of_range &/*e1*/) { 00220 } 00221 } 00222 else { 00223 try { 00224 errorCode = fromString.substr(start+(sizeof("errorCode=")/sizeof("e"))); 00225 } 00226 catch(out_of_range &/*e2*/) { 00227 } 00228 } 00229 } 00230 if (end != string::npos) { 00231 try { 00232 reason = fromString.substr(end+(sizeof(" message=")/sizeof("e"))); 00233 } 00234 catch(out_of_range &/*e3*/) { 00235 } 00236 } 00237 try { 00238 return XmlBlasterException(errorCode, "XmlBlasterException", "en", reason); 00239 } 00240 catch (...) { 00241 return XmlBlasterException(INTERNAL_ILLEGALARGUMENT.errorCode, "XmlBlasterException", "en", fromString); 00242 } 00243 } 00244 00254 string XmlBlasterException::toXml() const 00255 { 00256 string buf = "<exception errorCode='" + getErrorCodeStr() + "'>\n"; 00257 if (getNode() != "") buf += " <node>" + getNode() + "</node>\n"; 00258 if (getLocation() != "") buf += " <location>" + getLocation() + "</location>\n"; 00259 if (getLang() != "en") buf += " <lang>" + getLang() + "</lang>\n"; 00260 if (getRawMessage() != "") buf += " <message><![CDATA[" + getRawMessage() + "]]></message>\n"; 00261 if (getVersionInfo() != "") buf += " <versionInfo>" + getVersionInfo() + "</versionInfo>\n"; 00262 buf += " <timestamp>" + getTimestamp() + "</timestamp>\n"; 00263 if (getStackTraceStr() != "") buf += " <stackTrace><![CDATA[" + getStackTraceStr() + "]]></stackTrace>\n"; 00264 if (getEmbeddedMessage() != "") buf += " <embeddedMessage><![CDATA[" + getEmbeddedMessage() + "]]></embeddedMessage>\n"; 00265 // buf += " <transactionInfo><![CDATA[" + getTransactionInfo() + "]]></transactionInfo>\n"; 00266 buf += "</exception>"; 00267 return buf; 00268 } 00269 00270 #if defined(_ENABLE_STACK_TRACE_) && defined(__GNUC__) 00271 string XmlBlasterException::getStackTrace(int maxNumOfLines) 00272 { 00273 void** arr = new void*[maxNumOfLines]; 00274 /* 00275 > +Currently, the function name and offset can only be obtained on systems 00276 > +that use the ELF binary format for programs and libraries. 00277 Perhaps a reference to the addr2line program can be added here. It 00278 can be used to retrieve symbols even if the -rdynamic flag wasn't 00279 passed to the linker, and it should work on non-ELF targets as well. 00280 o Under linux, gcc interprets it by setting the 00281 "-export-dynamic" option for ld, which has that effect, according 00282 to the linux ld manpage. 00283 00284 o Under IRIX it's ignored, and the program's happy as a clam. 00285 00286 o Under SunOS-4.1, gcc interprets it by setting the -dc -dp 00287 options for ld, which again forces the allocation of the symbol 00288 table in the code produced (see ld(1) on a Sun). 00289 */ 00290 int bt = backtrace(arr, maxNumOfLines); 00291 char** list = backtrace_symbols(arr, bt); // malloc the return pointer, the entries don't need to be freed 00292 string ret; 00293 for (int i=0; i<bt; i++) { 00294 if (list[i] != NULL) ret += list[i] + string("\n"); 00295 } 00296 free(list); 00297 delete[] arr; 00298 if (ret.size() < 1) { 00299 ret = "Creation of stackTrace failed"; 00300 } 00301 return ret; 00302 } 00303 #else 00304 string XmlBlasterException::getStackTrace(int ) 00305 { 00306 return ""; //no stack trace provided in this system"; 00307 } 00308 #endif 00309 00310 }}} // namespaces 00311 00312