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.1 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"
38 * SECTION:gdbusobjectmanagerserver
39 * @short_description: Service-side object manager
42 * #GDBusObjectManagerServer is used to export #GDBusObject instances using
44 * [org.freedesktop.DBus.ObjectManager](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
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
51 * The recommended path to export an object manager at is the path form of the
52 * well-known name of a D-Bus service, or below. For example, if a D-Bus service
53 * is available at the well-known name `net.example.ExampleService1`, the object
54 * manager should typically be exported at `/net/example/ExampleService1`, or
55 * below (to allow for multiple object managers in a service).
57 * It is supported, but not recommended, to export an object manager at the root
60 * See #GDBusObjectManagerClient for the client-side code that is
61 * intended to be used with #GDBusObjectManagerServer or any D-Bus
62 * object implementing the org.freedesktop.DBus.ObjectManager
68 GDBusObjectSkeleton
*object
;
69 GDBusObjectManagerServer
*manager
;
70 GHashTable
*map_iface_name_to_iface
;
74 static void registration_data_free (RegistrationData
*data
);
76 static void export_all (GDBusObjectManagerServer
*manager
);
77 static void unexport_all (GDBusObjectManagerServer
*manager
, gboolean only_manager
);
79 static void g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer
*manager
,
80 RegistrationData
*data
,
81 const gchar
*const *interfaces
,
82 const gchar
*object_path
);
84 static void g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer
*manager
,
85 RegistrationData
*data
,
86 const gchar
*const *interfaces
);
88 static gboolean
g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer
*manager
,
89 const gchar
*object_path
);
91 struct _GDBusObjectManagerServerPrivate
94 GDBusConnection
*connection
;
96 gchar
*object_path_ending_in_slash
;
97 GHashTable
*map_object_path_to_data
;
108 static void dbus_object_manager_interface_init (GDBusObjectManagerIface
*iface
);
110 G_DEFINE_TYPE_WITH_CODE (GDBusObjectManagerServer
, g_dbus_object_manager_server
, G_TYPE_OBJECT
,
111 G_ADD_PRIVATE (GDBusObjectManagerServer
)
112 G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT_MANAGER
, dbus_object_manager_interface_init
))
114 static void g_dbus_object_manager_server_constructed (GObject
*object
);
117 g_dbus_object_manager_server_finalize (GObject
*object
)
119 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (object
);
121 if (manager
->priv
->connection
!= NULL
)
123 unexport_all (manager
, TRUE
);
124 g_object_unref (manager
->priv
->connection
);
126 g_hash_table_unref (manager
->priv
->map_object_path_to_data
);
127 g_free (manager
->priv
->object_path
);
128 g_free (manager
->priv
->object_path_ending_in_slash
);
130 g_mutex_clear (&manager
->priv
->lock
);
132 if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class
)->finalize
!= NULL
)
133 G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class
)->finalize (object
);
137 g_dbus_object_manager_server_get_property (GObject
*object
,
142 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (object
);
146 case PROP_CONNECTION
:
147 g_mutex_lock (&manager
->priv
->lock
);
148 g_value_set_object (value
, manager
->priv
->connection
);
149 g_mutex_unlock (&manager
->priv
->lock
);
152 case PROP_OBJECT_PATH
:
153 g_value_set_string (value
, g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (manager
)));
157 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
163 g_dbus_object_manager_server_set_property (GObject
*object
,
168 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (object
);
172 case PROP_CONNECTION
:
173 g_dbus_object_manager_server_set_connection (manager
, g_value_get_object (value
));
176 case PROP_OBJECT_PATH
:
177 g_assert (manager
->priv
->object_path
== NULL
);
178 g_assert (g_variant_is_object_path (g_value_get_string (value
)));
179 manager
->priv
->object_path
= g_value_dup_string (value
);
180 if (g_str_equal (manager
->priv
->object_path
, "/"))
181 manager
->priv
->object_path_ending_in_slash
= g_strdup (manager
->priv
->object_path
);
183 manager
->priv
->object_path_ending_in_slash
= g_strdup_printf ("%s/", manager
->priv
->object_path
);
187 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
193 g_dbus_object_manager_server_class_init (GDBusObjectManagerServerClass
*klass
)
195 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
197 gobject_class
->finalize
= g_dbus_object_manager_server_finalize
;
198 gobject_class
->constructed
= g_dbus_object_manager_server_constructed
;
199 gobject_class
->set_property
= g_dbus_object_manager_server_set_property
;
200 gobject_class
->get_property
= g_dbus_object_manager_server_get_property
;
203 * GDBusObjectManagerServer:connection:
205 * The #GDBusConnection to export objects on.
209 g_object_class_install_property (gobject_class
,
211 g_param_spec_object ("connection",
213 "The connection to export objects on",
214 G_TYPE_DBUS_CONNECTION
,
217 G_PARAM_STATIC_STRINGS
));
220 * GDBusObjectManagerServer:object-path:
222 * The object path to register the manager object at.
226 g_object_class_install_property (gobject_class
,
228 g_param_spec_string ("object-path",
230 "The object path to register the manager object at",
234 G_PARAM_CONSTRUCT_ONLY
|
235 G_PARAM_STATIC_STRINGS
));
239 g_dbus_object_manager_server_init (GDBusObjectManagerServer
*manager
)
241 manager
->priv
= g_dbus_object_manager_server_get_instance_private (manager
);
242 g_mutex_init (&manager
->priv
->lock
);
243 manager
->priv
->map_object_path_to_data
= g_hash_table_new_full (g_str_hash
,
246 (GDestroyNotify
) registration_data_free
);
250 * g_dbus_object_manager_server_new:
251 * @object_path: The object path to export the manager object at.
253 * Creates a new #GDBusObjectManagerServer object.
255 * The returned server isn't yet exported on any connection. To do so,
256 * use g_dbus_object_manager_server_set_connection(). Normally you
257 * want to export all of your objects before doing so to avoid
258 * [InterfacesAdded](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
259 * signals being emitted.
261 * Returns: A #GDBusObjectManagerServer object. Free with g_object_unref().
265 GDBusObjectManagerServer
*
266 g_dbus_object_manager_server_new (const gchar
*object_path
)
268 g_return_val_if_fail (g_variant_is_object_path (object_path
), NULL
);
269 return G_DBUS_OBJECT_MANAGER_SERVER (g_object_new (G_TYPE_DBUS_OBJECT_MANAGER_SERVER
,
270 "object-path", object_path
,
275 * g_dbus_object_manager_server_set_connection:
276 * @manager: A #GDBusObjectManagerServer.
277 * @connection: (nullable): A #GDBusConnection or %NULL.
279 * Exports all objects managed by @manager on @connection. If
280 * @connection is %NULL, stops exporting objects.
283 g_dbus_object_manager_server_set_connection (GDBusObjectManagerServer
*manager
,
284 GDBusConnection
*connection
)
286 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager
));
287 g_return_if_fail (connection
== NULL
|| G_IS_DBUS_CONNECTION (connection
));
289 g_mutex_lock (&manager
->priv
->lock
);
291 if (manager
->priv
->connection
== connection
)
293 g_mutex_unlock (&manager
->priv
->lock
);
297 if (manager
->priv
->connection
!= NULL
)
299 unexport_all (manager
, FALSE
);
300 g_object_unref (manager
->priv
->connection
);
301 manager
->priv
->connection
= NULL
;
304 manager
->priv
->connection
= connection
!= NULL
? g_object_ref (connection
) : NULL
;
305 if (manager
->priv
->connection
!= NULL
)
306 export_all (manager
);
308 g_mutex_unlock (&manager
->priv
->lock
);
310 g_object_notify (G_OBJECT (manager
), "connection");
316 * g_dbus_object_manager_server_get_connection:
317 * @manager: A #GDBusObjectManagerServer
319 * Gets the #GDBusConnection used by @manager.
321 * Returns: (transfer full): A #GDBusConnection object or %NULL if
322 * @manager isn't exported on a connection. The returned object should
323 * be freed with g_object_unref().
328 g_dbus_object_manager_server_get_connection (GDBusObjectManagerServer
*manager
)
330 GDBusConnection
*ret
;
331 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager
), NULL
);
332 g_mutex_lock (&manager
->priv
->lock
);
333 ret
= manager
->priv
->connection
!= NULL
? g_object_ref (manager
->priv
->connection
) : NULL
;
334 g_mutex_unlock (&manager
->priv
->lock
);
338 /* ---------------------------------------------------------------------------------------------------- */
341 registration_data_export_interface (RegistrationData
*data
,
342 GDBusInterfaceSkeleton
*interface_skeleton
,
343 const gchar
*object_path
)
345 GDBusInterfaceInfo
*info
;
348 info
= g_dbus_interface_skeleton_get_info (interface_skeleton
);
350 if (data
->manager
->priv
->connection
!= NULL
)
352 if (!g_dbus_interface_skeleton_export (interface_skeleton
,
353 data
->manager
->priv
->connection
,
357 g_warning ("%s: Error registering object at %s with interface %s: %s",
362 g_error_free (error
);
366 g_assert (g_hash_table_lookup (data
->map_iface_name_to_iface
, info
->name
) == NULL
);
367 g_hash_table_insert (data
->map_iface_name_to_iface
,
369 g_object_ref (interface_skeleton
));
371 /* if we are already exported, then... */
374 const gchar
*interfaces
[2];
375 /* emit InterfacesAdded on the ObjectManager object */
376 interfaces
[0] = info
->name
;
377 interfaces
[1] = NULL
;
378 g_dbus_object_manager_server_emit_interfaces_added (data
->manager
, data
, interfaces
, object_path
);
383 registration_data_unexport_interface (RegistrationData
*data
,
384 GDBusInterfaceSkeleton
*interface_skeleton
)
386 GDBusInterfaceInfo
*info
;
387 GDBusInterfaceSkeleton
*iface
;
389 info
= g_dbus_interface_skeleton_get_info (interface_skeleton
);
390 iface
= g_hash_table_lookup (data
->map_iface_name_to_iface
, info
->name
);
391 g_assert (iface
!= NULL
);
393 if (data
->manager
->priv
->connection
!= NULL
)
394 g_dbus_interface_skeleton_unexport (iface
);
396 g_warn_if_fail (g_hash_table_remove (data
->map_iface_name_to_iface
, info
->name
));
398 /* if we are already exported, then... */
401 const gchar
*interfaces
[2];
402 /* emit InterfacesRemoved on the ObjectManager object */
403 interfaces
[0] = info
->name
;
404 interfaces
[1] = NULL
;
405 g_dbus_object_manager_server_emit_interfaces_removed (data
->manager
, data
, interfaces
);
409 /* ---------------------------------------------------------------------------------------------------- */
412 on_interface_added (GDBusObject
*object
,
413 GDBusInterface
*interface
,
416 RegistrationData
*data
= user_data
;
417 const gchar
*object_path
;
418 g_mutex_lock (&data
->manager
->priv
->lock
);
419 object_path
= g_dbus_object_get_object_path (G_DBUS_OBJECT (data
->object
));
420 registration_data_export_interface (data
, G_DBUS_INTERFACE_SKELETON (interface
), object_path
);
421 g_mutex_unlock (&data
->manager
->priv
->lock
);
425 on_interface_removed (GDBusObject
*object
,
426 GDBusInterface
*interface
,
429 RegistrationData
*data
= user_data
;
430 g_mutex_lock (&data
->manager
->priv
->lock
);
431 registration_data_unexport_interface (data
, G_DBUS_INTERFACE_SKELETON (interface
));
432 g_mutex_unlock (&data
->manager
->priv
->lock
);
435 /* ---------------------------------------------------------------------------------------------------- */
439 registration_data_free (RegistrationData
*data
)
442 GDBusInterfaceSkeleton
*iface
;
444 data
->exported
= FALSE
;
446 g_hash_table_iter_init (&iter
, data
->map_iface_name_to_iface
);
447 while (g_hash_table_iter_next (&iter
, NULL
, (gpointer
) &iface
))
449 if (data
->manager
->priv
->connection
!= NULL
)
450 g_dbus_interface_skeleton_unexport (iface
);
453 g_signal_handlers_disconnect_by_func (data
->object
, G_CALLBACK (on_interface_added
), data
);
454 g_signal_handlers_disconnect_by_func (data
->object
, G_CALLBACK (on_interface_removed
), data
);
455 g_object_unref (data
->object
);
456 g_hash_table_destroy (data
->map_iface_name_to_iface
);
460 /* ---------------------------------------------------------------------------------------------------- */
463 g_dbus_object_manager_server_export_unlocked (GDBusObjectManagerServer
*manager
,
464 GDBusObjectSkeleton
*object
,
465 const gchar
*object_path
)
467 RegistrationData
*data
;
468 GList
*existing_interfaces
;
470 GPtrArray
*interface_names
;
472 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager
));
473 g_return_if_fail (G_IS_DBUS_OBJECT (object
));
474 g_return_if_fail (g_str_has_prefix (object_path
, manager
->priv
->object_path_ending_in_slash
));
476 interface_names
= g_ptr_array_new ();
478 data
= g_hash_table_lookup (manager
->priv
->map_object_path_to_data
, object_path
);
480 g_dbus_object_manager_server_unexport_unlocked (manager
, object_path
);
482 data
= g_new0 (RegistrationData
, 1);
483 data
->object
= g_object_ref (object
);
484 data
->manager
= manager
;
485 data
->map_iface_name_to_iface
= g_hash_table_new_full (g_str_hash
,
488 (GDestroyNotify
) g_object_unref
);
490 g_signal_connect (object
,
492 G_CALLBACK (on_interface_added
),
494 g_signal_connect (object
,
496 G_CALLBACK (on_interface_removed
),
499 /* Register all known interfaces - note that data->exported is FALSE so
500 * we don't emit any InterfacesAdded signals.
502 existing_interfaces
= g_dbus_object_get_interfaces (G_DBUS_OBJECT (object
));
503 for (l
= existing_interfaces
; l
!= NULL
; l
= l
->next
)
505 GDBusInterfaceSkeleton
*interface_skeleton
= G_DBUS_INTERFACE_SKELETON (l
->data
);
506 registration_data_export_interface (data
, interface_skeleton
, object_path
);
507 g_ptr_array_add (interface_names
, g_dbus_interface_skeleton_get_info (interface_skeleton
)->name
);
509 g_list_free_full (existing_interfaces
, g_object_unref
);
510 g_ptr_array_add (interface_names
, NULL
);
512 data
->exported
= TRUE
;
514 /* now emit InterfacesAdded() for all the interfaces */
515 g_dbus_object_manager_server_emit_interfaces_added (manager
, data
, (const gchar
*const *) interface_names
->pdata
, object_path
);
516 g_ptr_array_unref (interface_names
);
518 g_hash_table_insert (manager
->priv
->map_object_path_to_data
,
519 g_strdup (object_path
),
524 * g_dbus_object_manager_server_export:
525 * @manager: A #GDBusObjectManagerServer.
526 * @object: A #GDBusObjectSkeleton.
528 * Exports @object on @manager.
530 * If there is already a #GDBusObject exported at the object path,
531 * then the old object is removed.
533 * The object path for @object must be in the hierarchy rooted by the
534 * object path for @manager.
536 * Note that @manager will take a reference on @object for as long as
542 g_dbus_object_manager_server_export (GDBusObjectManagerServer
*manager
,
543 GDBusObjectSkeleton
*object
)
545 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager
));
546 g_mutex_lock (&manager
->priv
->lock
);
547 g_dbus_object_manager_server_export_unlocked (manager
, object
,
548 g_dbus_object_get_object_path (G_DBUS_OBJECT (object
)));
549 g_mutex_unlock (&manager
->priv
->lock
);
553 * g_dbus_object_manager_server_export_uniquely:
554 * @manager: A #GDBusObjectManagerServer.
555 * @object: An object.
557 * Like g_dbus_object_manager_server_export() but appends a string of
558 * the form _N (with N being a natural number) to @object's object path
559 * if an object with the given path already exists. As such, the
560 * #GDBusObjectProxy:g-object-path property of @object may be modified.
565 g_dbus_object_manager_server_export_uniquely (GDBusObjectManagerServer
*manager
,
566 GDBusObjectSkeleton
*object
)
568 gchar
*orig_object_path
;
573 orig_object_path
= g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object
)));
575 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager
));
576 g_return_if_fail (G_IS_DBUS_OBJECT (object
));
577 g_return_if_fail (g_str_has_prefix (orig_object_path
, manager
->priv
->object_path_ending_in_slash
));
579 g_mutex_lock (&manager
->priv
->lock
);
581 object_path
= g_strdup (orig_object_path
);
586 RegistrationData
*data
;
587 data
= g_hash_table_lookup (manager
->priv
->map_object_path_to_data
, object_path
);
592 g_free (object_path
);
593 object_path
= g_strdup_printf ("%s_%d", orig_object_path
, count
++);
597 g_dbus_object_manager_server_export_unlocked (manager
, object
, object_path
);
599 g_mutex_unlock (&manager
->priv
->lock
);
602 g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object
), object_path
);
604 g_free (object_path
);
605 g_free (orig_object_path
);
610 * g_dbus_object_manager_server_is_exported:
611 * @manager: A #GDBusObjectManagerServer.
612 * @object: An object.
614 * Returns whether @object is currently exported on @manager.
616 * Returns: %TRUE if @object is exported
621 g_dbus_object_manager_server_is_exported (GDBusObjectManagerServer
*manager
,
622 GDBusObjectSkeleton
*object
)
624 RegistrationData
*data
= NULL
;
625 const gchar
*object_path
;
626 gboolean object_is_exported
;
628 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager
), FALSE
);
629 g_return_val_if_fail (G_IS_DBUS_OBJECT (object
), FALSE
);
631 g_mutex_lock (&manager
->priv
->lock
);
633 object_path
= g_dbus_object_get_object_path (G_DBUS_OBJECT (object
));
634 if (object_path
!= NULL
)
635 data
= g_hash_table_lookup (manager
->priv
->map_object_path_to_data
, object_path
);
636 object_is_exported
= (data
!= NULL
);
638 g_mutex_unlock (&manager
->priv
->lock
);
640 return object_is_exported
;
643 /* ---------------------------------------------------------------------------------------------------- */
646 g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer
*manager
,
647 const gchar
*object_path
)
649 RegistrationData
*data
;
652 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager
), FALSE
);
653 g_return_val_if_fail (g_variant_is_object_path (object_path
), FALSE
);
654 g_return_val_if_fail (g_str_has_prefix (object_path
, manager
->priv
->object_path_ending_in_slash
), FALSE
);
658 data
= g_hash_table_lookup (manager
->priv
->map_object_path_to_data
, object_path
);
661 GPtrArray
*interface_names
;
663 const gchar
*iface_name
;
665 interface_names
= g_ptr_array_new ();
666 g_hash_table_iter_init (&iter
, data
->map_iface_name_to_iface
);
667 while (g_hash_table_iter_next (&iter
, (gpointer
) &iface_name
, NULL
))
668 g_ptr_array_add (interface_names
, (gpointer
) iface_name
);
669 g_ptr_array_add (interface_names
, NULL
);
670 /* now emit InterfacesRemoved() for all the interfaces */
671 g_dbus_object_manager_server_emit_interfaces_removed (manager
, data
, (const gchar
*const *) interface_names
->pdata
);
672 g_ptr_array_unref (interface_names
);
674 g_hash_table_remove (manager
->priv
->map_object_path_to_data
, object_path
);
682 * g_dbus_object_manager_server_unexport:
683 * @manager: A #GDBusObjectManagerServer.
684 * @object_path: An object path.
686 * If @manager has an object at @path, removes the object. Otherwise
689 * Note that @object_path must be in the hierarchy rooted by the
690 * object path for @manager.
692 * Returns: %TRUE if object at @object_path was removed, %FALSE otherwise.
697 g_dbus_object_manager_server_unexport (GDBusObjectManagerServer
*manager
,
698 const gchar
*object_path
)
701 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager
), FALSE
);
702 g_mutex_lock (&manager
->priv
->lock
);
703 ret
= g_dbus_object_manager_server_unexport_unlocked (manager
, object_path
);
704 g_mutex_unlock (&manager
->priv
->lock
);
709 /* ---------------------------------------------------------------------------------------------------- */
711 static const GDBusArgInfo manager_interfaces_added_signal_info_arg0
=
716 (GDBusAnnotationInfo
**) NULL
,
719 static const GDBusArgInfo manager_interfaces_added_signal_info_arg1
=
722 "interfaces_and_properties",
724 (GDBusAnnotationInfo
**) NULL
,
727 static const GDBusArgInfo
* const manager_interfaces_added_signal_info_arg_pointers
[] =
729 &manager_interfaces_added_signal_info_arg0
,
730 &manager_interfaces_added_signal_info_arg1
,
734 static const GDBusSignalInfo manager_interfaces_added_signal_info
=
738 (GDBusArgInfo
**) &manager_interfaces_added_signal_info_arg_pointers
,
739 (GDBusAnnotationInfo
**) NULL
744 static const GDBusArgInfo manager_interfaces_removed_signal_info_arg0
=
749 (GDBusAnnotationInfo
**) NULL
,
752 static const GDBusArgInfo manager_interfaces_removed_signal_info_arg1
=
757 (GDBusAnnotationInfo
**) NULL
,
760 static const GDBusArgInfo
* const manager_interfaces_removed_signal_info_arg_pointers
[] =
762 &manager_interfaces_removed_signal_info_arg0
,
763 &manager_interfaces_removed_signal_info_arg1
,
767 static const GDBusSignalInfo manager_interfaces_removed_signal_info
=
771 (GDBusArgInfo
**) &manager_interfaces_removed_signal_info_arg_pointers
,
772 (GDBusAnnotationInfo
**) NULL
777 static const GDBusSignalInfo
* const manager_signal_info_pointers
[] =
779 &manager_interfaces_added_signal_info
,
780 &manager_interfaces_removed_signal_info
,
786 static const GDBusArgInfo manager_get_all_method_info_out_arg0
=
789 "object_paths_interfaces_and_properties",
791 (GDBusAnnotationInfo
**) NULL
,
794 static const GDBusArgInfo
* const manager_get_all_method_info_out_arg_pointers
[] =
796 &manager_get_all_method_info_out_arg0
,
800 static const GDBusMethodInfo manager_get_all_method_info
=
804 (GDBusArgInfo
**) NULL
,
805 (GDBusArgInfo
**) &manager_get_all_method_info_out_arg_pointers
,
806 (GDBusAnnotationInfo
**) NULL
809 static const GDBusMethodInfo
* const manager_method_info_pointers
[] =
811 &manager_get_all_method_info
,
817 static const GDBusInterfaceInfo manager_interface_info
=
820 "org.freedesktop.DBus.ObjectManager",
821 (GDBusMethodInfo
**) manager_method_info_pointers
,
822 (GDBusSignalInfo
**) manager_signal_info_pointers
,
823 (GDBusPropertyInfo
**) NULL
,
824 (GDBusAnnotationInfo
**) NULL
828 manager_method_call (GDBusConnection
*connection
,
830 const gchar
*object_path
,
831 const gchar
*interface_name
,
832 const gchar
*method_name
,
833 GVariant
*parameters
,
834 GDBusMethodInvocation
*invocation
,
837 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (user_data
);
838 GVariantBuilder array_builder
;
839 GHashTableIter object_iter
;
840 RegistrationData
*data
;
842 g_mutex_lock (&manager
->priv
->lock
);
844 if (g_strcmp0 (method_name
, "GetManagedObjects") == 0)
846 g_variant_builder_init (&array_builder
, G_VARIANT_TYPE ("a{oa{sa{sv}}}"));
847 g_hash_table_iter_init (&object_iter
, manager
->priv
->map_object_path_to_data
);
848 while (g_hash_table_iter_next (&object_iter
, NULL
, (gpointer
) &data
))
850 GVariantBuilder interfaces_builder
;
851 GHashTableIter interface_iter
;
852 GDBusInterfaceSkeleton
*iface
;
853 const gchar
*iter_object_path
;
855 g_variant_builder_init (&interfaces_builder
, G_VARIANT_TYPE ("a{sa{sv}}"));
856 g_hash_table_iter_init (&interface_iter
, data
->map_iface_name_to_iface
);
857 while (g_hash_table_iter_next (&interface_iter
, NULL
, (gpointer
) &iface
))
859 GVariant
*properties
= g_dbus_interface_skeleton_get_properties (iface
);
860 g_variant_builder_add (&interfaces_builder
, "{s@a{sv}}",
861 g_dbus_interface_skeleton_get_info (iface
)->name
,
863 g_variant_unref (properties
);
865 iter_object_path
= g_dbus_object_get_object_path (G_DBUS_OBJECT (data
->object
));
866 g_variant_builder_add (&array_builder
,
869 &interfaces_builder
);
872 g_dbus_method_invocation_return_value (invocation
,
873 g_variant_new ("(a{oa{sa{sv}}})",
878 g_dbus_method_invocation_return_error (invocation
,
880 G_DBUS_ERROR_UNKNOWN_METHOD
,
881 "Unknown method %s - only GetManagedObjects() is supported",
884 g_mutex_unlock (&manager
->priv
->lock
);
887 static const GDBusInterfaceVTable manager_interface_vtable
=
889 manager_method_call
, /* handle_method_call */
890 NULL
, /* get_property */
891 NULL
/* set_property */
894 /* ---------------------------------------------------------------------------------------------------- */
897 g_dbus_object_manager_server_constructed (GObject
*object
)
899 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (object
);
901 if (manager
->priv
->connection
!= NULL
)
902 export_all (manager
);
904 if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class
)->constructed
!= NULL
)
905 G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class
)->constructed (object
);
909 g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer
*manager
,
910 RegistrationData
*data
,
911 const gchar
*const *interfaces
,
912 const gchar
*object_path
)
914 GVariantBuilder array_builder
;
918 if (data
->manager
->priv
->connection
== NULL
)
921 g_variant_builder_init (&array_builder
, G_VARIANT_TYPE ("a{sa{sv}}"));
922 for (n
= 0; interfaces
[n
] != NULL
; n
++)
924 GDBusInterfaceSkeleton
*iface
;
925 GVariant
*properties
;
927 iface
= g_hash_table_lookup (data
->map_iface_name_to_iface
, interfaces
[n
]);
928 g_assert (iface
!= NULL
);
929 properties
= g_dbus_interface_skeleton_get_properties (iface
);
930 g_variant_builder_add (&array_builder
, "{s@a{sv}}", interfaces
[n
], properties
);
931 g_variant_unref (properties
);
935 g_dbus_connection_emit_signal (data
->manager
->priv
->connection
,
936 NULL
, /* destination_bus_name */
937 manager
->priv
->object_path
,
938 manager_interface_info
.name
,
940 g_variant_new ("(oa{sa{sv}})",
946 if (!g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CLOSED
))
947 g_warning ("Couldn't emit InterfacesAdded signal: %s", error
->message
);
948 g_error_free (error
);
955 g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer
*manager
,
956 RegistrationData
*data
,
957 const gchar
*const *interfaces
)
959 GVariantBuilder array_builder
;
962 const gchar
*object_path
;
964 if (data
->manager
->priv
->connection
== NULL
)
967 g_variant_builder_init (&array_builder
, G_VARIANT_TYPE ("as"));
968 for (n
= 0; interfaces
[n
] != NULL
; n
++)
969 g_variant_builder_add (&array_builder
, "s", interfaces
[n
]);
972 object_path
= g_dbus_object_get_object_path (G_DBUS_OBJECT (data
->object
));
973 g_dbus_connection_emit_signal (data
->manager
->priv
->connection
,
974 NULL
, /* destination_bus_name */
975 manager
->priv
->object_path
,
976 manager_interface_info
.name
,
978 g_variant_new ("(oas)",
984 if (!g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CLOSED
))
985 g_warning ("Couldn't emit InterfacesRemoved signal: %s", error
->message
);
986 g_error_free (error
);
992 /* ---------------------------------------------------------------------------------------------------- */
995 g_dbus_object_manager_server_get_objects (GDBusObjectManager
*_manager
)
997 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (_manager
);
1000 RegistrationData
*data
;
1002 g_mutex_lock (&manager
->priv
->lock
);
1005 g_hash_table_iter_init (&iter
, manager
->priv
->map_object_path_to_data
);
1006 while (g_hash_table_iter_next (&iter
, NULL
, (gpointer
) &data
))
1008 ret
= g_list_prepend (ret
, g_object_ref (data
->object
));
1011 g_mutex_unlock (&manager
->priv
->lock
);
1016 static const gchar
*
1017 g_dbus_object_manager_server_get_object_path (GDBusObjectManager
*_manager
)
1019 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (_manager
);
1020 return manager
->priv
->object_path
;
1023 static GDBusObject
*
1024 g_dbus_object_manager_server_get_object (GDBusObjectManager
*_manager
,
1025 const gchar
*object_path
)
1027 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (_manager
);
1029 RegistrationData
*data
;
1033 g_mutex_lock (&manager
->priv
->lock
);
1034 data
= g_hash_table_lookup (manager
->priv
->map_object_path_to_data
, object_path
);
1036 ret
= g_object_ref (G_DBUS_OBJECT (data
->object
));
1037 g_mutex_unlock (&manager
->priv
->lock
);
1042 static GDBusInterface
*
1043 g_dbus_object_manager_server_get_interface (GDBusObjectManager
*_manager
,
1044 const gchar
*object_path
,
1045 const gchar
*interface_name
)
1047 GDBusInterface
*ret
;
1048 GDBusObject
*object
;
1052 object
= g_dbus_object_manager_get_object (_manager
, object_path
);
1056 ret
= g_dbus_object_get_interface (object
, interface_name
);
1057 g_object_unref (object
);
1064 dbus_object_manager_interface_init (GDBusObjectManagerIface
*iface
)
1066 iface
->get_object_path
= g_dbus_object_manager_server_get_object_path
;
1067 iface
->get_objects
= g_dbus_object_manager_server_get_objects
;
1068 iface
->get_object
= g_dbus_object_manager_server_get_object
;
1069 iface
->get_interface
= g_dbus_object_manager_server_get_interface
;
1072 /* ---------------------------------------------------------------------------------------------------- */
1075 export_all (GDBusObjectManagerServer
*manager
)
1077 GHashTableIter iter
;
1078 const gchar
*object_path
;
1079 RegistrationData
*data
;
1080 GHashTableIter iface_iter
;
1081 GDBusInterfaceSkeleton
*iface
;
1084 g_return_if_fail (manager
->priv
->connection
!= NULL
);
1087 g_warn_if_fail (manager
->priv
->manager_reg_id
== 0);
1088 manager
->priv
->manager_reg_id
= g_dbus_connection_register_object (manager
->priv
->connection
,
1089 manager
->priv
->object_path
,
1090 (GDBusInterfaceInfo
*) &manager_interface_info
,
1091 &manager_interface_vtable
,
1093 NULL
, /* user_data_free_func */
1095 if (manager
->priv
->manager_reg_id
== 0)
1097 g_warning ("%s: Error registering manager at %s: %s",
1099 manager
->priv
->object_path
,
1101 g_error_free (error
);
1104 g_hash_table_iter_init (&iter
, manager
->priv
->map_object_path_to_data
);
1105 while (g_hash_table_iter_next (&iter
, (gpointer
) &object_path
, (gpointer
) &data
))
1107 g_hash_table_iter_init (&iface_iter
, data
->map_iface_name_to_iface
);
1108 while (g_hash_table_iter_next (&iface_iter
, NULL
, (gpointer
) &iface
))
1110 g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface
) == NULL
);
1112 if (!g_dbus_interface_skeleton_export (iface
,
1113 manager
->priv
->connection
,
1117 g_warning ("%s: Error registering object at %s with interface %s: %s",
1120 g_dbus_interface_skeleton_get_info (iface
)->name
,
1122 g_error_free (error
);
1129 unexport_all (GDBusObjectManagerServer
*manager
, gboolean only_manager
)
1131 GHashTableIter iter
;
1132 RegistrationData
*data
;
1133 GHashTableIter iface_iter
;
1134 GDBusInterfaceSkeleton
*iface
;
1136 g_return_if_fail (manager
->priv
->connection
!= NULL
);
1138 g_warn_if_fail (manager
->priv
->manager_reg_id
> 0);
1139 if (manager
->priv
->manager_reg_id
> 0)
1141 g_warn_if_fail (g_dbus_connection_unregister_object (manager
->priv
->connection
,
1142 manager
->priv
->manager_reg_id
));
1143 manager
->priv
->manager_reg_id
= 0;
1148 g_hash_table_iter_init (&iter
, manager
->priv
->map_object_path_to_data
);
1149 while (g_hash_table_iter_next (&iter
, NULL
, (gpointer
) &data
))
1151 g_hash_table_iter_init (&iface_iter
, data
->map_iface_name_to_iface
);
1152 while (g_hash_table_iter_next (&iface_iter
, NULL
, (gpointer
) &iface
))
1154 g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface
) != NULL
);
1155 g_dbus_interface_skeleton_unexport (iface
);
1162 /* ---------------------------------------------------------------------------------------------------- */