From: David Zeuthen Date: Sat, 15 Mar 2008 20:51:48 +0000 (-0400) Subject: Export the recently added GetAll() method on org.fd.DBus.Properties X-Git-Url: http://gitweb.freedesktop.org/?p=dbus/dbus-glib.git;a=commitdiff;h=09b0fc5818812d0167243bae9fd52cdaf67f0af0 Export the recently added GetAll() method on org.fd.DBus.Properties Because round-trip city is a bad place. --- --- a/dbus/dbus-gobject.c +++ b/dbus/dbus-gobject.c @@ -612,7 +612,7 @@ handle_introspect (DBusConnection *conne g_string_append (xml, " \n"); g_string_append (xml, " \n"); - /* We support get/set properties */ + /* We support get/set/getall properties */ g_string_append_printf (xml, " \n", DBUS_INTERFACE_PROPERTIES); g_string_append (xml, " \n"); g_string_append_printf (xml, " \n", DBUS_TYPE_STRING_AS_STRING); @@ -624,6 +624,17 @@ handle_introspect (DBusConnection *conne g_string_append_printf (xml, " \n", DBUS_TYPE_STRING_AS_STRING); g_string_append_printf (xml, " \n", DBUS_TYPE_VARIANT_AS_STRING); g_string_append (xml, " \n"); + g_string_append (xml, " \n"); + g_string_append_printf (xml, " \n", DBUS_TYPE_STRING_AS_STRING); + g_string_append_printf (xml, " \n", + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING + ); + + g_string_append (xml, " \n"); g_string_append (xml, " \n"); introspect_interfaces (object, xml); @@ -752,6 +763,113 @@ get_object_property (DBusConnection *con return ret; } +static DBusMessage* +get_all_object_properties (DBusConnection *connection, + DBusMessage *message, + const DBusGObjectInfo *object_info, + GObject *object) +{ + DBusMessage *ret; + DBusMessageIter iter_ret; + DBusMessageIter iter_dict; + DBusMessageIter iter_dict_entry; + DBusMessageIter iter_dict_value; + const char *p; + + ret = dbus_message_new_method_return (message); + if (ret == NULL) + goto oom; + + dbus_message_iter_init_append (ret, &iter_ret); + + if (!dbus_message_iter_open_container (&iter_ret, + DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &iter_dict)) + goto oom; + + p = object_info->exported_properties; + while (p != NULL && *p != '\0') + { + const char *prop_ifname; + const char *prop_name; + GParamSpec *pspec; + GType value_gtype; + GValue value = {0, }; + gchar *variant_sig; + + prop_ifname = p; + + while (*p != '\0') + p++; + p++; + if (*p == '\0') { + g_warning ("malformed exported_properties in object_info"); + break; + } + prop_name = p; + while (*p != '\0') + p++; + p++; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), prop_name); + if (pspec == NULL) + { + g_warning ("introspection data references non-existing property %s", prop_name); + continue; + } + + g_value_init (&value, pspec->value_type); + g_object_get_property (object, pspec->name, &value); + + variant_sig = _dbus_gvalue_to_signature (&value); + if (variant_sig == NULL) + { + value_gtype = G_VALUE_TYPE (&value); + g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype)); + g_value_unset (&value); + continue; + } + + if (!dbus_message_iter_open_container (&iter_dict, + DBUS_TYPE_DICT_ENTRY, + NULL, + &iter_dict_entry)) + goto oom; + if (!dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &prop_name)) + goto oom; + + if (!dbus_message_iter_open_container (&iter_dict_entry, + DBUS_TYPE_VARIANT, + variant_sig, + &iter_dict_value)) + goto oom; + + if (!_dbus_gvalue_marshal (&iter_dict_value, &value)) + goto oom; + + if (!dbus_message_iter_close_container (&iter_dict_entry, + &iter_dict_value)) + goto oom; + if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry)) + goto oom; + + g_value_unset (&value); + g_free (variant_sig); + } + + if (!dbus_message_iter_close_container (&iter_ret, &iter_dict)) + goto oom; + + return ret; + + oom: + g_error ("out of memory"); +} + static gboolean lookup_object_and_method (GObject *object, DBusMessage *message, @@ -1278,12 +1396,14 @@ gobject_message_function (DBusConnection GObject *object; gboolean setter; gboolean getter; + gboolean getall; char *s; const char *wincaps_propname; /* const char *wincaps_propiface; */ DBusMessageIter iter; const DBusGMethodInfo *method; const DBusGObjectInfo *object_info; + DBusMessage *ret; object = G_OBJECT (user_data); @@ -1291,8 +1411,9 @@ gobject_message_function (DBusConnection DBUS_INTERFACE_INTROSPECTABLE, "Introspect")) return handle_introspect (connection, message, object); - + /* Try the metainfo, which lets us invoke methods */ + object_info = NULL; if (lookup_object_and_method (object, message, &object_info, &method)) return invoke_object_method (object, object_info, method, connection, message); @@ -1301,6 +1422,7 @@ gobject_message_function (DBusConnection */ getter = FALSE; setter = FALSE; + getall = FALSE; if (dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "Get")) @@ -1309,10 +1431,16 @@ gobject_message_function (DBusConnection DBUS_INTERFACE_PROPERTIES, "Set")) setter = TRUE; + else if (dbus_message_is_method_call (message, + DBUS_INTERFACE_PROPERTIES, + "GetAll")) + getall = TRUE; - if (!(setter || getter)) + if (!(setter || getter || getall)) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + ret = NULL; + dbus_message_iter_init (message, &iter); if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) @@ -1326,59 +1454,65 @@ gobject_message_function (DBusConnection /* dbus_message_iter_get_basic (&iter, &wincaps_propiface); */ dbus_message_iter_next (&iter); - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) + if (getall) { - g_warning ("Property get or set does not have a property name string as second arg\n"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (object_info != NULL) + ret = get_all_object_properties (connection, message, object_info, object); + else + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - dbus_message_iter_get_basic (&iter, &wincaps_propname); - dbus_message_iter_next (&iter); - - s = _dbus_gutils_wincaps_to_uscore (wincaps_propname); + else if (getter || setter) + { + if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) + { + g_warning ("Property get or set does not have a property name string as second arg\n"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + dbus_message_iter_get_basic (&iter, &wincaps_propname); + dbus_message_iter_next (&iter); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), - s); + s = _dbus_gutils_wincaps_to_uscore (wincaps_propname); - g_free (s); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), + s); - if (pspec != NULL) - { - DBusMessage *ret; + g_free (s); - if (setter) + if (pspec != NULL) { - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) + if (setter) { - g_warning ("Property set does not have a variant value as third arg\n"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) + { + g_warning ("Property set does not have a variant value as third arg\n"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + ret = set_object_property (connection, message, &iter, + object, pspec); + dbus_message_iter_next (&iter); + } + else if (getter) + { + ret = get_object_property (connection, message, + object, pspec); + } + else + { + g_assert_not_reached (); + ret = NULL; } - - ret = set_object_property (connection, message, &iter, - object, pspec); - dbus_message_iter_next (&iter); - } - else if (getter) - { - ret = get_object_property (connection, message, - object, pspec); - } - else - { - g_assert_not_reached (); - ret = NULL; } + } - g_assert (ret != NULL); - - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) - g_warning ("Property get or set had too many arguments\n"); + g_assert (ret != NULL); - dbus_connection_send (connection, ret, NULL); - dbus_message_unref (ret); - return DBUS_HANDLER_RESULT_HANDLED; - } + if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) + g_warning ("Property get, set or set all had too many arguments\n"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + dbus_connection_send (connection, ret, NULL); + dbus_message_unref (ret); + return DBUS_HANDLER_RESULT_HANDLED; } static const DBusObjectPathVTable gobject_dbus_vtable = {