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; using namespace icinga;
REGISTER_NTYPE(CheckerComponent);
REGISTER_TYPE(CheckerComponent); REGISTER_TYPE(CheckerComponent);
void CheckerComponent::Start(void) void CheckerComponent::Start(void)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -37,6 +37,7 @@
#include "base/logger_fwd.h" #include "base/logger_fwd.h"
#include "base/exception.h" #include "base/exception.h"
#include "base/utility.h" #include "base/utility.h"
#include "base/serializer.h"
#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/classification.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/algorithm/string/split.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]; fp << m_Separators[0];
} }
} else if (m_OutputFormat == "json") { } else if (m_OutputFormat == "json") {
fp << Value(rs).Serialize(); fp << JsonSerialize(rs);
} }
} }

View File

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

View File

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

View File

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

View File

@ -26,7 +26,7 @@ mkclass_target(sysloglogger.ti sysloglogger.th)
add_library(base SHARED add_library(base SHARED
application.cpp application.th array.cpp bufferedstream.cpp consolelogger.cpp 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 dynamicobject.th dynamictype.cpp exception.cpp fifo.cpp filelogger.cpp
filelogger.th logger.cpp logger.th netstring.cpp networkstream.cpp object.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 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 scriptinterpreter.cpp scriptlanguage.cpp scriptvariable.cpp serializer.cpp
socket.cpp stacktrace.cpp stdiostream.cpp stream_bio.cpp stream.cpp socket.cpp stacktrace.cpp stdiostream.cpp stream_bio.cpp stream.cpp
streamlogger.cpp streamlogger.th sysloglogger.cpp sysloglogger.th tcpsocket.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 utility.cpp value.cpp workqueue.cpp zlibstream.cpp
) )

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -35,7 +35,7 @@ inline bool InitializeOnceHelper(InitializeFunc func)
} }
#define INITIALIZE_ONCE(name, 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; using namespace icinga;
REGISTER_NTYPE(Logger);
std::set<Logger::Ptr> Logger::m_Loggers; std::set<Logger::Ptr> Logger::m_Loggers;
boost::mutex Logger::m_Mutex; boost::mutex Logger::m_Mutex;

View File

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

View File

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

View File

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

View File

