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>
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"
38 * SECTION:gdbusobjectmanagerserver
39 * @short_description: Service-side object manager
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
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
59 GDBusObjectSkeleton
*object
;
60 GDBusObjectManagerServer
*manager
;
61 GHashTable
*map_iface_name_to_iface
;
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
85 GDBusConnection
*connection
;
87 gchar
*object_path_ending_in_slash
;
88 GHashTable
*map_object_path_to_data
;
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
);
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
);
127 g_dbus_object_manager_server_get_property (GObject
*object
,
132 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (object
);
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
);
142 case PROP_OBJECT_PATH
:
143 g_value_set_string (value
, g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (manager
)));
147 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
153 g_dbus_object_manager_server_set_property (GObject
*object
,
158 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (object
);
162 case PROP_CONNECTION
:
163 g_dbus_object_manager_server_set_connection (manager
, g_value_get_object (value
));
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
);
174 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
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.
196 g_object_class_install_property (gobject_class
,
198 g_param_spec_object ("connection",
200 "The connection to export objects on",
201 G_TYPE_DBUS_CONNECTION
,
204 G_PARAM_STATIC_STRINGS
));
207 * GDBusObjectManagerServer:object-path:
209 * The object path to register the manager object at.
213 g_object_class_install_property (gobject_class
,
215 g_param_spec_string ("object-path",
217 "The object path to register the manager object at",
221 G_PARAM_CONSTRUCT_ONLY
|
222 G_PARAM_STATIC_STRINGS
));
224 g_type_class_add_private (klass
, sizeof (GDBusObjectManagerServerPrivate
));
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
,
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().
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
,
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.
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
);
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");
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().
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
);
329 /* ---------------------------------------------------------------------------------------------------- */
332 registration_data_export_interface (RegistrationData
*data
,
333 GDBusInterfaceSkeleton
*interface_skeleton
,
334 const gchar
*object_path
)
336 GDBusInterfaceInfo
*info
;
339 info
= g_dbus_interface_skeleton_get_info (interface_skeleton
);
341 if (data
->manager
->priv
->connection
!= NULL
)
343 if (!g_dbus_interface_skeleton_export (interface_skeleton
,
344 data
->manager
->priv
->connection
,
348 g_warning ("%s: Error registering object at %s with interface %s: %s",
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
,
360 g_object_ref (interface_skeleton
));
362 /* if we are already exported, then... */
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
);
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... */
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 /* ---------------------------------------------------------------------------------------------------- */
403 on_interface_added (GDBusObject
*object
,
404 GDBusInterface
*interface
,
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
);
416 on_interface_removed (GDBusObject
*object
,
417 GDBusInterface
*interface
,
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 /* ---------------------------------------------------------------------------------------------------- */
430 registration_data_free (RegistrationData
*data
)
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
);
451 /* ---------------------------------------------------------------------------------------------------- */
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
;
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
);
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
,
479 (GDestroyNotify
) g_object_unref
);
481 g_signal_connect (object
,
483 G_CALLBACK (on_interface_added
),
485 g_signal_connect (object
,
487 G_CALLBACK (on_interface_removed
),
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_free_full (existing_interfaces
, g_object_unref
);
501 g_ptr_array_add (interface_names
, NULL
);
503 data
->exported
= TRUE
;
505 /* now emit InterfacesAdded() for all the interfaces */
506 g_dbus_object_manager_server_emit_interfaces_added (manager
, data
, (const gchar
*const *) interface_names
->pdata
, object_path
);
507 g_ptr_array_unref (interface_names
);
509 g_hash_table_insert (manager
->priv
->map_object_path_to_data
,
510 g_strdup (object_path
),
515 * g_dbus_object_manager_server_export:
516 * @manager: A #GDBusObjectManagerServer.
517 * @object: A #GDBusObjectSkeleton.
519 * Exports @object on @manager.
521 * If there is already a #GDBusObject exported at the object path,
522 * then the old object is removed.
524 * The object path for @object must be in the hierarchy rooted by the
525 * object path for @manager.
527 * Note that @manager will take a reference on @object for as long as
533 g_dbus_object_manager_server_export (GDBusObjectManagerServer
*manager
,
534 GDBusObjectSkeleton
*object
)
536 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager
));
537 g_mutex_lock (&manager
->priv
->lock
);
538 g_dbus_object_manager_server_export_unlocked (manager
, object
,
539 g_dbus_object_get_object_path (G_DBUS_OBJECT (object
)));
540 g_mutex_unlock (&manager
->priv
->lock
);
544 * g_dbus_object_manager_server_export_uniquely:
545 * @manager: A #GDBusObjectManagerServer.
546 * @object: An object.
548 * Like g_dbus_object_manager_server_export() but appends a string of
549 * the form <literal>_N</literal> (with N being a natural number) to
550 * @object<!-- -->'s object path if an object with the given path
551 * already exists. As such, the #GDBusObjectProxy:g-object-path property
552 * of @object may be modified.
557 g_dbus_object_manager_server_export_uniquely (GDBusObjectManagerServer
*manager
,
558 GDBusObjectSkeleton
*object
)
560 gchar
*orig_object_path
;
565 orig_object_path
= g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object
)));
567 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager
));
568 g_return_if_fail (G_IS_DBUS_OBJECT (object
));
569 g_return_if_fail (g_str_has_prefix (orig_object_path
, manager
->priv
->object_path_ending_in_slash
));
571 g_mutex_lock (&manager
->priv
->lock
);
573 object_path
= g_strdup (orig_object_path
);
578 RegistrationData
*data
;
579 data
= g_hash_table_lookup (manager
->priv
->map_object_path_to_data
, object_path
);
584 g_free (object_path
);
585 object_path
= g_strdup_printf ("%s_%d", orig_object_path
, count
++);
589 g_dbus_object_manager_server_export_unlocked (manager
, object
, object_path
);
591 g_mutex_unlock (&manager
->priv
->lock
);
594 g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object
), object_path
);
596 g_free (object_path
);
597 g_free (orig_object_path
);
601 /* ---------------------------------------------------------------------------------------------------- */
604 g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer
*manager
,
605 const gchar
*object_path
)
607 RegistrationData
*data
;
610 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager
), FALSE
);
611 g_return_val_if_fail (g_variant_is_object_path (object_path
), FALSE
);
612 g_return_val_if_fail (g_str_has_prefix (object_path
, manager
->priv
->object_path_ending_in_slash
), FALSE
);
616 data
= g_hash_table_lookup (manager
->priv
->map_object_path_to_data
, object_path
);
619 GPtrArray
*interface_names
;
621 const gchar
*iface_name
;
623 interface_names
= g_ptr_array_new ();
624 g_hash_table_iter_init (&iter
, data
->map_iface_name_to_iface
);
625 while (g_hash_table_iter_next (&iter
, (gpointer
) &iface_name
, NULL
))
626 g_ptr_array_add (interface_names
, (gpointer
) iface_name
);
627 g_ptr_array_add (interface_names
, NULL
);
628 /* now emit InterfacesRemoved() for all the interfaces */
629 g_dbus_object_manager_server_emit_interfaces_removed (manager
, data
, (const gchar
*const *) interface_names
->pdata
);
630 g_ptr_array_unref (interface_names
);
632 g_hash_table_remove (manager
->priv
->map_object_path_to_data
, object_path
);
640 * g_dbus_object_manager_server_unexport:
641 * @manager: A #GDBusObjectManagerServer.
642 * @object_path: An object path.
644 * If @manager has an object at @path, removes the object. Otherwise
647 * Note that @object_path must be in the hierarchy rooted by the
648 * object path for @manager.
650 * Returns: %TRUE if object at @object_path was removed, %FALSE otherwise.
655 g_dbus_object_manager_server_unexport (GDBusObjectManagerServer
*manager
,
656 const gchar
*object_path
)
659 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager
), FALSE
);
660 g_mutex_lock (&manager
->priv
->lock
);
661 ret
= g_dbus_object_manager_server_unexport_unlocked (manager
, object_path
);
662 g_mutex_unlock (&manager
->priv
->lock
);
667 /* ---------------------------------------------------------------------------------------------------- */
669 static const GDBusArgInfo manager_interfaces_added_signal_info_arg0
=
674 (GDBusAnnotationInfo
**) NULL
,
677 static const GDBusArgInfo manager_interfaces_added_signal_info_arg1
=
680 "interfaces_and_properties",
682 (GDBusAnnotationInfo
**) NULL
,
685 static const GDBusArgInfo
* const manager_interfaces_added_signal_info_arg_pointers
[] =
687 &manager_interfaces_added_signal_info_arg0
,
688 &manager_interfaces_added_signal_info_arg1
,
692 static const GDBusSignalInfo manager_interfaces_added_signal_info
=
696 (GDBusArgInfo
**) &manager_interfaces_added_signal_info_arg_pointers
,
697 (GDBusAnnotationInfo
**) NULL
702 static const GDBusArgInfo manager_interfaces_removed_signal_info_arg0
=
707 (GDBusAnnotationInfo
**) NULL
,
710 static const GDBusArgInfo manager_interfaces_removed_signal_info_arg1
=
715 (GDBusAnnotationInfo
**) NULL
,
718 static const GDBusArgInfo
* const manager_interfaces_removed_signal_info_arg_pointers
[] =
720 &manager_interfaces_removed_signal_info_arg0
,
721 &manager_interfaces_removed_signal_info_arg1
,
725 static const GDBusSignalInfo manager_interfaces_removed_signal_info
=
729 (GDBusArgInfo
**) &manager_interfaces_removed_signal_info_arg_pointers
,
730 (GDBusAnnotationInfo
**) NULL
735 static const GDBusSignalInfo
* const manager_signal_info_pointers
[] =
737 &manager_interfaces_added_signal_info
,
738 &manager_interfaces_removed_signal_info
,
744 static const GDBusArgInfo manager_get_all_method_info_out_arg0
=
747 "object_paths_interfaces_and_properties",
749 (GDBusAnnotationInfo
**) NULL
,
752 static const GDBusArgInfo
* const manager_get_all_method_info_out_arg_pointers
[] =
754 &manager_get_all_method_info_out_arg0
,
758 static const GDBusMethodInfo manager_get_all_method_info
=
762 (GDBusArgInfo
**) NULL
,
763 (GDBusArgInfo
**) &manager_get_all_method_info_out_arg_pointers
,
764 (GDBusAnnotationInfo
**) NULL
767 static const GDBusMethodInfo
* const manager_method_info_pointers
[] =
769 &manager_get_all_method_info
,
775 static const GDBusInterfaceInfo manager_interface_info
=
778 "org.freedesktop.DBus.ObjectManager",
779 (GDBusMethodInfo
**) manager_method_info_pointers
,
780 (GDBusSignalInfo
**) manager_signal_info_pointers
,
781 (GDBusPropertyInfo
**) NULL
,
782 (GDBusAnnotationInfo
**) NULL
786 manager_method_call (GDBusConnection
*connection
,
788 const gchar
*object_path
,
789 const gchar
*interface_name
,
790 const gchar
*method_name
,
791 GVariant
*parameters
,
792 GDBusMethodInvocation
*invocation
,
795 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (user_data
);
796 GVariantBuilder array_builder
;
797 GHashTableIter object_iter
;
798 RegistrationData
*data
;
800 g_mutex_lock (&manager
->priv
->lock
);
802 if (g_strcmp0 (method_name
, "GetManagedObjects") == 0)
804 g_variant_builder_init (&array_builder
, G_VARIANT_TYPE ("a{oa{sa{sv}}}"));
805 g_hash_table_iter_init (&object_iter
, manager
->priv
->map_object_path_to_data
);
806 while (g_hash_table_iter_next (&object_iter
, NULL
, (gpointer
) &data
))
808 GVariantBuilder interfaces_builder
;
809 GHashTableIter interface_iter
;
810 GDBusInterfaceSkeleton
*iface
;
811 const gchar
*iter_object_path
;
813 g_variant_builder_init (&interfaces_builder
, G_VARIANT_TYPE ("a{sa{sv}}"));
814 g_hash_table_iter_init (&interface_iter
, data
->map_iface_name_to_iface
);
815 while (g_hash_table_iter_next (&interface_iter
, NULL
, (gpointer
) &iface
))
817 GVariant
*properties
= g_dbus_interface_skeleton_get_properties (iface
);
818 g_variant_builder_add (&interfaces_builder
, "{s@a{sv}}",
819 g_dbus_interface_skeleton_get_info (iface
)->name
,
821 g_variant_unref (properties
);
823 iter_object_path
= g_dbus_object_get_object_path (G_DBUS_OBJECT (data
->object
));
824 g_variant_builder_add (&array_builder
,
827 &interfaces_builder
);
830 g_dbus_method_invocation_return_value (invocation
,
831 g_variant_new ("(a{oa{sa{sv}}})",
836 g_dbus_method_invocation_return_error (invocation
,
838 G_DBUS_ERROR_UNKNOWN_METHOD
,
839 "Unknown method %s - only GetManagedObjects() is supported",
842 g_mutex_unlock (&manager
->priv
->lock
);
845 static const GDBusInterfaceVTable manager_interface_vtable
=
847 manager_method_call
, /* handle_method_call */
848 NULL
, /* get_property */
849 NULL
/* set_property */
852 /* ---------------------------------------------------------------------------------------------------- */
855 g_dbus_object_manager_server_constructed (GObject
*object
)
857 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (object
);
859 if (manager
->priv
->connection
!= NULL
)
860 export_all (manager
);
862 if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class
)->constructed
!= NULL
)
863 G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class
)->constructed (object
);
867 g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer
*manager
,
868 RegistrationData
*data
,
869 const gchar
*const *interfaces
,
870 const gchar
*object_path
)
872 GVariantBuilder array_builder
;
876 if (data
->manager
->priv
->connection
== NULL
)
879 g_variant_builder_init (&array_builder
, G_VARIANT_TYPE ("a{sa{sv}}"));
880 for (n
= 0; interfaces
[n
] != NULL
; n
++)
882 GDBusInterfaceSkeleton
*iface
;
883 GVariant
*properties
;
885 iface
= g_hash_table_lookup (data
->map_iface_name_to_iface
, interfaces
[n
]);
886 g_assert (iface
!= NULL
);
887 properties
= g_dbus_interface_skeleton_get_properties (iface
);
888 g_variant_builder_add (&array_builder
, "{s@a{sv}}", interfaces
[n
], properties
);
889 g_variant_unref (properties
);
893 g_dbus_connection_emit_signal (data
->manager
->priv
->connection
,
894 NULL
, /* destination_bus_name */
895 manager
->priv
->object_path
,
896 manager_interface_info
.name
,
898 g_variant_new ("(oa{sa{sv}})",
902 g_assert_no_error (error
);
908 g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer
*manager
,
909 RegistrationData
*data
,
910 const gchar
*const *interfaces
)
912 GVariantBuilder array_builder
;
915 const gchar
*object_path
;
917 if (data
->manager
->priv
->connection
== NULL
)
920 g_variant_builder_init (&array_builder
, G_VARIANT_TYPE ("as"));
921 for (n
= 0; interfaces
[n
] != NULL
; n
++)
922 g_variant_builder_add (&array_builder
, "s", interfaces
[n
]);
925 object_path
= g_dbus_object_get_object_path (G_DBUS_OBJECT (data
->object
));
926 g_dbus_connection_emit_signal (data
->manager
->priv
->connection
,
927 NULL
, /* destination_bus_name */
928 manager
->priv
->object_path
,
929 manager_interface_info
.name
,
931 g_variant_new ("(oas)",
935 g_assert_no_error (error
);
940 /* ---------------------------------------------------------------------------------------------------- */
943 g_dbus_object_manager_server_get_objects (GDBusObjectManager
*_manager
)
945 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (_manager
);
948 RegistrationData
*data
;
950 g_mutex_lock (&manager
->priv
->lock
);
953 g_hash_table_iter_init (&iter
, manager
->priv
->map_object_path_to_data
);
954 while (g_hash_table_iter_next (&iter
, NULL
, (gpointer
) &data
))
956 ret
= g_list_prepend (ret
, g_object_ref (data
->object
));
959 g_mutex_unlock (&manager
->priv
->lock
);
965 g_dbus_object_manager_server_get_object_path (GDBusObjectManager
*_manager
)
967 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (_manager
);
968 return manager
->priv
->object_path
;
972 g_dbus_object_manager_server_get_object (GDBusObjectManager
*_manager
,
973 const gchar
*object_path
)
975 GDBusObjectManagerServer
*manager
= G_DBUS_OBJECT_MANAGER_SERVER (_manager
);
977 RegistrationData
*data
;
981 g_mutex_lock (&manager
->priv
->lock
);
982 data
= g_hash_table_lookup (manager
->priv
->map_object_path_to_data
, object_path
);
984 ret
= g_object_ref (data
->object
);
985 g_mutex_unlock (&manager
->priv
->lock
);
990 static GDBusInterface
*
991 g_dbus_object_manager_server_get_interface (GDBusObjectManager
*_manager
,
992 const gchar
*object_path
,
993 const gchar
*interface_name
)
1000 object
= g_dbus_object_manager_get_object (_manager
, object_path
);
1004 ret
= g_dbus_object_get_interface (object
, interface_name
);
1005 g_object_unref (object
);
1012 dbus_object_manager_interface_init (GDBusObjectManagerIface
*iface
)
1014 iface
->get_object_path
= g_dbus_object_manager_server_get_object_path
;
1015 iface
->get_objects
= g_dbus_object_manager_server_get_objects
;
1016 iface
->get_object
= g_dbus_object_manager_server_get_object
;
1017 iface
->get_interface
= g_dbus_object_manager_server_get_interface
;
1020 /* ---------------------------------------------------------------------------------------------------- */
1023 export_all (GDBusObjectManagerServer
*manager
)
1025 GHashTableIter iter
;
1026 const gchar
*object_path
;
1027 RegistrationData
*data
;
1028 GHashTableIter iface_iter
;
1029 GDBusInterfaceSkeleton
*iface
;
1032 g_return_if_fail (manager
->priv
->connection
!= NULL
);
1035 g_warn_if_fail (manager
->priv
->manager_reg_id
== 0);
1036 manager
->priv
->manager_reg_id
= g_dbus_connection_register_object (manager
->priv
->connection
,
1037 manager
->priv
->object_path
,
1038 (GDBusInterfaceInfo
*) &manager_interface_info
,
1039 &manager_interface_vtable
,
1041 NULL
, /* user_data_free_func */
1043 if (manager
->priv
->manager_reg_id
== 0)
1045 g_warning ("%s: Error registering manager at %s: %s",
1047 manager
->priv
->object_path
,
1049 g_error_free (error
);
1052 g_hash_table_iter_init (&iter
, manager
->priv
->map_object_path_to_data
);
1053 while (g_hash_table_iter_next (&iter
, (gpointer
) &object_path
, (gpointer
) &data
))
1055 g_hash_table_iter_init (&iface_iter
, data
->map_iface_name_to_iface
);
1056 while (g_hash_table_iter_next (&iface_iter
, NULL
, (gpointer
) &iface
))
1058 g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface
) == NULL
);
1060 if (!g_dbus_interface_skeleton_export (iface
,
1061 manager
->priv
->connection
,
1065 g_warning ("%s: Error registering object at %s with interface %s: %s",
1068 g_dbus_interface_skeleton_get_info (iface
)->name
,
1070 g_error_free (error
);
1077 unexport_all (GDBusObjectManagerServer
*manager
, gboolean only_manager
)
1079 GHashTableIter iter
;
1080 RegistrationData
*data
;
1081 GHashTableIter iface_iter
;
1082 GDBusInterfaceSkeleton
*iface
;
1084 g_return_if_fail (manager
->priv
->connection
!= NULL
);
1086 g_warn_if_fail (manager
->priv
->manager_reg_id
> 0);
1087 if (manager
->priv
->manager_reg_id
> 0)
1089 g_warn_if_fail (g_dbus_connection_unregister_object (manager
->priv
->connection
,
1090 manager
->priv
->manager_reg_id
));
1091 manager
->priv
->manager_reg_id
= 0;
1096 g_hash_table_iter_init (&iter
, manager
->priv
->map_object_path_to_data
);
1097 while (g_hash_table_iter_next (&iter
, NULL
, (gpointer
) &data
))
1099 g_hash_table_iter_init (&iface_iter
, data
->map_iface_name_to_iface
);
1100 while (g_hash_table_iter_next (&iface_iter
, NULL
, (gpointer
) &iface
))
1102 g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface
) != NULL
);
1103 g_dbus_interface_skeleton_unexport (iface
);
1110 /* ---------------------------------------------------------------------------------------------------- */