2005-06-30 Colin Walters <walters@verbum.org>
authorColin Walters <walters@verbum.org>
Thu, 30 Jun 2005 18:22:10 +0000 (18:22 +0000)
committerColin Walters <walters@verbum.org>
Thu, 30 Jun 2005 18:22:10 +0000 (18:22 +0000)
* test/glib/test-dbus-glib.c:
* test/glib/test-service-glib.c:
* test/glib/test-service-glib.xml: Update tests for new error
setting bits, also add async tests (patch from Ross Burton).

* test/glib/Makefile.am (test_service_glib_LDADD): Add
DBUS_GLIB_THREADS_LIBS.

* glib/dbus-gproxy.c (get_name_owner)
(dbus_g_pending_call_end_valist): Ditto.

* glib/dbus-gobject.c (error_metadata): New mapping from GError
domain (GQuark) to DBusGErrorInfo.
(gerror_domaincode_to_dbus_error_name): Attempt to look up error
quark in error_metadata.  Take message interface as default
error message interface.
(gerror_to_dbus_error_message): Pass message interface.
(dbus_set_g_error): Resurrected.
(dbus_g_error_info_free): New function.
(dbus_g_object_type_install_info): Use g_type_class_ref instead
of _peek to actually create the object class if it hasn't been
created yet.
(dbus_g_error_domain_register): New function.

* glib/dbus-gmain.c (dbus_g_bus_get): Switch to dbus_set_g_error.

* glib/dbus-gparser.c (validate_signature): Ditto.

* dbus/dbus-glib.h (dbus_g_error_set): Delete.
(dbus_g_error_domain_register): Prototype.

* glib/dbus-glib.c (dbus_g_error_set): Delete.
Update tests.

ChangeLog
dbus/dbus-glib.h
glib/dbus-glib.c
glib/dbus-gmain.c
glib/dbus-gobject.c
glib/dbus-gparser.c
glib/dbus-gproxy.c
test/glib/Makefile.am
test/glib/test-dbus-glib.c
test/glib/test-service-glib.c
test/glib/test-service-glib.xml

index bce59c6..0476f33 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+2005-06-30  Colin Walters  <walters@verbum.org>
+
+       * test/glib/test-dbus-glib.c:
+       * test/glib/test-service-glib.c:
+       * test/glib/test-service-glib.xml: Update tests for new error
+       setting bits, also add async tests (patch from Ross Burton).
+
+       * test/glib/Makefile.am (test_service_glib_LDADD): Add
+       DBUS_GLIB_THREADS_LIBS.
+
+       * glib/dbus-gproxy.c (get_name_owner)
+       (dbus_g_pending_call_end_valist): Ditto.
+
+       * glib/dbus-gobject.c (error_metadata): New mapping from GError
+       domain (GQuark) to DBusGErrorInfo.  
+       (gerror_domaincode_to_dbus_error_name): Attempt to look up error
+       quark in error_metadata.  Take message interface as default
+       error message interface.
+       (gerror_to_dbus_error_message): Pass message interface.
+       (dbus_set_g_error): Resurrected.
+       (dbus_g_error_info_free): New function.
+       (dbus_g_object_type_install_info): Use g_type_class_ref instead
+       of _peek to actually create the object class if it hasn't been
+       created yet.
+       (dbus_g_error_domain_register): New function.
+
+       * glib/dbus-gmain.c (dbus_g_bus_get): Switch to dbus_set_g_error.
+
+       * glib/dbus-gparser.c (validate_signature): Ditto.
+
+       * dbus/dbus-glib.h (dbus_g_error_set): Delete.
+       (dbus_g_error_domain_register): Prototype.
+
+       * glib/dbus-glib.c (dbus_g_error_set): Delete.
+       Update tests.
+
 2005-06-29  Colin Walters  <walters@verbum.org>
 
        * dbus/dbus-glib.h: Delete DBUS_TYPE_G_PROXY_ARRAY.  Add
index 5e791e0..41b3d9c 100644 (file)
@@ -81,9 +81,6 @@ typedef enum
 #include <dbus/dbus-glib-error-enum.h>    
 } DBusGError;
 
-void             dbus_g_error_set         (GError     **error,
-                                          const char  *name,
-                                          const char  *msg);
 gboolean         dbus_g_error_has_name    (GError      *error,
                                           const char  *name);
 const char *     dbus_g_error_get_name    (GError      *error);
@@ -126,6 +123,10 @@ struct _DBusGObjectInfo
 void       dbus_g_object_type_install_info     (GType                 object_type,
                                                 const DBusGObjectInfo *info);
 
