]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
D-Bus: Fix error handling in static clients
authorDidier 'Ptitjes <ptitjes@free.fr>
Wed, 6 May 2009 00:06:20 +0000 (02:06 +0200)
committerJürg Billeter <j@bitron.ch>
Mon, 14 Sep 2009 21:44:02 +0000 (23:44 +0200)
Fixes bug 581101.

Signed-off-by: Didier 'Ptitjes <ptitjes@free.fr>
codegen/valadbusclientmodule.vala
tests/dbus/arrays.test
tests/dbus/async.test
tests/dbus/basic-types.test

index c5f25f4c221c58fdd070aaf1ca37b774dc674606..bf89555cb106811dd41c0ca63a15913f6d7ac0d3 100644 (file)
@@ -45,6 +45,15 @@ internal class Vala.DBusClientModule : DBusModule {
                }
        }
 
+       bool has_dbus_error (Gee.List<DataType> error_types) {
+               foreach (DataType error_type in error_types) {
+                       if (((ErrorType) error_type).error_domain.get_full_name () == "DBus.Error") {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
        public override void generate_dynamic_method_wrapper (DynamicMethod method) {
                var dynamic_method = (DynamicMethod) method;
 
@@ -1486,6 +1495,12 @@ internal class Vala.DBusClientModule : DBusModule {
                }
                block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block));
 
+               cdecl = new CCodeDeclaration ("DBusError");
+               cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
+               block.add_statement (cdecl);
+
+               var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
+
                cdecl = new CCodeDeclaration ("DBusGConnection");
                cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
                block.add_statement (cdecl);
@@ -1510,6 +1525,10 @@ internal class Vala.DBusClientModule : DBusModule {
                gconnection.add_argument (new CCodeConstant ("NULL"));
                block.add_statement (new CCodeExpressionStatement (gconnection));
 
+               var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
+               dbus_error_init.add_argument (dbus_error);
+               block.add_statement (new CCodeExpressionStatement (dbus_error_init));
+
                var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
                connection.add_argument (new CCodeIdentifier ("_connection"));
 
@@ -1517,7 +1536,7 @@ internal class Vala.DBusClientModule : DBusModule {
                ccall.add_argument (connection);
                ccall.add_argument (new CCodeIdentifier ("_message"));
                ccall.add_argument (new CCodeConstant ("-1"));
-               ccall.add_argument (new CCodeConstant ("NULL"));
+               ccall.add_argument (dbus_error);
                block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
 
                var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
@@ -1528,6 +1547,42 @@ internal class Vala.DBusClientModule : DBusModule {
                message_unref.add_argument (new CCodeIdentifier ("_message"));
                block.add_statement (new CCodeExpressionStatement (message_unref));
 
+               var error_types = m.get_error_types ();
+               if (!has_dbus_error (error_types)) {
+                       Report.error (m.source_reference, "D-Bus methods must throw DBus.Error");
+               } else {
+                       var error_block = new CCodeBlock ();
+
+                       cdecl = new CCodeDeclaration ("GQuark");
+                       cdecl.add_declarator (new CCodeVariableDeclarator ("_edomain"));
+                       error_block.add_statement (cdecl);
+
+                       cdecl = new CCodeDeclaration ("gint");
+                       cdecl.add_declarator (new CCodeVariableDeclarator ("_ecode"));
+                       error_block.add_statement (cdecl);
+
+                       generate_client_error_cases (error_block, error_types, new CCodeMemberAccess (new CCodeIdentifier ("_dbus_error"), "name"), new CCodeIdentifier ("_edomain"), new CCodeIdentifier ("_ecode"));
+
+                       var g_set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
+                       g_set_error.add_argument (new CCodeIdentifier ("error"));
+                       g_set_error.add_argument (new CCodeIdentifier ("_edomain"));
+                       g_set_error.add_argument (new CCodeIdentifier ("_ecode"));
+                       g_set_error.add_argument (new CCodeMemberAccess (new CCodeIdentifier ("_dbus_error"), "message"));
+                       error_block.add_statement (new CCodeExpressionStatement (g_set_error));
+
+                       var dbus_error_free = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_free"));
+                       dbus_error_free.add_argument (dbus_error);
+                       error_block.add_statement (new CCodeExpressionStatement (dbus_error_free));
+
+                       if (!(m.return_type is VoidType)) {
+                               error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
+                       }
+
+                       var dbus_error_is_set = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_is_set"));
+                       dbus_error_is_set.add_argument (dbus_error);
+                       block.add_statement (new CCodeIfStatement (dbus_error_is_set, error_block));
+               }
+
                block.add_statement (postfragment);
 
                var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
@@ -1545,6 +1600,72 @@ internal class Vala.DBusClientModule : DBusModule {
                return proxy_name;
        }
 
+       void generate_client_error_cases (CCodeBlock error_block, Gee.List<DataType> error_types, CCodeExpression dbus_error_name, CCodeExpression result_edomain, CCodeExpression result_ecode) {
+               CCodeStatement if_else_if = null;
+               CCodeIfStatement last_statement = null;
+
+               foreach (DataType error_type in error_types) {
+                       var edomain = ((ErrorType) error_type).error_domain;
+
+                       var edomain_dbus_name = get_dbus_name (edomain);
+                       if (edomain_dbus_name == null) {
+                               Report.error (edomain.source_reference, "Errordomain must have a DBus.name annotation to be serialized over DBus");
+                       }
+
+                       var true_block = new CCodeBlock ();
+                       true_block.suppress_newline = true;
+
+                       string temp_name = "_tmp%d_".printf (next_temp_var_id++);
+
+                       var cdecl = new CCodeDeclaration ("const char*");
+                       cdecl.add_declarator (new CCodeVariableDeclarator (temp_name));
+                       true_block.add_statement (cdecl);
+
+                       true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (result_edomain, new CCodeIdentifier (edomain.get_upper_case_cname ()))));
+
+                       true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (temp_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, dbus_error_name, new CCodeConstant ("%ld".printf (edomain_dbus_name.length + 1))))));
+
+                       CCodeStatement inner_if_else_if = null;
+                       CCodeIfStatement inner_last_statement = null;
+                       foreach (ErrorCode ecode in edomain.get_codes ()) {
+                               var inner_true_block = new CCodeBlock ();
+                               inner_true_block.suppress_newline = true;
+                               inner_true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (result_ecode, new CCodeIdentifier (ecode.get_cname ()))));
+
+                               var ecode_dbus_name = get_dbus_name (ecode);
+                               if (ecode_dbus_name == null) {
+                                       ecode_dbus_name = Symbol.lower_case_to_camel_case (ecode.name.down ());
+                               }
+
+                               var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
+                               string_comparison.add_argument (new CCodeIdentifier (temp_name));
+                               string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (ecode_dbus_name)));
+                               var stmt = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, string_comparison, new CCodeConstant ("0")), inner_true_block);
+
+                               if (inner_last_statement != null) {
+                                       inner_last_statement.false_statement = stmt;
+                               } else {
+                                       inner_if_else_if = stmt;
+                               }
+                               inner_last_statement = stmt;
+                       }
+                       true_block.add_statement (inner_if_else_if);
+
+                       var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strstr"));
+                       string_comparison.add_argument (dbus_error_name);
+                       string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (edomain_dbus_name)));
+                       var stmt = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, string_comparison, dbus_error_name), true_block);
+
+                       if (last_statement != null) {
+                               last_statement.false_statement = stmt;
+                       } else {
+                               if_else_if = stmt;
+                       }
+                       last_statement = stmt;
+               }
+               error_block.add_statement (if_else_if);
+       }
+
        string generate_async_dbus_proxy_method (Interface iface, Method m) {
                string proxy_name = "%sdbus_proxy_%s_async".printf (iface.get_lower_case_cprefix (), m.name);
 
index 4d6e9ecfc4221ca891914680122557b222b9f3ca..4ee95ff52f368714d835d2ecc6ca01aa8fc92aac 100644 (file)
@@ -6,8 +6,8 @@ Program: client
 interface Test : Object {
        public abstract string[] test_property { owned get; set; }
 
-       public abstract int[] test_int (int[] i, out int[] j);
-       public abstract string[] test_string (string[] s, out string[] t);
+       public abstract int[] test_int (int[] i, out int[] j) throws DBus.Error;
+       public abstract string[] test_string (string[] s, out string[] t) throws DBus.Error;
 }
 
 void main () {
index 74e534685df0ada73adaf9fa1b38900e6bd48e68..0393bb2d3acacc2340e7ae758cd06ad3aba7d649 100644 (file)
@@ -4,8 +4,8 @@ Program: client
 
 [DBus (name = "org.example.Test")]
 interface Test : Object {
-       public abstract async int test_int (int i);
-       public abstract async string test_string (string s);
+       public abstract async int test_int (int i) throws DBus.Error;
+       public abstract async string test_string (string s) throws DBus.Error;
 }
 
 MainLoop main_loop;
index 5ae27468e407d77b056f3ea1e55ba45ade9c2e99..289ca1763fc4c3a49a4806a6c87a986ea22cb78d 100644 (file)
@@ -6,8 +6,8 @@ Program: client
 interface Test : Object {
        public abstract string test_property { owned get; set; }
 
-       public abstract int test_int (int i, out int j);
-       public abstract string test_string (string s, out string t);
+       public abstract int test_int (int i, out int j) throws DBus.Error;
+       public abstract string test_string (string s, out string t) throws DBus.Error;
 }
 
 void main () {