[gupnp: 12/18] Make GUPnPRootDevice implement GInitable



commit 638c77aa22ed9d59ff91f64f51d0eb57f225e558
Author: Jens Georg <mail jensge org>
Date:   Sat Jul 30 13:51:49 2011 +0200

    Make GUPnPRootDevice implement GInitable
    
    https://bugzilla.gnome.org/show_bug.cgi?id=654446

 libgupnp/gupnp-device-info.c |   10 +-
 libgupnp/gupnp-error.c       |   18 ++++
 libgupnp/gupnp-error.h       |   19 ++++
 libgupnp/gupnp-root-device.c |  218 ++++++++++++++++++++----------------------
 libgupnp/gupnp-root-device.h |    6 +-
 tests/gtest/test-bugs.c      |   18 +++-
 vala/GUPnP-1.2.metadata      |    2 +
 vala/gupnp-1.2-custom.vala   |    7 ++
 8 files changed, 172 insertions(+), 126 deletions(-)
---
diff --git a/libgupnp/gupnp-device-info.c b/libgupnp/gupnp-device-info.c
index 6e932d3..754833d 100644
--- a/libgupnp/gupnp-device-info.c
+++ b/libgupnp/gupnp-device-info.c
@@ -89,7 +89,7 @@ gupnp_device_info_set_property (GObject      *object,
                         GUPNP_RESOURCE_FACTORY (g_value_dup_object (value));
                 break;
         case PROP_CONTEXT:
-                info->priv->context = g_object_ref (g_value_get_object (value));
+                info->priv->context = g_value_dup_object (value);
                 break;
         case PROP_LOCATION:
                 info->priv->location = g_value_dup_string (value);
@@ -191,7 +191,7 @@ gupnp_device_info_finalize (GObject *object)
         g_free (info->priv->udn);
         g_free (info->priv->device_type);
 
-        soup_uri_free (info->priv->url_base);
+        g_clear_pointer (&info->priv->url_base, soup_uri_free);
 
         G_OBJECT_CLASS (gupnp_device_info_parent_class)->finalize (object);
 }
@@ -260,7 +260,7 @@ gupnp_device_info_class_init (GUPnPDeviceInfoClass *klass)
                                       "file",
                                       NULL,
                                       G_PARAM_READWRITE |
-                                      G_PARAM_CONSTRUCT_ONLY |
+                                      G_PARAM_CONSTRUCT |
                                       G_PARAM_STATIC_NAME |
                                       G_PARAM_STATIC_NICK |
                                       G_PARAM_STATIC_BLURB));
@@ -314,7 +314,7 @@ gupnp_device_info_class_init (GUPnPDeviceInfoClass *klass)
                                      "The URL base",
                                      SOUP_TYPE_URI,
                                      G_PARAM_READWRITE |
-                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_CONSTRUCT |
                                      G_PARAM_STATIC_NAME |
                                      G_PARAM_STATIC_NICK |
                                      G_PARAM_STATIC_BLURB));
@@ -355,7 +355,7 @@ gupnp_device_info_class_init (GUPnPDeviceInfoClass *klass)
                                        "The XML element related to this "
                                        "device",
                                        G_PARAM_WRITABLE |
-                                       G_PARAM_CONSTRUCT_ONLY |
+                                       G_PARAM_CONSTRUCT |
                                        G_PARAM_STATIC_NAME |
                                        G_PARAM_STATIC_NICK |
                                        G_PARAM_STATIC_BLURB));
diff --git a/libgupnp/gupnp-error.c b/libgupnp/gupnp-error.c
index 6a483f4..c7a577e 100644
--- a/libgupnp/gupnp-error.c
+++ b/libgupnp/gupnp-error.c
@@ -99,6 +99,24 @@ gupnp_xml_error_quark (void)
         return quark;
 }
 