+void       dbus_g_error_domain_register        (GQuark                domain,
+                                               const char *          default_iface,
+                                               GType                 code_enum);
+
 void       dbus_g_connection_register_g_object (DBusGConnection       *connection,
                                                const char            *at_path,
                                                GObject               *object);
index 3153dee..5b30ce7 100644 (file)
@@ -26,6 +26,7 @@
 #include <dbus/dbus-glib-lowlevel.h>
 #include "dbus-gtest.h"
 #include "dbus-gutils.h"
+#include "dbus-gobject.h"
 #include <string.h>
 
 #include <libintl.h>
@@ -149,41 +150,6 @@ dbus_g_error_quark (void)
   return quark;
 }
 
-#include "dbus-glib-error-switch.h"
-
-/**
- * Set a GError return location from a D-BUS error name and message.
- * This function should only be used in the implementation of service
- * methods.
- *
- * @param gerror location to store a GError, or #NULL
- * @param name the D-BUS error name
- * @param msg the D-BUS error detailed message
- */
-void
-dbus_g_error_set (GError    **gerror,
-                  const char *name,
-                 const char *msg)
-{
-  int code;
-  g_return_if_fail (name != NULL);
-  g_return_if_fail (msg != NULL);
-
-  code = dbus_error_to_gerror_code (name);
-  if (code == DBUS_GERROR_REMOTE_EXCEPTION)
-    g_set_error (gerror, DBUS_GERROR,
-                code,
-                "%s%c%s",
-                msg,
-                '\0',
-                name);
-  else
-    g_set_error (gerror, DBUS_GERROR,
-                code,
-                "%s",
-                msg);
-}
-
 /**
  * Determine whether D-BUS error name for a remote exception matches
  * the given name.  This function is intended to be invoked on a
@@ -463,7 +429,7 @@ _dbus_glib_test (const char *test_data_dir)
   dbus_error_init (&err);
   dbus_set_error_const (&err, DBUS_ERROR_NO_MEMORY, "Out of memory!");
 
-  dbus_g_error_set (&gerror, err.name, err.message);
+  dbus_set_g_error (&gerror, &err);
   g_assert (gerror != NULL);
   g_assert (gerror->domain == DBUS_GERROR);
   g_assert (gerror->code == DBUS_GERROR_NO_MEMORY);
@@ -472,13 +438,6 @@ _dbus_glib_test (const char *test_data_dir)
   dbus_error_init (&err);
   g_clear_error (&gerror);
 
-  dbus_g_error_set (&gerror, "com.example.Foo.BlahFailed", "blah failed");
-  g_assert (gerror != NULL);
-  g_assert (gerror->domain == DBUS_GERROR);
-  g_assert (gerror->code == DBUS_GERROR_REMOTE_EXCEPTION);
-  g_assert (dbus_g_error_has_name (gerror, "com.example.Foo.BlahFailed"));
-  g_assert (!strcmp (gerror->message, "blah failed"));
-
   return TRUE;
 }
 
index 6d3b56c..9d45ca0 100644 (file)
@@ -28,6 +28,7 @@
 #include "dbus-gtest.h"
 #include "dbus-gutils.h"
 #include "dbus-gvalue.h"
+#include "dbus-gobject.h"
 #include "dbus-gvalue-utils.h"
 #include <string.h>
 
@@ -720,7 +721,7 @@ dbus_g_bus_get (DBusBusType     type,
   connection = dbus_bus_get (type, &derror);
   if (connection == NULL)
     {
-      dbus_g_error_set (error, derror.name, derror.message);
+      dbus_set_g_error (error, &derror);
       dbus_error_free (&derror);
       return NULL;
     }
index 8e39979..c91f185 100644 (file)
  * @{
  */
 
+typedef struct
+{
+  char *default_iface;
+  GType code_enum;
+} DBusGErrorInfo;
+
 static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
 static GHashTable *info_hash = NULL;
 static GHashTable *marshal_table = NULL;
+static GData *error_metadata = NULL;
 
 static char*
 uscore_to_wincaps (const char *uscore)
