syncevolution/src/syncevo/Exception.h

229 lines
7.9 KiB
C++

/*
* Copyright (C) 2008-2009 Patrick Ohly <patrick.ohly@gmx.de>
* Copyright (C) 2014 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
#ifndef INCL_SYNCEVOLUTION_EXCEPTION
# define INCL_SYNCEVOLUTION_EXCEPTION
#include <syncevo/Logging.h>
#include <syncevo/SyncML.h>
#include <string>
#include <syncevo/declarations.h>
SE_BEGIN_CXX
/** Encapsulates source information. */
class SourceLocation
{
public:
const char *m_file;
int m_line;
SourceLocation(const char *file, int line) :
m_file(file),
m_line(line)
{}
};
/** Convenience macro to create a SourceLocation for the current location. */
#define SE_HERE SyncEvo::SourceLocation(__FILE__, __LINE__)
enum HandleExceptionFlags {
HANDLE_EXCEPTION_FLAGS_NONE = 0,
/**
* a 404 status error is possible and must not be logged as ERROR
*/
HANDLE_EXCEPTION_404_IS_OKAY = 1 << 0,
HANDLE_EXCEPTION_FATAL = 1 << 1,
/**
* don't log exception as ERROR
*/
HANDLE_EXCEPTION_NO_ERROR = 1 << 2,
HANDLE_EXCEPTION_MAX = 1 << 3,
};
/**
* an exception which records the source file and line
* where it was thrown
*
* @TODO add function name
*/
class Exception : public std::runtime_error
{
public:
Exception(const std::string &file,
int line,
const std::string &what) :
std::runtime_error(what),
m_file(file),
m_line(line)
{}
~Exception() throw() {}
const std::string m_file;
const int m_line;
/**
* Convenience function, to be called inside a catch(..) block.
*
* Rethrows the exception to determine what it is, then logs it
* at the chosen level (error by default).
*
* Turns certain known exceptions into the corresponding
* status code if status still was STATUS_OK when called.
* Returns updated status code.
*
* @param logPrefix passed to SE_LOG* messages
* @retval explanation set to explanation for problem, if non-NULL
* @param level level to be used for logging
*/
static SyncMLStatus handle(SyncMLStatus *status = NULL, const std::string *logPrefix = NULL, std::string *explanation = NULL, Logger::Level = Logger::ERROR, HandleExceptionFlags flags = HANDLE_EXCEPTION_FLAGS_NONE);
static SyncMLStatus handle(const std::string &logPrefix, HandleExceptionFlags flags = HANDLE_EXCEPTION_FLAGS_NONE) { return handle(NULL, &logPrefix, NULL, Logger::ERROR, flags); }
static SyncMLStatus handle(std::string &explanation, HandleExceptionFlags flags = HANDLE_EXCEPTION_FLAGS_NONE) { return handle(NULL, NULL, &explanation, Logger::ERROR, flags); }
static void handle(HandleExceptionFlags flags) { handle(NULL, NULL, NULL, Logger::ERROR, flags); }
static void log() { handle(NULL, NULL, NULL, Logger::DEBUG); }
/**
* Tries to identify exception class based on explanation string created by
* handle(). If successful, that exception is throw with the same
* attributes as in the original exception.
*
* If not, tryRethrow() returns (mustThrow false) or throws a std::runtime_error
* with the explanation as text.
*/
static void tryRethrow(const std::string &explanation, bool mustThrow = false);
/**
* Same as tryRethrow() for strings with a 'org.syncevolution.xxxx:' prefix,
* as passed as D-Bus error strings.
*/
static void tryRethrowDBus(const std::string &error);
/**
* throws a StatusException with a local, fatal error with the given string
* or (on the iPhone, where exception handling is not
* supported by the toolchain) prints an error directly
* and aborts
*
* output format: <error>
*
* @param error a string describing the error
*/
static void throwError(const SourceLocation &where, const std::string &error) SE_NORETURN;
/**
* throw an exception with a specific status code after an operation failed and
* remember that this instance has failed
*
* output format: <failure>
*
* @param status a more specific status code; other throwError() variants
* use STATUS_FATAL + sysync::LOCAL_STATUS_CODE, which is interpreted
* as a fatal local error
* @param action a string describing what was attempted *and* how it failed
*/
static void throwError(const SourceLocation &where, SyncMLStatus status, const std::string &failure) SE_NORETURN;
/**
* throw an exception after an operation failed and
* remember that this instance has failed
*
* output format: <action>: <error string>
*
* @Param action a string describing the operation or object involved
* @param error the errno error code for the failure
*/
static void throwError(const SourceLocation &where, const std::string &action, int error) SE_NORETURN;
/**
* An error handler which prints the error message and then
* stops the program. Never returns.
*
* The API was chosen so that it can be used as libebook/libecal
* "backend-dies" signal handler.
*/
static void fatalError(void *object, const char *error) SE_NORETURN;
};
/**
* StatusException by wrapping a SyncML status
*/
class StatusException : public Exception
{
public:
StatusException(const std::string &file,
int line,
const std::string &what,
SyncMLStatus status)
: Exception(file, line, what), m_status(status)
{}
SyncMLStatus syncMLStatus() const { return m_status; }
protected:
SyncMLStatus m_status;
};
class TransportException : public Exception
{
public:
TransportException(const std::string &file,
int line,
const std::string &what) :
Exception(file, line, what) {}
~TransportException() throw() {}
};
class TransportStatusException : public StatusException
{
public:
TransportStatusException(const std::string &file,
int line,
const std::string &what,
SyncMLStatus status) :
StatusException(file, line, what, status) {}
~TransportStatusException() throw() {}
};
/** throw a normal SyncEvolution Exception, including source information */
#define SE_THROW(_what) \
SE_THROW_EXCEPTION(Exception, _what)
/** throw a class which accepts file, line, what parameters */
#define SE_THROW_EXCEPTION(_class, _what) \
throw _class(__FILE__, __LINE__, _what)
/** throw a class which accepts file, line, what plus 1 additional parameter */
#define SE_THROW_EXCEPTION_1(_class, _what, _x1) \
throw _class(__FILE__, __LINE__, (_what), (_x1))
/** throw a class which accepts file, line, what plus 2 additional parameters */
#define SE_THROW_EXCEPTION_2(_class, _what, _x1, _x2) \
throw _class(__FILE__, __LINE__, (_what), (_x1), (_x2))
/** throw a class which accepts file, line, what plus 2 additional parameters */
#define SE_THROW_EXCEPTION_3(_class, _what, _x1, _x2, _x3) \
throw _class(__FILE__, __LINE__, (_what), (_x1), (_x2), (_x3))
/** throw a class which accepts file, line, what plus 2 additional parameters */
#define SE_THROW_EXCEPTION_4(_class, _what, _x1, _x2, _x3, _x4) \
throw _class(__FILE__, __LINE__, (_what), (_x1), (_x2), (_x3), (_x4))
/** throw a class which accepts file, line, what parameters and status parameters*/
#define SE_THROW_EXCEPTION_STATUS(_class, _what, _status) \
throw _class(__FILE__, __LINE__, _what, _status)
SE_END_CXX
#endif // INCL_SYNCEVOLUTION_EXCEPTION