Use STL exceptions as far as possible.

This commit is contained in:
Gunnar Beutner 2012-05-26 21:30:04 +02:00
parent c38e9c8468
commit 33d67401b9
20 changed files with 79 additions and 121 deletions

View File

@ -230,7 +230,7 @@ Component::Ptr Application::LoadComponent(const string& path,
#endif /* _WIN32 */ #endif /* _WIN32 */
if (hModule == NULL) if (hModule == NULL)
throw ComponentLoadException("Could not load module"); throw runtime_error("Could not load module");
#ifdef _WIN32 #ifdef _WIN32
pCreateComponent = (CreateComponentFunction)GetProcAddress(hModule, pCreateComponent = (CreateComponentFunction)GetProcAddress(hModule,
@ -245,8 +245,8 @@ Component::Ptr Application::LoadComponent(const string& path,
#endif /* _WIN32 */ #endif /* _WIN32 */
if (pCreateComponent == NULL) if (pCreateComponent == NULL)
throw ComponentLoadException("Loadable module does not " throw runtime_error("Loadable module does not contain "
"contain CreateComponent function"); "CreateComponent function");
component = Component::Ptr(pCreateComponent()); component = Component::Ptr(pCreateComponent());
component->SetConfig(componentConfig); component->SetConfig(componentConfig);
@ -368,7 +368,7 @@ string Application::GetExeDirectory(void) const
free(PathEnv); free(PathEnv);
if (!FoundPath) if (!FoundPath)
throw Exception("Could not determine executable path."); throw runtime_error("Could not determine executable path.");
} }
} }

View File