@@ -696,6 +703,7 @@ lookup_object_and_method (GObject      *object,
 
 static char *
 gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info,
+                                     const char *msg_interface,
                                      GQuark domain, gint code)
 {
   const char *domain_str;
@@ -707,6 +715,36 @@ gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info,
 
   if (!domain_str || !code_str)
     {
+      DBusGErrorInfo *info;
+
+      g_static_rw_lock_reader_lock (&globals_lock);
+
+      if (error_metadata != NULL)
+       info = g_datalist_id_get_data (&error_metadata, domain);
+      else
+       info = NULL;
+
+      g_static_rw_lock_reader_unlock (&globals_lock);
+
+      if (info)
+       {
+         GEnumValue *value;
+         GEnumClass *klass;
+
+         klass = g_type_class_ref (info->code_enum);
+         value = g_enum_get_value (klass, code);
+         g_type_class_unref (klass);
+
+         domain_str = info->default_iface;
+         code_str = value->value_nick;
+       }
+    }
+
+  if (!domain_str)
+    domain_str = msg_interface;
+
+  if (!domain_str || !code_str)
+    {
       /* If we can't map it sensibly, make up an error name */
       char *domain_from_quark;
       
@@ -752,7 +790,9 @@ gerror_to_dbus_error_message (const DBusGObjectInfo *object_info,
       else
        {
          char *error_name;
-         error_name = gerror_domaincode_to_dbus_error_name (object_info, error->domain, error->code);
+         error_name = gerror_domaincode_to_dbus_error_name (object_info,
+                                                            dbus_message_get_interface (message),
+                                                            error->domain, error->code);
          reply = dbus_message_new_error (message, error_name, error->message);
          g_free (error_name); 
        }
@@ -1256,6 +1296,40 @@ export_signals (DBusGConnection *connection, const DBusGObjectInfo *info, GObjec
     }
 }
 
+#include "dbus-glib-error-switch.h"
+
+void
+dbus_set_g_error (GError    **gerror,
+                 DBusError  *error)
+{
+  int code;
+
+  code = dbus_error_to_gerror_code (error->name);
+  if (code != DBUS_GERROR_REMOTE_EXCEPTION)
+    g_set_error (gerror, DBUS_GERROR,
+                code,
+                "%s",
+                error->message);
+  else
+    g_set_error (gerror, DBUS_GERROR,
+                code,
+                "%s%c%s",
+                error->message,
+                '\0',
+                error->name);
+}
+
+static void
+dbus_g_error_info_free (gpointer p)
+{
+  DBusGErrorInfo *info;
+
+  info = p;
+
+  g_free (info->default_iface);
+  g_free (info);
+}
+
 /** @} */ /* end of internals */
 
 /**
@@ -1287,7 +1361,7 @@ dbus_g_object_type_install_info (GType                  object_type,
 
   dbus_g_value_types_init ();
 
-  object_class = g_type_class_peek (object_type);
+  object_class = g_type_class_ref (object_type);
 
   g_return_if_fail (G_IS_OBJECT_CLASS (object_class));
 
@@ -1301,6 +1375,55 @@ dbus_g_object_type_install_info (GType                  object_type,
   g_hash_table_replace (info_hash, object_class, (void*) info);
 
   g_static_rw_lock_writer_unlock (&globals_lock);
+
+  g_type_class_unref (object_class);
+}
+
+/**
+ * Register a GError domain and set of codes with D-BUS.  You must
+ * have created a GEnum for the error codes.  This function will not
+ * be needed with an introspection-capable GLib.
+ *
+ * @param domain the GError domain 
+ * @param default_iface the D-BUS interface used for error values by default, or #NULL
+ * @param code_enum a GType for a GEnum of the error codes
+ */
+void
+dbus_g_error_domain_register (GQuark                domain,
+                             const char           *default_iface,
+                             GType                 code_enum)
+{
+  DBusGErrorInfo *info;
+  
+  g_return_if_fail (g_quark_to_string (domain) != NULL);
+  g_return_if_fail (code_enum != G_TYPE_INVALID);
+  g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM);
+
+  g_static_rw_lock_writer_lock (&globals_lock);
+
+  if (error_metadata == NULL)
+    g_datalist_init (&error_metadata);
+
+  info = g_datalist_id_get_data (&error_metadata, domain);
+
+  if (info != NULL)
+    {
+      g_warning ("Metadata for error domain \"%s\" already registered\n",
+                g_quark_to_string (domain));
+    }
+  else
+    {
+      info = g_new0 (DBusGErrorInfo, 1);
+      info->default_iface = g_strdup (default_iface);
+      info->code_enum = code_enum;
+
+      g_datalist_id_set_data_full (&error_metadata,
+                                  domain,
+                                  info,
+                                  dbus_g_error_info_free);
+    }
+
+  g_static_rw_lock_writer_unlock (&globals_lock);
 }
 
 static void
index 90798b1..daf9bc8 100644 (file)
@@ -23,6 +23,7 @@
 #include "dbus-gparser.h"
 #include "dbus/dbus-glib-lowlevel.h"
 #include "dbus-gidl.h"
+#include "dbus-gobject.h"
 #include "dbus/dbus-signature.h"
 #include <string.h>
 
@@ -474,7 +475,7 @@ validate_signature (const char *str,
   
   if (!dbus_signature_validate (str, &derror))
     {
-      dbus_g_error_set (error, derror.name, derror.message);
+      dbus_set_g_error (&derror, error);
       return FALSE;
     }
   return TRUE;
index 9ea4c16..91cda82 100644 (file)
@@ -818,7 +818,7 @@ get_name_owner (DBusConnection     *connection,
 
  error:
   g_assert (dbus_error_is_set (&derror));
-  dbus_g_error_set (error, derror.name, derror.message);
+  dbus_set_g_error (error, &derror);
   dbus_error_free (&derror);
 
  out:
@@ -2009,14 +2009,14 @@ dbus_g_pending_call_end_valist (DBusGConnection   *connection,
       break;
     case DBUS_MESSAGE_TYPE_ERROR:
       dbus_set_error_from_message (&derror, reply);
-      dbus_g_error_set (error, derror.name, derror.message);
+      dbus_set_g_error (error, &derror);
       dbus_error_free (&derror);
       goto out;
       break;
     default:
       dbus_set_error (&derror, DBUS_ERROR_FAILED,
                       "Reply was neither a method return nor an exception");
-      dbus_g_error_set (error, derror.name, derror.message);
+      dbus_set_g_error (error, &derror);
       dbus_error_free (&derror);
       goto out;
       break;
index 77ee190..04d9c64 100644 (file)
@@ -61,7 +61,7 @@ my-object-marshal.h: Makefile my-object-marshal.list
 
 CLEANFILES = $(BUILT_SOURCES)
 
-test_service_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la
+test_service_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la $(DBUS_GLIB_THREADS_LIBS) 
 
 else
 ### not building tests
index e8cb74a..fd71d74 100644 (file)
@@ -441,7 +441,8 @@ main (int argc, char **argv)
   if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID) != FALSE)
     lose ("ThrowError call unexpectedly succeeded!");
   if (!dbus_g_error_has_name (error, "org.freedesktop.DBus.Tests.MyObject.Foo"))
-    lose ("ThrowError call returned unexpected error %s", dbus_g_error_get_name (error));
+    lose ("ThrowError call returned unexpected error \"%s\": %s", dbus_g_error_get_name (error),
+         error->message);
 
   g_print ("ThrowError failed (as expected) returned error: %s\n", error->message);
   g_clear_error (&error);
@@ -490,6 +491,13 @@ main (int argc, char **argv)
   if (v_UINT32_2 != 43)
     lose ("(wrapped) increment call returned %d, should be 43", v_UINT32_2);
 
+  v_UINT32_2 = 0;
+  if (!org_freedesktop_DBus_Tests_MyObject_async_increment (proxy, 42, &v_UINT32_2, &error))
+    lose_gerror ("Failed to complete (wrapped) AsyncIncrement call", error);
+
+  if (v_UINT32_2 != 43)
+    lose ("(wrapped) async increment call returned %d, should be 43", v_UINT32_2);
+
   g_print ("Calling (wrapped) throw_error\n");
   if (org_freedesktop_DBus_Tests_MyObject_throw_error (proxy, &error) != FALSE)
     lose ("(wrapped) ThrowError call unexpectedly succeeded!");
@@ -497,6 +505,12 @@ main (int argc, char **argv)
   g_print ("(wrapped) ThrowError failed (as expected) returned error: %s\n", error->message);
   g_clear_error (&error);
 
+  if (org_freedesktop_DBus_Tests_MyObject_async_throw_error (proxy, &error) != FALSE)
+    lose ("(wrapped) AsyncThrowError call unexpectedly succeeded!");
+
+  g_print ("(wrapped) AsyncThrowError failed (as expected) returned error: %s\n", error->message);
+  g_clear_error (&error);
+
   g_print ("Calling (wrapped) uppercase\n");
   if (!org_freedesktop_DBus_Tests_MyObject_uppercase (proxy, "foobar", &v_STRING_2, &error)) 
     lose_gerror ("Failed to complete (wrapped) Uppercase call", error);
index 9d5dfcc..84b57c6 100644 (file)
@@ -44,7 +44,9 @@ typedef enum
   MY_OBJECT_ERROR_BAR
 } MyObjectError;
 
-#define MY_OBJECT_ERROR my_object_error_quark ()
+#define MY_OBJECT_ERROR (my_object_error_quark ())
+
+#define MY_TYPE_ERROR (my_object_error_get_type ()) 
 
 gboolean my_object_do_nothing (MyObject *obj, GError **error);
 
@@ -85,10 +87,16 @@ gboolean my_object_emit_frobnicate (MyObject *obj, GError **error);
 
 gboolean my_object_terminate (MyObject *obj, GError **error);
 
+gboolean my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *context);
+
+gboolean my_object_async_throw_error (MyObject *obj, DBusGMethodInvocation *context);
+
 #include "test-service-glib-glue.h"
 
 GQuark my_object_error_quark (void);
 
