gitignore
[glib.git] / gio / gdbusobjectmanagerserver.c
blobc9a2673812eab960404a0e6b6c212b125ed3cc99
1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: David Zeuthen <davidz@redhat.com>
23 #include "config.h"
25 #include "gdbusobjectmanager.h"
26 #include "gdbusobjectmanagerserver.h"
27 #include "gdbusobject.h"
28 #include "gdbusobjectskeleton.h"
29 #include "gdbusinterfaceskeleton.h"
30 #include "gdbusconnection.h"
31 #include "gdbusintrospection.h"
32 #include "gdbusmethodinvocation.h"
33 #include "gdbuserror.h"
35 #include "glibintl.h"
37 /**
38 * SECTION:gdbusobjectmanagerserver
39 * @short_description: Service-side object manager
40 * @include: gio/gio.h
42 * #GDBusObjectManagerServer is used to export #GDBusObject instances using
43 * the standardized <ulink
44 * url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">org.freedesktop.DBus.ObjectManager</ulink>
45 * interface. For example, remote D-Bus clients can get all objects
46 * and properties in a single call. Additionally, any change in the
47 * object hierarchy is broadcast using signals. This means that D-Bus
48 * clients can keep caches up to date by only listening to D-Bus
49 * signals.
51 * See #GDBusObjectManagerClient for the client-side code that is
52 * intended to be used with #GDBusObjectManagerServer or any D-Bus
53 * object implementing the org.freedesktop.DBus.ObjectManager
54 * interface.
57 typedef struct
59 GDBusObjectSkeleton *object;
60 GDBusObjectManagerServer *manager;
61 GHashTable *map_iface_name_to_iface;
62 gboolean exported;
63 } RegistrationData;
65 static void registration_data_free (RegistrationData *data);
67 static void export_all (GDBusObjectManagerServer *manager);
68 static void unexport_all (GDBusObjectManagerServer *manager, gboolean only_manager);
70 static void g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager,
71 RegistrationData *data,
72 const gchar *const *interfaces,
73 const gchar *object_path);
75 static void g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager,
76 RegistrationData *data,
77 const gchar *const *interfaces);
79 static gboolean g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer *manager,
80 const gchar *object_path);
82 struct _GDBusObjectManagerServerPrivate
84 GMutex lock;
85 GDBusConnection *connection;
86 gchar *object_path;
87 gchar *object_path_ending_in_slash;
88 GHashTable *map_object_path_to_data;
89 guint manager_reg_id;
92 enum
94 PROP_0,
95 PROP_CONNECTION,
96 PROP_OBJECT_PATH
99 static void dbus_object_manager_interface_init (GDBusObjectManagerIface *iface);
101 G_DEFINE_TYPE_WITH_CODE (GDBusObjectManagerServer, g_dbus_object_manager_server, G_TYPE_OBJECT,
102 G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT_MANAGER, dbus_object_manager_interface_init));
104 static void g_dbus_object_manager_server_constructed (GObject *object);
106 static void
107 g_dbus_object_manager_server_finalize (GObject *object)
109 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
111 if (manager->priv->connection != NULL)
113 unexport_all (manager, TRUE);
114 g_object_unref (manager->priv->connection);
116 g_hash_table_unref (manager->priv->map_object_path_to_data);
117 g_free (manager->priv->object_path);
118 g_free (manager->priv->object_path_ending_in_slash);
120 g_mutex_clear (&manager->priv->lock);
122 if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize != NULL)
123 G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize (object);
126 static void
127 g_dbus_object_manager_server_get_property (GObject *object,
128 guint prop_id,
129 GValue *value,
130 GParamSpec *pspec)
132 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
134 switch (prop_id)
136 case PROP_CONNECTION:
137 g_mutex_lock (&manager->priv->lock);
138 g_value_set_object (value, manager->priv->connection);
139 g_mutex_unlock (&manager->priv->lock);
140 break;
142 case PROP_OBJECT_PATH:
143 g_value_set_string (value, g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (manager)));
144 break;
146 default:
147 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
148 break;
152 static void
153 g_dbus_object_manager_server_set_property (GObject *object,
154 guint prop_id,
155 const GValue *value,
156 GParamSpec *pspec)
158 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
160 switch (prop_id)
162 case PROP_CONNECTION:
163 g_dbus_object_manager_server_set_connection (manager, g_value_get_object (value));
164 break;
166 case PROP_OBJECT_PATH:
167 g_assert (manager->priv->object_path == NULL);
168 g_assert (g_variant_is_object_path (g_value_get_string (value)));
169 manager->priv->object_path = g_value_dup_string (value);
170 manager->priv->object_path_ending_in_slash = g_strdup_printf ("%s/", manager->priv->object_path);
171 break;
173 default:
174 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
175 break;
179 static void
180 g_dbus_object_manager_server_class_init (GDBusObjectManagerServerClass *klass)
182 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
184 gobject_class->finalize = g_dbus_object_manager_server_finalize;
185 gobject_class->constructed = g_dbus_object_manager_server_constructed;
186 gobject_class->set_property = g_dbus_object_manager_server_set_property;
187 gobject_class->get_property = g_dbus_object_manager_server_get_property;
190 * GDBusObjectManagerServer:connection:
192 * The #GDBusConnection to export objects on.
194 * Since: 2.30
196 g_object_class_install_property (gobject_class,
197 PROP_CONNECTION,
198 g_param_spec_object ("connection",
199 "Connection",
200 "The connection to export objects on",
201 G_TYPE_DBUS_CONNECTION,
202 G_PARAM_READABLE |
203 G_PARAM_WRITABLE |
204 G_PARAM_STATIC_STRINGS));
207 * GDBusObjectManagerServer:object-path:
209 * The object path to register the manager object at.
211 * Since: 2.30
213 g_object_class_install_property (gobject_class,
214 PROP_OBJECT_PATH,
215 g_param_spec_string ("object-path",
216 "Object Path",
217 "The object path to register the manager object at",
218 NULL,
219 G_PARAM_READABLE |
220 G_PARAM_WRITABLE |
221 G_PARAM_CONSTRUCT_ONLY |
222 G_PARAM_STATIC_STRINGS));
224 g_type_class_add_private (klass, sizeof (GDBusObjectManagerServerPrivate));
227 static void
228 g_dbus_object_manager_server_init (GDBusObjectManagerServer *manager)
230 manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
231 G_TYPE_DBUS_OBJECT_MANAGER_SERVER,
232 GDBusObjectManagerServerPrivate);
233 g_mutex_init (&manager->priv->lock);
234 manager->priv->map_object_path_to_data = g_hash_table_new_full (g_str_hash,
235 g_str_equal,
236 g_free,
237 (GDestroyNotify) registration_data_free);
241 * g_dbus_object_manager_server_new:
242 * @object_path: The object path to export the manager object at.
244 * Creates a new #GDBusObjectManagerServer object.
246 * The returned server isn't yet exported on any connection. To do so,
247 * use g_dbus_object_manager_server_set_connection(). Normally you
248 * want to export all of your objects before doing so to avoid <ulink
249 * url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">InterfacesAdded</ulink>
250 * signals being emitted.
252 * Returns: A #GDBusObjectManagerServer object. Free with g_object_unref().
254 * Since: 2.30
256 GDBusObjectManagerServer *
257 g_dbus_object_manager_server_new (const gchar *object_path)
259 g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
260 return G_DBUS_OBJECT_MANAGER_SERVER (g_object_new (G_TYPE_DBUS_OBJECT_MANAGER_SERVER,
261 "object-path", object_path,
262 NULL));
266 * g_dbus_object_manager_server_set_connection:
267 * @manager: A #GDBusObjectManagerServer.
268 * @connection: (allow-none): A #GDBusConnection or %NULL.
270 * Exports all objects managed by @manager on @connection. If
271 * @connection is %NULL, stops exporting objects.
273 void
274 g_dbus_object_manager_server_set_connection (GDBusObjectManagerServer *manager,
275 GDBusConnection *connection)
277 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
278 g_return_if_fail (connection == NULL || G_IS_DBUS_CONNECTION (connection));
280 g_mutex_lock (&manager->priv->lock);
282 if (manager->priv->connection == connection)
284 g_mutex_unlock (&manager->priv->lock);
285 goto out;
288 if (manager->priv->connection != NULL)
290 unexport_all (manager, FALSE);
291 g_object_unref (manager->priv->connection);
292 manager->priv->connection = NULL;
295 manager->priv->connection = connection != NULL ? g_object_ref (connection) : NULL;
296 if (manager->priv->connection != NULL)
297 export_all (manager);
299 g_mutex_unlock (&manager->priv->lock);
301 g_object_notify (G_OBJECT (manager), "connection");
302 out:
307 * g_dbus_object_manager_server_get_connection:
308 * @manager: A #GDBusObjectManagerServer
310 * Gets the #GDBusConnection used by @manager.
312 * Returns: (transfer full): A #GDBusConnection object or %NULL if
313 * @manager isn't exported on a connection. The returned object should
314 * be freed with g_object_unref().
316 * Since: 2.30
318 GDBusConnection *
319 g_dbus_object_manager_server_get_connection (GDBusObjectManagerServer *manager)
321 GDBusConnection *ret;
322 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), NULL);
323 g_mutex_lock (&manager->priv->lock);
324 ret = manager->priv->connection != NULL ? g_object_ref (manager->priv->connection) : NULL;
325 g_mutex_unlock (&manager->priv->lock);
326 return ret;
329 /* ---------------------------------------------------------------------------------------------------- */
331 static void
332 registration_data_export_interface (RegistrationData *data,
333 GDBusInterfaceSkeleton *interface_skeleton,
334 const gchar *object_path)
336 GDBusInterfaceInfo *info;
337 GError *error;
339 info = g_dbus_interface_skeleton_get_info (interface_skeleton);
340 error = NULL;
341 if (data->manager->priv->connection != NULL)
343 if (!g_dbus_interface_skeleton_export (interface_skeleton,
344 data->manager->priv->connection,
345 object_path,
346 &error))
348 g_warning ("%s: Error registering object at %s with interface %s: %s",
349 G_STRLOC,
350 object_path,
351 info->name,
352 error->message);
353 g_error_free (error);
357 g_assert (g_hash_table_lookup (data->map_iface_name_to_iface, info->name) == NULL);
358 g_hash_table_insert (data->map_iface_name_to_iface,
359 info->name,
360 g_object_ref (interface_skeleton));
362 /* if we are already exported, then... */
363 if (data->exported)
365 const gchar *interfaces[2];
366 /* emit InterfacesAdded on the ObjectManager object */
367 interfaces[0] = info->name;
368 interfaces[1] = NULL;
369 g_dbus_object_manager_server_emit_interfaces_added (data->manager, data, interfaces, object_path);
373 static void
374 registration_data_unexport_interface (RegistrationData *data,
375 GDBusInterfaceSkeleton *interface_skeleton)
377 GDBusInterfaceInfo *info;
378 GDBusInterfaceSkeleton *iface;
380 info = g_dbus_interface_skeleton_get_info (interface_skeleton);
381 iface = g_hash_table_lookup (data->map_iface_name_to_iface, info->name);
382 g_assert (iface != NULL);
384 if (data->manager->priv->connection != NULL)
385 g_dbus_interface_skeleton_unexport (iface);
387 g_warn_if_fail (g_hash_table_remove (data->map_iface_name_to_iface, info->name));
389 /* if we are already exported, then... */
390 if (data->exported)
392 const gchar *interfaces[2];
393 /* emit InterfacesRemoved on the ObjectManager object */
394 interfaces[0] = info->name;
395 interfaces[1] = NULL;
396 g_dbus_object_manager_server_emit_interfaces_removed (data->manager, data, interfaces);
400 /* ---------------------------------------------------------------------------------------------------- */
402 static void
403 on_interface_added (GDBusObject *object,
404 GDBusInterface *interface,
405 gpointer user_data)
407 RegistrationData *data = user_data;
408 const gchar *object_path;
409 g_mutex_lock (&data->manager->priv->lock);
410 object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
411 registration_data_export_interface (data, G_DBUS_INTERFACE_SKELETON (interface), object_path);
412 g_mutex_unlock (&data->manager->priv->lock);
415 static void
416 on_interface_removed (GDBusObject *object,
417 GDBusInterface *interface,
418 gpointer user_data)
420 RegistrationData *data = user_data;
421 g_mutex_lock (&data->manager->priv->lock);
422 registration_data_unexport_interface (data, G_DBUS_INTERFACE_SKELETON (interface));
423 g_mutex_unlock (&data->manager->priv->lock);
426 /* ---------------------------------------------------------------------------------------------------- */
429 static void
430 registration_data_free (RegistrationData *data)
432 GHashTableIter iter;
433 GDBusInterfaceSkeleton *iface;
435 data->exported = FALSE;
437 g_hash_table_iter_init (&iter, data->map_iface_name_to_iface);
438 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &iface))
440 if (data->manager->priv->connection != NULL)
441 g_dbus_interface_skeleton_unexport (iface);
444 g_signal_handlers_disconnect_by_func (data->object, G_CALLBACK (on_interface_added), data);
445 g_signal_handlers_disconnect_by_func (data->object, G_CALLBACK (on_interface_removed), data);
446 g_object_unref (data->object);
447 g_hash_table_destroy (data->map_iface_name_to_iface);
448 g_free (data);
451 /* ---------------------------------------------------------------------------------------------------- */
453 static void
454 g_dbus_object_manager_server_export_unlocked (GDBusObjectManagerServer *manager,
455 GDBusObjectSkeleton *object,
456 const gchar *object_path)
458 RegistrationData *data;
459 GList *existing_interfaces;
460 GList *l;
461 GPtrArray *interface_names;
463 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
464 g_return_if_fail (G_IS_DBUS_OBJECT (object));
465 g_return_if_fail (g_str_has_prefix (object_path, manager->priv->object_path_ending_in_slash));
467 interface_names = g_ptr_array_new ();
469 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
470 if (data != NULL)
471 g_dbus_object_manager_server_unexport_unlocked (manager, object_path);
473 data = g_new0 (RegistrationData, 1);
474 data->object = g_object_ref (object);
475 data->manager = manager;
476 data->map_iface_name_to_iface = g_hash_table_new_full (g_str_hash,
477 g_str_equal,
478 NULL,
479 (GDestroyNotify) g_object_unref);
481 g_signal_connect (object,
482 "interface-added",
483 G_CALLBACK (on_interface_added),
484 data);
485 g_signal_connect (object,
486 "interface-removed",
487 G_CALLBACK (on_interface_removed),
488 data);
490 /* Register all known interfaces - note that data->exported is FALSE so
491 * we don't emit any InterfacesAdded signals.
493 existing_interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (object));
494 for (l = existing_interfaces; l != NULL; l = l->next)
496 GDBusInterfaceSkeleton *interface_skeleton = G_DBUS_INTERFACE_SKELETON (l->data);
497 registration_data_export_interface (data, interface_skeleton, object_path);
498 g_ptr_array_add (interface_names, g_dbus_interface_skeleton_get_info (interface_skeleton)->name);
500 g_list_foreach (existing_interfaces, (GFunc) g_object_unref, NULL);
501 g_list_free (existing_interfaces);
502 g_ptr_array_add (interface_names, NULL);
504 data->exported = TRUE;
506 /* now emit InterfacesAdded() for all the interfaces */
507 g_dbus_object_manager_server_emit_interfaces_added (manager, data, (const gchar *const *) interface_names->pdata, object_path);
508 g_ptr_array_unref (interface_names);
510 g_hash_table_insert (manager->priv->map_object_path_to_data,
511 g_strdup (object_path),
512 data);
516 * g_dbus_object_manager_server_export:
517 * @manager: A #GDBusObjectManagerServer.
518 * @object: A #GDBusObjectSkeleton.
520 * Exports @object on @manager.
522 * If there is already a #GDBusObject exported at the object path,
523 * then the old object is removed.
525 * The object path for @object must be in the hierarchy rooted by the
526 * object path for @manager.
528 * Note that @manager will take a reference on @object for as long as
529 * it is exported.
531 * Since: 2.30
533 void
534 g_dbus_object_manager_server_export (GDBusObjectManagerServer *manager,
535 GDBusObjectSkeleton *object)
537 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
538 g_mutex_lock (&manager->priv->lock);
539 g_dbus_object_manager_server_export_unlocked (manager, object,
540 g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
541 g_mutex_unlock (&manager->priv->lock);
545 * g_dbus_object_manager_server_export_uniquely:
546 * @manager: A #GDBusObjectManagerServer.
547 * @object: An object.
549 * Like g_dbus_object_manager_server_export() but appends a string of
550 * the form <literal>_N</literal> (with N being a natural number) to
551 * @object<!-- -->'s object path if an object with the given path
552 * already exists. As such, the #GDBusObjectProxy:g-object-path property
553 * of @object may be modified.
555 * Since: 2.30
557 void
558 g_dbus_object_manager_server_export_uniquely (GDBusObjectManagerServer *manager,
559 GDBusObjectSkeleton *object)
561 gchar *orig_object_path;
562 gchar *object_path;
563 guint count;
564 gboolean modified;
566 orig_object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
568 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
569 g_return_if_fail (G_IS_DBUS_OBJECT (object));
570 g_return_if_fail (g_str_has_prefix (orig_object_path, manager->priv->object_path_ending_in_slash));
572 g_mutex_lock (&manager->priv->lock);
574 object_path = g_strdup (orig_object_path);
575 count = 1;
576 modified = FALSE;
577 while (TRUE)
579 RegistrationData *data;
580 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
581 if (data == NULL)
583 break;
585 g_free (object_path);
586 object_path = g_strdup_printf ("%s_%d", orig_object_path, count++);
587 modified = TRUE;
590 g_dbus_object_manager_server_export_unlocked (manager, object, object_path);
592 g_mutex_unlock (&manager->priv->lock);
594 if (modified)
595 g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), object_path);
597 g_free (object_path);
598 g_free (orig_object_path);
602 /* ---------------------------------------------------------------------------------------------------- */
604 static gboolean
605 g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer *manager,
606 const gchar *object_path)
608 RegistrationData *data;
609 gboolean ret;
611 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
612 g_return_val_if_fail (g_variant_is_object_path (object_path), FALSE);
613 g_return_val_if_fail (g_str_has_prefix (object_path, manager->priv->object_path_ending_in_slash), FALSE);
615 ret = FALSE;
617 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
618 if (data != NULL)
620 GPtrArray *interface_names;
621 GHashTableIter iter;
622 const gchar *iface_name;
624 interface_names = g_ptr_array_new ();
625 g_hash_table_iter_init (&iter, data->map_iface_name_to_iface);
626 while (g_hash_table_iter_next (&iter, (gpointer) &iface_name, NULL))
627 g_ptr_array_add (interface_names, (gpointer) iface_name);
628 g_ptr_array_add (interface_names, NULL);
629 /* now emit InterfacesRemoved() for all the interfaces */
630 g_dbus_object_manager_server_emit_interfaces_removed (manager, data, (const gchar *const *) interface_names->pdata);
631 g_ptr_array_unref (interface_names);
633 g_hash_table_remove (manager->priv->map_object_path_to_data, object_path);
634 ret = TRUE;
637 return ret;
641 * g_dbus_object_manager_server_unexport:
642 * @manager: A #GDBusObjectManagerServer.
643 * @object_path: An object path.
645 * If @manager has an object at @path, removes the object. Otherwise
646 * does nothing.
648 * Note that @object_path must be in the hierarchy rooted by the
649 * object path for @manager.
651 * Returns: %TRUE if object at @object_path was removed, %FALSE otherwise.
653 * Since: 2.30
655 gboolean
656 g_dbus_object_manager_server_unexport (GDBusObjectManagerServer *manager,
657 const gchar *object_path)
659 gboolean ret;
660 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
661 g_mutex_lock (&manager->priv->lock);
662 ret = g_dbus_object_manager_server_unexport_unlocked (manager, object_path);
663 g_mutex_unlock (&manager->priv->lock);
664 return ret;
668 /* ---------------------------------------------------------------------------------------------------- */
670 static const GDBusArgInfo manager_interfaces_added_signal_info_arg0 =
673 "object_path",
674 "o",
675 (GDBusAnnotationInfo**) NULL,
678 static const GDBusArgInfo manager_interfaces_added_signal_info_arg1 =
681 "interfaces_and_properties",
682 "a{sa{sv}}",
683 (GDBusAnnotationInfo**) NULL,
686 static const GDBusArgInfo * const manager_interfaces_added_signal_info_arg_pointers[] =
688 &manager_interfaces_added_signal_info_arg0,
689 &manager_interfaces_added_signal_info_arg1,
690 NULL
693 static const GDBusSignalInfo manager_interfaces_added_signal_info =
696 "InterfacesAdded",
697 (GDBusArgInfo**) &manager_interfaces_added_signal_info_arg_pointers,
698 (GDBusAnnotationInfo**) NULL
701 /* ---------- */
703 static const GDBusArgInfo manager_interfaces_removed_signal_info_arg0 =
706 "object_path",
707 "o",
708 (GDBusAnnotationInfo**) NULL,
711 static const GDBusArgInfo manager_interfaces_removed_signal_info_arg1 =
714 "interfaces",
715 "as",
716 (GDBusAnnotationInfo**) NULL,
719 static const GDBusArgInfo * const manager_interfaces_removed_signal_info_arg_pointers[] =
721 &manager_interfaces_removed_signal_info_arg0,
722 &manager_interfaces_removed_signal_info_arg1,
723 NULL
726 static const GDBusSignalInfo manager_interfaces_removed_signal_info =
729 "InterfacesRemoved",
730 (GDBusArgInfo**) &manager_interfaces_removed_signal_info_arg_pointers,
731 (GDBusAnnotationInfo**) NULL
734 /* ---------- */
736 static const GDBusSignalInfo * const manager_signal_info_pointers[] =
738 &manager_interfaces_added_signal_info,
739 &manager_interfaces_removed_signal_info,
740 NULL
743 /* ---------- */
745 static const GDBusArgInfo manager_get_all_method_info_out_arg0 =
748 "object_paths_interfaces_and_properties",
749 "a{oa{sa{sv}}}",
750 (GDBusAnnotationInfo**) NULL,
753 static const GDBusArgInfo * const manager_get_all_method_info_out_arg_pointers[] =
755 &manager_get_all_method_info_out_arg0,
756 NULL
759 static const GDBusMethodInfo manager_get_all_method_info =
762 "GetManagedObjects",
763 (GDBusArgInfo**) NULL,
764 (GDBusArgInfo**) &manager_get_all_method_info_out_arg_pointers,
765 (GDBusAnnotationInfo**) NULL
768 static const GDBusMethodInfo * const manager_method_info_pointers[] =
770 &manager_get_all_method_info,
771 NULL
774 /* ---------- */
776 static const GDBusInterfaceInfo manager_interface_info =
779 "org.freedesktop.DBus.ObjectManager",
780 (GDBusMethodInfo **) manager_method_info_pointers,
781 (GDBusSignalInfo **) manager_signal_info_pointers,
782 (GDBusPropertyInfo **) NULL,
783 (GDBusAnnotationInfo **) NULL
786 static void
787 manager_method_call (GDBusConnection *connection,
788 const gchar *sender,
789 const gchar *object_path,
790 const gchar *interface_name,
791 const gchar *method_name,
792 GVariant *parameters,
793 GDBusMethodInvocation *invocation,
794 gpointer user_data)
796 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (user_data);
797 GVariantBuilder array_builder;
798 GHashTableIter object_iter;
799 RegistrationData *data;
801 g_mutex_lock (&manager->priv->lock);
803 if (g_strcmp0 (method_name, "GetManagedObjects") == 0)
805 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a{oa{sa{sv}}}"));
806 g_hash_table_iter_init (&object_iter, manager->priv->map_object_path_to_data);
807 while (g_hash_table_iter_next (&object_iter, NULL, (gpointer) &data))
809 GVariantBuilder interfaces_builder;
810 GHashTableIter interface_iter;
811 GDBusInterfaceSkeleton *iface;
812 const gchar *iter_object_path;
814 g_variant_builder_init (&interfaces_builder, G_VARIANT_TYPE ("a{sa{sv}}"));
815 g_hash_table_iter_init (&interface_iter, data->map_iface_name_to_iface);
816 while (g_hash_table_iter_next (&interface_iter, NULL, (gpointer) &iface))
818 GVariant *properties = g_dbus_interface_skeleton_get_properties (iface);
819 g_variant_builder_add (&interfaces_builder, "{s@a{sv}}",
820 g_dbus_interface_skeleton_get_info (iface)->name,
821 properties);
822 g_variant_unref (properties);
824 iter_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
825 g_variant_builder_add (&array_builder,
826 "{oa{sa{sv}}}",
827 iter_object_path,
828 &interfaces_builder);
831 g_dbus_method_invocation_return_value (invocation,
832 g_variant_new ("(a{oa{sa{sv}}})",
833 &array_builder));
835 else
837 g_dbus_method_invocation_return_error (invocation,
838 G_DBUS_ERROR,
839 G_DBUS_ERROR_UNKNOWN_METHOD,
840 "Unknown method %s - only GetManagedObjects() is supported",
841 method_name);
843 g_mutex_unlock (&manager->priv->lock);
846 static const GDBusInterfaceVTable manager_interface_vtable =
848 manager_method_call, /* handle_method_call */
849 NULL, /* get_property */
850 NULL /* set_property */
853 /* ---------------------------------------------------------------------------------------------------- */
855 static void
856 g_dbus_object_manager_server_constructed (GObject *object)
858 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
860 if (manager->priv->connection != NULL)
861 export_all (manager);
863 if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->constructed != NULL)
864 G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->constructed (object);
867 static void
868 g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager,
869 RegistrationData *data,
870 const gchar *const *interfaces,
871 const gchar *object_path)
873 GVariantBuilder array_builder;
874 GError *error;
875 guint n;
877 if (data->manager->priv->connection == NULL)
878 goto out;
880 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a{sa{sv}}"));
881 for (n = 0; interfaces[n] != NULL; n++)
883 GDBusInterfaceSkeleton *iface;
884 GVariant *properties;
886 iface = g_hash_table_lookup (data->map_iface_name_to_iface, interfaces[n]);
887 g_assert (iface != NULL);
888 properties = g_dbus_interface_skeleton_get_properties (iface);
889 g_variant_builder_add (&array_builder, "{s@a{sv}}", interfaces[n], properties);
890 g_variant_unref (properties);
893 error = NULL;
894 g_dbus_connection_emit_signal (data->manager->priv->connection,
895 NULL, /* destination_bus_name */
896 manager->priv->object_path,
897 manager_interface_info.name,
898 "InterfacesAdded",
899 g_variant_new ("(oa{sa{sv}})",
900 object_path,
901 &array_builder),
902 &error);
903 g_assert_no_error (error);
904 out:
908 static void
909 g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager,
910 RegistrationData *data,
911 const gchar *const *interfaces)
913 GVariantBuilder array_builder;
914 GError *error;
915 guint n;
916 const gchar *object_path;
918 if (data->manager->priv->connection == NULL)
919 goto out;
921 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
922 for (n = 0; interfaces[n] != NULL; n++)
923 g_variant_builder_add (&array_builder, "s", interfaces[n]);
925 error = NULL;
926 object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
927 g_dbus_connection_emit_signal (data->manager->priv->connection,
928 NULL, /* destination_bus_name */
929 manager->priv->object_path,
930 manager_interface_info.name,
931 "InterfacesRemoved",
932 g_variant_new ("(oas)",
933 object_path,
934 &array_builder),
935 &error);
936 g_assert_no_error (error);
937 out:
941 /* ---------------------------------------------------------------------------------------------------- */
943 static GList *
944 g_dbus_object_manager_server_get_objects (GDBusObjectManager *_manager)
946 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
947 GList *ret;
948 GHashTableIter iter;
949 RegistrationData *data;
951 g_mutex_lock (&manager->priv->lock);
953 ret = NULL;
954 g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
955 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data))
957 ret = g_list_prepend (ret, g_object_ref (data->object));
960 g_mutex_unlock (&manager->priv->lock);
962 return ret;
965 static const gchar *
966 g_dbus_object_manager_server_get_object_path (GDBusObjectManager *_manager)
968 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
969 return manager->priv->object_path;
972 static GDBusObject *
973 g_dbus_object_manager_server_get_object (GDBusObjectManager *_manager,
974 const gchar *object_path)
976 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
977 GDBusObject *ret;
978 RegistrationData *data;
980 ret = NULL;
982 g_mutex_lock (&manager->priv->lock);
983 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
984 if (data != NULL)
985 ret = g_object_ref (data->object);
986 g_mutex_unlock (&manager->priv->lock);
988 return ret;
991 static GDBusInterface *
992 g_dbus_object_manager_server_get_interface (GDBusObjectManager *_manager,
993 const gchar *object_path,
994 const gchar *interface_name)
996 GDBusInterface *ret;
997 GDBusObject *object;
999 ret = NULL;
1001 object = g_dbus_object_manager_get_object (_manager, object_path);
1002 if (object == NULL)
1003 goto out;
1005 ret = g_dbus_object_get_interface (object, interface_name);
1006 g_object_unref (object);
1008 out:
1009 return ret;
1012 static void
1013 dbus_object_manager_interface_init (GDBusObjectManagerIface *iface)
1015 iface->get_object_path = g_dbus_object_manager_server_get_object_path;
1016 iface->get_objects = g_dbus_object_manager_server_get_objects;
1017 iface->get_object = g_dbus_object_manager_server_get_object;
1018 iface->get_interface = g_dbus_object_manager_server_get_interface;
1021 /* ---------------------------------------------------------------------------------------------------- */
1023 static void
1024 export_all (GDBusObjectManagerServer *manager)
1026 GHashTableIter iter;
1027 const gchar *object_path;
1028 RegistrationData *data;
1029 GHashTableIter iface_iter;
1030 GDBusInterfaceSkeleton *iface;
1031 GError *error;
1033 g_return_if_fail (manager->priv->connection != NULL);
1035 error = NULL;
1036 g_warn_if_fail (manager->priv->manager_reg_id == 0);
1037 manager->priv->manager_reg_id = g_dbus_connection_register_object (manager->priv->connection,
1038 manager->priv->object_path,
1039 (GDBusInterfaceInfo *) &manager_interface_info,
1040 &manager_interface_vtable,
1041 manager,
1042 NULL, /* user_data_free_func */
1043 &error);
1044 if (manager->priv->manager_reg_id == 0)
1046 g_warning ("%s: Error registering manager at %s: %s",
1047 G_STRLOC,
1048 manager->priv->object_path,
1049 error->message);
1050 g_error_free (error);
1053 g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1054 while (g_hash_table_iter_next (&iter, (gpointer) &object_path, (gpointer) &data))
1056 g_hash_table_iter_init (&iface_iter, data->map_iface_name_to_iface);
1057 while (g_hash_table_iter_next (&iface_iter, NULL, (gpointer) &iface))
1059 g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface) == NULL);
1060 error = NULL;
1061 if (!g_dbus_interface_skeleton_export (iface,
1062 manager->priv->connection,
1063 object_path,
1064 &error))
1066 g_warning ("%s: Error registering object at %s with interface %s: %s",
1067 G_STRLOC,
1068 object_path,
1069 g_dbus_interface_skeleton_get_info (iface)->name,
1070 error->message);
1071 g_error_free (error);
1077 static void
1078 unexport_all (GDBusObjectManagerServer *manager, gboolean only_manager)
1080 GHashTableIter iter;
1081 RegistrationData *data;
1082 GHashTableIter iface_iter;
1083 GDBusInterfaceSkeleton *iface;
1085 g_return_if_fail (manager->priv->connection != NULL);
1087 g_warn_if_fail (manager->priv->manager_reg_id > 0);
1088 if (manager->priv->manager_reg_id > 0)
1090 g_warn_if_fail (g_dbus_connection_unregister_object (manager->priv->connection,
1091 manager->priv->manager_reg_id));
1092 manager->priv->manager_reg_id = 0;
1094 if (only_manager)
1095 goto out;
1097 g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1098 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data))
1100 g_hash_table_iter_init (&iface_iter, data->map_iface_name_to_iface);
1101 while (g_hash_table_iter_next (&iface_iter, NULL, (gpointer) &iface))
1103 g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface) != NULL);
1104 g_dbus_interface_skeleton_unexport (iface);
1107 out:
1111 /* ---------------------------------------------------------------------------------------------------- */