Implement serializer support for arbitrary classes.

Fixes #5024
This commit is contained in:
Gunnar Beutner 2013-11-08 11:17:46 +01:00
parent 59739d9ae4
commit a84536bea3
66 changed files with 610 additions and 136 deletions

View File

@ -28,6 +28,7 @@
using namespace icinga;
REGISTER_NTYPE(CheckerComponent);
REGISTER_TYPE(CheckerComponent);
void CheckerComponent::Start(void)

View File

@ -20,6 +20,7 @@
#ifndef CHECKERCOMPONENT_H
#define CHECKERCOMPONENT_H
#include "checker/checkercomponent.th"
#include "icinga/service.h"
#include "base/dynamicobject.h"
#include "base/timer.h"
@ -63,7 +64,7 @@ struct ServiceNextCheckExtractor
/**
* @ingroup checker
*/
class CheckerComponent : public DynamicObject
class CheckerComponent : public ObjectImpl<CheckerComponent>
{
public:
DECLARE_PTR_TYPEDEFS(CheckerComponent);

View File

@ -34,6 +34,7 @@
using namespace icinga;
REGISTER_NTYPE(ClusterListener);
REGISTER_TYPE(ClusterListener);
/**
@ -210,13 +211,12 @@ void ClusterListener::PersistMessage(const Endpoint::Ptr& source, const Dictiona
if (source)
pmessage->Set("source", source->GetName());
pmessage->Set("message", Value(message).Serialize());
pmessage->Set("message", JsonSerialize(message));
pmessage->Set("security", message->Get("security"));
ObjectLock olock(this);
if (m_LogFile) {
String json = Value(pmessage).Serialize();
NetString::WriteStringToStream(m_LogFile, json);
NetString::WriteStringToStream(m_LogFile, JsonSerialize(pmessage));
m_LogMessageCount++;
SetLogMessageTimestamp(ts);
@ -404,7 +404,7 @@ void ClusterListener::ReplayLog(const Endpoint::Ptr& endpoint, const Stream::Ptr
if (!NetString::ReadStringFromStream(lstream, &message))
break;
pmessage = Value::Deserialize(message);
pmessage = JsonDeserialize(message);
} catch (std::exception&) {
Log(LogWarning, "cluster", "Unexpected end-of-file for cluster log: " + path);
@ -539,8 +539,7 @@ void ClusterListener::NewClientHandler(const Socket::Ptr& client, TlsRole role)
message->Set("method", "cluster::Config");
message->Set("params", params);
String json = Value(message).Serialize();
NetString::WriteStringToStream(tlsStream, json);
NetString::WriteStringToStream(tlsStream, JsonSerialize(message));
ReplayLog(endpoint, tlsStream);
}

View File

@ -28,6 +28,7 @@
using namespace icinga;
REGISTER_NTYPE(Endpoint);
REGISTER_TYPE(Endpoint);
boost::signals2::signal<void (const Endpoint::Ptr&)> Endpoint::OnConnected;

View File

@ -21,6 +21,7 @@
#include "base/netstring.h"
#include "base/objectlock.h"
#include "base/logger_fwd.h"
#include "base/serializer.h"
#include <boost/exception/diagnostic_information.hpp>
#include <iostream>
@ -33,7 +34,7 @@ using namespace icinga;
*/
void JsonRpc::SendMessage(const Stream::Ptr& stream, const Dictionary::Ptr& message)
{
String json = Value(message).Serialize();
String json = JsonSerialize(message);
// std::cerr << ">> " << json << std::endl;
NetString::WriteStringToStream(stream, json);
}
@ -45,7 +46,7 @@ Dictionary::Ptr JsonRpc::ReadMessage(const Stream::Ptr& stream)
BOOST_THROW_EXCEPTION(std::runtime_error("ReadStringFromStream signalled EOF."));
// std::cerr << "<< " << jsonString << std::endl;
Value value = Value::Deserialize(jsonString);
Value value = JsonDeserialize(jsonString);
if (!value.IsObjectType<Dictionary>()) {
BOOST_THROW_EXCEPTION(std::invalid_argument("JSON-RPC"

View File

@ -30,6 +30,7 @@
using namespace icinga;
REGISTER_NTYPE(CheckResultReader);
REGISTER_TYPE(CheckResultReader);
/**

View File

@ -39,6 +39,7 @@
using namespace icinga;
REGISTER_NTYPE(CompatLogger);
REGISTER_TYPE(CompatLogger);
REGISTER_SCRIPTFUNCTION(ValidateRotationMethod, &CompatLogger::ValidateRotationMethod);

View File

@ -27,6 +27,7 @@
using namespace icinga;
REGISTER_NTYPE(ExternalCommandListener);
REGISTER_TYPE(ExternalCommandListener);
/**

View File

@ -41,6 +41,7 @@
using namespace icinga;
REGISTER_NTYPE(StatusDataWriter);
REGISTER_TYPE(StatusDataWriter);
/**

View File

@ -33,6 +33,7 @@
using namespace icinga;
REGISTER_NTYPE(IdoMysqlConnection);
REGISTER_TYPE(IdoMysqlConnection);
#define SCHEMA_VERSION "1.10.0"

View File

@ -33,6 +33,7 @@
using namespace icinga;
REGISTER_NTYPE(IdoPgsqlConnection);
REGISTER_TYPE(IdoPgsqlConnection);
#define SCHEMA_VERSION "1.10.0"

View File

@ -23,6 +23,7 @@
using namespace icinga;
REGISTER_NTYPE(Demo);
REGISTER_TYPE(Demo);
/**

View File

@ -34,6 +34,7 @@
using namespace icinga;
using namespace livestatus;
REGISTER_NTYPE(LivestatusListener);
REGISTER_TYPE(LivestatusListener);
REGISTER_SCRIPTFUNCTION(ValidateSocketType, &LivestatusListener::ValidateSocketType);

View File

@ -37,6 +37,7 @@
#include "base/logger_fwd.h"
#include "base/exception.h"
#include "base/utility.h"
#include "base/serializer.h"
#include <boost/algorithm/string/classification.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string/split.hpp>
@ -370,7 +371,7 @@ void Query::PrintResultSet(std::ostream& fp, const std::vector<String>& columns,
fp << m_Separators[0];
}
} else if (m_OutputFormat == "json") {
fp << Value(rs).Serialize();
fp << JsonSerialize(rs);
}
}

View File

@ -28,6 +28,7 @@
using namespace icinga;
REGISTER_NTYPE(NotificationComponent);
REGISTER_TYPE(NotificationComponent);
/**

View File

@ -42,6 +42,7 @@
using namespace icinga;
REGISTER_NTYPE(GraphiteWriter);
REGISTER_TYPE(GraphiteWriter);
void GraphiteWriter::Start(void)

View File

@ -30,6 +30,7 @@
using namespace icinga;
REGISTER_NTYPE(PerfdataWriter);
REGISTER_TYPE(PerfdataWriter);
void PerfdataWriter::Start(void)

View File

@ -26,7 +26,7 @@ mkclass_target(sysloglogger.ti sysloglogger.th)
add_library(base SHARED
application.cpp application.th array.cpp bufferedstream.cpp consolelogger.cpp
consolelogger.th convert.cpp dictionary.cpp dynamicobject.cpp
consolelogger.th convert.cpp dictionary.cpp dynamicobject.cpp
dynamicobject.th dynamictype.cpp exception.cpp fifo.cpp filelogger.cpp
filelogger.th logger.cpp logger.th netstring.cpp networkstream.cpp object.cpp
objectlock.cpp process.cpp process-unix.cpp process-windows.cpp qstring.cpp
@ -34,7 +34,7 @@ add_library(base SHARED
scriptinterpreter.cpp scriptlanguage.cpp scriptvariable.cpp serializer.cpp
socket.cpp stacktrace.cpp stdiostream.cpp stream_bio.cpp stream.cpp
streamlogger.cpp streamlogger.th sysloglogger.cpp sysloglogger.th tcpsocket.cpp
threadpool.cpp timer.cpp tlsstream.cpp tlsutility.cpp unixsocket.cpp
threadpool.cpp timer.cpp tlsstream.cpp tlsutility.cpp type.cpp unixsocket.cpp
utility.cpp value.cpp workqueue.cpp zlibstream.cpp
)

View File

@ -25,6 +25,7 @@
#include "base/objectlock.h"
#include "base/utility.h"
#include "base/debug.h"
#include "base/type.h"
#include "base/scriptvariable.h"
#include "icinga-version.h"
#include <sstream>
@ -42,6 +43,8 @@
using namespace icinga;
REGISTER_NTYPE(Application);
Application *Application::m_Instance = NULL;
bool Application::m_ShuttingDown = false;
bool Application::m_Restarting = false;

View File

@ -3,7 +3,7 @@
namespace icinga
{
class Application : DynamicObject
abstract class Application : DynamicObject
{
};

View File

@ -23,6 +23,7 @@
using namespace icinga;
REGISTER_NTYPE(ConsoleLogger);
REGISTER_TYPE(ConsoleLogger);
/**

View File

@ -37,6 +37,8 @@
using namespace icinga;
REGISTER_NTYPE(DynamicObject);
boost::signals2::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnStarted;
boost::signals2::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnStopped;
boost::signals2::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnStateChanged;
@ -221,15 +223,14 @@ void DynamicObject::DumpObjects(const String& filename, int attributeTypes)
persistentObject->Set("type", type->GetName());
persistentObject->Set("name", object->GetName());
Dictionary::Ptr update = Serializer::Serialize(object, attributeTypes);
Dictionary::Ptr update = Serialize(object, attributeTypes);
if (!update)
continue;
persistentObject->Set("update", update);
Value value = persistentObject;
String json = value.Serialize();
String json = JsonSerialize(persistentObject);
NetString::WriteStringToStream(sfp, json);
}
@ -264,7 +265,7 @@ void DynamicObject::RestoreObjects(const String& filename, int attributeTypes)
String message;
while (NetString::ReadStringFromStream(sfp, &message)) {
Dictionary::Ptr persistentObject = Value::Deserialize(message);
Dictionary::Ptr persistentObject = JsonDeserialize(message);
String type = persistentObject->Get("type");
String name = persistentObject->Get("name");
@ -280,7 +281,7 @@ void DynamicObject::RestoreObjects(const String& filename, int attributeTypes)
if (object) {
ASSERT(!object->IsActive());
Log(LogDebug, "base", "Restoring object '" + name + "' of type '" + type + "'.");
Serializer::Deserialize(object, update, attributeTypes);
Deserialize(object, update, attributeTypes);
object->OnStateLoaded();
}

View File

@ -1,7 +1,7 @@
namespace icinga
{
class DynamicObject
abstract class DynamicObject
{
[config] String __name (Name);
[config, get_protected] String __type (TypeName);

View File

@ -139,7 +139,7 @@ DynamicObject::Ptr DynamicType::CreateObject(const Dictionary::Ptr& serializedUp
DynamicObject::Ptr object = factory();
Serializer::Deserialize(object, serializedUpdate, FAConfig);
Deserialize(object, serializedUpdate, FAConfig);
return object;
}

View File

@ -23,6 +23,7 @@
using namespace icinga;
REGISTER_NTYPE(FileLogger);
REGISTER_TYPE(FileLogger);
/**

View File

@ -35,7 +35,7 @@ inline bool InitializeOnceHelper(InitializeFunc func)
}
#define INITIALIZE_ONCE(name, func) \
bool l_InitializeOnce ## name(InitializeOnceHelper(func));
I2_EXPORT bool l_InitializeOnce ## name(InitializeOnceHelper(func))
}

View File

@ -29,6 +29,8 @@
using namespace icinga;
REGISTER_NTYPE(Logger);
std::set<Logger::Ptr> Logger::m_Loggers;
boost::mutex Logger::m_Mutex;

View File

@ -3,7 +3,7 @@
namespace icinga
{
class Logger : DynamicObject
abstract class Logger : DynamicObject
{
[config] String severity;
};

View File

@ -184,11 +184,6 @@ public:
}
};
template<typename T>
class TypeImpl
{
};
template<typename T>
class ObjectImpl
{

View File

@ -26,6 +26,7 @@
using namespace icinga;
REGISTER_NTYPE(Script);
REGISTER_TYPE(Script);
void Script::Start(void)

View File

@ -19,14 +19,93 @@
#include "base/serializer.h"
#include "base/type.h"
#include "base/application.h"
#include "base/objectlock.h"
#include <boost/foreach.hpp>
#include <boost/tuple/tuple.hpp>
#include <cJSON.h>
using namespace icinga;
Dictionary::Ptr Serializer::Serialize(const Object::Ptr& object, int attributeTypes)
/**
* Serializes a Value into a JSON string.
*
* @returns A string representing the Value.
*/
String icinga::JsonSerialize(const Value& value)
{
const Type *type = object->GetReflectionType();
cJSON *json = value.ToJson();
Dictionary::Ptr update = make_shared<Dictionary>();
char *jsonString;
if (Application::IsDebugging())
jsonString = cJSON_Print(json);
else
jsonString = cJSON_PrintUnformatted(json);
cJSON_Delete(json);
String result = jsonString;
free(jsonString);
return result;
}
/**
* Deserializes the string representation of a Value.
*
* @param data A JSON string obtained from JsonSerialize
* @returns The newly deserialized Value.
*/
Value icinga::JsonDeserialize(const String& data)
{
cJSON *json = cJSON_Parse(data.CStr());
if (!json)
BOOST_THROW_EXCEPTION(std::runtime_error("Invalid JSON String: " + data));
Value value = Value::FromJson(json);
cJSON_Delete(json);
return value;
}
static Array::Ptr SerializeArray(const Array::Ptr& input, int attributeTypes)
{
Array::Ptr result = make_shared<Array>();
ObjectLock olock(input);
BOOST_FOREACH(const Value& value, input) {
result->Add(Serialize(value, attributeTypes));
}
return result;
}
static Dictionary::Ptr SerializeDictionary(const Dictionary::Ptr& input, int attributeTypes)
{
Dictionary::Ptr result = make_shared<Dictionary>();
ObjectLock olock(input);
String key;
Value value;
BOOST_FOREACH(boost::tie(key, value), input) {
result->Set(key, Serialize(value, attributeTypes));
}
return result;
}
static Object::Ptr SerializeObject(const Object::Ptr& input, int attributeTypes)
{
const Type *type = input->GetReflectionType();
VERIFY(type);
Dictionary::Ptr fields = make_shared<Dictionary>();
for (int i = 0; i < type->GetFieldCount(); i++) {
Field field = type->GetFieldInfo(i);
@ -34,15 +113,58 @@ Dictionary::Ptr Serializer::Serialize(const Object::Ptr& object, int attributeTy
if ((field.Attributes & attributeTypes) == 0)
continue;
update->Set(field.Name, object->GetField(i));
fields->Set(field.Name, Serialize(input->GetField(i), attributeTypes));
}
return update;
fields->Set("__type", type->GetName());
return fields;
}
void Serializer::Deserialize(const Object::Ptr& object, const Dictionary::Ptr& update, int attributeTypes)
static Array::Ptr DeserializeArray(const Array::Ptr& input, int attributeTypes)
{
const Type *type = object->GetReflectionType();
Array::Ptr result = make_shared<Array>();
ObjectLock olock(input);
BOOST_FOREACH(const Value& value, input) {
result->Add(Deserialize(value, attributeTypes));
}
return result;
}
static Dictionary::Ptr DeserializeDictionary(const Dictionary::Ptr& input, int attributeTypes)
{
Dictionary::Ptr result = make_shared<Dictionary>();
ObjectLock olock(input);
String key;
Value value;
BOOST_FOREACH(boost::tie(key, value), input) {
result->Set(key, Deserialize(value, attributeTypes));
}
return result;
}
static Object::Ptr DeserializeObject(const Object::Ptr& object, const Dictionary::Ptr& input, int attributeTypes)
{
const Type *type;
if (object)
type = object->GetReflectionType();
else
type = Type::GetByName(input->Get("__type"));
if (!type)
return object;
Object::Ptr instance = object;
if (!instance)
instance = type->Instantiate();
for (int i = 0; i < type->GetFieldCount(); i++) {
Field field = type->GetFieldInfo(i);
@ -50,9 +172,58 @@ void Serializer::Deserialize(const Object::Ptr& object, const Dictionary::Ptr& u
if ((field.Attributes & attributeTypes) == 0)
continue;
if (!update->Contains(field.Name))
if (!input->Contains(field.Name))
continue;
object->SetField(i, update->Get(field.Name));
instance->SetField(i, Deserialize(input->Get(field.Name), attributeTypes));
}
return instance;
}
Value icinga::Serialize(const Value& value, int attributeTypes)
{
if (!value.IsObject())
return value;
Object::Ptr input = value;
Array::Ptr array = dynamic_pointer_cast<Array>(input);
if (array != NULL)
return SerializeArray(array, attributeTypes);
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(input);
if (dict != NULL)
return SerializeDictionary(dict, attributeTypes);
return SerializeObject(input, attributeTypes);
}
Value icinga::Deserialize(const Value& value, int attributeTypes)
{
return Deserialize(Object::Ptr(), value, attributeTypes);
}
Value icinga::Deserialize(const Object::Ptr& object, const Value& value, int attributeTypes)
{
if (!value.IsObject())
return value;
Object::Ptr input = value;
Array::Ptr array = dynamic_pointer_cast<Array>(input);
if (array != NULL)
return DeserializeArray(array, attributeTypes);
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(input);
ASSERT(dict != NULL);
if (!dict->Contains("__type"))
return DeserializeDictionary(dict, attributeTypes);
return DeserializeObject(object, dict, attributeTypes);
}

View File

@ -21,26 +21,24 @@
#define SERIALIZER_H
#include "base/i2-base.h"
#include "base/dictionary.h"
#include "base/value.h"
namespace icinga
{
/**
* Serializer utilities.
*
* @ingroup base
*/
class I2_BASE_API Serializer
enum FieldAttribute
{
public:
static Dictionary::Ptr Serialize(const Object::Ptr& object, int attributeTypes);
static void Deserialize(const Object::Ptr& object, const Dictionary::Ptr& update, int attributeTypes);
private:
Serializer(void);
FAConfig = 1,
FAState = 2
};
I2_BASE_API String JsonSerialize(const Value& value);
I2_BASE_API Value JsonDeserialize(const String& data);
I2_BASE_API Value Serialize(const Value& value, int attributeTypes = FAState);
I2_BASE_API Value Deserialize(const Value& value, int attributeTypes = FAState);
I2_BASE_API Value Deserialize(const Object::Ptr& object, const Value& value, int attributeTypes = FAState);
}
#endif /* SERIALIZER_H */

View File

@ -26,6 +26,8 @@
using namespace icinga;
REGISTER_NTYPE(StreamLogger);
boost::mutex StreamLogger::m_Mutex;
/**

View File

@ -23,6 +23,7 @@
#ifndef _WIN32
using namespace icinga;
REGISTER_NTYPE(SyslogLogger);
REGISTER_TYPE(SyslogLogger);
/**

67
lib/base/type.cpp Normal file
View File

@ -0,0 +1,67 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2013 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "base/type.h"
using namespace icinga;
Type::TypeMap& Type::GetTypes(void)
{
static TypeMap types;
return types;
}
void Type::Register(const Type *type)
{
VERIFY(GetByName(type->GetName()) == NULL);
GetTypes()[type->GetName()] = type;
}
const Type *Type::GetByName(const String& name)
{
std::map<String, const Type *>::const_iterator it;
it = GetTypes().find(name);
if (it == GetTypes().end())
return NULL;
return it->second;
}
Object::Ptr Type::Instantiate(void) const
{
return m_Factory();
}
bool Type::IsAssignableFrom(const Type *other) const
{
for (const Type *t = other; t; t = t->GetBaseType())
if (t == this)
return true;
return false;
}
void Type::SetFactory(const Type::Factory& factory)
{
m_Factory = factory;
}

View File

@ -22,16 +22,13 @@
#include "base/i2-base.h"
#include "base/qstring.h"
#include "base/serializer.h"
#include "base/initialize.h"
#include <boost/function.hpp>
namespace icinga
{
enum FieldAttribute
{
FAConfig = 1,
FAState = 2
};
struct Field
{
int ID;
@ -46,12 +43,70 @@ struct Field
class I2_BASE_API Type
{
public:
virtual Type *GetBaseType(void) const = 0;
typedef boost::function<Object::Ptr (void)> Factory;
virtual String GetName(void) const = 0;
virtual const Type *GetBaseType(void) const = 0;
virtual bool IsAbstract(void) const = 0;
virtual int GetFieldId(const String& name) const = 0;
virtual Field GetFieldInfo(int id) const = 0;
virtual int GetFieldCount(void) const = 0;
Object::Ptr Instantiate(void) const;
bool IsAssignableFrom(const Type *other) const;
static void Register(const Type *type);
static const Type *GetByName(const String& name);
void SetFactory(const Factory& factory);
private:
typedef std::map<String, const Type *> TypeMap;
static TypeMap& GetTypes(void);
Factory m_Factory;
};
template<typename T>
class TypeImpl
{
};
template<typename T>
Type *GetType(void)
{
return TypeImpl<T>::GetInstance();
}
template<typename T>
shared_ptr<T> ObjectFactory(void)
{
return make_shared<T>();
}
template<typename T>
struct FactoryHelper
{
Type::Factory GetFactory(void)
{
return ObjectFactory<T>;
}
};
#define REGISTER_NTYPE(type) \
namespace { \
void RegisterType(void) \
{ \
icinga::Type *t = icinga::GetType<type>(); \
t->SetFactory(FactoryHelper<type>().GetFactory()); \
icinga::Type::Register(GetType<type>()); \
} \
\
INITIALIZE_ONCE(type, RegisterType); \
}
}
#endif /* TYPE_H */

View File

@ -153,31 +153,6 @@ Value Value::FromJson(cJSON *json)
BOOST_THROW_EXCEPTION(std::invalid_argument("Unsupported JSON type."));
}
/**
* Serializes a variant into a string.
*
* @returns A string representing this variant.
*/
String Value::Serialize(void) const
{
cJSON *json = ToJson();
char *jsonString;
if (Application::IsDebugging())
jsonString = cJSON_Print(json);
else
jsonString = cJSON_PrintUnformatted(json);
cJSON_Delete(json);
String result = jsonString;
free(jsonString);
return result;
}
/**
* Serializes the variant.
*
@ -199,9 +174,10 @@ cJSON *Value::ToJson(void) const
} else if (IsObjectType<Array>()) {
Array::Ptr array = *this;
return array->ToJson();
} else {
Log(LogDebug, "base", "Ignoring unknown object while converting variant to JSON.");
} else if (IsEmpty()) {
return cJSON_CreateNull();
} else {
BOOST_THROW_EXCEPTION(std::runtime_error("Unknown object type."));
}
case ValueEmpty:
@ -212,25 +188,6 @@ cJSON *Value::ToJson(void) const
}
}
/**
* Deserializes the string representation of a variant.
*
* @param jsonString A JSON string obtained from Value::Serialize
* @returns The newly deserialized variant.
*/
Value Value::Deserialize(const String& jsonString)
{
cJSON *json = cJSON_Parse(jsonString.CStr());
if (!json)
BOOST_THROW_EXCEPTION(std::runtime_error("Invalid JSON String: " + jsonString));
Value value = FromJson(json);
cJSON_Delete(json);
return value;
}
/**
* Returns the type of the value.
*

View File

@ -118,9 +118,6 @@ public:
static Value FromJson(cJSON *json);
cJSON *ToJson(void) const;
String Serialize(void) const;
static Value Deserialize(const String& jsonString);
ValueType GetType(void) const;
private:

View File

@ -31,6 +31,8 @@
using namespace icinga;
REGISTER_NTYPE(DbConnection);
Timer::Ptr DbConnection::m_ProgramStatusTimer;
INITIALIZE_ONCE(DbConnection, &DbConnection::StaticInitialize);

View File

@ -4,7 +4,7 @@
namespace icinga
{
class DbConnection : DynamicObject
abstract class DbConnection : DynamicObject
{
[config] String table_prefix {
default {{{ return "icinga_"; }}}

View File

@ -23,6 +23,7 @@
using namespace icinga;
REGISTER_NTYPE(Hello);
REGISTER_TYPE(Hello);
/**

View File

@ -22,6 +22,7 @@
using namespace icinga;
REGISTER_NTYPE(CheckCommand);
REGISTER_TYPE(CheckCommand);
Dictionary::Ptr CheckCommand::Execute(const Service::Ptr& service)

View File

@ -21,6 +21,8 @@
using namespace icinga;
REGISTER_NTYPE(Command);
bool Command::ResolveMacro(const String& macro, const Dictionary::Ptr&, String *result) const
{
Dictionary::Ptr macros = GetMacros();

View File

@ -3,7 +3,7 @@
namespace icinga
{
class Command : DynamicObject
abstract class Command : DynamicObject
{
[config] Value command (CommandLine);
[config] Value timeout {

View File

@ -22,6 +22,7 @@
using namespace icinga;
REGISTER_NTYPE(Domain);
REGISTER_TYPE(Domain);
int Domain::GetPrivileges(const String& instance) const

View File

@ -22,6 +22,7 @@
using namespace icinga;
REGISTER_NTYPE(EventCommand);
REGISTER_TYPE(EventCommand);
void EventCommand::Execute(const Service::Ptr& service)

View File

@ -30,6 +30,7 @@
#include "base/utility.h"
#include "base/scriptfunction.h"
#include "base/debug.h"
#include "base/serializer.h"
#include "config/configitembuilder.h"
#include "config/configcompilercontext.h"
#include <boost/tuple/tuple.hpp>
@ -37,6 +38,7 @@
using namespace icinga;
REGISTER_NTYPE(Host);
REGISTER_TYPE(Host);
void Host::Start(void)
@ -265,7 +267,7 @@ Service::Ptr Host::GetServiceByShortName(const Value& name) const
return Service::GetByNamePair(dict->Get("host"), dict->Get("service"));
} else {
BOOST_THROW_EXCEPTION(std::invalid_argument("Host/Service name pair is invalid: " + name.Serialize()));
BOOST_THROW_EXCEPTION(std::invalid_argument("Host/Service name pair is invalid: " + JsonSerialize(name)));
}
}

View File

@ -27,6 +27,7 @@
using namespace icinga;
REGISTER_NTYPE(HostGroup);
REGISTER_TYPE(HostGroup);
std::set<Host::Ptr> HostGroup::GetMembers(void) const

View File

@ -32,6 +32,7 @@ using namespace icinga;
static Timer::Ptr l_RetentionTimer;
REGISTER_NTYPE(IcingaApplication);
REGISTER_TYPE(IcingaApplication);
INITIALIZE_ONCE(IcingaApplication, &IcingaApplication::StaticInitialize);

View File

@ -32,6 +32,7 @@
using namespace icinga;
REGISTER_NTYPE(Notification);
REGISTER_TYPE(Notification);
boost::signals2::signal<void (const Notification::Ptr&, double, const String&)> Notification::OnNextNotificationChanged;

View File

@ -22,6 +22,7 @@
using namespace icinga;
REGISTER_NTYPE(NotificationCommand);
REGISTER_TYPE(NotificationCommand);
Dictionary::Ptr NotificationCommand::Execute(const Notification::Ptr& notification,

View File

@ -6,6 +6,11 @@
using namespace icinga;
REGISTER_NTYPE(PerfdataValue);
PerfdataValue::PerfdataValue(void)
{ }
PerfdataValue::PerfdataValue(double value, bool counter, const String& unit,
const Value& warn, const Value& crit, const Value& min, const Value& max)
{

View File

@ -12,7 +12,9 @@ class I2_ICINGA_API PerfdataValue : public ObjectImpl<PerfdataValue>
public:
DECLARE_PTR_TYPEDEFS(PerfdataValue);
PerfdataValue(double value, bool counter, const String& unit,
PerfdataValue(void);
PerfdataValue(double value, bool counter = false, const String& unit = "",
const Value& warn = Empty, const Value& crit = Empty,
const Value& min = Empty, const Value& max = Empty);

View File

@ -5,13 +5,13 @@ namespace icinga
class PerfdataValue
{
[state] double Value;
[state] bool Counter;
[state] String Unit;
[state] Value Crit;
[state] Value Warn;
[state] Value Min;
[state] Value Max;
[state] double value;
[state] bool counter;
[state] String unit;
[state] Value crit;
[state] Value warn;
[state] Value min;
[state] Value max;
};
}

View File

@ -33,6 +33,7 @@
using namespace icinga;
REGISTER_NTYPE(Service);
REGISTER_TYPE(Service);
boost::signals2::signal<void (const Service::Ptr&, const String&, const String&, AcknowledgementType, double, const String&)> Service::OnAcknowledgementSet;

View File

@ -28,6 +28,7 @@
using namespace icinga;
REGISTER_NTYPE(ServiceGroup);
REGISTER_TYPE(ServiceGroup);
std::set<Service::Ptr> ServiceGroup::GetMembers(void) const

View File

@ -29,6 +29,7 @@
using namespace icinga;
REGISTER_NTYPE(TimePeriod);
REGISTER_TYPE(TimePeriod);
REGISTER_SCRIPTFUNCTION(EmptyTimePeriod, &TimePeriod::EmptyTimePeriodUpdate);
REGISTER_SCRIPTFUNCTION(EvenMinutesTimePeriod, &TimePeriod::EvenMinutesTimePeriodUpdate);

View File

@ -25,6 +25,7 @@
using namespace icinga;
REGISTER_NTYPE(User);
REGISTER_TYPE(User);
void User::OnConfigLoaded(void)

View File

@ -27,6 +27,7 @@
using namespace icinga;
REGISTER_NTYPE(UserGroup);
REGISTER_TYPE(UserGroup);
std::set<User::Ptr> UserGroup::GetMembers(void) const

View File

@ -19,16 +19,16 @@ include(BoostTestTargets)
add_boost_test(base
SOURCES base-array.cpp base-convert.cpp base-dictionary.cpp base-fifo.cpp
base-match.cpp base-netstring.cpp base-object.cpp base-shellescape.cpp
base-stacktrace.cpp base-string.cpp base-timer.cpp base-value.cpp
icinga-perfdata.cpp test.cpp
base-match.cpp base-netstring.cpp base-object.cpp base-serialize.cpp
base-shellescape.cpp base-stacktrace.cpp base-string.cpp base-timer.cpp
base-type.cpp base-value.cpp icinga-perfdata.cpp test.cpp
LIBRARIES base config icinga
TESTS base_array/construct
base_array/getset
base_array/remove
base_array/foreach
base_array/clone
base_array/serialize
base_array/json
base_convert/tolong
base_convert/todouble
base_convert/tostring
@ -39,7 +39,7 @@ add_boost_test(base
base_dictionary/foreach
base_dictionary/remove
base_dictionary/clone
base_dictionary/serialize
base_dictionary/json
base_fifo/construct
base_fifo/io
base_match/tolong

View File

@ -19,6 +19,7 @@
#include "base/array.h"
#include "base/objectlock.h"
#include "base/serializer.h"
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>
@ -104,17 +105,17 @@ BOOST_AUTO_TEST_CASE(clone)
BOOST_CHECK(clone->Get(2) == 5);
}
BOOST_AUTO_TEST_CASE(serialize)
BOOST_AUTO_TEST_CASE(json)
{
Array::Ptr array = make_shared<Array>();
array->Add(7);
array->Add(2);
array->Add(5);
String json = Value(array).Serialize();
String json = JsonSerialize(array);
BOOST_CHECK(json.GetLength() > 0);
Array::Ptr deserialized = Value::Deserialize(json);
Array::Ptr deserialized = JsonDeserialize(json);
BOOST_CHECK(deserialized);
BOOST_CHECK(deserialized->GetLength() == 3);
BOOST_CHECK(deserialized->Get(0) == 7);

View File

@ -19,6 +19,7 @@
#include "base/dictionary.h"
#include "base/objectlock.h"
#include "base/serializer.h"
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>
#include <boost/tuple/tuple.hpp>
@ -161,16 +162,16 @@ BOOST_AUTO_TEST_CASE(clone)
BOOST_CHECK(dictionary->Get("test2") == "hello world");
}
BOOST_AUTO_TEST_CASE(serialize)
BOOST_AUTO_TEST_CASE(json)
{
Dictionary::Ptr dictionary = make_shared<Dictionary>();
dictionary->Set("test1", 7);
dictionary->Set("test2", "hello world");
String json = Value(dictionary).Serialize();
String json = JsonSerialize(dictionary);
BOOST_CHECK(json.GetLength() > 0);
Dictionary::Ptr deserialized = Value::Deserialize(json);
Dictionary::Ptr deserialized = JsonDeserialize(json);
BOOST_CHECK(deserialized->GetLength() == 2);
BOOST_CHECK(deserialized->Get("test1") == 7);
BOOST_CHECK(deserialized->Get("test2") == "hello world");

89
test/base-serialize.cpp Normal file
View File

@ -0,0 +1,89 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2013 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "icinga/perfdatavalue.h"
#include "base/dictionary.h"
#include "base/objectlock.h"
#include "base/serializer.h"
#include "base/array.h"
#include "base/dictionary.h"
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>
#include <boost/tuple/tuple.hpp>
using namespace icinga;
BOOST_AUTO_TEST_SUITE(base_serialize)
BOOST_AUTO_TEST_CASE(scalar)
{
BOOST_CHECK(Deserialize(Serialize(7)) == 7);
BOOST_CHECK(Deserialize(Serialize(7.3)) == 7.3);
BOOST_CHECK(Deserialize(Serialize(Empty)) == Empty);
BOOST_CHECK(Deserialize(Serialize("hello")) == "hello");
}
BOOST_AUTO_TEST_CASE(array)
{
Array::Ptr array = make_shared<Array>();
array->Add(7);
array->Add(7.3);
array->Add(Empty);
array->Add("hello");
Array::Ptr result = Deserialize(Serialize(array));
BOOST_CHECK(result->GetLength() == array->GetLength());
BOOST_CHECK(result->Get(0) == 7);
BOOST_CHECK(result->Get(1) == 7.3);
BOOST_CHECK(result->Get(2) == Empty);
BOOST_CHECK(result->Get(3) == "hello");
}
BOOST_AUTO_TEST_CASE(dictionary)
{
Dictionary::Ptr dict = make_shared<Dictionary>();
dict->Set("k1", 7);
dict->Set("k2", 7.3);
dict->Set("k3", Empty);
dict->Set("k4", "hello");
Dictionary::Ptr result = Deserialize(Serialize(dict));
BOOST_CHECK(result->GetLength() == dict->GetLength());
BOOST_CHECK(result->Get("k1") == 7);
BOOST_CHECK(result->Get("k2") == 7.3);
BOOST_CHECK(result->Get("k3") == Empty);
BOOST_CHECK(result->Get("k4") == "hello");
}
BOOST_AUTO_TEST_CASE(object)
{
PerfdataValue::Ptr pdv = make_shared<PerfdataValue>(100, true, "bytes");
std::cout << JsonSerialize(Serialize(pdv)) << std::endl;
PerfdataValue::Ptr result = Deserialize(Serialize(pdv));
BOOST_CHECK(result->GetValue() == pdv->GetValue());
}
BOOST_AUTO_TEST_SUITE_END()

66
test/base-type.cpp Normal file
View File

@ -0,0 +1,66 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2013 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "icinga/perfdatavalue.h"
#include "base/dictionary.h"
#include "base/objectlock.h"
#include "base/application.h"
#include "base/type.h"
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>
#include <boost/tuple/tuple.hpp>
using namespace icinga;
BOOST_AUTO_TEST_SUITE(base_type)
BOOST_AUTO_TEST_CASE(gettype)
{
const Type *t = GetType<Application>();
BOOST_CHECK(t);
}
BOOST_AUTO_TEST_CASE(assign)
{
const Type *t1 = GetType<Application>();
const Type *t2 = GetType<DynamicObject>();
BOOST_CHECK(t1->IsAssignableFrom(t1));
BOOST_CHECK(t2->IsAssignableFrom(t1));
BOOST_CHECK(!t1->IsAssignableFrom(t2));
}
BOOST_AUTO_TEST_CASE(byname)
{
const Type *t = Type::GetByName("Application");
BOOST_CHECK(t);
}
BOOST_AUTO_TEST_CASE(instantiate)
{
const Type *t = Type::GetByName("PerfdataValue");
Object::Ptr p = t->Instantiate();
BOOST_CHECK(p);
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -27,14 +27,14 @@ using namespace icinga;
#include "class_parser.hh"
#define YY_EXTRA_TYPE ClassCompiler *
#define YY_USER_ACTION \
do { \
yylloc->path = yyextra->GetPath(); \
yylloc->first_line = yylineno; \
yylloc->first_column = yycolumn; \
yylloc->last_line = yylineno; \
yylloc->last_column = yycolumn + yyleng - 1;\
yycolumn += yyleng; \
#define YY_USER_ACTION \
do { \
yylloc->path = yyextra->GetPath(); \
yylloc->first_line = yylineno; \
yylloc->first_column = yycolumn; \
yylloc->last_line = yylineno; \
yylloc->last_column = yycolumn + yyleng - 1; \
yycolumn += yyleng; \
} while (0);
#define YY_INPUT(buf, result, max_size) \

View File

@ -92,8 +92,20 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
<< "{" << std::endl
<< "public:" << std::endl;
/* GetName */
std::cout << "\t" << "virtual String GetName(void) const" << std::endl
<< "\t" << "{" << std::endl
<< "\t\t" << "return \"" << klass.Name << "\";" << std::endl
<< "\t" << "}" << std::endl << std::endl;
/* IsAbstract */
std::cout << "\t" << "virtual bool IsAbstract(void) const" << std::endl
<< "\t" << "{" << std::endl
<< "\t\t" << "return " << (klass.Abstract ? "true" : "false") << ";" << std::endl
<< "\t" << "}" << std::endl << std::endl;
/* GetBaseType */
std::cout << "\t" << "virtual Type *GetBaseType(void) const" << std::endl
std::cout << "\t" << "virtual const Type *GetBaseType(void) const" << std::endl
<< "\t" << "{" << std::endl;
std::cout << "\t\t" << "return ";
@ -365,6 +377,18 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
}
std::cout << "};" << std::endl << std::endl;
/* FactoryHelper */
if (klass.Abstract) {
std::cout << "template<>" << std::endl
<< "struct FactoryHelper<" << klass.Name << ">" << std::endl
<< "{" << std::endl
<< "\t" << "Type::Factory GetFactory(void)" << std::endl
<< "\t" << "{" << std::endl
<< "\t\t" << "return Type::Factory();"
<< "\t" << "}"
<< "};" << std::endl << std::endl;
}
}
void ClassCompiler::CompileFile(const std::string& path)