From 03d040311afd4b988b9a277a8aa360fa20243c92 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 30 Jun 2005 18:22:10 +0000 Subject: 2005-06-30 Colin Walters * 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. --- glib/dbus-glib.c | 45 +------------------ glib/dbus-gmain.c | 3 +- glib/dbus-gobject.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++- glib/dbus-gparser.c | 3 +- glib/dbus-gproxy.c | 6 +-- 5 files changed, 134 insertions(+), 50 deletions(-) (limited to 'glib') diff --git a/glib/dbus-glib.c b/glib/dbus-glib.c index 3153deef..5b30ce7a 100644 --- a/glib/dbus-glib.c +++ b/glib/dbus-glib.c @@ -26,6 +26,7 @@ #include #include "dbus-gtest.h" #include "dbus-gutils.h" +#include "dbus-gobject.h" #include #include @@ -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; } diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c index 6d3b56c8..9d45ca0e 100644 --- a/glib/dbus-gmain.c +++ b/glib/dbus-gmain.c @@ -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 @@ -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; } diff --git a/glib/dbus-gobject.c b/glib/dbus-gobject.c index 8e399796..c91f1851 100644 --- a/glib/dbus-gobject.c +++ b/glib/dbus-gobject.c @@ -39,9 +39,16 @@ * @{ */ +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; @@ -705,6 +713,36 @@ gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info, domain_str = object_error_domain_prefix_from_object_info (object_info); code_str = object_error_code_from_object_info (object_info, domain, code); + 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 */ @@ -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 diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c index 90798b19..daf9bc8e 100644 --- a/glib/dbus-gparser.c +++ b/glib/dbus-gparser.c @@ -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 @@ -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; diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 9ea4c16c..91cda82f 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -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; -- cgit