Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / base / Exception.h
index e9c3253..3bde1ee 100644 (file)
 #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
 { /////////////////////////////////////////////////////////////////
@@ -105,12 +108,37 @@ 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
   {
@@ -118,6 +146,9 @@ namespace zypp
 
   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.
@@ -129,6 +160,12 @@ namespace zypp
     */
     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();
 
@@ -151,9 +188,58 @@ namespace zypp
     /** 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. */
@@ -174,7 +260,8 @@ namespace zypp
 
   private:
     mutable CodeLocation _where;
-    std::string _msg;
+    std::string          _msg;
+    History              _history;
 
     /** Return message string. */
     virtual const char * what() const throw()
@@ -192,36 +279,37 @@ namespace zypp
   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
@@ -231,15 +319,15 @@ namespace zypp
   //@{
   /** 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. */