+GType my_object_error_get_type (void);
+
 /* Properties */
 enum
 {
@@ -231,6 +239,30 @@ my_object_error_quark (void)
   return quark;
 }
 
+/* This should really be standard. */
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+my_object_error_get_type (void)
+{
+       static GType etype = 0;
+
+       if (etype == 0)
+       {
+               static const GEnumValue values[] =
+               {
+
+                       ENUM_ENTRY (MY_OBJECT_ERROR_FOO, "Foo"),
+                       ENUM_ENTRY (MY_OBJECT_ERROR_BAR, "Bar"),
+                       { 0, 0, 0 }
+               };
+
+               etype = g_enum_register_static ("MyObjectError", values);
+       }
+
+       return etype;
+}
+
 static GObject *obj;
 static GObject *obj2;
 
@@ -250,9 +282,11 @@ my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error)
 gboolean
 my_object_throw_error (MyObject *obj, GError **error)
 {
-  dbus_g_error_set (error,
-                   "org.freedesktop.DBus.Tests.MyObject.Foo",
-                   "this method always loses");    
+  g_set_error (error,
+              MY_OBJECT_ERROR,
+              MY_OBJECT_ERROR_FOO,
+              "%s",
+              "this method always loses");    
   return FALSE;
 }
 
@@ -464,6 +498,53 @@ my_object_emit_signal2 (MyObject *obj, GError **error)
   return TRUE;
 }
 
