util/XmlBlasterException.cpp

Go to the documentation of this file.
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 &timestampStr,
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 &timestampStr,
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