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 "OW_config.h"
00037 #include "OW_Exception.hpp"
00038 #include "OW_StackTrace.hpp"
00039 #include "OW_Format.hpp"
00040 #if defined(OW_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00041 #include "OW_Mutex.hpp"
00042 #endif
00043 #include <string.h>
00044
00045
00046 #include <cstdlib>
00047 #if defined(OW_HAVE_ISTREAM) && defined(OW_HAVE_OSTREAM)
00048 #include <istream>
00049 #include <ostream>
00050 #else
00051 #include <iostream>
00052 #endif
00053 #include <algorithm>
00054
00055 namespace OW_NAMESPACE
00056 {
00057
00058 #if defined(OW_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00059 Mutex* Exception::m_mutex = new Mutex();
00060 #endif
00061
00062 static void freeBuf(char** ptr)
00063 {
00064 delete [] *ptr;
00065 *ptr = NULL;
00066 }
00068 char* Exception::dupString(const char* str)
00069 {
00070 if (!str)
00071 {
00072 return 0;
00073 }
00074 char* rv = new (std::nothrow) char[strlen(str)+1];
00075 if (!rv)
00076 {
00077 return 0;
00078 }
00079 strcpy(rv, str);
00080 return rv;
00081 }
00083 Exception::Exception(const char* file, int line, const char* msg)
00084 : std::exception()
00085 , m_file(dupString(file))
00086 , m_line(line)
00087 , m_msg(dupString(msg))
00088 , m_subClassId(UNKNOWN_SUBCLASS_ID)
00089 , m_subException(0)
00090 , m_errorCode(UNKNOWN_ERROR_CODE)
00091 {
00092 #ifdef OW_ENABLE_STACK_TRACE_ON_EXCEPTIONS
00093 StackTrace::printStackTrace();
00094 #endif
00095 #if defined(OW_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00096 m_mutex->acquire();
00097 #endif
00098 }
00100 Exception::Exception(int subClassId, const char* file, int line, const char* msg, int errorCode, const Exception* subException)
00101 : std::exception()
00102 , m_file(dupString(file))
00103 , m_line(line)
00104 , m_msg(dupString(msg))
00105 , m_subClassId(subClassId)
00106 , m_subException(subException ? subException->clone() : 0)
00107 , m_errorCode(errorCode)
00108 {
00109 #ifdef OW_ENABLE_STACK_TRACE_ON_EXCEPTIONS
00110 StackTrace::printStackTrace();
00111 #endif
00112 #if defined(OW_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00113 m_mutex->acquire();
00114 #endif
00115 }
00117 Exception::Exception(const char* file, int line, const char* msg, int errorCode, const Exception* subException, int subClassId)
00118 : std::exception()
00119 , m_file(dupString(file))
00120 , m_line(line)
00121 , m_msg(dupString(msg))
00122 , m_subClassId(subClassId)
00123 , m_subException(subException ? subException->clone() : 0)
00124 , m_errorCode(errorCode)
00125 {
00126 #ifdef OW_ENABLE_STACK_TRACE_ON_EXCEPTIONS
00127 StackTrace::printStackTrace();
00128 #endif
00129 #if defined(OW_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00130 m_mutex->acquire();
00131 #endif
00132 }
00134 Exception::Exception( const Exception& e )
00135 : std::exception(e)
00136 , m_file(dupString(e.m_file))
00137 , m_line(e.m_line)
00138 , m_msg(dupString(e.m_msg))
00139 , m_subClassId(e.m_subClassId)
00140 , m_subException(e.m_subException ? e.m_subException->clone() : 0)
00141 , m_errorCode(e.m_errorCode)
00142 {
00143 #if defined(OW_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00144 m_mutex->acquire();
00145 #endif
00146 }
00148 Exception::~Exception() throw()
00149 {
00150 try
00151 {
00152 delete m_subException;
00153 freeBuf(&m_file);
00154 freeBuf(&m_msg);
00155 #if defined(OW_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00156 m_mutex->release();
00157 #endif
00158 }
00159 catch (...)
00160 {
00161
00162 }
00163 }
00165 Exception&
00166 Exception::operator=(const Exception& rhs)
00167 {
00168 Exception(rhs).swap(*this);
00169 return *this;
00170 }
00172 void
00173 Exception::swap(Exception& rhs)
00174 {
00175 std::swap(static_cast<std::exception&>(*this), static_cast<std::exception&>(rhs));
00176 std::swap(m_file, rhs.m_file);
00177 std::swap(m_line, rhs.m_line);
00178 std::swap(m_msg, rhs.m_msg);
00179 std::swap(m_subClassId, rhs.m_subClassId);
00180 std::swap(m_subException, rhs.m_subException);
00181 std::swap(m_errorCode, rhs.m_errorCode);
00182 }
00183
00185 const char*
00186 Exception::type() const
00187 {
00188 return "Exception";
00189 }
00190
00192 int
00193 Exception::getLine() const
00194 {
00195 return m_line;
00196 }
00197
00199 const char*
00200 Exception::getMessage() const
00201 {
00202 return (m_msg != NULL) ? m_msg : "";
00203 }
00205 const char*
00206 Exception::getFile() const
00207 {
00208 return (m_file != NULL) ? m_file : "";
00209 }
00211 std::ostream&
00212 operator<<(std::ostream& os, const Exception& e)
00213 {
00214 if (*e.getFile() == '\0')
00215 {
00216 os << "[no file]: ";
00217 }
00218 else
00219 {
00220 os << e.getFile() << ": ";
00221 }
00222
00223 if (e.getLine() == 0)
00224 {
00225 os << "[no line] ";
00226 }
00227 else
00228 {
00229 os << e.getLine() << ' ';
00230 }
00231
00232 os << e.type() << ": ";
00233
00234 if (*e.getMessage() == '\0')
00235 {
00236 os << "[no message]";
00237 }
00238 else
00239 {
00240 os << e.getMessage();
00241 }
00242
00243 const Exception* subEx = e.getSubException();
00244 if (subEx)
00245 {
00246 os << " <" << *subEx << '>';
00247 }
00248 return os;
00249 }
00251 const char*
00252 Exception::what() const throw()
00253 {
00254 return getMessage();
00255 }
00256
00258 int
00259 Exception::getSubClassId() const
00260 {
00261 return m_subClassId;
00262 }
00263
00265 void
00266 Exception::setSubClassId(int subClassId)
00267 {
00268 m_subClassId = subClassId;
00269 }
00270
00272 Exception*
00273 Exception::clone() const
00274 {
00275 return new(std::nothrow) Exception(*this);
00276 }
00277
00279 const Exception*
00280 Exception::getSubException() const
00281 {
00282 return m_subException;
00283 }
00284
00286 int
00287 Exception::getErrorCode() const
00288 {
00289 return m_errorCode;
00290 }
00291
00293 void
00294 Exception::setErrorCode(int errorCode)
00295 {
00296 m_errorCode = errorCode;
00297 }
00298
00299 namespace ExceptionDetail
00300 {
00301
00302
00303 #if defined(OW_HPUX) || defined(OW_SOLARIS) || defined(OW_WIN32)
00304
00305 void portable_strerror_r(int errnum, char * buf, unsigned n)
00306 {
00307 ::strncpy(buf, strerror(errnum), n);
00308 buf[n-1] = '\0';
00309 }
00310
00311 #else
00312 typedef int (*posix_fct)(int, char *, ::std::size_t);
00313 typedef char * (*gnu_fct)(int, char *, ::std::size_t);
00314 typedef int (*aix_fct)(int, char *, int);
00315
00316 struct dummy
00317 {
00318 };
00319
00320
00321
00322
00323 template <typename Dummy>
00324 inline int
00325 strerror_r_wrap(posix_fct strerror_r, int errnum, char * buf, unsigned n,
00326 Dummy)
00327 {
00328 return strerror_r(errnum, buf, n);
00329 }
00330
00331 template <typename Dummy>
00332 inline int
00333 strerror_r_wrap(aix_fct strerror_r, int errnum, char * buf, unsigned n,
00334 Dummy)
00335 {
00336 return strerror_r(errnum, buf, n);
00337 }
00338
00339 template <typename Dummy>
00340 inline int
00341 strerror_r_wrap(gnu_fct strerror_r, int errnum, char * buf, unsigned n,
00342 Dummy)
00343 {
00344 char * errstr = strerror_r(errnum, buf, n);
00345 if (errstr != buf)
00346 {
00347 if (errstr)
00348 {
00349 ::strncpy(buf, errstr, n);
00350 }
00351 else
00352 {
00353 return -1;
00354 }
00355 }
00356 return 0;
00357 }
00358
00359 void portable_strerror_r(int errnum, char * buf, unsigned n)
00360 {
00361 int errc = strerror_r_wrap(&::strerror_r, errnum, buf, n, dummy());
00362 if (errc != 0)
00363 {
00364 ::strncpy(buf, "[Could not create error message for error code]", n);
00365 }
00366 buf[n-1] = '\0';
00367 }
00368 #endif
00369
00370 struct OW_COMMON_API FormatMsgImpl
00371 {
00372 String fm;
00373 };
00374
00375 FormatMsg::FormatMsg(char const * msg, int errnum)
00376 : pImpl(new FormatMsgImpl)
00377 {
00378 char arr[BUFSZ];
00379 portable_strerror_r(errnum, arr, BUFSZ);
00380 char const * sarr = static_cast<char const *>(arr);
00381 pImpl->fm = Format("%1: %2(%3)", msg, errnum, sarr).toString();
00382 }
00383
00384 FormatMsg::~FormatMsg()
00385 {
00386 }
00387
00388 char const * FormatMsg::get() const
00389 {
00390 return pImpl->fm.c_str();
00391 }
00392
00393 }
00394
00395 }
00396