OWBI1_Exception.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
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 // Not <cstring>, because strerror_r is not part of C or C++ standard lib,
00045 // but is a POSIX function defined to be in <string.h>.
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> // for std::swap
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       // don't let exceptions escape
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 // HPUX, solaris have a thread safe strerror(), windows doesn't have strerror_r(), and doesn't document whether strerror() is thread safe or not.
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'; // just in case...
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    // We make the strerror_r_wrap functions into templates so that
00289    // code is generated only for the one that gets used.
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'; // just in case...
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 } // namespace ExceptionDetail
00362 
00363 } // end namespace OWBI1
00364 

Generated on Thu Feb 9 08:48:27 2006 for openwbem by  doxygen 1.4.6