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