@ -24,8 +24,6 @@ namespace icinga {
class Component; class Component;
DEFINE_EXCEPTION_CLASS(ComponentLoadException);
/** /**
* Abstract base class for applications. * Abstract base class for applications.
* *

View File

@ -42,7 +42,7 @@ ConfigObject::ConfigObject(const string& type, const string& name)
void ConfigObject::SetHive(const ConfigHive::WeakPtr& hive) void ConfigObject::SetHive(const ConfigHive::WeakPtr& hive)
{ {
if (m_Hive.lock()) if (m_Hive.lock())
throw InvalidArgumentException("Config object already has a parent hive."); throw logic_error("Config object already has a parent hive.");
m_Hive = hive; m_Hive = hive;
} }

View File

@ -73,7 +73,7 @@ public:
*value = dynamic_pointer_cast<Dictionary>(object); *value = dynamic_pointer_cast<Dictionary>(object);
if (!*value) if (!*value)
throw InvalidCastException(); throw runtime_error("Object is not a dictionary.");
return true; return true;
} }

View File

@ -21,35 +21,6 @@
using namespace icinga; using namespace icinga;
/**
* Default constructor for the Exception class.
*/
Exception::Exception(void)
{
m_Code = 0;
m_Message = NULL;
}
/**
* Constructor for the exception class.
*
* @param message A message describing the exception.
*/
Exception::Exception(const char *message)
{
m_Code = 0;
m_Message = NULL;
SetMessage(message);
}
/**
* Destructor for the Exception class. Must be virtual for RTTI to work.
*/
Exception::~Exception(void) throw()
{
Memory::Free(m_Message);
}
/** /**
* Retrieves the error code for the exception. * Retrieves the error code for the exception.
* *
@ -75,7 +46,7 @@ void Exception::SetCode(int code)
* *
* @returns The description. * @returns The description.
*/ */
const char *Exception::GetMessage(void) const string Exception::GetMessage(void) const
{ {
return m_Message; return m_Message;
} }
@ -87,7 +58,7 @@ const char *Exception::GetMessage(void) const
*/ */
const char *Exception::what(void) const throw() const char *Exception::what(void) const throw()
{ {
return GetMessage(); return GetMessage().c_str();
} }
/** /**
@ -95,10 +66,9 @@ const char *Exception::what(void) const throw()
* *
* @param message The description. * @param message The description.
*/ */
void Exception::SetMessage(const char *message) void Exception::SetMessage(string message)
{ {
Memory::Free(m_Message); m_Message = message;
m_Message = Memory::StrDup(message);
} }
#ifdef _WIN32 #ifdef _WIN32

View File

@ -31,21 +31,35 @@ namespace icinga
class I2_BASE_API Exception : public virtual std::exception class I2_BASE_API Exception : public virtual std::exception
{ {
public: public:
Exception(void); Exception(void)
Exception(const char *message); : m_Message(), m_Code(0)
virtual ~Exception(void) throw(); { }
Exception(string message)
: m_Message(message), m_Code(0)
{ }
Exception(string message, int code)
: m_Message(message), m_Code(code)
{ }
/**
* Destructor for the Exception class. Must be virtual for RTTI to work.
*/
virtual ~Exception(void) throw()
{ }
int GetCode(void) const; int GetCode(void) const;
const char *GetMessage(void) const; string GetMessage(void) const;
virtual const char *what(void) const throw(); virtual const char *what(void) const throw();
protected: protected:
void SetCode(int code); void SetCode(int code);
void SetMessage(const char *message); void SetMessage(string message);
private: private:
char *m_Message; string m_Message;
int m_Code; int m_Code;
}; };
@ -54,13 +68,11 @@ private:
{ \ { \
public: \ public: \
inline klass(void) : Exception() \ inline klass(void) : Exception() \
{ \ { } \
} \
\ \
inline klass(const char *message) \ inline klass(string message) \
: Exception(message) \ : Exception(message) \
{ \ { } \
} \
} }
/** /**
@ -71,22 +83,6 @@ private:
*/ */
DEFINE_EXCEPTION_CLASS(NotImplementedException); DEFINE_EXCEPTION_CLASS(NotImplementedException);
/**
* An exception that is thrown when an argument to
* a function is invalid.
*
* @ingroup base
*/
DEFINE_EXCEPTION_CLASS(InvalidArgumentException);
/**
* An exception that is thrown when a cast yields
* an invalid result.
*
* @ingroup base
*/
DEFINE_EXCEPTION_CLASS(InvalidCastException);
#ifdef _WIN32 #ifdef _WIN32
/** /**
* A Win32 error encapsulated in an exception. * A Win32 error encapsulated in an exception.
@ -101,11 +97,8 @@ public:
* @param errorCode A Win32 error code. * @param errorCode A Win32 error code.
*/ */
inline Win32Exception(const string& message, int errorCode) inline Win32Exception(const string& message, int errorCode)
{ : Exception(message + ": " + FormatErrorCode(errorCode), errorCode)
string msg = message + ": " + FormatErrorCode(errorCode); { }
SetMessage(msg.c_str());
SetCode(errorCode);
}
/** /**
* Returns a string that describes the Win32 error. * Returns a string that describes the Win32 error.
@ -130,11 +123,8 @@ public:
* @param errorCode A Posix (errno) error code. * @param errorCode A Posix (errno) error code.
*/ */
inline PosixException(const string& message, int errorCode) inline PosixException(const string& message, int errorCode)
{ : Exception(message + ": " + FormatErrorCode(errorCode), errorCode)
string msg = message + ": " + FormatErrorCode(errorCode); { }
SetMessage(msg.c_str());
SetCode(errorCode);
}
/** /**
* Returns a string that describes the Posix error. * Returns a string that describes the Posix error.
@ -158,10 +148,8 @@ public:
* @param errorCode An OpenSSL error code. * @param errorCode An OpenSSL error code.
*/ */
inline OpenSSLException(const string& message, int errorCode) inline OpenSSLException(const string& message, int errorCode)
{ : Exception(message + ": " + FormatErrorCode(errorCode), errorCode)
string msg = message + ": " + FormatErrorCode(errorCode); { }
SetMessage(msg.c_str());
}
/** /**
* Returns a string that describes the OpenSSL error. * Returns a string that describes the OpenSSL error.

View File

@ -167,17 +167,17 @@ int Socket::GetLastSocketError(void)
* Handles a socket error by calling the OnError event or throwing an exception * Handles a socket error by calling the OnError event or throwing an exception
* when there are no observers for the OnError event. * when there are no observers for the OnError event.
* *
* @param exception An exception. * @param ex An exception.
*/ */
void Socket::HandleSocketError(const Exception& exception) void Socket::HandleSocketError(const exception& ex)
{ {
if (OnError.HasObservers()) { if (OnError.HasObservers()) {
SocketErrorEventArgs sea(exception); SocketErrorEventArgs sea(ex);
OnError(sea); OnError(sea);
Close(); Close();
} else { } else {
throw exception; throw ex;
} }
} }
@ -226,7 +226,8 @@ string Socket::GetAddressFromSockaddr(sockaddr *address, socklen_t len)
char service[NI_MAXSERV]; char service[NI_MAXSERV];
if (getnameinfo(address, len, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV) < 0) if (getnameinfo(address, len, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
throw InvalidArgumentException(); /* TODO: throw proper exception */ throw SocketException("getnameinfo() failed",
GetLastSocketError());
stringstream s; stringstream s;
s << "[" << host << "]:" << service; s << "[" << host << "]:" << service;

View File

@ -29,10 +29,10 @@ namespace icinga {
*/ */
struct I2_BASE_API SocketErrorEventArgs : public EventArgs struct I2_BASE_API SocketErrorEventArgs : public EventArgs
{ {
const Exception& Error; const exception& Exception;
SocketErrorEventArgs(const Exception& exception) SocketErrorEventArgs(const exception& ex)
: Error(exception) { } : Exception(ex) { }
}; };
/** /**
@ -78,7 +78,7 @@ protected:
int GetError(void) const; int GetError(void) const;
static int GetLastSocketError(void); static int GetLastSocketError(void);
void HandleSocketError(const Exception& exception); void HandleSocketError(const exception& ex);
virtual void CloseInternal(bool from_dtor); virtual void CloseInternal(bool from_dtor);

View File

@ -110,7 +110,8 @@ void TcpClient::Connect(const string& node, const string& service)
freeaddrinfo(result); freeaddrinfo(result);
if (fd == INVALID_SOCKET) if (fd == INVALID_SOCKET)
HandleSocketError(InvalidArgumentException()); HandleSocketError(runtime_error(
"Could not create a suitable socket."));
} }
/** /**

View File

@ -116,5 +116,6 @@ void TcpSocket::Bind(string node, string service, int family)
freeaddrinfo(result); freeaddrinfo(result);
if (fd == INVALID_SOCKET) if (fd == INVALID_SOCKET)
HandleSocketError(InvalidArgumentException()); HandleSocketError(runtime_error(
"Could not create a suitable socket."));
} }

View File

@ -80,7 +80,7 @@ void TlsClient::Start(void)
throw OpenSSLException("SSL_new failed", ERR_get_error()); throw OpenSSLException("SSL_new failed", ERR_get_error());
if (!GetClientCertificate()) if (!GetClientCertificate())
throw InvalidArgumentException("No X509 client certificate was specified."); throw logic_error("No X509 client certificate was specified.");
if (!m_SSLIndexInitialized) { if (!m_SSLIndexInitialized) {
m_SSLIndex = SSL_get_ex_new_index(0, (void *)"TlsClient", NULL, NULL, NULL); m_SSLIndex = SSL_get_ex_new_index(0, (void *)"TlsClient", NULL, NULL, NULL);

View File

@ -34,7 +34,7 @@ void Utility::Daemonize(void) {
pid = fork(); pid = fork();
if (pid < 0) if (pid < 0)
throw PosixException("fork failed", errno); throw PosixException("fork() failed", errno);
if (pid) if (pid)
exit(0); exit(0);
@ -42,7 +42,7 @@ void Utility::Daemonize(void) {
fd = open("/dev/null", O_RDWR); fd = open("/dev/null", O_RDWR);
if (fd < 0) if (fd < 0)
throw PosixException("open failed", errno); throw PosixException("open() failed", errno);
if (fd != 0) if (fd != 0)
dup2(fd, 0); dup2(fd, 0);
@ -57,7 +57,7 @@ void Utility::Daemonize(void) {
close(fd); close(fd);
if (setsid() < 0) if (setsid() < 0)
throw PosixException("setsid failed", errno); throw PosixException("setsid() failed", errno);
#endif #endif
} }
@ -94,13 +94,13 @@ shared_ptr<SSL_CTX> Utility::MakeSSLContext(string pubkey, string privkey, strin
SSL_CTX_set_mode(sslContext.get(), SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); SSL_CTX_set_mode(sslContext.get(), SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
if (!SSL_CTX_use_certificate_chain_file(sslContext.get(), pubkey.c_str())) if (!SSL_CTX_use_certificate_chain_file(sslContext.get(), pubkey.c_str()))
throw InvalidArgumentException("Could not load public X509 key file."); throw OpenSSLException("Could not load public X509 key file", ERR_get_error());
if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.c_str(), SSL_FILETYPE_PEM)) if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.c_str(), SSL_FILETYPE_PEM))
throw InvalidArgumentException("Could not load private X509 key file."); throw OpenSSLException("Could not load private X509 key file", ERR_get_error());
if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.c_str(), NULL)) if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.c_str(), NULL))
throw InvalidArgumentException("Could not load public CA key file."); throw OpenSSLException("Could not load public CA key file", ERR_get_error());
return sslContext; return sslContext;
} }
@ -118,7 +118,7 @@ string Utility::GetCertificateCN(const shared_ptr<X509>& certificate)
int rc = X509_NAME_get_text_by_NID(X509_get_subject_name(certificate.get()), NID_commonName, buffer, sizeof(buffer)); int rc = X509_NAME_get_text_by_NID(X509_get_subject_name(certificate.get()), NID_commonName, buffer, sizeof(buffer));
if (rc == -1) if (rc == -1)
throw InvalidArgumentException("X509 certificate has no CN attribute."); throw OpenSSLException("X509 certificate has no CN attribute", ERR_get_error());
return buffer; return buffer;
} }

View File

@ -39,7 +39,7 @@ void Variant::Convert(VariantType newType) const
} }
// TODO: convert variant data // TODO: convert variant data
throw InvalidArgumentException("Invalid variant conversion."); throw runtime_error("Invalid variant conversion.");
} }
/** /**

View File

@ -36,11 +36,11 @@ void ConfigFileComponent::Start(void)
string filename; string filename;
if (!GetConfig()->GetProperty("configFilename", &filename)) if (!GetConfig()->GetProperty("configFilename", &filename))
throw InvalidArgumentException("Missing 'configFilename' property"); throw logic_error("Missing 'configFilename' property");
fp.open(filename.c_str(), ifstream::in); fp.open(filename.c_str(), ifstream::in);
if (fp.fail()) if (fp.fail())
throw ConfigParserException("Could not open config file"); throw runtime_error("Could not open config file");
GetIcingaApplication()->Log("Reading config file: " + filename); GetIcingaApplication()->Log("Reading config file: " + filename);
@ -49,7 +49,7 @@ void ConfigFileComponent::Start(void)
char *buffer = (char *)fifo->GetWriteBuffer(&bufferSize); char *buffer = (char *)fifo->GetWriteBuffer(&bufferSize);
fp.read(buffer, bufferSize); fp.read(buffer, bufferSize);
if (fp.bad()) if (fp.bad())
throw ConfigParserException("Could not read from config file"); throw runtime_error("Could not read from config file");
fifo->Write(NULL, fp.gcount()); fifo->Write(NULL, fp.gcount());
} }

View File

@ -363,7 +363,7 @@ bool DiscoveryComponent::HasMessagePermission(Dictionary::Ptr roles, string mess
Dictionary::Ptr permissions = dynamic_pointer_cast<Dictionary>(object); Dictionary::Ptr permissions = dynamic_pointer_cast<Dictionary>(object);
if (!permissions) if (!permissions)
throw InvalidCastException(); throw runtime_error("Object is not a dictionary.");
for (DictionaryIterator is = permissions->Begin(); is != permissions->End(); is++) { for (DictionaryIterator is = permissions->Begin(); is != permissions->End(); is++) {
if (Utility::Match(is->second.GetString(), message)) if (Utility::Match(is->second.GetString(), message))
@ -404,9 +404,8 @@ void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessa
Object::Ptr object; Object::Ptr object;
if (endpointConfig->GetProperty("roles", &object)) { if (endpointConfig->GetProperty("roles", &object)) {
roles = dynamic_pointer_cast<Dictionary>(object); roles = dynamic_pointer_cast<Dictionary>(object);
if (!roles) if (!roles)
throw InvalidCastException(); throw runtime_error("Object is not a dictionary.");
} }
} }

View File

@ -70,7 +70,7 @@ shared_ptr<SSL_CTX> EndpointManager::GetSSLContext(void) const
void EndpointManager::AddListener(string service) void EndpointManager::AddListener(string service)
{ {
if (!GetSSLContext()) if (!GetSSLContext())
throw InvalidArgumentException("SSL context is required for AddListener()"); throw logic_error("SSL context is required for AddListener()");
stringstream s; stringstream s;
s << "Adding new listener: port " << service; s << "Adding new listener: port " << service;
@ -151,7 +151,7 @@ void EndpointManager::UnregisterServer(JsonRpcServer::Ptr server)
void EndpointManager::RegisterEndpoint(Endpoint::Ptr endpoint) void EndpointManager::RegisterEndpoint(Endpoint::Ptr endpoint)
{ {
if (!endpoint->IsLocal() && endpoint->GetIdentity() != "") if (!endpoint->IsLocal() && endpoint->GetIdentity() != "")
throw InvalidArgumentException("Identity must be empty."); throw invalid_argument("Identity must be empty.");
endpoint->SetEndpointManager(static_pointer_cast<EndpointManager>(shared_from_this())); endpoint->SetEndpointManager(static_pointer_cast<EndpointManager>(shared_from_this()));
m_Endpoints.push_back(endpoint); m_Endpoints.push_back(endpoint);
@ -220,11 +220,11 @@ void EndpointManager::SendMulticastMessage(Endpoint::Ptr sender,
{ {
string id; string id;
if (message.GetID(&id)) if (message.GetID(&id))
throw InvalidArgumentException("Multicast requests must not have an ID."); throw invalid_argument("Multicast requests must not have an ID.");
string method; string method;
if (!message.GetMethod(&method)) if (!message.GetMethod(&method))
throw InvalidArgumentException("Message is missing the 'method' property."); throw invalid_argument("Message is missing the 'method' property.");
for (vector<Endpoint::Ptr>::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++) for (vector<Endpoint::Ptr>::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++)
{ {

View File

@ -168,7 +168,7 @@ int IcingaApplication::NewIcingaConfigHandler(const EventArgs& ea)
int IcingaApplication::DeletedIcingaConfigHandler(const EventArgs&) int IcingaApplication::DeletedIcingaConfigHandler(const EventArgs&)
{ {
throw Exception("Unsupported operation."); throw runtime_error("Unsupported operation.");
} }
void IcingaApplication::SetPrivateKeyFile(string privkey) void IcingaApplication::SetPrivateKeyFile(string privkey)

View File

@ -132,7 +132,7 @@ int JsonRpcEndpoint::ClientClosedHandler(const EventArgs&)
int JsonRpcEndpoint::ClientErrorHandler(const SocketErrorEventArgs& ea) int JsonRpcEndpoint::ClientErrorHandler(const SocketErrorEventArgs& ea)
{ {
cerr << "Error occured for JSON-RPC socket: Code=" << ea.Error.GetCode() << "; Message=" << ea.Error.GetMessage() << endl; cerr << "Error occured for JSON-RPC socket: Message=" << ea.Exception.what() << endl;
return 0; return 0;
} }

View File

@ -41,7 +41,7 @@ MessagePart::MessagePart(string jsonString)
json_t *json = cJSON_Parse(jsonString.c_str()); json_t *json = cJSON_Parse(jsonString.c_str());
if (!json) if (!json)
throw InvalidArgumentException("Invalid JSON string"); throw runtime_error("Invalid JSON string");
m_Dictionary = GetDictionaryFromJson(json); m_Dictionary = GetDictionaryFromJson(json);
@ -184,7 +184,7 @@ bool MessagePart::GetProperty(string key, MessagePart *value) const
Dictionary::Ptr dictionary = dynamic_pointer_cast<Dictionary>(object); Dictionary::Ptr dictionary = dynamic_pointer_cast<Dictionary>(object);
if (!dictionary) if (!dictionary)
throw InvalidCastException(); throw runtime_error("Object is not a dictionary.");
*value = MessagePart(dictionary); *value = MessagePart(dictionary);
return true; return true;

View File

@ -41,7 +41,7 @@ bool Netstring::ReadStringFromFIFO(FIFO::Ptr fifo, string *str)
/* no leading zeros allowed */ /* no leading zeros allowed */
if (buffer[0] == '0' && isdigit(buffer[1])) if (buffer[0] == '0' && isdigit(buffer[1]))
throw InvalidArgumentException("Invalid netstring (leading zero)"); throw invalid_argument("Invalid netstring (leading zero)");
size_t len, i; size_t len, i;
@ -49,7 +49,7 @@ bool Netstring::ReadStringFromFIFO(FIFO::Ptr fifo, string *str)
for (i = 0; i < buffer_length && isdigit(buffer[i]); i++) { for (i = 0; i < buffer_length && isdigit(buffer[i]); i++) {
/* length specifier must have at most 9 characters */ /* length specifier must have at most 9 characters */
if (i >= 9) if (i >= 9)
throw InvalidArgumentException("Length specifier must not exceed 9 characters"); throw invalid_argument("Length specifier must not exceed 9 characters");
len = len * 10 + (buffer[i] - '0'); len = len * 10 + (buffer[i] - '0');
} }
@ -60,11 +60,11 @@ bool Netstring::ReadStringFromFIFO(FIFO::Ptr fifo, string *str)
/* check for the colon delimiter */ /* check for the colon delimiter */
if (buffer[i++] != ':') if (buffer[i++] != ':')
throw InvalidArgumentException("Invalid Netstring (missing :)"); throw invalid_argument("Invalid Netstring (missing :)");
/* check for the comma delimiter after the string */ /* check for the comma delimiter after the string */
if (buffer[i + len] != ',') if (buffer[i + len] != ',')
throw InvalidArgumentException("Invalid Netstring (missing ,)"); throw invalid_argument("Invalid Netstring (missing ,)");
*str = string(&buffer[i], &buffer[i + len]); *str = string(&buffer[i], &buffer[i + len]);