#ifndef ZYPP_BASE_EXCEPTION_H
#define ZYPP_BASE_EXCEPTION_H
-#include <cerrno>
#include <iosfwd>
+#include <string>
+#include <list>
#include <stdexcept>
+#include "zypp/base/Errno.h"
+
///////////////////////////////////////////////////////////////////
namespace zypp
{ /////////////////////////////////////////////////////////////////
* Main.cc(main):57 CAUGHT: Main.cc(main):51: Something bad happened.
* \endcode
*
+ *
+ * Class Exception now offers a history list of message strings.
+ * These messages should describe what lead to the exception.
+ *
+ * The Exceptions message itself is NOT included in the history.
+ *
+ * Rethrow, remembering an old exception:
+ * \code
+ * try
+ * {
+ * ....
+ * }
+ * catch( const Exception & olderr_r )
+ * {
+ * ZYPP_CAUGHT( olderr_r )
+ * HighLevelException newerr( "Something failed." );
+ * newerr.rember( olderr_r );
+ * ZYPP_THROW( newerr );
+ * }
+ * \endcode
+ *
+ * Print an Exception followed by it's history if available:
+ * \code
+ * Exception error;
+ * ERR << error << endl << error.historyAsString();
+ * \endcode
+ *
* \todo That's a draft to have a common way of throwing exceptions.
* Most probabely we'll finally use blocxx exceptions. Here, but not
* in the remaining code of zypp. If we can we should try to wrap
* the blocxx macros and typedef the classes in here.
- *
- * \todo maybe location and message stack.
**/
class Exception : public std::exception
{
public:
typedef exception_detail::CodeLocation CodeLocation;
+ typedef std::list<std::string> History;
+ typedef History::const_iterator HistoryIterator;
+ typedef History::size_type HistorySize;
/** Default ctor.
* Use \ref ZYPP_THROW to throw exceptions.
*/
Exception( const std::string & msg_r );
+ /** Ctor taking a message and an exception to remember as history
+ * \see \ref remember
+ * Use \ref ZYPP_THROW to throw exceptions.
+ */
+ Exception( const std::string & msg_r, const Exception & history_r );
+
/** Dtor. */
virtual ~Exception() throw();
/** Error message provided by \ref dumpOn as string. */
std::string asString() const;
- /** Translated error message as string suitable for the user. */
+ /** Translated error message as string suitable for the user.
+ * \see \ref asUserStringHistory
+ */
std::string asUserString() const;
+ public:
+ /** \name History list of message strings.
+ * Maintain a simple list of individual error messages, that lead
+ * to this Exception. The Exceptions message itself is not included
+ * in the history. The History list stores the most recent message
+ * fist.
+ */
+ //@{
+
+ /** Store an other Exception as history. */
+ void remember( const Exception & old_r );
+
+ /** Add some message text to the history. */
+ void addHistory( const std::string & msg_r );
+
+ /** Iterator pointing to the most recent message. */
+ HistoryIterator historyBegin() const
+ { return _history.begin(); }
+
+ /** Iterator pointing behind the last message. */
+ HistoryIterator historyEnd() const
+ { return _history.end(); }
+
+ /** Whether the history list is empty. */
+ bool historyEmpty() const
+ { return _history.empty(); }
+
+ /** The size of the history list. */
+ HistorySize historySize() const
+ { return _history.size(); }
+
+ /** The history as string. Empty if \ref historyEmpty.
+ * Otherwise:
+ * \code
+ * History:
+ * - most recent message
+ * - 2nd message
+ * ...
+ * - oldest message
+ * \endcode
+ */
+ std::string historyAsString() const;
+
+ /** A single (multiline) string composed of \ref asUserString and \ref historyAsString. */
+ std::string asUserHistory() const;
+ //@}
+
protected:
/** Overload this to print a proper error message. */
private:
mutable CodeLocation _where;
- std::string _msg;
+ std::string _msg;
+ History _history;
/** Return message string. */
virtual const char * what() const throw()
std::ostream & operator<<( std::ostream & str, const Exception & obj );
///////////////////////////////////////////////////////////////////
-
- /** Helper for \ref ZYPP_THROW. */
- template<class _Excpt>
- void _ZYPP_THROW( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r ) __attribute__((noreturn));
- template<class _Excpt>
- void _ZYPP_THROW( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r )
+ namespace exception_detail
+ {
+ /** Helper for \ref ZYPP_THROW. */
+ template<class TExcpt>
+ void do_ZYPP_THROW( const TExcpt & excpt_r, const CodeLocation & where_r ) __attribute__((noreturn));
+ template<class TExcpt>
+ void do_ZYPP_THROW( const TExcpt & excpt_r, const CodeLocation & where_r )
{
excpt_r.relocate( where_r );
Exception::log( excpt_r, where_r, "THROW: " );
throw( excpt_r );
}
- /** Helper for \ref ZYPP_THROW. */
- template<class _Excpt>
- void _ZYPP_CAUGHT( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r )
+ /** Helper for \ref ZYPP_THROW. */
+ template<class TExcpt>
+ void do_ZYPP_CAUGHT( const TExcpt & excpt_r, const CodeLocation & where_r )
{
Exception::log( excpt_r, where_r, "CAUGHT: " );
}
- /** Helper for \ref ZYPP_THROW. */
- template<class _Excpt>
- void _ZYPP_RETHROW( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r ) __attribute__((noreturn));
- template<class _Excpt>
- void _ZYPP_RETHROW( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r )
+ /** Helper for \ref ZYPP_THROW. */
+ template<class TExcpt>
+ void do_ZYPP_RETHROW( const TExcpt & excpt_r, const CodeLocation & where_r ) __attribute__((noreturn));
+ template<class TExcpt>
+ void do_ZYPP_RETHROW( const TExcpt & excpt_r, const CodeLocation & where_r )
{
Exception::log( excpt_r, where_r, "RETHROW: " );
excpt_r.relocate( where_r );
throw;
}
-
+ } // namespace exception_detail
///////////////////////////////////////////////////////////////////
/** \defgroup ZYPP_THROW ZYPP_THROW macros
//@{
/** Drops a logline and throws the Exception. */
#define ZYPP_THROW(EXCPT)\
- _ZYPP_THROW( EXCPT, ZYPP_EX_CODELOCATION )
+ ::zypp::exception_detail::do_ZYPP_THROW( EXCPT, ZYPP_EX_CODELOCATION )
/** Drops a logline telling the Exception was caught (in order to handle it). */
#define ZYPP_CAUGHT(EXCPT)\
- _ZYPP_CAUGHT( EXCPT, ZYPP_EX_CODELOCATION )
+ ::zypp::exception_detail::do_ZYPP_CAUGHT( EXCPT, ZYPP_EX_CODELOCATION )
/** Drops a logline and rethrows, updating the CodeLocation. */
#define ZYPP_RETHROW(EXCPT)\
- _ZYPP_RETHROW( EXCPT, ZYPP_EX_CODELOCATION )
+ ::zypp::exception_detail::do_ZYPP_RETHROW( EXCPT, ZYPP_EX_CODELOCATION )
/** Throw Exception built from a message string. */