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, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
23 #include "gdbusobjectmanager.h"
24 #include "gdbusobjectmanagerserver.h"
25 #include "gdbusobject.h"
26 #include "gdbusobjectskeleton.h"
27 #include "gdbusinterfaceskeleton.h"
28 #include "gdbusconnection.h"
29 #include "gdbusintrospection.h"
30 #include "gdbusmethodinvocation.h"
31 #include "gdbuserror.h"
36 * SECTION:gdbusobjectmanagerserver
37 * @short_description: Service-side object manager
40 * #GDBusObjectManagerServer is used to export #GDBusObject instances using
42 * [org.freedesktop.DBus.ObjectManager](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
43 * interface. For example, remote D-Bus clients can get all objects
44 * and properties in a single call. Additionally, any change in the
45 * object hierarchy is broadcast using signals. This means that D-Bus
46 * clients can keep caches up to date by only listening to D-Bus
49 * See #GDBusObjectManagerClient for the client-side code that is
50 * intended to be used with #GDBusObjectManagerServer or any D-Bus
51 * object implementing the org.freedesktop.DBus.ObjectManager
57 GDBusObjectSkeleton *object;
58 GDBusObjectManagerServer *manager;
59 GHashTable *map_iface_name_to_iface;
63 static void registration_data_free (RegistrationData *data);
65 static void export_all (GDBusObjectManagerServer *manager);
66 static void unexport_all (GDBusObjectManagerServer *manager, gboolean only_manager);
68 static void g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager,
69 RegistrationData *data,
70 const gchar *const *interfaces,
71 const gchar *object_path);
73 static void g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager,
74 RegistrationData *data,
75 const gchar *const *interfaces);
77 static gboolean g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer *manager,
78 const gchar *object_path);
80 struct _GDBusObjectManagerServerPrivate
83 GDBusConnection *connection;
85 gchar *object_path_ending_in_slash;
86 GHashTable *map_object_path_to_data;
97 static void dbus_object_manager_interface_init (GDBusObjectManagerIface *iface);
99 G_DEFINE_TYPE_WITH_CODE (GDBusObjectManagerServer, g_dbus_object_manager_server, G_TYPE_OBJECT,
100 G_ADD_PRIVATE (GDBusObjectManagerServer)
101 G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT_MANAGER, dbus_object_manager_interface_init))
103 static void g_dbus_object_manager_server_constructed (GObject *object);
106 g_dbus_object_manager_server_finalize (GObject *object)
108 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
110 if (manager->priv->connection != NULL)
112 unexport_all (manager, TRUE);
113 g_object_unref (manager->priv->connection);
115 g_hash_table_unref (manager->priv->map_object_path_to_data);
116 g_free (manager->priv->object_path);
117 g_free (manager->priv->object_path_ending_in_slash);
119 g_mutex_clear (&manager->priv->lock);
121 if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize != NULL)
122 G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize (object);
126 g_dbus_object_manager_server_get_property (GObject *object,
131 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
135 case PROP_CONNECTION:
136 g_mutex_lock (&manager->priv->lock);
137 g_value_set_object (value, manager->priv->connection);
138 g_mutex_unlock (&manager->priv->lock);
141 case PROP_OBJECT_PATH:
142 g_value_set_string (value, g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (manager)));
146 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
152 g_dbus_object_manager_server_set_property (GObject *object,
157 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
161 case PROP_CONNECTION:
162 g_dbus_object_manager_server_set_connection (manager, g_value_get_object (value));
165 case PROP_OBJECT_PATH:
166 g_assert (manager->priv->object_path == NULL);
167 g_assert (g_variant_is_object_path (g_value_get_string (value)));
168 manager->priv->object_path = g_value_dup_string (value);
169 manager->priv->object_path_ending_in_slash = g_strdup_printf ("%s/", manager->priv->object_path);
173 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
179 g_dbus_object_manager_server_class_init (GDBusObjectManagerServerClass *klass)
181 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
183 gobject_class->finalize = g_dbus_object_manager_server_finalize;
184 gobject_class->constructed = g_dbus_object_manager_server_constructed;
185 gobject_class->set_property = g_dbus_object_manager_server_set_property;
186 gobject_class->get_property = g_dbus_object_manager_server_get_property;
189 * GDBusObjectManagerServer:connection:
191 * The #GDBusConnection to export objects on.
195 g_object_class_install_property (gobject_class,
197 g_param_spec_object ("connection",
199 "The connection to export objects on",
200 G_TYPE_DBUS_CONNECTION,
203 G_PARAM_STATIC_STRINGS));
206 * GDBusObjectManagerServer:object-path:
208 * The object path to register the manager object at.
212 g_object_class_install_property (gobject_class,
214 g_param_spec_string ("object-path",
216 "The object path to register the manager object at",
220 G_PARAM_CONSTRUCT_ONLY |
221 G_PARAM_STATIC_STRINGS));
225 g_dbus_object_manager_server_init (GDBusObjectManagerServer *manager)
227 manager->priv = g_dbus_object_manager_server_get_instance_private (manager);
228 g_mutex_init (&manager->priv->lock);
229 manager->priv->map_object_path_to_data = g_hash_table_new_full (g_str_hash,
232 (GDestroyNotify) registration_data_free);
236 * g_dbus_object_manager_server_new:
237 * @object_path: The object path to export the manager object at.
239 * Creates a new #GDBusObjectManagerServer object.
241 * The returned server isn't yet exported on any connection. To do so,
242 * use g_dbus_object_manager_server_set_connection(). Normally you
243 * want to export all of your objects before doing so to avoid <ulink
244 * url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">InterfacesAdded</ulink>
245 * signals being emitted.
247 * Returns: A #GDBusObjectManagerServer object. Free with g_object_unref().
251 GDBusObjectManagerServer *
252 g_dbus_object_manager_server_new (const gchar *object_path)
254 g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
255 return G_DBUS_OBJECT_MANAGER_SERVER (g_object_new (G_TYPE_DBUS_OBJECT_MANAGER_SERVER,
256 "object-path", object_path,
261 * g_dbus_object_manager_server_set_connection:
262 * @manager: A #GDBusObjectManagerServer.
263 * @connection: (allow-none): A #GDBusConnection or %NULL.
265 * Exports all objects managed by @manager on @connection. If
266 * @connection is %NULL, stops exporting objects.
269 g_dbus_object_manager_server_set_connection (GDBusObjectManagerServer *manager,
270 GDBusConnection *connection)
272 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
273 g_return_if_fail (connection == NULL || G_IS_DBUS_CONNECTION (connection));
275 g_mutex_lock (&manager->priv->lock);
277 if (manager->priv->connection == connection)
279 g_mutex_unlock (&manager->priv->lock);
283 if (manager->priv->connection != NULL)
285 unexport_all (manager, FALSE);
286 g_object_unref (manager->priv->connection);
287 manager->priv->connection = NULL;
290 manager->priv->connection = connection != NULL ? g_object_ref (connection) : NULL;
291 if (manager->priv->connection != NULL)
292 export_all (manager);
294 g_mutex_unlock (&manager->priv->lock);
296 g_object_notify (G_OBJECT (manager), "connection");
302 * g_dbus_object_manager_server_get_connection:
303 * @manager: A #GDBusObjectManagerServer
305 * Gets the #GDBusConnection used by @manager.
307 * Returns: (transfer full): A #GDBusConnection object or %NULL if
308 * @manager isn't exported on a connection. The returned object should
309 * be freed with g_object_unref().
314 g_dbus_object_manager_server_get_connection (GDBusObjectManagerServer *manager)
316 GDBusConnection *ret;
317 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), NULL);
318 g_mutex_lock (&manager->priv->lock);
319 ret = manager->priv->connection != NULL ? g_object_ref (manager->priv->connection) : NULL;
320 g_mutex_unlock (&manager->priv->lock);
324 /* ---------------------------------------------------------------------------------------------------- */
327 registration_data_export_interface (RegistrationData *data,
328 GDBusInterfaceSkeleton *interface_skeleton,
329 const gchar *object_path)
331 GDBusInterfaceInfo *info;
334 info = g_dbus_interface_skeleton_get_info (interface_skeleton);
336 if (data->manager->priv->connection != NULL)
338 if (!g_dbus_interface_skeleton_export (interface_skeleton,
339 data->manager->priv->connection,
343 g_warning ("%s: Error registering object at %s with interface %s: %s",
348 g_error_free (error);
352 g_assert (g_hash_table_lookup (data->map_iface_name_to_iface, info->name) == NULL);
353 g_hash_table_insert (data->map_iface_name_to_iface,
355 g_object_ref (interface_skeleton));
357 /* if we are already exported, then... */
360 const gchar *interfaces[2];
361 /* emit InterfacesAdded on the ObjectManager object */
362 interfaces[0] = info->name;
363 interfaces[1] = NULL;
364 g_dbus_object_manager_server_emit_interfaces_added (data->manager, data, interfaces, object_path);
369 registration_data_unexport_interface (RegistrationData *data,
370 GDBusInterfaceSkeleton *interface_skeleton)
372 GDBusInterfaceInfo *info;
373 GDBusInterfaceSkeleton *iface;
375 info = g_dbus_interface_skeleton_get_info (interface_skeleton);
376 iface = g_hash_table_lookup (data->map_iface_name_to_iface, info->name);
377 g_assert (iface != NULL);
379 if (data->manager->priv->connection != NULL)
380 g_dbus_interface_skeleton_unexport (iface);
382 g_warn_if_fail (g_hash_table_remove (data->map_iface_name_to_iface, info->name));
384 /* if we are already exported, then... */
387 const gchar *interfaces[2];
388 /* emit InterfacesRemoved on the ObjectManager object */
389 interfaces[0] = info->name;
390 interfaces[1] = NULL;
391 g_dbus_object_manager_server_emit_interfaces_removed (data->manager, data, interfaces);
395 /* ---------------------------------------------------------------------------------------------------- */
398 on_interface_added (GDBusObject *object,
399 GDBusInterface *interface,
402 RegistrationData *data = user_data;
403 const gchar *object_path;
404 g_mutex_lock (&data->manager->priv->lock);
405 object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
406 registration_data_export_interface (data, G_DBUS_INTERFACE_SKELETON (interface), object_path);
407 g_mutex_unlock (&data->manager->priv->lock);
411 on_interface_removed (GDBusObject *object,
412 GDBusInterface *interface,
415 RegistrationData *data = user_data;
416 g_mutex_lock (&data->manager->priv->lock);
417 registration_data_unexport_interface (data, G_DBUS_INTERFACE_SKELETON (interface));
418 g_mutex_unlock (&data->manager->priv->lock);
421 /* ---------------------------------------------------------------------------------------------------- */
425 registration_data_free (RegistrationData *data)
428 GDBusInterfaceSkeleton *iface;
430 data->exported = FALSE;
432 g_hash_table_iter_init (&iter, data->map_iface_name_to_iface);
433 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &iface))
435 if (data->manager->priv->connection != NULL)
436 g_dbus_interface_skeleton_unexport (iface);
439 g_signal_handlers_disconnect_by_func (data->object, G_CALLBACK (on_interface_added), data);
440 g_signal_handlers_disconnect_by_func (data->object, G_CALLBACK (on_interface_removed), data);
441 g_object_unref (data->object);
442 g_hash_table_destroy (data->map_iface_name_to_iface);
446 /* ---------------------------------------------------------------------------------------------------- */
449 g_dbus_object_manager_server_export_unlocked (GDBusObjectManagerServer *manager,
450 GDBusObjectSkeleton *object,
451 const gchar *object_path)
453 RegistrationData *data;
454 GList *existing_interfaces;
456 GPtrArray *interface_names;
458 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
459 g_return_if_fail (G_IS_DBUS_OBJECT (object));
460 g_return_if_fail (g_str_has_prefix (object_path, manager->priv->object_path_ending_in_slash));
462 interface_names = g_ptr_array_new ();
464 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
466 g_dbus_object_manager_server_unexport_unlocked (manager, object_path);
468 data = g_new0 (RegistrationData, 1);
469 data->object = g_object_ref (object);
470 data->manager = manager;
471 data->map_iface_name_to_iface = g_hash_table_new_full (g_str_hash,
474 (GDestroyNotify) g_object_unref);
476 g_signal_connect (object,
478 G_CALLBACK (on_interface_added),
480 g_signal_connect (object,
482 G_CALLBACK (on_interface_removed),
485 /* Register all known interfaces - note that data->exported is FALSE so
486 * we don't emit any InterfacesAdded signals.
488 existing_interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (object));
489 for (l = existing_interfaces; l != NULL; l = l->next)
491 GDBusInterfaceSkeleton *interface_skeleton = G_DBUS_INTERFACE_SKELETON (l->data);
492 registration_data_export_interface (data, interface_skeleton, object_path);
493 g_ptr_array_add (interface_names, g_dbus_interface_skeleton_get_info (interface_skeleton)->name);
495 g_list_free_full (existing_interfaces, g_object_unref);
496 g_ptr_array_add (interface_names, NULL);
498 data->exported = TRUE;
500 /* now emit InterfacesAdded() for all the interfaces */
501 g_dbus_object_manager_server_emit_interfaces_added (manager, data, (const gchar *const *) interface_names->pdata, object_path);
502 g_ptr_array_unref (interface_names);
504 g_hash_table_insert (manager->priv->map_object_path_to_data,
505 g_strdup (object_path),
510 * g_dbus_object_manager_server_export:
511 * @manager: A #GDBusObjectManagerServer.
512 * @object: A #GDBusObjectSkeleton.
514 * Exports @object on @manager.
516 * If there is already a #GDBusObject exported at the object path,
517 * then the old object is removed.
519 * The object path for @object must be in the hierarchy rooted by the
520 * object path for @manager.
522 * Note that @manager will take a reference on @object for as long as
528 g_dbus_object_manager_server_export (GDBusObjectManagerServer *manager,
529 GDBusObjectSkeleton *object)
531 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
532 g_mutex_lock (&manager->priv->lock);
533 g_dbus_object_manager_server_export_unlocked (manager, object,
534 g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
535 g_mutex_unlock (&manager->priv->lock);
539 * g_dbus_object_manager_server_export_uniquely:
540 * @manager: A #GDBusObjectManagerServer.
541 * @object: An object.
543 * Like g_dbus_object_manager_server_export() but appends a string of
544 * the form _N (with N being a natural number) to @object's object path
545 * if an object with the given path already exists. As such, the
546 * #GDBusObjectProxy:g-object-path property of @object may be modified.
551 g_dbus_object_manager_server_export_uniquely (GDBusObjectManagerServer *manager,
552 GDBusObjectSkeleton *object)
554 gchar *orig_object_path;
559 orig_object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
561 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
562 g_return_if_fail (G_IS_DBUS_OBJECT (object));
563 g_return_if_fail (g_str_has_prefix (orig_object_path, manager->priv->object_path_ending_in_slash));
565 g_mutex_lock (&manager->priv->lock);
567 object_path = g_strdup (orig_object_path);
572 RegistrationData *data;
573 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
578 g_free (object_path);
579 object_path = g_strdup_printf ("%s_%d", orig_object_path, count++);
583 g_dbus_object_manager_server_export_unlocked (manager, object, object_path);
585 g_mutex_unlock (&manager->priv->lock);
588 g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), object_path);
590 g_free (object_path);
591 g_free (orig_object_path);
596 * g_dbus_object_manager_server_is_exported:
597 * @manager: A #GDBusObjectManagerServer.
598 * @object: An object.
600 * Returns whether @object is currently exported on @manager.
602 * Returns: %TRUE if @object is exported
607 g_dbus_object_manager_server_is_exported (GDBusObjectManagerServer *manager,
608 GDBusObjectSkeleton *object)
610 RegistrationData *data = NULL;
611 const gchar *object_path;
612 gboolean object_is_exported;
614 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
615 g_return_val_if_fail (G_IS_DBUS_OBJECT (object), FALSE);
617 g_mutex_lock (&manager->priv->lock);
619 object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
620 if (object_path != NULL)
621 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
622 object_is_exported = (data != NULL);
624 g_mutex_unlock (&manager->priv->lock);
626 return object_is_exported;
629 /* ---------------------------------------------------------------------------------------------------- */
632 g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer *manager,
633 const gchar *object_path)
635 RegistrationData *data;
638 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
639 g_return_val_if_fail (g_variant_is_object_path (object_path), FALSE);
640 g_return_val_if_fail (g_str_has_prefix (object_path, manager->priv->object_path_ending_in_slash), FALSE);
644 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
647 GPtrArray *interface_names;
649 const gchar *iface_name;
651 interface_names = g_ptr_array_new ();
652 g_hash_table_iter_init (&iter, data->map_iface_name_to_iface);
653 while (g_hash_table_iter_next (&iter, (gpointer) &iface_name, NULL))
654 g_ptr_array_add (interface_names, (gpointer) iface_name);
655 g_ptr_array_add (interface_names, NULL);
656 /* now emit InterfacesRemoved() for all the interfaces */
657 g_dbus_object_manager_server_emit_interfaces_removed (manager, data, (const gchar *const *) interface_names->pdata);
658 g_ptr_array_unref (interface_names);
660 g_hash_table_remove (manager->priv->map_object_path_to_data, object_path);
668 * g_dbus_object_manager_server_unexport:
669 * @manager: A #GDBusObjectManagerServer.
670 * @object_path: An object path.
672 * If @manager has an object at @path, removes the object. Otherwise
675 * Note that @object_path must be in the hierarchy rooted by the
676 * object path for @manager.
678 * Returns: %TRUE if object at @object_path was removed, %FALSE otherwise.
683 g_dbus_object_manager_server_unexport (GDBusObjectManagerServer *manager,
684 const gchar *object_path)
687 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
688 g_mutex_lock (&manager->priv->lock);
689 ret = g_dbus_object_manager_server_unexport_unlocked (manager, object_path);
690 g_mutex_unlock (&manager->priv->lock);
695 /* ---------------------------------------------------------------------------------------------------- */
697 static const GDBusArgInfo manager_interfaces_added_signal_info_arg0 =
702 (GDBusAnnotationInfo**) NULL,
705 static const GDBusArgInfo manager_interfaces_added_signal_info_arg1 =
708 "interfaces_and_properties",
710 (GDBusAnnotationInfo**) NULL,
713 static const GDBusArgInfo * const manager_interfaces_added_signal_info_arg_pointers[] =
715 &manager_interfaces_added_signal_info_arg0,
716 &manager_interfaces_added_signal_info_arg1,
720 static const GDBusSignalInfo manager_interfaces_added_signal_info =
724 (GDBusArgInfo**) &manager_interfaces_added_signal_info_arg_pointers,
725 (GDBusAnnotationInfo**) NULL
730 static const GDBusArgInfo manager_interfaces_removed_signal_info_arg0 =
735 (GDBusAnnotationInfo**) NULL,
738 static const GDBusArgInfo manager_interfaces_removed_signal_info_arg1 =
743 (GDBusAnnotationInfo**) NULL,
746 static const GDBusArgInfo * const manager_interfaces_removed_signal_info_arg_pointers[] =
748 &manager_interfaces_removed_signal_info_arg0,
749 &manager_interfaces_removed_signal_info_arg1,
753 static const GDBusSignalInfo manager_interfaces_removed_signal_info =
757 (GDBusArgInfo**) &manager_interfaces_removed_signal_info_arg_pointers,
758 (GDBusAnnotationInfo**) NULL
763 static const GDBusSignalInfo * const manager_signal_info_pointers[] =
765 &manager_interfaces_added_signal_info,
766 &manager_interfaces_removed_signal_info,
772 static const GDBusArgInfo manager_get_all_method_info_out_arg0 =
775 "object_paths_interfaces_and_properties",
777 (GDBusAnnotationInfo**) NULL,
780 static const GDBusArgInfo * const manager_get_all_method_info_out_arg_pointers[] =
782 &manager_get_all_method_info_out_arg0,
786 static const GDBusMethodInfo manager_get_all_method_info =
790 (GDBusArgInfo**) NULL,
791 (GDBusArgInfo**) &manager_get_all_method_info_out_arg_pointers,
792 (GDBusAnnotationInfo**) NULL
795 static const GDBusMethodInfo * const manager_method_info_pointers[] =
797 &manager_get_all_method_info,
803 static const GDBusInterfaceInfo manager_interface_info =
806 "org.freedesktop.DBus.ObjectManager",
807 (GDBusMethodInfo **) manager_method_info_pointers,
808 (GDBusSignalInfo **) manager_signal_info_pointers,
809 (GDBusPropertyInfo **) NULL,
810 (GDBusAnnotationInfo **) NULL
814 manager_method_call (GDBusConnection *connection,
816 const gchar *object_path,
817 const gchar *interface_name,
818 const gchar *method_name,
819 GVariant *parameters,
820 GDBusMethodInvocation *invocation,
823 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (user_data);
824 GVariantBuilder array_builder;
825 GHashTableIter object_iter;
826 RegistrationData *data;
828 g_mutex_lock (&manager->priv->lock);
830 if (g_strcmp0 (method_name, "GetManagedObjects") == 0)
832 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a{oa{sa{sv}}}"));
833 g_hash_table_iter_init (&object_iter, manager->priv->map_object_path_to_data);
834 while (g_hash_table_iter_next (&object_iter, NULL, (gpointer) &data))
836 GVariantBuilder interfaces_builder;
837 GHashTableIter interface_iter;
838 GDBusInterfaceSkeleton *iface;
839 const gchar *iter_object_path;
841 g_variant_builder_init (&interfaces_builder, G_VARIANT_TYPE ("a{sa{sv}}"));
842 g_hash_table_iter_init (&interface_iter, data->map_iface_name_to_iface);
843 while (g_hash_table_iter_next (&interface_iter, NULL, (gpointer) &iface))
845 GVariant *properties = g_dbus_interface_skeleton_get_properties (iface);
846 g_variant_builder_add (&interfaces_builder, "{s@a{sv}}",
847 g_dbus_interface_skeleton_get_info (iface)->name,
849 g_variant_unref (properties);
851 iter_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
852 g_variant_builder_add (&array_builder,
855 &interfaces_builder);
858 g_dbus_method_invocation_return_value (invocation,
859 g_variant_new ("(a{oa{sa{sv}}})",
864 g_dbus_method_invocation_return_error (invocation,
866 G_DBUS_ERROR_UNKNOWN_METHOD,
867 "Unknown method %s - only GetManagedObjects() is supported",
870 g_mutex_unlock (&manager->priv->lock);
873 static const GDBusInterfaceVTable manager_interface_vtable =
875 manager_method_call, /* handle_method_call */
876 NULL, /* get_property */
877 NULL /* set_property */
880 /* ---------------------------------------------------------------------------------------------------- */
883 g_dbus_object_manager_server_constructed (GObject *object)
885 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
887 if (manager->priv->connection != NULL)
888 export_all (manager);
890 if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->constructed != NULL)
891 G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->constructed (object);
895 g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager,
896 RegistrationData *data,
897 const gchar *const *interfaces,
898 const gchar *object_path)
900 GVariantBuilder array_builder;
904 if (data->manager->priv->connection == NULL)
907 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a{sa{sv}}"));
908 for (n = 0; interfaces[n] != NULL; n++)
910 GDBusInterfaceSkeleton *iface;
911 GVariant *properties;
913 iface = g_hash_table_lookup (data->map_iface_name_to_iface, interfaces[n]);
914 g_assert (iface != NULL);
915 properties = g_dbus_interface_skeleton_get_properties (iface);
916 g_variant_builder_add (&array_builder, "{s@a{sv}}", interfaces[n], properties);
917 g_variant_unref (properties);
921 g_dbus_connection_emit_signal (data->manager->priv->connection,
922 NULL, /* destination_bus_name */
923 manager->priv->object_path,
924 manager_interface_info.name,
926 g_variant_new ("(oa{sa{sv}})",
930 g_assert_no_error (error);
936 g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager,
937 RegistrationData *data,
938 const gchar *const *interfaces)
940 GVariantBuilder array_builder;
943 const gchar *object_path;
945 if (data->manager->priv->connection == NULL)
948 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
949 for (n = 0; interfaces[n] != NULL; n++)
950 g_variant_builder_add (&array_builder, "s", interfaces[n]);
953 object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
954 g_dbus_connection_emit_signal (data->manager->priv->connection,
955 NULL, /* destination_bus_name */
956 manager->priv->object_path,
957 manager_interface_info.name,
959 g_variant_new ("(oas)",
963 g_assert_no_error (error);
968 /* ---------------------------------------------------------------------------------------------------- */
971 g_dbus_object_manager_server_get_objects (GDBusObjectManager *_manager)
973 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
976 RegistrationData *data;
978 g_mutex_lock (&manager->priv->lock);
981 g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
982 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data))
984 ret = g_list_prepend (ret, g_object_ref (data->object));
987 g_mutex_unlock (&manager->priv->lock);
993 g_dbus_object_manager_server_get_object_path (GDBusObjectManager *_manager)
995 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
996 return manager->priv->object_path;
1000 g_dbus_object_manager_server_get_object (GDBusObjectManager *_manager,
1001 const gchar *object_path)
1003 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
1005 RegistrationData *data;
1009 g_mutex_lock (&manager->priv->lock);
1010 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
1012 ret = g_object_ref (data->object);
1013 g_mutex_unlock (&manager->priv->lock);
1018 static GDBusInterface *
1019 g_dbus_object_manager_server_get_interface (GDBusObjectManager *_manager,
1020 const gchar *object_path,
1021 const gchar *interface_name)
1023 GDBusInterface *ret;
1024 GDBusObject *object;
1028 object = g_dbus_object_manager_get_object (_manager, object_path);
1032 ret = g_dbus_object_get_interface (object, interface_name);
1033 g_object_unref (object);
1040 dbus_object_manager_interface_init (GDBusObjectManagerIface *iface)
1042 iface->get_object_path = g_dbus_object_manager_server_get_object_path;
1043 iface->get_objects = g_dbus_object_manager_server_get_objects;
1044 iface->get_object = g_dbus_object_manager_server_get_object;
1045 iface->get_interface = g_dbus_object_manager_server_get_interface;
1048 /* ---------------------------------------------------------------------------------------------------- */
1051 export_all (GDBusObjectManagerServer *manager)
1053 GHashTableIter iter;
1054 const gchar *object_path;
1055 RegistrationData *data;
1056 GHashTableIter iface_iter;
1057 GDBusInterfaceSkeleton *iface;
1060 g_return_if_fail (manager->priv->connection != NULL);
1063 g_warn_if_fail (manager->priv->manager_reg_id == 0);
1064 manager->priv->manager_reg_id = g_dbus_connection_register_object (manager->priv->connection,
1065 manager->priv->object_path,
1066 (GDBusInterfaceInfo *) &manager_interface_info,
1067 &manager_interface_vtable,
1069 NULL, /* user_data_free_func */
1071 if (manager->priv->manager_reg_id == 0)
1073 g_warning ("%s: Error registering manager at %s: %s",
1075 manager->priv->object_path,
1077 g_error_free (error);
1080 g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1081 while (g_hash_table_iter_next (&iter, (gpointer) &object_path, (gpointer) &data))
1083 g_hash_table_iter_init (&iface_iter, data->map_iface_name_to_iface);
1084 while (g_hash_table_iter_next (&iface_iter, NULL, (gpointer) &iface))
1086 g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface) == NULL);
1088 if (!g_dbus_interface_skeleton_export (iface,
1089 manager->priv->connection,
1093 g_warning ("%s: Error registering object at %s with interface %s: %s",
1096 g_dbus_interface_skeleton_get_info (iface)->name,
1098 g_error_free (error);
1105 unexport_all (GDBusObjectManagerServer *manager, gboolean only_manager)
1107 GHashTableIter iter;
1108 RegistrationData *data;
1109 GHashTableIter iface_iter;
1110 GDBusInterfaceSkeleton *iface;
1112 g_return_if_fail (manager->priv->connection != NULL);
1114 g_warn_if_fail (manager->priv->manager_reg_id > 0);
1115 if (manager->priv->manager_reg_id > 0)
1117 g_warn_if_fail (g_dbus_connection_unregister_object (manager->priv->connection,
1118 manager->priv->manager_reg_id));
1119 manager->priv->manager_reg_id = 0;
1124 g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1125 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data))
1127 g_hash_table_iter_init (&iface_iter, data->map_iface_name_to_iface);
1128 while (g_hash_table_iter_next (&iface_iter, NULL, (gpointer) &iface))
1130 g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface) != NULL);
1131 g_dbus_interface_skeleton_unexport (iface);
1138 /* ---------------------------------------------------------------------------------------------------- */