diff --git a/base/application.cpp b/base/application.cpp index c373b0c25..b2730d91c 100644 --- a/base/application.cpp +++ b/base/application.cpp @@ -400,7 +400,7 @@ int Application::Run(int argc, char **argv) Application::m_Instance.reset(); Logger::Write(LogCritical, "base", "---"); - Logger::Write(LogCritical, "base", "Exception: " + Utility::GetTypeName(ex)); + Logger::Write(LogCritical, "base", "Exception: " + Utility::GetTypeName(typeid(ex))); Logger::Write(LogCritical, "base", "Message: " + string(ex.what())); return EXIT_FAILURE; diff --git a/base/dictionary.h b/base/dictionary.h index 4aa17f987..d6c7f490f 100644 --- a/base/dictionary.h +++ b/base/dictionary.h @@ -57,27 +57,6 @@ public: return true; } - /** - * Retrieves a value from the dictionary. - * - * @param key The key. - * @param[out] value Pointer to the value. - * @returns true if the value was retrieved, false otherwise. - */ - bool Get(const string& key, Dictionary::Ptr *value) - { - Object::Ptr object; - - if (!Get(key, &object)) - return false; - - *value = dynamic_pointer_cast(object); - if (!*value) - throw runtime_error("Object is not a dictionary."); - - return true; - } - /** * Sets a value in the dictionary. * diff --git a/base/i2-base.h b/base/i2-base.h index eddb501d8..29ee50d59 100644 --- a/base/i2-base.h +++ b/base/i2-base.h @@ -108,11 +108,14 @@ using std::ostream; using std::ofstream; using std::exception; +using std::bad_cast; using std::runtime_error; using std::logic_error; using std::invalid_argument; using std::domain_error; +using std::type_info; + #include #include #include @@ -121,6 +124,8 @@ using std::domain_error; #include #include #include +#include +#include using boost::shared_ptr; using boost::weak_ptr; diff --git a/base/utility.cpp b/base/utility.cpp index 2a078d77f..4c63066ee 100644 --- a/base/utility.cpp +++ b/base/utility.cpp @@ -24,6 +24,30 @@ using namespace icinga; bool I2_EXPORT Utility::m_SSLInitialized = false; +/** + * Returns a human-readable type name of a type_info object. + * + * @param ti A type_info object. + * @returns The type name of the object. + */ +string Utility::GetTypeName(const type_info& ti) +{ + string klass = ti.name(); + +#ifdef HAVE_GCC_ABI_DEMANGLE + int status; + char *realname = abi::__cxa_demangle(klass.c_str(), 0, 0, &status); + + if (realname != NULL) { + klass = string(realname); + free(realname); + } +#endif /* HAVE_GCC_ABI_DEMANGLE */ + + return klass; +} + + /** * Detaches from the controlling terminal. */ diff --git a/base/utility.h b/base/utility.h index bf9b08233..4370be683 100644 --- a/base/utility.h +++ b/base/utility.h @@ -31,29 +31,7 @@ namespace icinga class I2_BASE_API Utility { public: - /** - * Returns a human-readable type name of an object (using RTTI). - * - * @param value An object. - * @returns The type name of the object. - */ - template - static string GetTypeName(const T& value) - { - string klass = typeid(value).name(); - -#ifdef HAVE_GCC_ABI_DEMANGLE - int status; - char *realname = abi::__cxa_demangle(klass.c_str(), 0, 0, &status); - - if (realname != NULL) { - klass = string(realname); - free(realname); - } -#endif /* HAVE_GCC_ABI_DEMANGLE */ - - return klass; - } + static string GetTypeName(const type_info& ti); static void Daemonize(void); diff --git a/base/variant.cpp b/base/variant.cpp index f1956d416..330989a74 100644 --- a/base/variant.cpp +++ b/base/variant.cpp @@ -21,94 +21,6 @@ using namespace icinga; -/** - * Converts the variant's value to a new type. - * - * @param newType The new type of the variant. - */ -void Variant::Convert(VariantType newType) const -{ - if (newType == m_Type) - return; - - if (m_Type == VariantString && newType == VariantInteger) { - m_IntegerValue = strtol(m_StringValue.c_str(), NULL, 10); - m_Type = VariantInteger; - - return; - } - - if (m_Type == VariantInteger && newType == VariantString) { - stringstream sbuf; - sbuf << m_IntegerValue; - m_StringValue = sbuf.str(); - m_Type = VariantString; - - return; - } - - // TODO: convert variant data - throw runtime_error("Invalid variant conversion."); -} - -/** - * Retrieves the variant value's type. - * - * @returns The variant's type. - */ -VariantType Variant::GetType(void) const -{ - return m_Type; -} - -/** - * Retrieves the variant's value as an integer. - * - * @returns The variant's value as an integer. - */ -long Variant::GetInteger(void) const -{ - Convert(VariantInteger); - - return m_IntegerValue; -} - -/** - * Retrieves the variant's value as a bool. - * - * @returns The variant's value as a bool. - */ -bool Variant::GetBool(void) const -{ - Convert(VariantInteger); - - return (m_IntegerValue != 0); -} - -/** - * Retrieves the variant's value as a string. - * - * @returns The variant's value as a string. - */ -string Variant::GetString(void) const -{ - Convert(VariantString); - - return m_StringValue; -} - -/** - * Retrieves the variant's value as an object. - * - * @returns The variant's value as an object. - */ -Object::Ptr Variant::GetObject(void) const -{ - Convert(VariantObject); - - return m_ObjectValue; -} - /** * Checks whether the variant is empty. * @@ -116,45 +28,15 @@ Object::Ptr Variant::GetObject(void) const */ bool Variant::IsEmpty(void) const { - return (m_Type == VariantEmpty); + return (m_Value.empty()); } -/** - * Retrieves the variant's value as an integer. - * - * @returns The variant's value as an integer. - */ -Variant::operator long(void) const +bool Variant::IsScalar(void) const { - return GetInteger(); + return !IsEmpty() && !IsObject(); } -/** - * Retrieves the variant's value as a bool. - * - * @returns The variant's value as a bool. - */ -Variant::operator bool(void) const +bool Variant::IsObject(void) const { - return GetBool(); -} - -/** - * Retrieves the variant's value as a string. - * - * @returns The variant's value as a string. - */ -Variant::operator string(void) const -{ - return GetString(); -} - -/** - * Retrieves the variant's value as an object. - * - * @returns The variant's value as an object. - */ -Variant::operator Object::Ptr(void) const -{ - return GetObject(); + return !IsEmpty() && (m_Value.type() == typeid(Object::Ptr)); } diff --git a/base/variant.h b/base/variant.h index 19db37a76..4889518a5 100644 --- a/base/variant.h +++ b/base/variant.h @@ -23,20 +23,6 @@ namespace icinga { -/** - * The type of a Variant object. - * - * @ingroup base - */ -enum VariantType -{ - VariantEmpty, /**< Denotes that the Variant is empty. */ - VariantInteger, /**< Denotes that the Variant is holding an integer. */ - VariantString, /**< Denotes that the Variant is holding a string. */ - VariantObject /**< Denotes that the Variant is holding an object - that inherits from the Object class. */ -}; - /** * A type that can hold an arbitrary value. * @@ -45,52 +31,81 @@ enum VariantType class I2_BASE_API Variant { public: - inline Variant(void) : m_Type(VariantEmpty) { } + inline Variant(void) + : m_Value() + { } - inline Variant(int value) - : m_Type(VariantInteger), m_IntegerValue(value) { } + inline Variant(double value) + : m_Value(value) + { } - inline Variant(bool value) - : m_Type(VariantInteger), m_IntegerValue(value ? 1 : 0) { } - - inline Variant(long value) - : m_Type(VariantInteger), m_IntegerValue(value) { } + inline Variant(const string& value) + : m_Value(value) + { } inline Variant(const char *value) - : m_Type(VariantString), m_StringValue(string(value)) { } - - inline Variant(string value) - : m_Type(VariantString), m_StringValue(value) { } + : m_Value(string(value)) + { } template - Variant(const shared_ptr& value) - : m_Type(VariantObject), m_ObjectValue(value) { } + inline Variant(const shared_ptr& value) + { + Object::Ptr object = dynamic_pointer_cast(value); - VariantType GetType(void) const; + if (!object) + throw invalid_argument("shared_ptr value type must inherit from Object class."); - long GetInteger(void) const; - bool GetBool(void) const; - string GetString(void) const; - Object::Ptr GetObject(void) const; + m_Value = object; + } + + operator double(void) const + { + if (m_Value.type() != typeid(double)) { + double result = boost::lexical_cast(m_Value); + m_Value = result; + return result; + } else { + return boost::get(m_Value); + } + } + + operator string(void) const + { + if (m_Value.type() != typeid(string)) { + string result = boost::lexical_cast(m_Value); + m_Value = result; + return result; + } else { + return boost::get(m_Value); + } + } + + template + operator shared_ptr(void) const + { + shared_ptr object = dynamic_pointer_cast(boost::get(m_Value)); + + if (!object) + throw bad_cast(); + + return object; + } bool IsEmpty(void) const; + bool IsScalar(void) const; + bool IsObject(void) const; - operator long(void) const; - operator bool(void) const; - operator string(void) const; - operator Object::Ptr(void) const; + template + bool IsObjectType(void) const + { + if (!IsObject()) + return false; + + return (dynamic_pointer_cast(boost::get(m_Value))); + } private: - mutable VariantType m_Type; /**< The type of the Variant. */ - - mutable long m_IntegerValue; /**< The value of the Variant - if m_Type == VariantInteger */ - mutable string m_StringValue; /**< The value of the Variant - if m_Type == VariantString */ - mutable Object::Ptr m_ObjectValue; /**< The value of the Variant - if m_Type == VariantObject */ - - void Convert(VariantType newType) const; + mutable boost::variant m_Value; }; } diff --git a/components/convenience/conveniencecomponent.cpp b/components/convenience/conveniencecomponent.cpp index 733fe29aa..0f32a63fc 100644 --- a/components/convenience/conveniencecomponent.cpp +++ b/components/convenience/conveniencecomponent.cpp @@ -125,13 +125,10 @@ void ConvenienceComponent::HostCommittedHandler(const ConfigItem::Ptr& item) CopyServiceAttributes(host, host->GetProperties(), builder); - if (svcdesc.GetType() == VariantString) { + if (svcdesc.IsScalar()) { builder->AddParent(svcdesc); - } else if (svcdesc.GetType() == VariantObject) { - Dictionary::Ptr service = dynamic_pointer_cast(svcdesc.GetObject()); - - if (!service) - throw invalid_argument("Service description invalid."); + } else if (svcdesc.IsObjectType()) { + Dictionary::Ptr service = svcdesc; string parent; if (!service->Get("service", &parent)) @@ -154,7 +151,7 @@ void ConvenienceComponent::HostCommittedHandler(const ConfigItem::Ptr& item) if (oldServices) { Dictionary::Iterator it; for (it = oldServices->Begin(); it != oldServices->End(); it++) { - ConfigItem::Ptr service = static_pointer_cast(it->second.GetObject()); + ConfigItem::Ptr service = it->second; if (!newServices->Contains(service->GetName())) service->Unregister(); @@ -182,7 +179,7 @@ void ConvenienceComponent::HostRemovedHandler(const ConfigItem::Ptr& item) Dictionary::Iterator it; for (it = services->Begin(); it != services->End(); it++) { - ConfigItem::Ptr service = static_pointer_cast(it->second.GetObject()); + ConfigItem::Ptr service = it->second; service->Unregister(); } } diff --git a/components/discovery/discoverycomponent.cpp b/components/discovery/discoverycomponent.cpp index f240d28bc..2b7102e3b 100644 --- a/components/discovery/discoverycomponent.cpp +++ b/components/discovery/discoverycomponent.cpp @@ -327,16 +327,12 @@ bool DiscoveryComponent::HasMessagePermission(const Dictionary::Ptr& roles, cons for (ConfigObject::TMap::Iterator ip = range.first; ip != range.second; ip++) { ConfigObject::Ptr role = ip->second; - Object::Ptr object; - if (!role->GetProperty(messageType, &object)) + Dictionary::Ptr permissions; + if (!role->GetProperty(messageType, &permissions)) continue; - Dictionary::Ptr permissions = dynamic_pointer_cast(object); - if (!permissions) - throw runtime_error("Object is not a dictionary."); - for (Dictionary::Iterator is = permissions->Begin(); is != permissions->End(); is++) { - if (Utility::Match(is->second.GetString(), message)) + if (Utility::Match(is->second, message)) return true; } } @@ -372,14 +368,8 @@ void DiscoveryComponent::ProcessDiscoveryMessage(const string& identity, const D ConfigObject::Ptr endpointConfig = ConfigObject::GetObject("endpoint", identity); Dictionary::Ptr roles; - if (endpointConfig) { - Object::Ptr object; - if (endpointConfig->GetProperty("roles", &object)) { - roles = dynamic_pointer_cast(object); - if (!roles) - throw runtime_error("Object is not a dictionary."); - } - } + if (endpointConfig) + endpointConfig->GetProperty("roles", &roles); Endpoint::Ptr endpoint = EndpointManager::GetInstance()->GetEndpointByIdentity(identity); diff --git a/dyn/config_parser.cc b/dyn/config_parser.cc index 55e9c5b90..4676d4203 100644 --- a/dyn/config_parser.cc +++ b/dyn/config_parser.cc @@ -535,9 +535,9 @@ static const yytype_int8 yyrhs[] = static const yytype_uint8 yyrline[] = { 0, 94, 94, 95, 98, 98, 101, 107, 112, 107, - 132, 133, 136, 140, 146, 147, 150, 157, 158, 162, - 161, 173, 174, 176, 177, 178, 181, 189, 203, 212, - 213, 214, 215, 216, 222, 227, 231, 237, 238 + 131, 132, 135, 139, 145, 146, 149, 156, 157, 161, + 160, 172, 173, 175, 176, 177, 180, 188, 202, 211, + 212, 213, 214, 215, 221, 226, 230, 236, 237 }; #endif @@ -1582,9 +1582,8 @@ yyreduce: /* Line 1806 of yacc.c */ #line 118 "config_parser.yy" { - Object::Ptr exprl_object = *(yyvsp[(8) - (8)].variant); + ExpressionList::Ptr exprl = *(yyvsp[(8) - (8)].variant); delete (yyvsp[(8) - (8)].variant); - ExpressionList::Ptr exprl = dynamic_pointer_cast(exprl_object); m_Item->AddExpressionList(exprl); m_Item->SetLocal(m_Local); @@ -1598,7 +1597,7 @@ yyreduce: case 12: /* Line 1806 of yacc.c */ -#line 137 "config_parser.yy" +#line 136 "config_parser.yy" { m_Abstract = true; } @@ -1607,7 +1606,7 @@ yyreduce: case 13: /* Line 1806 of yacc.c */ -#line 141 "config_parser.yy" +#line 140 "config_parser.yy" { m_Local = true; } @@ -1616,7 +1615,7 @@ yyreduce: case 16: /* Line 1806 of yacc.c */ -#line 151 "config_parser.yy" +#line 150 "config_parser.yy" { m_Item->AddParent((yyvsp[(1) - (1)].text)); free((yyvsp[(1) - (1)].text)); @@ -1626,7 +1625,7 @@ yyreduce: case 19: /* Line 1806 of yacc.c */ -#line 162 "config_parser.yy" +#line 161 "config_parser.yy" { m_ExpressionLists.push(boost::make_shared()); } @@ -1635,7 +1634,7 @@ yyreduce: case 20: /* Line 1806 of yacc.c */ -#line 167 "config_parser.yy" +#line 166 "config_parser.yy" { (yyval.variant) = new Variant(m_ExpressionLists.top()); m_ExpressionLists.pop(); @@ -1645,7 +1644,7 @@ yyreduce: case 26: /* Line 1806 of yacc.c */ -#line 182 "config_parser.yy" +#line 181 "config_parser.yy" { Expression expr((yyvsp[(1) - (3)].text), (yyvsp[(2) - (3)].op), *(yyvsp[(3) - (3)].variant), yylloc); free((yyvsp[(1) - (3)].text)); @@ -1658,7 +1657,7 @@ yyreduce: case 27: /* Line 1806 of yacc.c */ -#line 190 "config_parser.yy" +#line 189 "config_parser.yy" { Expression subexpr((yyvsp[(3) - (6)].text), (yyvsp[(5) - (6)].op), *(yyvsp[(6) - (6)].variant), yylloc); free((yyvsp[(3) - (6)].text)); @@ -1677,7 +1676,7 @@ yyreduce: case 28: /* Line 1806 of yacc.c */ -#line 204 "config_parser.yy" +#line 203 "config_parser.yy" { Expression expr((yyvsp[(1) - (1)].text), OperatorSet, (yyvsp[(1) - (1)].text), yylloc); free((yyvsp[(1) - (1)].text)); @@ -1689,7 +1688,7 @@ yyreduce: case 33: /* Line 1806 of yacc.c */ -#line 217 "config_parser.yy" +#line 216 "config_parser.yy" { (yyval.op) = (yyvsp[(1) - (1)].op); } @@ -1698,7 +1697,7 @@ yyreduce: case 34: /* Line 1806 of yacc.c */ -#line 223 "config_parser.yy" +#line 222 "config_parser.yy" { (yyval.variant) = new Variant((yyvsp[(1) - (1)].text)); free((yyvsp[(1) - (1)].text)); @@ -1708,7 +1707,7 @@ yyreduce: case 35: /* Line 1806 of yacc.c */ -#line 228 "config_parser.yy" +#line 227 "config_parser.yy" { (yyval.variant) = new Variant((yyvsp[(1) - (1)].num)); } @@ -1717,7 +1716,7 @@ yyreduce: case 36: /* Line 1806 of yacc.c */ -#line 232 "config_parser.yy" +#line 231 "config_parser.yy" { (yyval.variant) = new Variant(); } @@ -1726,7 +1725,7 @@ yyreduce: case 38: /* Line 1806 of yacc.c */ -#line 239 "config_parser.yy" +#line 238 "config_parser.yy" { (yyval.variant) = (yyvsp[(1) - (1)].variant); } @@ -1735,7 +1734,7 @@ yyreduce: /* Line 1806 of yacc.c */ -#line 1739 "config_parser.cc" +#line 1738 "config_parser.cc" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1973,6 +1972,6 @@ yyreturn: /* Line 2067 of yacc.c */ -#line 243 "config_parser.yy" +#line 242 "config_parser.yy" diff --git a/dyn/config_parser.yy b/dyn/config_parser.yy index ec0312624..98f2817f2 100644 --- a/dyn/config_parser.yy +++ b/dyn/config_parser.yy @@ -116,9 +116,8 @@ attributes T_OBJECT T_IDENTIFIER T_STRING } inherits_specifier expressionlist { - Object::Ptr exprl_object = *$8; + ExpressionList::Ptr exprl = *$8; delete $8; - ExpressionList::Ptr exprl = dynamic_pointer_cast(exprl_object); m_Item->AddExpressionList(exprl); m_Item->SetLocal(m_Local); diff --git a/dyn/expression.cpp b/dyn/expression.cpp index cbca7eb42..9dc567646 100644 --- a/dyn/expression.cpp +++ b/dyn/expression.cpp @@ -32,10 +32,11 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const ExpressionList::Ptr valueExprl; Dictionary::Ptr valueDict; - if (m_Value.GetType() == VariantObject) { - valueExprl = dynamic_pointer_cast(m_Value.GetObject()); - valueDict = dynamic_pointer_cast(m_Value.GetObject()); - } + if (m_Value.IsObjectType()) + valueExprl = m_Value; + + if (m_Value.IsObjectType()) + valueDict = m_Value; newValue = m_Value; @@ -62,8 +63,8 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const case OperatorPlus: dictionary->Get(m_Key, &oldValue); - if (oldValue.GetType() == VariantObject) - dict = dynamic_pointer_cast(oldValue.GetObject()); + if (oldValue.IsObjectType()) + dict = oldValue; if (!dict) { if (!oldValue.IsEmpty()) { diff --git a/jsonrpc/messagepart.cpp b/jsonrpc/messagepart.cpp index 7b3a2ef7e..994753a73 100644 --- a/jsonrpc/messagepart.cpp +++ b/jsonrpc/messagepart.cpp @@ -113,21 +113,15 @@ json_t *MessagePart::GetJsonFromDictionary(const Dictionary::Ptr& dictionary) json = cJSON_CreateObject(); for (Dictionary::Iterator i = dictionary->Begin(); i != dictionary->End(); i++) { - switch (i->second.GetType()) { - case VariantInteger: - cJSON_AddNumberToObject(json, i->first.c_str(), i->second.GetInteger()); - break; - case VariantString: - valueString = i->second.GetString(); - cJSON_AddStringToObject(json, i->first.c_str(), valueString.c_str()); - break; - case VariantObject: - valueDictionary = dynamic_pointer_cast(i->second.GetObject()); - - if (valueDictionary) - cJSON_AddItemToObject(json, i->first.c_str(), GetJsonFromDictionary(valueDictionary)); - default: - break; + 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()); } } @@ -178,14 +172,10 @@ Dictionary::Ptr MessagePart::GetDictionary(void) const */ bool MessagePart::Get(string key, MessagePart *value) const { - Object::Ptr object; - if (!GetDictionary()->Get(key, &object)) + Dictionary::Ptr dictionary; + if (!GetDictionary()->Get(key, &dictionary)) return false; - Dictionary::Ptr dictionary = dynamic_pointer_cast(object); - if (!dictionary) - throw runtime_error("Object is not a dictionary."); - *value = MessagePart(dictionary); return true; }