00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00036 #include "OWBI1_config.h"
00037 #include "OWBI1_Exception.hpp"
00038 #include "OW_StackTrace.hpp"
00039 #include "OW_Format.hpp"
00040 #if defined(OWBI1_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00041 #include "OW_Mutex.hpp"
00042 #endif
00043 #include <string.h>
00044
00045
00046 #include <cstdlib>
00047 #if defined(OWBI1_HAVE_ISTREAM) && defined(OWBI1_HAVE_OSTREAM)
00048 #include <istream>
00049 #include <ostream>
00050 #else
00051 #include <iostream>
00052 #endif
00053 #include <algorithm>
00054
00055 namespace OWBI1
00056 {
00057
00058 using namespace OpenWBEM;
00059
00060 #if defined(OWBI1_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00061 Mutex* Exception::m_mutex = new Mutex();
00062 #endif
00063
00064 static void freeBuf(char** ptr)
00065 {
00066 delete [] *ptr;
00067 *ptr = NULL;
00068 }
00070 char* Exception::dupString(const char* str)
00071 {
00072 if (!str)
00073 {
00074 return 0;
00075 }
00076 char* rv = new (std::nothrow) char[strlen(str)+1];
00077 if (!rv)
00078 {
00079 return 0;
00080 }
00081 strcpy(rv, str);
00082 return rv;
00083 }
00085 Exception::Exception(const char* file, int line, const char* msg, int errorCode, const Exception* subException, int subClassId)
00086 : std::exception()
00087 , m_file(dupString(file))
00088 , m_line(line)
00089 , m_msg(dupString(msg))
00090 , m_subClassId(subClassId)
00091 , m_subException(subException ? subException->clone() : 0)
00092 , m_errorCode(errorCode)
00093 {
00094 #ifdef OWBI1_ENABLE_STACK_TRACE_ON_EXCEPTIONS
00095 StackTrace::printStackTrace();
00096 #endif
00097 #if defined(OWBI1_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00098 m_mutex->acquire();
00099 #endif
00100 }
00102 Exception::Exception( const Exception& e )
00103 : std::exception(e)
00104 , m_file(dupString(e.m_file))
00105 , m_line(e.m_line)
00106 , m_msg(dupString(e.m_msg))
00107 , m_subClassId(e.m_subClassId)
00108 , m_subException(e.m_subException ? e.m_subException->clone() : 0)
00109 , m_errorCode(e.m_errorCode)
00110 {
00111 #if defined(OWBI1_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00112 m_mutex->acquire();
00113 #endif
00114 }
00116 Exception::~Exception() throw()
00117 {
00118 try
00119 {
00120 delete m_subException;
00121 freeBuf(&m_file);
00122 freeBuf(&m_msg);
00123 #if defined(OWBI1_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00124 m_mutex->release();
00125 #endif
00126 }
00127 catch (...)
00128 {
00129
00130 }
00131 }
00133 Exception&
00134 Exception::operator=(const Exception& rhs)
00135 {
00136 Exception(rhs).swap(*this);
00137 return *this;
00138 }
00140 void
00141 Exception::swap(Exception& rhs)
00142 {
00143 std::swap(static_cast<std::exception&>(*this), static_cast<std::exception&>(rhs));
00144 std::swap(m_file, rhs.m_file);
00145 std::swap(m_line, rhs.m_line);
00146 std::swap(m_msg, rhs.m_msg);
00147 std::swap(m_subClassId, rhs.m_subClassId);
00148 std::swap(m_subException, rhs.m_subException);
00149 std::swap(m_errorCode, rhs.m_errorCode);
00150 }
00151
00153 const char*
00154 Exception::type() const
00155 {
00156 return "Exception";
00157 }
00158
00160 int
00161 Exception::getLine() const
00162 {
00163 return m_line;
00164 }
00165
00167 const char*
00168 Exception::getMessage() const
00169 {
00170 return (m_msg != NULL) ? m_msg : "";
00171 }
00173 const char*
00174 Exception::getFile() const
00175 {
00176 return (m_file != NULL) ? m_file : "";
00177 }
00179 std::ostream&
00180 operator<<(std::ostream& os, const Exception& e)
00181 {
00182 if (*e.getFile() == '\0')
00183 {
00184 os << "[no file]: ";
00185 }
00186 else
00187 {
00188 os << e.getFile() << ": ";
00189 }
00190
00191 if (e.getLine() == 0)
00192 {
00193 os << "[no line] ";
00194 }
00195 else
00196 {
00197 os << e.getLine() << ' ';
00198 }
00199
00200 os << e.type() << ": ";
00201
00202 if (*e.getMessage() == '\0')
00203 {
00204 os << "[no message]";
00205 }
00206 else
00207 {
00208 os << e.getMessage();
00209 }
00210
00211 const Exception* subEx = e.getSubException();
00212 if (subEx)
00213 {
00214 os << " <" << *subEx << '>';
00215 }
00216 return os;
00217 }
00219 const char*
00220 Exception::what() const throw()
00221 {
00222 return getMessage();
00223 }
00224
00226 int
00227 Exception::getSubClassId() const
00228 {
00229 return m_subClassId;
00230 }
00231
00233 void
00234 Exception::setSubClassId(int subClassId)
00235 {
00236 m_subClassId = subClassId;
00237 }
00238
00240 Exception*
00241 Exception::clone() const
00242 {
00243 return new(std::nothrow) Exception(*this);
00244 }
00245
00247 const Exception*
00248 Exception::getSubException() const
00249 {
00250 return m_subException;
00251 }
00252
00254 int
00255 Exception::getErrorCode() const
00256 {
00257 return m_errorCode;
00258 }
00259
00261 void
00262 Exception::setErrorCode(int errorCode)
00263 {
00264 m_errorCode = errorCode;
00265 }
00266
00267 namespace ExceptionDetail
00268 {
00269
00270
00271 #if defined(OWBI1_HPUX) || defined(OWBI1_SOLARIS) || defined(OWBI1_WIN32)
00272
00273 void portable_strerror_r(int errnum, char * buf, unsigned n)
00274 {
00275 ::strncpy(buf, strerror(errnum), n);
00276 buf[n-1] = '\0';
00277 }
00278
00279 #else
00280 typedef int (*posix_fct)(int, char *, ::std::size_t);
00281 typedef char * (*gnu_fct)(int, char *, ::std::size_t);
00282 typedef int (*aix_fct)(int, char *, int);
00283
00284 struct dummy
00285 {
00286 };
00287
00288
00289
00290
00291 template <typename Dummy>
00292 inline int
00293 strerror_r_wrap(posix_fct strerror_r, int errnum, char * buf, unsigned n,
00294 Dummy)
00295 {
00296 return strerror_r(errnum, buf, n);
00297 }
00298
00299 template <typename Dummy>
00300 inline int
00301 strerror_r_wrap(aix_fct strerror_r, int errnum, char * buf, unsigned n,
00302 Dummy)
00303 {
00304 return strerror_r(errnum, buf, n);
00305 }
00306
00307 template <typename Dummy>
00308 inline int
00309 strerror_r_wrap(gnu_fct strerror_r, int errnum, char * buf, unsigned n,
00310 Dummy)
00311 {
00312 char * errstr = strerror_r(errnum, buf, n);
00313 if (errstr != buf)
00314 {
00315 if (errstr)
00316 {
00317 ::strncpy(buf, errstr, n);
00318 }
00319 else
00320 {
00321 return -1;
00322 }
00323 }
00324 return 0;
00325 }
00326
00327 void portable_strerror_r(int errnum, char * buf, unsigned n)
00328 {
00329 int errc = strerror_r_wrap(&::strerror_r, errnum, buf, n, dummy());
00330 if (errc != 0)
00331 {
00332 ::strncpy(buf, "[Could not create error message for error code]", n);
00333 }
00334 buf[n-1] = '\0';
00335 }
00336 #endif
00337
00338 struct OWBI1_OWBI1PROVIFC_API FormatMsgImpl
00339 {
00340 String fm;
00341 };
00342
00343 FormatMsg::FormatMsg(char const * msg, int errnum)
00344 : pImpl(new FormatMsgImpl)
00345 {
00346 char arr[BUFSZ];
00347 portable_strerror_r(errnum, arr, BUFSZ);
00348 char const * sarr = static_cast<char const *>(arr);
00349 pImpl->fm = Format("%1: %2(%3)", msg, errnum, sarr).toString();
00350 }
00351
00352 FormatMsg::~FormatMsg()
00353 {
00354 }
00355
00356 char const * FormatMsg::get() const
00357 {
00358 return pImpl->fm.c_str();
00359 }
00360
00361 }
00362
00363 }
00364