]> granicus.if.org Git - icinga2/commitdiff
Moved serialization functionality into the base library.
authorGunnar Beutner <gunnar@beutner.name>
Tue, 24 Jul 2012 08:50:53 +0000 (10:50 +0200)
committerGunnar Beutner <gunnar@beutner.name>
Tue, 24 Jul 2012 08:50:53 +0000 (10:50 +0200)
13 files changed:
base/base.vcxproj
base/component.cpp
base/component.h
base/dictionary.cpp
base/dictionary.h
base/utility.cpp
base/utility.h
base/variant.cpp
base/variant.h
jsonrpc/jsonrpc.vcxproj
jsonrpc/jsonrpcclient.cpp
jsonrpc/messagepart.cpp
jsonrpc/messagepart.h

index 72cfeb18c884ad8781e81c7325ae0a05d4753f43..7666a3368aec768537cec498bf766bb86a780187 100644 (file)
   </ImportGroup>
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <IncludePath>$(SolutionDir)\third-party\mmatch;$(IncludePath)</IncludePath>
+    <IncludePath>$(SolutionDir)\third-party\mmatch;$(SolutionDir)\third-party\cJSON;$(IncludePath)</IncludePath>
     <LibraryPath>$(OutDir);$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <IncludePath>$(SolutionDir)\third-party\mmatch;$(IncludePath)</IncludePath>
+    <IncludePath>$(SolutionDir)\third-party\mmatch;$(SolutionDir)\third-party\cJSON;$(IncludePath)</IncludePath>
     <LibraryPath>$(OutDir);$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <Link>
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>ws2_32.lib;shlwapi.lib;mmatch.lib;libeay32MTd.lib;ssleay32MTd.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>ws2_32.lib;shlwapi.lib;mmatch.lib;cJSON.lib;libeay32MTd.lib;ssleay32MTd.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
     <Lib>
       <AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>ws2_32.lib;shlwapi.lib;mmatch.lib;libeay32MT.lib;ssleay32MT.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>ws2_32.lib;shlwapi.lib;mmatch.lib;cJSON.lib;libeay32MT.lib;ssleay32MT.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
     <Lib>
       <AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
index 52c27b5a3fb5d9ed939f7c9078b55dc717ad7b94..b9fe5e8e3bfa032262858f6930a750bad379fc0a 100644 (file)
@@ -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.
  *
index a59c1faa7fa7ebaee688621bb152a233016be489..db73381036cbd1938e271e02bfbe6cd96010ab39 100644 (file)
@@ -35,9 +35,6 @@ public:
        typedef shared_ptr<Component> Ptr;
        typedef weak_ptr<Component> WeakPtr;
 
-       Component(void);
-       virtual ~Component(void);
-
        ConfigObject::Ptr GetConfig(void) const;
 
        virtual void Start(void);
index 8626916bb060fc2c20c31a0ead9b8ce985f056f4..01500c8891e29c1b621b12e3e824d30f0ef46a58 100644 (file)
@@ -18,6 +18,7 @@
  ******************************************************************************/
 
 #include "i2-base.h"
+#include <cJSON.h>
 
 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<Dictionary>();
+
+       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
index 919a608701ac290a731f2ba0ade8891957c2ffc1..9c0e5d760cdc4b7d4bdfce377dafb9e432799d32 100644 (file)
@@ -105,6 +105,9 @@ public:
 
        void Remove(const string& key);
 
+       static Dictionary::Ptr FromJson(cJSON *json);
+       cJSON *ToJson(void) const;
+
 private:
        map<string, Variant> m_Data;
 };
index 685d6018ba588f4276f4df7b6d404162f6216a8d..c5eb45b7392b43d383d25cdf7c55079ef23c4f31 100644 (file)
@@ -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. */
+}
index 4370be683d68fca330431f4151017ce375a2d47d..3f89383358d0805a390a0aa653960d06ecf5c95d 100644 (file)
@@ -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;
 
index dfddc6ca4e7d064c0220924e4bef74d724895b83..25c3975c4a0627c4bc6ff8c1501c56a5afab2753 100644 (file)
@@ -18,6 +18,7 @@
  ******************************************************************************/
 
 #include "i2-base.h"
+#include <cJSON.h>
 
 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<long>(m_Value));
+       } else if (m_Value.type() == typeid(double)) {
+               return cJSON_CreateNumber(boost::get<double>(m_Value));
+       } else if (m_Value.type() == typeid(string)) {
+               return cJSON_CreateString(boost::get<string>(m_Value).c_str());
+       } else if (m_Value.type() == typeid(Object::Ptr)) {
+               if (IsObjectType<Dictionary>()) {
+                       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;
+}
index 4f1c996cde68ae3083b3ac2480d9f6da3e384936..4f0a4f956ec2c804f5e7ba44ce70af0b98547d43 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef VARIANT_H
 #define VARIANT_H
 
+struct cJSON;
+
 namespace icinga
 {
 
@@ -128,6 +130,12 @@ public:
                return (dynamic_pointer_cast<T>(boost::get<Object::Ptr>(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<boost::blank, long, double, string, Object::Ptr> m_Value;
 };
index ac8e6ac70b7130615d70d7ab7f955e9705f9c5a2..095152f4e34f4c45a02b3f41481b5ad35984b5ac 100644 (file)
   </ImportGroup>
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <IncludePath>$(SolutionDir)\base;$(SolutionDir)\third-party\cJSON;$(IncludePath)</IncludePath>
+    <IncludePath>$(SolutionDir)\base;$(IncludePath)</IncludePath>
     <LibraryPath>$(OutDir);$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <IncludePath>$(SolutionDir)\base;$(SolutionDir)\third-party\cJSON;$(IncludePath)</IncludePath>
+    <IncludePath>$(SolutionDir)\base;$(IncludePath)</IncludePath>
     <LibraryPath>$(OutDir);$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -79,7 +79,7 @@
     <Link>
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>base.lib;cJSON.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>base.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
     <Lib>
       <AdditionalDependencies>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>base.lib;cJSON.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>base.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
     <Lib>
       <AdditionalDependencies>
index 6d0871b228abbaabe1e1fd10e713bc775821fc8b..28e8720327e787584c0b6a83ba48414eb76c0181 100644 (file)
@@ -40,7 +40,8 @@ JsonRpcClient::JsonRpcClient(TcpClientRole role, shared_ptr<SSL_CTX> 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<Dictionary>())
+                               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()));
                }
index 48faed4f4a71a77bbc9eed641f0e757aeaada5f0..1e90322ce090681667157bcaef924ff502f01cfa 100644 (file)
@@ -18,7 +18,6 @@
  ******************************************************************************/
 
 #include "i2-jsonrpc.h"
-#include <cJSON.h>
 
 using namespace icinga;
 
@@ -30,24 +29,6 @@ MessagePart::MessagePart(void)
        m_Dictionary = boost::make_shared<Dictionary>();
 }
 
-/**
- * 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<Dictionary>();
-
-       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<string>(i->second);
-                       cJSON_AddStringToObject(json, i->first.c_str(), valueString.c_str());
-               } else if (i->second.IsObjectType<Dictionary>()) {
-                       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.
  *
index 276d3e92879a07111c9062f26d3ba7a5376670d7..8a6cc021caef4b3fed619f0d44000dc5da26b1c1 100644 (file)
@@ -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);
 };
 
 }