+/**
+ * GUPNP_ROOT_DEVICE_ERROR:
+ *
+ * The #GQuark uniquely used by GUPnP RootDevice creation errors.
+ *
+ * Returns: a #GQuark uniquely used by GUPnP RootDevice creation errors.
+ */
+GQuark
+gupnp_rootdevice_error_quark (void)
+{
+        static GQuark quark = 0;
+
+        if (!quark)
+                quark = g_quark_from_static_string ("gupnp-root-device-error");
+
+        return quark;
+}
+
 /* Soup status code => GUPnPServerError */
 static int
 code_from_status_code (int status_code)
diff --git a/libgupnp/gupnp-error.h b/libgupnp/gupnp-error.h
index a850857..890fd1b 100644
--- a/libgupnp/gupnp-error.h
+++ b/libgupnp/gupnp-error.h
@@ -118,6 +118,25 @@ typedef enum {
         GUPNP_XML_ERROR_OTHER
 } GUPnPXMLError;
 
+GQuark
+gupnp_rootdevice_error_quark (void) G_GNUC_CONST;
+
+#define GUPNP_ROOT_DEVICE_ERROR (gupnp_rootdevice_error_quark ())
+
+/**
+ * GUPnPRootDeviceError:
+ * @GUPNP_ROOT_DEVICE_ERROR_NO_CONTEXT: No #GUPnPContext was passed to the root device.
+ * @GUPNP_ROOT_DEVICE_ERROR_NO_DESCRIPTION_PATH: Device description path was missing
+ * @GUPNP_ROOT_DEVICE_ERROR_NO_DESCRIPTION_FOLDER: Description folder was missing
+ *
+ * #GError codes used for errors during #GUPnPRootDevice creation
+ */
+typedef enum {
+        GUPNP_ROOT_DEVICE_ERROR_NO_CONTEXT,
+        GUPNP_ROOT_DEVICE_ERROR_NO_DESCRIPTION_PATH,
+        GUPNP_ROOT_DEVICE_ERROR_NO_DESCRIPTION_FOLDER
+} GUPnPRootdeviceError;
+
 G_END_DECLS
 
 #endif /* __GUPNP_ERROR_H__ */
diff --git a/libgupnp/gupnp-root-device.c b/libgupnp/gupnp-root-device.c
index cf207fc..55a2740 100644
--- a/libgupnp/gupnp-root-device.c
+++ b/libgupnp/gupnp-root-device.c
@@ -32,12 +32,26 @@
 
 #include "gupnp-root-device.h"
 #include "gupnp-context-private.h"
+#include "gupnp-error.h"
 #include "http-headers.h"
 #include "xml-util.h"
 
-G_DEFINE_TYPE (GUPnPRootDevice,
-               gupnp_root_device,
-               GUPNP_TYPE_DEVICE);
+static void
+gupnp_root_device_initable_iface_init (gpointer g_iface,
+                                       gpointer iface_data);
+
+static gboolean
+gupnp_root_device_initable_init (GInitable     *initable,
+                                 GCancellable  *cancellable,
+                                 GError       **error);
+
+G_DEFINE_TYPE_EXTENDED (GUPnPRootDevice,
+                        gupnp_root_device,
+                        GUPNP_TYPE_DEVICE,
+                        0,
+                        G_IMPLEMENT_INTERFACE
+                                (G_TYPE_INITABLE,
+                                 gupnp_root_device_initable_iface_init));
 
 struct _GUPnPRootDevicePrivate {
         GUPnPXMLDoc *description_doc;
@@ -65,7 +79,7 @@ gupnp_root_device_finalize (GObject *object)
 
         device = GUPNP_ROOT_DEVICE (object);
 
-        g_object_unref (device->priv->description_doc);
+        g_clear_object (&device->priv->description_doc);
         g_free (device->priv->description_path);
         g_free (device->priv->description_dir);
         g_free (device->priv->relative_location);
@@ -102,6 +116,14 @@ gupnp_root_device_init (GUPnPRootDevice *device)
 }
 
 static void
