diff --git a/base/base.vcxproj b/base/base.vcxproj
index 72cfeb18c..7666a3368 100644
--- a/base/base.vcxproj
+++ b/base/base.vcxproj
@@ -105,11 +105,11 @@
- $(SolutionDir)\third-party\mmatch;$(IncludePath)
+ $(SolutionDir)\third-party\mmatch;$(SolutionDir)\third-party\cJSON;$(IncludePath)
$(OutDir);$(LibraryPath)
- $(SolutionDir)\third-party\mmatch;$(IncludePath)
+ $(SolutionDir)\third-party\mmatch;$(SolutionDir)\third-party\cJSON;$(IncludePath)
$(OutDir);$(LibraryPath)
@@ -125,7 +125,7 @@
Windows
true
- ws2_32.lib;shlwapi.lib;mmatch.lib;libeay32MTd.lib;ssleay32MTd.lib;%(AdditionalDependencies)
+ ws2_32.lib;shlwapi.lib;mmatch.lib;cJSON.lib;libeay32MTd.lib;ssleay32MTd.lib;%(AdditionalDependencies)
ws2_32.lib;shlwapi.lib
@@ -149,7 +149,7 @@
true
true
true
- ws2_32.lib;shlwapi.lib;mmatch.lib;libeay32MT.lib;ssleay32MT.lib;%(AdditionalDependencies)
+ ws2_32.lib;shlwapi.lib;mmatch.lib;cJSON.lib;libeay32MT.lib;ssleay32MT.lib;%(AdditionalDependencies)
ws2_32.lib;shlwapi.lib
diff --git a/base/component.cpp b/base/component.cpp
index 52c27b5a3..b9fe5e8e3 100644
--- a/base/component.cpp
+++ b/base/component.cpp
@@ -145,19 +145,6 @@ void Component::AddSearchDir(const string& componentDirectory)
#endif /* _WIN32 */
}
-/**
- * Constructor for the Component class.
- */
-Component::Component(void)
- : m_ModuleHandle(0)
-{ }
-
-/**
- * Destructor for the Component class.
- */
-Component::~Component(void)
-{ }
-
/**
* Retrieves the name of the component.
*
diff --git a/base/component.h b/base/component.h
index a59c1faa7..db7338103 100644
--- a/base/component.h
+++ b/base/component.h
@@ -35,9 +35,6 @@ public:
typedef shared_ptr Ptr;
typedef weak_ptr WeakPtr;
- Component(void);
- virtual ~Component(void);
-
ConfigObject::Ptr GetConfig(void) const;
virtual void Start(void);
diff --git a/base/dictionary.cpp b/base/dictionary.cpp
index 8626916bb..01500c889 100644
--- a/base/dictionary.cpp
+++ b/base/dictionary.cpp
@@ -18,6 +18,7 @@
******************************************************************************/
#include "i2-base.h"
+#include
using namespace icinga;
@@ -77,3 +78,48 @@ void Dictionary::Remove(const string& key)
m_Data.erase(it);
}
+
+/**
+ * Converts a JSON object to a dictionary.
+ *
+ * @param json The JSON object.
+ * @returns A dictionary that is equivalent to the JSON object.
+ */
+Dictionary::Ptr Dictionary::FromJson(cJSON *json)
+{
+ Dictionary::Ptr dictionary = boost::make_shared();
+
+ if (json->type != cJSON_Object)
+ throw invalid_argument("JSON type must be cJSON_Object.");
+
+ for (cJSON *i = json->child; i != NULL; i = i->next) {
+ dictionary->Set(i->string, Variant::FromJson(i));
+ }
+
+ return dictionary;
+}
+
+/**
+ * Converts a dictionary to a JSON object.
+ *
+ * @param dictionary The dictionary.
+ * @returns A JSON object that is equivalent to the dictionary. Values that
+ * cannot be represented in JSON are omitted.
+ */
+cJSON *Dictionary::ToJson(void) const
+{
+ cJSON *json = cJSON_CreateObject();
+
+ try {
+ string key;
+ Variant value;
+ BOOST_FOREACH(tie(key, value), m_Data) {
+ cJSON_AddItemToObject(json, key.c_str(), value.ToJson());
+ }
+ } catch (...) {
+ cJSON_Delete(json);
+ throw;
+ }
+
+ return json;
+}
\ No newline at end of file
diff --git a/base/dictionary.h b/base/dictionary.h
index 919a60870..9c0e5d760 100644
--- a/base/dictionary.h
+++ b/base/dictionary.h
@@ -105,6 +105,9 @@ public:
void Remove(const string& key);
+ static Dictionary::Ptr FromJson(cJSON *json);
+ cJSON *ToJson(void) const;
+
private:
map m_Data;
};
diff --git a/base/utility.cpp b/base/utility.cpp
index 685d6018b..c5eb45b73 100644
--- a/base/utility.cpp
+++ b/base/utility.cpp
@@ -245,3 +245,13 @@ string Utility::BaseName(const string& path)
return result;
}
+
+/**
+ * Null deleter. Used as a parameter for the shared_ptr constructor.
+ *
+ * @param obj The object that should be deleted.
+ */
+void Utility::NullDeleter(void *obj)
+{
+ /* Nothing to do here. */
+}
diff --git a/base/utility.h b/base/utility.h
index 4370be683..3f8938335 100644
--- a/base/utility.h
+++ b/base/utility.h
@@ -44,6 +44,8 @@ public:
static string DirName(const string& path);
static string BaseName(const string& path);
+ static void NullDeleter(void *obj);
+
private:
static bool m_SSLInitialized;
diff --git a/base/variant.cpp b/base/variant.cpp
index dfddc6ca4..25c3975c4 100644
--- a/base/variant.cpp
+++ b/base/variant.cpp
@@ -18,6 +18,7 @@
******************************************************************************/
#include "i2-base.h"
+#include
using namespace icinga;
@@ -40,3 +41,75 @@ bool Variant::IsObject(void) const
{
return !IsEmpty() && (m_Value.type() == typeid(Object::Ptr));
}
+
+Variant Variant::FromJson(cJSON *json)
+{
+ if (json->type == cJSON_Number)
+ return json->valuedouble;
+ else if (json->type == cJSON_String)
+ return json->valuestring;
+ else if (json->type == cJSON_True)
+ return 1;
+ else if (json->type == cJSON_False)
+ return 0;
+ else if (json->type == cJSON_Object)
+ return Dictionary::FromJson(json);
+ else if (json->type == cJSON_NULL)
+ return Variant();
+ else
+ throw invalid_argument("Unsupported JSON type.");
+}
+
+string Variant::Serialize(void) const
+{
+ cJSON *json = ToJson();
+
+ char *jsonString;
+
+ if (!Application::GetInstance()->IsDebugging())
+ jsonString = cJSON_Print(json);
+ else
+ jsonString = cJSON_PrintUnformatted(json);
+
+ cJSON_Delete(json);
+
+ string result = jsonString;
+
+ free(jsonString);
+
+ return result;
+}
+
+cJSON *Variant::ToJson(void) const
+{
+ if (m_Value.type() == typeid(long)) {
+ return cJSON_CreateNumber(boost::get(m_Value));
+ } else if (m_Value.type() == typeid(double)) {
+ return cJSON_CreateNumber(boost::get(m_Value));
+ } else if (m_Value.type() == typeid(string)) {
+ return cJSON_CreateString(boost::get(m_Value).c_str());
+ } else if (m_Value.type() == typeid(Object::Ptr)) {
+ if (IsObjectType()) {
+ Dictionary::Ptr dictionary = *this;
+ return dictionary->ToJson();
+ } else {
+ Logger::Write(LogDebug, "base", "Ignoring unknown object while converting variant to JSON.");
+ return cJSON_CreateNull();
+ }
+ } else {
+ throw runtime_error("Invalid variant type.");
+ }
+}
+
+Variant Variant::Deserialize(const string& jsonString)
+{
+ cJSON *json = cJSON_Parse(jsonString.c_str());
+
+ if (!json)
+ throw_exception(runtime_error("Invalid JSON string"));
+
+ Variant value = FromJson(json);
+ cJSON_Delete(json);
+
+ return value;
+}
diff --git a/base/variant.h b/base/variant.h
index 4f1c996cd..4f0a4f956 100644
--- a/base/variant.h
+++ b/base/variant.h
@@ -20,6 +20,8 @@
#ifndef VARIANT_H
#define VARIANT_H
+struct cJSON;
+
namespace icinga
{
@@ -128,6 +130,12 @@ public:
return (dynamic_pointer_cast(boost::get(m_Value)));
}
+ static Variant FromJson(cJSON *json);
+ cJSON *ToJson(void) const;
+
+ string Serialize(void) const;
+ static Variant Deserialize(const string& jsonString);
+
private:
mutable boost::variant m_Value;
};
diff --git a/jsonrpc/jsonrpc.vcxproj b/jsonrpc/jsonrpc.vcxproj
index ac8e6ac70..095152f4e 100644
--- a/jsonrpc/jsonrpc.vcxproj
+++ b/jsonrpc/jsonrpc.vcxproj
@@ -59,11 +59,11 @@
- $(SolutionDir)\base;$(SolutionDir)\third-party\cJSON;$(IncludePath)
+ $(SolutionDir)\base;$(IncludePath)
$(OutDir);$(LibraryPath)
- $(SolutionDir)\base;$(SolutionDir)\third-party\cJSON;$(IncludePath)
+ $(SolutionDir)\base;$(IncludePath)
$(OutDir);$(LibraryPath)
@@ -79,7 +79,7 @@
Windows
true
- base.lib;cJSON.lib;%(AdditionalDependencies)
+ base.lib;%(AdditionalDependencies)
@@ -104,7 +104,7 @@
true
true
true
- base.lib;cJSON.lib;%(AdditionalDependencies)
+ base.lib;%(AdditionalDependencies)
diff --git a/jsonrpc/jsonrpcclient.cpp b/jsonrpc/jsonrpcclient.cpp
index 6d0871b22..28e872032 100644
--- a/jsonrpc/jsonrpcclient.cpp
+++ b/jsonrpc/jsonrpcclient.cpp
@@ -40,7 +40,8 @@ JsonRpcClient::JsonRpcClient(TcpClientRole role, shared_ptr sslContext)
*/
void JsonRpcClient::SendMessage(const MessagePart& message)
{
- Netstring::WriteStringToIOQueue(this, message.ToJsonString());
+ Variant value = message.GetDictionary();
+ Netstring::WriteStringToIOQueue(this, value.Serialize());
}
/**
@@ -52,7 +53,12 @@ void JsonRpcClient::DataAvailableHandler(void)
while (Netstring::ReadStringFromIOQueue(this, &jsonString)) {
try {
- OnNewMessage(GetSelf(), MessagePart(jsonString));
+ Variant value = Variant::Deserialize(jsonString);
+
+ if (!value.IsObjectType())
+ throw invalid_argument("JSON-RPC message must be a dictionary.");
+
+ OnNewMessage(GetSelf(), MessagePart(value));
} catch (const exception& ex) {
Logger::Write(LogCritical, "jsonrpc", "Exception while processing message from JSON-RPC client: " + string(ex.what()));
}
diff --git a/jsonrpc/messagepart.cpp b/jsonrpc/messagepart.cpp
index 48faed4f4..1e90322ce 100644
--- a/jsonrpc/messagepart.cpp
+++ b/jsonrpc/messagepart.cpp
@@ -18,7 +18,6 @@
******************************************************************************/
#include "i2-jsonrpc.h"
-#include
using namespace icinga;
@@ -30,24 +29,6 @@ MessagePart::MessagePart(void)
m_Dictionary = boost::make_shared();
}
-/**
- * Constructor for the MessagePart class.
- *
- * @param jsonString The JSON string that should be used to initialize
- * the message.
- */
-MessagePart::MessagePart(string jsonString)
-{
- json_t *json = cJSON_Parse(jsonString.c_str());
-
- if (!json)
- throw_exception(runtime_error("Invalid JSON string"));
-
- m_Dictionary = GetDictionaryFromJson(json);
-
- cJSON_Delete(json);
-}
-
/**
* Constructor for the MessagePart class.
*
@@ -68,91 +49,6 @@ MessagePart::MessagePart(const MessagePart& message)
m_Dictionary = message.GetDictionary();
}
-/**
- * Converts a JSON object to a dictionary.
- *
- * @param json The JSON object.
- * @returns A dictionary that is equivalent to the JSON object.
- */
-Dictionary::Ptr MessagePart::GetDictionaryFromJson(json_t *json)
-{
- Dictionary::Ptr dictionary = boost::make_shared();
-
- for (cJSON *i = json->child; i != NULL; i = i->next) {
- switch (i->type) {
- case cJSON_Number:
- dictionary->Set(i->string, i->valueint);
- break;
- case cJSON_String:
- dictionary->Set(i->string, i->valuestring);
- break;
- case cJSON_Object:
- dictionary->Set(i->string, GetDictionaryFromJson(i));
- break;
- default:
- break;
- }
- }
-
- return dictionary;
-}
-
-/**
- * Converts a dictionary to a JSON object.
- *
- * @param dictionary The dictionary.
- * @returns A JSON object that is equivalent to the dictionary. Values that
- * cannot be represented in JSON are omitted.
- */
-json_t *MessagePart::GetJsonFromDictionary(const Dictionary::Ptr& dictionary)
-{
- cJSON *json;
- string valueString;
- Dictionary::Ptr valueDictionary;
-
- json = cJSON_CreateObject();
-
- for (Dictionary::Iterator i = dictionary->Begin(); i != dictionary->End(); i++) {
- if (i->second.IsScalar()) {
- valueString = static_cast(i->second);
- cJSON_AddStringToObject(json, i->first.c_str(), valueString.c_str());
- } else if (i->second.IsObjectType()) {
- cJSON_AddItemToObject(json, i->first.c_str(), GetJsonFromDictionary(i->second));
- } else {
- stringstream msgbuf;
- msgbuf << "Dictionary serialization: Ignored property '" << i->first << "' (unknown type)";
- Logger::Write(LogDebug, "jsonrpc", msgbuf.str());
- }
- }
-
- return json;
-}
-
-/**
- * Converts a message into a JSON string.
- *
- * @returns A JSON string representing the message.
- */
-string MessagePart::ToJsonString(void) const
-{
- json_t *json = GetJsonFromDictionary(m_Dictionary);
- char *jsonString;
- string result;
-
- if (!Application::GetInstance()->IsDebugging())
- jsonString = cJSON_Print(json);
- else
- jsonString = cJSON_PrintUnformatted(json);
-
- cJSON_Delete(json);
-
- result = jsonString;
-
- free(jsonString);
-
- return result;
-}
-
/**
* Retrieves the underlying dictionary for this message.
*
diff --git a/jsonrpc/messagepart.h b/jsonrpc/messagepart.h
index 276d3e928..8a6cc021c 100644
--- a/jsonrpc/messagepart.h
+++ b/jsonrpc/messagepart.h
@@ -36,12 +36,9 @@ class I2_JSONRPC_API MessagePart
{
public:
MessagePart(void);
- MessagePart(string json);
MessagePart(const Dictionary::Ptr& dictionary);
MessagePart(const MessagePart& message);
- string ToJsonString(void) const;
-
Dictionary::Ptr GetDictionary(void) const;
/**
@@ -92,9 +89,6 @@ public:
private:
Dictionary::Ptr m_Dictionary;
-
- static Dictionary::Ptr GetDictionaryFromJson(json_t *json);
- static json_t *GetJsonFromDictionary(const Dictionary::Ptr& dictionary);
};
}