@ -19,14 +19,93 @@
#include "base/serializer.h" #include "base/serializer.h"
#include "base/type.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; 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++) { for (int i = 0; i < type->GetFieldCount(); i++) {
Field field = type->GetFieldInfo(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) if ((field.Attributes & attributeTypes) == 0)
continue; 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++) { for (int i = 0; i < type->GetFieldCount(); i++) {
Field field = type->GetFieldInfo(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) if ((field.Attributes & attributeTypes) == 0)
continue; continue;
if (!update->Contains(field.Name)) if (!input->Contains(field.Name))
continue; 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 #define SERIALIZER_H
#include "base/i2-base.h" #include "base/i2-base.h"
#include "base/dictionary.h" #include "base/value.h"
namespace icinga namespace icinga
{ {
/** enum FieldAttribute
* Serializer utilities.
*
* @ingroup base
*/
class I2_BASE_API Serializer
{ {
public: FAConfig = 1,
static Dictionary::Ptr Serialize(const Object::Ptr& object, int attributeTypes); FAState = 2
static void Deserialize(const Object::Ptr& object, const Dictionary::Ptr& update, int attributeTypes);
private:
Serializer(void);
}; };
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 */ #endif /* SERIALIZER_H */

View File

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

View File

@ -23,6 +23,7 @@
#ifndef _WIN32 #ifndef _WIN32
using namespace icinga; using namespace icinga;
REGISTER_NTYPE(SyslogLogger);
REGISTER_TYPE(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/i2-base.h"
#include "base/qstring.h" #include "base/qstring.h"
#include "base/serializer.h"
#include "base/initialize.h"
#include <boost/function.hpp>
namespace icinga namespace icinga
{ {
enum FieldAttribute
{
FAConfig = 1,
FAState = 2
};
struct Field struct Field
{ {
int ID; int ID;
@ -46,12 +43,70 @@ struct Field
class I2_BASE_API Type class I2_BASE_API Type
{ {
public: 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 int GetFieldId(const String& name) const = 0;
virtual Field GetFieldInfo(int id) const = 0; virtual Field GetFieldInfo(int id) const = 0;
virtual int GetFieldCount(void) 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 */ #endif /* TYPE_H */

View File

@ -153,31 +153,6 @@ Value Value::FromJson(cJSON *json)
BOOST_THROW_EXCEPTION(std::invalid_argument("Unsupported JSON type.")); 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. * Serializes the variant.
* *
@ -199,9 +174,10 @@ cJSON *Value::ToJson(void) const
} else if (IsObjectType<Array>()) { } else if (IsObjectType<Array>()) {
Array::Ptr array = *this; Array::Ptr array = *this;
return array->ToJson(); return array->ToJson();
} else { } else if (IsEmpty()) {
Log(LogDebug, "base", "Ignoring unknown object while converting variant to JSON.");
return cJSON_CreateNull(); return cJSON_CreateNull();
} else {
BOOST_THROW_EXCEPTION(std::runtime_error("Unknown object type."));
} }
case ValueEmpty: 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. * Returns the type of the value.
* *

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -30,6 +30,7 @@
#include "base/utility.h" #include "base/utility.h"
#include "base/scriptfunction.h" #include "base/scriptfunction.h"
#include "base/debug.h" #include "base/debug.h"
#include "base/serializer.h"
#include "config/configitembuilder.h" #include "config/configitembuilder.h"
#include "config/configcompilercontext.h" #include "config/configcompilercontext.h"
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
@ -37,6 +38,7 @@
using namespace icinga; using namespace icinga;
REGISTER_NTYPE(Host);
REGISTER_TYPE(Host); REGISTER_TYPE(Host);
void Host::Start(void) 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")); return Service::GetByNamePair(dict->Get("host"), dict->Get("service"));
} else { } 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; using namespace icinga;
REGISTER_NTYPE(HostGroup);
REGISTER_TYPE(HostGroup); REGISTER_TYPE(HostGroup);
std::set<Host::Ptr> HostGroup::GetMembers(void) const std::set<Host::Ptr> HostGroup::GetMembers(void) const

View File

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

View File

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

View File

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

View File

@ -6,6 +6,11 @@
using namespace icinga; using namespace icinga;
REGISTER_NTYPE(PerfdataValue);
PerfdataValue::PerfdataValue(void)
{ }
PerfdataValue::PerfdataValue(double value, bool counter, const String& unit, PerfdataValue::PerfdataValue(double value, bool counter, const String& unit,
const Value& warn, const Value& crit, const Value& min, const Value& max) 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: public:
DECLARE_PTR_TYPEDEFS(PerfdataValue); 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& warn = Empty, const Value& crit = Empty,
const Value& min = Empty, const Value& max = Empty); const Value& min = Empty, const Value& max = Empty);

View File

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

View File

@ -33,6 +33,7 @@
using namespace icinga; using namespace icinga;
REGISTER_NTYPE(Service);
REGISTER_TYPE(Service); REGISTER_TYPE(Service);
boost::signals2::signal<void (const Service::Ptr&, const String&, const String&, AcknowledgementType, double, const String&)> Service::OnAcknowledgementSet; 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; using namespace icinga;
REGISTER_NTYPE(ServiceGroup);
REGISTER_TYPE(ServiceGroup); REGISTER_TYPE(ServiceGroup);
std::set<Service::Ptr> ServiceGroup::GetMembers(void) const std::set<Service::Ptr> ServiceGroup::GetMembers(void) const

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,6 +19,7 @@
#include "base/dictionary.h" #include "base/dictionary.h"
#include "base/objectlock.h" #include "base/objectlock.h"
#include "base/serializer.h"
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
@ -161,16 +162,16 @@ BOOST_AUTO_TEST_CASE(clone)
BOOST_CHECK(dictionary->Get("test2") == "hello world"); BOOST_CHECK(dictionary->Get("test2") == "hello world");
} }
BOOST_AUTO_TEST_CASE(serialize) BOOST_AUTO_TEST_CASE(json)
{ {
Dictionary::Ptr dictionary = make_shared<Dictionary>(); Dictionary::Ptr dictionary = make_shared<Dictionary>();
dictionary->Set("test1", 7); dictionary->Set("test1", 7);
dictionary->Set("test2", "hello world"); dictionary->Set("test2", "hello world");
String json = Value(dictionary).Serialize(); String json = JsonSerialize(dictionary);
BOOST_CHECK(json.GetLength() > 0); BOOST_CHECK(json.GetLength() > 0);
Dictionary::Ptr deserialized = Value::Deserialize(json); Dictionary::Ptr deserialized = JsonDeserialize(json);
BOOST_CHECK(deserialized->GetLength() == 2); BOOST_CHECK(deserialized->GetLength() == 2);
BOOST_CHECK(deserialized->Get("test1") == 7); BOOST_CHECK(deserialized->Get("test1") == 7);
BOOST_CHECK(deserialized->Get("test2") == "hello world"); 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" #include "class_parser.hh"
#define YY_EXTRA_TYPE ClassCompiler * #define YY_EXTRA_TYPE ClassCompiler *
#define YY_USER_ACTION \ #define YY_USER_ACTION \
do { \ do { \
yylloc->path = yyextra->GetPath(); \ yylloc->path = yyextra->GetPath(); \
yylloc->first_line = yylineno; \ yylloc->first_line = yylineno; \
yylloc->first_column = yycolumn; \ yylloc->first_column = yycolumn; \
yylloc->last_line = yylineno; \ yylloc->last_line = yylineno; \
yylloc->last_column = yycolumn + yyleng - 1;\ yylloc->last_column = yycolumn + yyleng - 1; \
yycolumn += yyleng; \ yycolumn += yyleng; \
} while (0); } while (0);
#define YY_INPUT(buf, result, max_size) \ #define YY_INPUT(buf, result, max_size) \

View File

@ -92,8 +92,20 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
<< "{" << std::endl << "{" << std::endl
<< "public:" << 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 */ /* 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; << "\t" << "{" << std::endl;
std::cout << "\t\t" << "return "; std::cout << "\t\t" << "return ";
@ -365,6 +377,18 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
} }
std::cout << "};" << std::endl << std::endl; 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) void ClassCompiler::CompileFile(const std::string& path)