+typedef struct {
+  gint32 x;
+  DBusGMethodInvocation *context;
+} IncrementData;
+
+static gboolean
+do_async_increment (IncrementData *data)
+{
+  gint32 newx = data->x + 1;
+  dbus_g_method_return (data->context, newx);
+  g_free (data);
+  return FALSE;
+}
+
+gboolean
+my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *context)
+{
+  IncrementData *data = g_new0 (IncrementData, 1);
+  data->x = x;
+  data->context = context;
+  g_idle_add ((GSourceFunc)do_async_increment, data);
+  return TRUE;
+}
+
+static gboolean
+do_async_error (IncrementData *data)
+{
+  GError *error;
+  error = g_error_new (MY_OBJECT_ERROR,
+                      MY_OBJECT_ERROR_FOO,
+                      "%s",
+                      "this method always loses");
+  dbus_g_method_return_error (data->context, error);
+  g_free (data);
+  return FALSE;
+}
+
+gboolean
+my_object_async_throw_error (MyObject *obj, DBusGMethodInvocation *context)
+{
+  IncrementData *data = g_new0(IncrementData, 1);
+  data->context = context;
+  g_idle_add ((GSourceFunc)do_async_error,  data);
+  return TRUE;
+}
+
+
 static GMainLoop *loop;
 
 gboolean
@@ -484,6 +565,14 @@ main (int argc, char **argv)
   guint32 request_name_ret;
 
   g_type_init ();
+  g_thread_init (NULL); dbus_g_thread_init ();
+
+  dbus_g_object_type_install_info (MY_TYPE_OBJECT,
+                                  &dbus_glib_my_object_object_info);
+
+  dbus_g_error_domain_register (MY_OBJECT_ERROR,
+                               NULL,
+                               MY_TYPE_ERROR);
 
   g_printerr ("Launching test-service-glib\n");
 
@@ -506,8 +595,6 @@ main (int argc, char **argv)
   obj = g_object_new (MY_TYPE_OBJECT, NULL);
   obj2 = g_object_new (MY_TYPE_OBJECT, NULL);
 
-  dbus_g_object_type_install_info (MY_TYPE_OBJECT,
-                                  &dbus_glib_my_object_object_info);
   dbus_g_connection_register_g_object (connection,
                                        "/org/freedesktop/DBus/Tests/MyTestObject",
                                        obj);
index 83240b4..5805862 100644 (file)
     <method name="IncrementVal">
     </method>
 
+    <method name="AsyncIncrement">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="x" />
+      <arg type="u" direction="out" />
+    </method>
+
+    <method name="AsyncThrowError">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+    </method>
+    
     <method name="GetVal">
       <arg type="u" direction="out" />
     </method>