+gupnp_root_device_initable_iface_init (gpointer g_iface,
+                                       gpointer iface_data)
+{
+        GInitableIface *iface = (GInitableIface *) g_iface;
+        iface->init = gupnp_root_device_initable_init;
+}
+
+static void
 gupnp_root_device_set_property (GObject      *object,
                                 guint         property_id,
                                 const GValue *value,
@@ -262,106 +284,86 @@ load_and_parse (const char *description_path)
         return description_doc;
 }
 
-static GObject *
-gupnp_root_device_constructor (GType                  type,
-                               guint                  n_construct_params,
-                               GObjectConstructParam *construct_params)
+static gboolean
+gupnp_root_device_initable_init (GInitable     *initable,
+                                 GCancellable  *cancellable,
+                                 GError       **error)
 {
-        GObjectClass *object_class;
-        GObject *object;
         GUPnPRootDevice *device;
         GUPnPContext *context;
-        const char *description_path, *description_dir, *udn;
+        const char *udn;
         SoupURI *uri;
         char *desc_path, *location, *usn, *relative_location;
-        unsigned int i;
-        GUPnPXMLDoc *description_doc;
         xmlNode *root_element, *element;
         SoupURI *url_base;
+        gboolean result = FALSE;
 
-        object = NULL;
-        location = NULL;
-
-        /* Get 'description-doc', 'context', 'description-dir' and
-         * 'description-path' property values */
-        description_doc   = NULL;
-        context           = NULL;
-        description_path  = NULL;
-        description_dir   = NULL;
-
-        for (i = 0; i < n_construct_params; i++) {
-                const char *par_name;
+        device = GUPNP_ROOT_DEVICE (initable);
 
-                par_name = construct_params[i].pspec->name;
-
-                if (strcmp (par_name, "description-doc") == 0) {
-                        description_doc =
-                                g_value_get_object (construct_params[i].value);
-
-                        continue;
-                } 
-
-                if (strcmp (par_name, "context") == 0) {
-                        context =
-                                g_value_get_object (construct_params[i].value);
-
-                        continue;
-                }
-
-                if (strcmp (par_name, "description-path") == 0) {
-                        description_path =
-                                g_value_get_string (construct_params[i].value);
+        location = NULL;
 
-                        continue;
-                }
+        g_object_get (G_OBJECT (device),
+                      "context", &context,
+                      NULL);
 
-                if (strcmp (par_name, "description-dir") == 0) {
-                        description_dir =
-                                g_value_get_string (construct_params[i].value);
+        if (context == NULL) {
+                g_set_error_literal (error,
+                                     GUPNP_ROOT_DEVICE_ERROR,
+                                     GUPNP_ROOT_DEVICE_ERROR_NO_CONTEXT,
+                                     "No context specified");
 
-                        continue;
-                }
+                return FALSE;
         }
 
-        if (!context) {
-                g_warning ("No context specified.");
+        if (device->priv->description_path == NULL) {
+                g_set_error_literal (error,
+                                     GUPNP_ROOT_DEVICE_ERROR,
+                                     GUPNP_ROOT_DEVICE_ERROR_NO_DESCRIPTION_PATH,
+                                     "Path to description document not specified.");
 
-                return NULL;
+                return FALSE;
         }
 
-        if (!description_path) {
-                g_warning ("Path to description document not specified.");
+        if (device->priv->description_dir == NULL) {
+                g_set_error_literal (error,
+                                     GUPNP_ROOT_DEVICE_ERROR,
+                                     GUPNP_ROOT_DEVICE_ERROR_NO_DESCRIPTION_FOLDER,
+                                     "Path to description directory not specified.");
 
-                return NULL;
+                return FALSE;
         }
 
-        if (!description_dir) {
-                g_warning ("Path to description directory not specified.");
-
-                return NULL;
-        }
 
-        if (g_path_is_absolute (description_path))
-                desc_path = g_strdup (description_path);
+        if (g_path_is_absolute (device->priv->description_path))
+                desc_path = g_strdup (device->priv->description_path);
         else
-                desc_path = g_build_filename (description_dir,
-                                              description_path,
+                desc_path = g_build_filename (device->priv->description_dir,
+                                              device->priv->description_path,
                                               NULL);
 
         /* Check whether we have a parsed description document */
-        if (!description_doc) {
+        if (device->priv->description_doc == NULL) {
                 /* We don't, so load and parse it */
-                description_doc = load_and_parse (desc_path);
-                if (description_doc == NULL)
+                device->priv->description_doc = load_and_parse (desc_path);
+                if (device->priv->description_doc == NULL) {
+                        g_set_error_literal (error,
+                                             GUPNP_XML_ERROR,
+                                             GUPNP_XML_ERROR_PARSE,
+                                             "Coupld not parse description document");
+
                         goto DONE;
+                }
         }
 
         /* Find correct element */
-        root_element = xml_util_get_element ((xmlNode *) description_doc->doc,
+        root_element = xml_util_get_element ((xmlNode *) device->priv->description_doc->doc,
                                              "root",
                                              NULL);
         if (!root_element) {
-                g_warning ("\"/root\" element not found.");
+                g_set_error_literal (error,
+                                     GUPNP_XML_ERROR,
+                                     GUPNP_XML_ERROR_NO_NODE,
+                                     "\"/root\" element not found.");
 
                 goto DONE;
         }
@@ -370,39 +372,17 @@ gupnp_root_device_constructor (GType                  type,
                                         "device",
                                         NULL);
         if (!element) {
-                g_warning ("\"/root/device\" element not found.");
+                g_set_error_literal (error,
+                                     GUPNP_XML_ERROR,
+                                     GUPNP_XML_ERROR_NO_NODE,
+                                     "\"/root/device\" element not found.");
 
                 goto DONE;
         }
 
-        /* Set 'element' and 'description-doc' properties */
-        for (i = 0; i < n_construct_params; i++) {
-                const char *par_name;
-
-                par_name = construct_params[i].pspec->name;
-
-                if (strcmp (par_name, "element") == 0) {
-                        g_value_set_pointer (construct_params[i].value,
-                                             element);
-
-                        continue;
-                }
-
-                if (strcmp (par_name, "description-doc") == 0) {
-                        g_value_set_object (construct_params[i].value,
-                                            description_doc);
-
-                        continue;
-                }
-        }
-
-        /* Create object */
-        object_class = G_OBJECT_CLASS (gupnp_root_device_parent_class);
-
-        object = object_class->constructor (type,
-                                            n_construct_params,
-                                            construct_params);
-        device = GUPNP_ROOT_DEVICE (object);
+        g_object_set (G_OBJECT (device),
+                      "element", element,
+                      NULL);
 
         /* Generate location relative to HTTP root */
         udn = gupnp_device_info_get_udn (GUPNP_DEVICE_INFO (device));
@@ -436,7 +416,7 @@ gupnp_root_device_constructor (GType                  type,
                 url_base = soup_uri_new (location);
 
         /* Set additional properties */
-        g_object_set (object,
+        g_object_set (G_OBJECT (device),
                       "location", location,
                       "url-base", url_base,
                       NULL);
@@ -456,12 +436,14 @@ gupnp_root_device_constructor (GType                  type,
 
         fill_resource_group (element, location, device->priv->group);
 
+        result = TRUE;
+
  DONE:
         /* Cleanup */
         g_free (desc_path);
         g_free (location);
 
-        return object;
+        return result;
 }
 
 static void
@@ -473,7 +455,6 @@ gupnp_root_device_class_init (GUPnPRootDeviceClass *klass)
 
         object_class->set_property = gupnp_root_device_set_property;
         object_class->get_property = gupnp_root_device_get_property;
-        object_class->constructor  = gupnp_root_device_constructor;
         object_class->dispose      = gupnp_root_device_dispose;
         object_class->finalize     = gupnp_root_device_finalize;
 
@@ -563,6 +544,8 @@ gupnp_root_device_class_init (GUPnPRootDeviceClass *klass)
  * @description_path: Path to device description document. This could either
  * be an absolute path or path relative to @description_dir.
  * @description_dir: Path to directory where description documents are provided.
+ * @error: (allow-none): The location for a #GError to report issue with
+ * creation on or %NULL.
  *
  * Create a new #GUPnPRootDevice object, automatically loading and parsing
  * device description document from @description_path.
@@ -572,7 +555,8 @@ gupnp_root_device_class_init (GUPnPRootDeviceClass *klass)
 GUPnPRootDevice *
 gupnp_root_device_new (GUPnPContext *context,
                        const char   *description_path,
-                       const char   *description_dir)
+                       const char   *description_dir,
+                       GError      **error)
 {
         GUPnPResourceFactory *factory;
 
@@ -582,7 +566,8 @@ gupnp_root_device_new (GUPnPContext *context,
                                            factory,
                                            NULL,
                                            description_path,
-                                           description_dir);
+                                           description_dir,
+                                           error);
 }
 
 /**
@@ -593,6 +578,8 @@ gupnp_root_device_new (GUPnPContext *context,
  * @description_path: Path to device description document. This could either
  * be an absolute path or path relative to @description_dir.
  * @description_dir: Path to directory where description documents are provided.
+ * @error: (allow-none): The location for a #GError to report issue with
+ * creation on or %NULL.
  *
  * Create a new #GUPnPRootDevice, automatically loading and parsing
  * device description document from @description_path if @description_doc is
@@ -605,19 +592,22 @@ gupnp_root_device_new_full (GUPnPContext         *context,
                             GUPnPResourceFactory *factory,
                             GUPnPXMLDoc          *description_doc,
                             const char           *description_path,
-                            const char           *description_dir)
+                            const char           *description_dir,
+                            GError              **error)
 {
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
         g_return_val_if_fail (GUPNP_IS_RESOURCE_FACTORY (factory), NULL);
 
-        return g_object_new (GUPNP_TYPE_ROOT_DEVICE,
-                             "context", context,
-                             "resource-factory", factory,
-                             "root-device", NULL,
-                             "description-doc", description_doc,
-                             "description-path", description_path,
-                             "description-dir", description_dir,
-                             NULL);
+        return g_initable_new (GUPNP_TYPE_ROOT_DEVICE,
+                               NULL,
+                               error,
+                               "context", context,
+                               "resource-factory", factory,
+                               "root-device", NULL,
+                               "description-doc", description_doc,
+                               "description-path", description_path,
+                               "description-dir", description_dir,
+                               NULL);
 }
 
 /**
diff --git a/libgupnp/gupnp-root-device.h b/libgupnp/gupnp-root-device.h
index 0c08791..54dd599 100644
--- a/libgupnp/gupnp-root-device.h
+++ b/libgupnp/gupnp-root-device.h
@@ -86,14 +86,16 @@ struct _GUPnPRootDeviceClass {
 GUPnPRootDevice *
 gupnp_root_device_new             (GUPnPContext         *context,
                                    const char           *description_path,
-                                   const char           *description_dir);
+                                   const char           *description_dir,
+                                   GError              **error);
 
 GUPnPRootDevice *
 gupnp_root_device_new_full        (GUPnPContext         *context,
                                    GUPnPResourceFactory *factory,
                                    GUPnPXMLDoc          *description_doc,
                                    const char           *description_path,
-                                   const char           *description_dir);
+                                   const char           *description_dir,
+                                   GError              **error);
 
 void
 gupnp_root_device_set_available   (GUPnPRootDevice      *root_device,
diff --git a/tests/gtest/test-bugs.c b/tests/gtest/test-bugs.c
index 0ffac76..89c6a60 100644
--- a/tests/gtest/test-bugs.c
+++ b/tests/gtest/test-bugs.c
@@ -229,7 +229,9 @@ test_bgo_696762 (void)
                       &data);
 
 
-    rd = gupnp_root_device_new (context, "TestDevice.xml", DATA_PATH);
+    rd = gupnp_root_device_new (context, "TestDevice.xml", DATA_PATH, &error);
+    g_assert_no_error (error);
+    g_assert (rd != NULL);
     gupnp_root_device_set_available (rd, TRUE);
     info = gupnp_device_info_get_service (GUPNP_DEVICE_INFO (rd),
                                           "urn:test-gupnp-org:service:TestService:1");
@@ -291,7 +293,9 @@ test_bgo_678701 (void)
                                                          "urn:test-gupnp-org:device:TestSubDevice:1",
                                                          test_bgo_678701_device_get_type ());
 
-    rd = gupnp_root_device_new (context, "TestDevice.xml", DATA_PATH);
+    rd = gupnp_root_device_new (context, "TestDevice.xml", DATA_PATH, &error);
+    g_assert_no_error (error);
+    g_assert (rd != NULL);
     gupnp_root_device_set_available (rd, TRUE);
 
     cp = gupnp_control_point_new (context,
@@ -347,7 +351,9 @@ test_bgo_690400 (void)
                       G_CALLBACK (test_on_sp_available),
                       &data);
 
-    rd = gupnp_root_device_new (context, "TestDevice.xml", DATA_PATH);
+    rd = gupnp_root_device_new (context, "TestDevice.xml", DATA_PATH, &error);
+    g_assert_no_error (error);
+    g_assert (rd != NULL);
     service = gupnp_device_info_get_service (GUPNP_DEVICE_INFO (rd),
                                              "urn:test-gupnp-org:service:TestService:1");
     g_signal_connect (service, "query-variable",
@@ -375,8 +381,8 @@ test_bgo_690400 (void)
     g_main_loop_unref (data.loop);
     g_object_unref (data.proxy);
     g_object_unref (cp);
-    g_object_unref (rd);
     g_object_unref (service);
+    g_object_unref (rd);
     g_object_unref (context);
 }
 
@@ -395,7 +401,9 @@ test_bgo_722696 (void)
     g_assert (context != NULL);
     g_assert (error == NULL);
 
-    rd = gupnp_root_device_new (context, "TestDevice.xml", DATA_PATH);
+    rd = gupnp_root_device_new (context, "TestDevice.xml", DATA_PATH, &error);
+    g_assert_no_error (error);
+    g_assert (rd != NULL);
 
     /* prefer bigger */
     width = -1;
diff --git a/vala/GUPnP-1.2.metadata b/vala/GUPnP-1.2.metadata
index 0d5c136..a62caea 100644
--- a/vala/GUPnP-1.2.metadata
+++ b/vala/GUPnP-1.2.metadata
@@ -42,6 +42,8 @@ ControlError skip
 control_error_quark skip
 EventingError skip
 eventing_error_quark skip
+RootdeviceError skip
+rootdevice_error_quark skip
 ServerError skip
 server_error_quark skip
 XMLError skip
diff --git a/vala/gupnp-1.2-custom.vala b/vala/gupnp-1.2-custom.vala
index 2e48e60..f8474fd 100644
--- a/vala/gupnp-1.2-custom.vala
+++ b/vala/gupnp-1.2-custom.vala
@@ -36,6 +36,13 @@ public interface GUPnP.Acl : GLib.Object {
 }
 
 namespace GUPnP {
+       [CCode (cheader_filename = "libgupnp/gupnp.h", cprefix = "GUPNP_ROOT_DEVICEL_ERROR_")]
+       public errordomain RootdeviceError {
+               NO_CONTEXT,
+               NO_DESCRIPTION_PATH,
+               NO_DESCRIPTION_FOLDER;
+               public static GLib.Quark quark ();
+       }
        [CCode (cheader_filename = "libgupnp/gupnp.h", cprefix = "GUPNP_CONTROL_ERROR_")]
        public errordomain ControlError {
                INVALID_ACTION,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]