nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* GDBus - GLib D-Bus Library
2 *
3 * Copyright (C) 2008-2010 Red Hat, Inc.
4 *
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.
9 *
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.
14 *
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/>.
17 *
18 * Author: David Zeuthen <davidz@redhat.com>
19 */
20  
21 #include "config.h"
22  
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"
32  
33 #include "gioerror.h"
34  
35 #include "glibintl.h"
36  
37 /**
38 * SECTION:gdbusobjectmanagerserver
39 * @short_description: Service-side object manager
40 * @include: gio/gio.h
41 *
42 * #GDBusObjectManagerServer is used to export #GDBusObject instances using
43 * the standardized
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
49 * signals.
50 *
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).
56 *
57 * It is not supported to export an object manager at the root path, `/`.
58 *
59 * See #GDBusObjectManagerClient for the client-side code that is
60 * intended to be used with #GDBusObjectManagerServer or any D-Bus
61 * object implementing the org.freedesktop.DBus.ObjectManager
62 * interface.
63 */
64  
65 typedef struct
66 {
67 GDBusObjectSkeleton *object;
68 GDBusObjectManagerServer *manager;
69 GHashTable *map_iface_name_to_iface;
70 gboolean exported;
71 } RegistrationData;
72  
73 static void registration_data_free (RegistrationData *data);
74  
75 static void export_all (GDBusObjectManagerServer *manager);
76 static void unexport_all (GDBusObjectManagerServer *manager, gboolean only_manager);
77  
78 static void g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager,
79 RegistrationData *data,
80 const gchar *const *interfaces,
81 const gchar *object_path);
82  
83 static void g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager,
84 RegistrationData *data,
85 const gchar *const *interfaces);
86  
87 static gboolean g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer *manager,
88 const gchar *object_path);
89  
90 struct _GDBusObjectManagerServerPrivate
91 {
92 GMutex lock;
93 GDBusConnection *connection;
94 gchar *object_path;
95 gchar *object_path_ending_in_slash;
96 GHashTable *map_object_path_to_data;
97 guint manager_reg_id;
98 };
99  
100 enum
101 {
102 PROP_0,
103 PROP_CONNECTION,
104 PROP_OBJECT_PATH
105 };
106  
107 static void dbus_object_manager_interface_init (GDBusObjectManagerIface *iface);
108  
109 G_DEFINE_TYPE_WITH_CODE (GDBusObjectManagerServer, g_dbus_object_manager_server, G_TYPE_OBJECT,
110 G_ADD_PRIVATE (GDBusObjectManagerServer)
111 G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT_MANAGER, dbus_object_manager_interface_init))
112  
113 static void g_dbus_object_manager_server_constructed (GObject *object);
114  
115 static void
116 g_dbus_object_manager_server_finalize (GObject *object)
117 {
118 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
119  
120 if (manager->priv->connection != NULL)
121 {
122 unexport_all (manager, TRUE);
123 g_object_unref (manager->priv->connection);
124 }
125 g_hash_table_unref (manager->priv->map_object_path_to_data);
126 g_free (manager->priv->object_path);
127 g_free (manager->priv->object_path_ending_in_slash);
128  
129 g_mutex_clear (&manager->priv->lock);
130  
131 if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize != NULL)
132 G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize (object);
133 }
134  
135 static void
136 g_dbus_object_manager_server_get_property (GObject *object,
137 guint prop_id,
138 GValue *value,
139 GParamSpec *pspec)
140 {
141 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
142  
143 switch (prop_id)
144 {
145 case PROP_CONNECTION:
146 g_mutex_lock (&manager->priv->lock);
147 g_value_set_object (value, manager->priv->connection);
148 g_mutex_unlock (&manager->priv->lock);
149 break;
150  
151 case PROP_OBJECT_PATH:
152 g_value_set_string (value, g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (manager)));
153 break;
154  
155 default:
156 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
157 break;
158 }
159 }
160  
161 static void
162 g_dbus_object_manager_server_set_property (GObject *object,
163 guint prop_id,
164 const GValue *value,
165 GParamSpec *pspec)
166 {
167 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
168  
169 switch (prop_id)
170 {
171 case PROP_CONNECTION:
172 g_dbus_object_manager_server_set_connection (manager, g_value_get_object (value));
173 break;
174  
175 case PROP_OBJECT_PATH:
176 g_assert (manager->priv->object_path == NULL);
177 g_assert (g_variant_is_object_path (g_value_get_string (value)));
178 manager->priv->object_path = g_value_dup_string (value);
179 manager->priv->object_path_ending_in_slash = g_strdup_printf ("%s/", manager->priv->object_path);
180 break;
181  
182 default:
183 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
184 break;
185 }
186 }
187  
188 static void
189 g_dbus_object_manager_server_class_init (GDBusObjectManagerServerClass *klass)
190 {
191 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
192  
193 gobject_class->finalize = g_dbus_object_manager_server_finalize;
194 gobject_class->constructed = g_dbus_object_manager_server_constructed;
195 gobject_class->set_property = g_dbus_object_manager_server_set_property;
196 gobject_class->get_property = g_dbus_object_manager_server_get_property;
197  
198 /**
199 * GDBusObjectManagerServer:connection:
200 *
201 * The #GDBusConnection to export objects on.
202 *
203 * Since: 2.30
204 */
205 g_object_class_install_property (gobject_class,
206 PROP_CONNECTION,
207 g_param_spec_object ("connection",
208 "Connection",
209 "The connection to export objects on",
210 G_TYPE_DBUS_CONNECTION,
211 G_PARAM_READABLE |
212 G_PARAM_WRITABLE |
213 G_PARAM_STATIC_STRINGS));
214  
215 /**
216 * GDBusObjectManagerServer:object-path:
217 *
218 * The object path to register the manager object at.
219 *
220 * Since: 2.30
221 */
222 g_object_class_install_property (gobject_class,
223 PROP_OBJECT_PATH,
224 g_param_spec_string ("object-path",
225 "Object Path",
226 "The object path to register the manager object at",
227 NULL,
228 G_PARAM_READABLE |
229 G_PARAM_WRITABLE |
230 G_PARAM_CONSTRUCT_ONLY |
231 G_PARAM_STATIC_STRINGS));
232 }
233  
234 static void
235 g_dbus_object_manager_server_init (GDBusObjectManagerServer *manager)
236 {
237 manager->priv = g_dbus_object_manager_server_get_instance_private (manager);
238 g_mutex_init (&manager->priv->lock);
239 manager->priv->map_object_path_to_data = g_hash_table_new_full (g_str_hash,
240 g_str_equal,
241 g_free,
242 (GDestroyNotify) registration_data_free);
243 }
244  
245 /**
246 * g_dbus_object_manager_server_new:
247 * @object_path: The object path to export the manager object at, which should
248 * not be `/`.
249 *
250 * Creates a new #GDBusObjectManagerServer object.
251 *
252 * The returned server isn't yet exported on any connection. To do so,
253 * use g_dbus_object_manager_server_set_connection(). Normally you
254 * want to export all of your objects before doing so to avoid
255 * [InterfacesAdded](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
256 * signals being emitted.
257 *
258 * Returns: A #GDBusObjectManagerServer object. Free with g_object_unref().
259 *
260 * Since: 2.30
261 */
262 GDBusObjectManagerServer *
263 g_dbus_object_manager_server_new (const gchar *object_path)
264 {
265 g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
266 return G_DBUS_OBJECT_MANAGER_SERVER (g_object_new (G_TYPE_DBUS_OBJECT_MANAGER_SERVER,
267 "object-path", object_path,
268 NULL));
269 }
270  
271 /**
272 * g_dbus_object_manager_server_set_connection:
273 * @manager: A #GDBusObjectManagerServer.
274 * @connection: (allow-none): A #GDBusConnection or %NULL.
275 *
276 * Exports all objects managed by @manager on @connection. If
277 * @connection is %NULL, stops exporting objects.
278 */
279 void
280 g_dbus_object_manager_server_set_connection (GDBusObjectManagerServer *manager,
281 GDBusConnection *connection)
282 {
283 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
284 g_return_if_fail (connection == NULL || G_IS_DBUS_CONNECTION (connection));
285  
286 g_mutex_lock (&manager->priv->lock);
287  
288 if (manager->priv->connection == connection)
289 {
290 g_mutex_unlock (&manager->priv->lock);
291 goto out;
292 }
293  
294 if (manager->priv->connection != NULL)
295 {
296 unexport_all (manager, FALSE);
297 g_object_unref (manager->priv->connection);
298 manager->priv->connection = NULL;
299 }
300  
301 manager->priv->connection = connection != NULL ? g_object_ref (connection) : NULL;
302 if (manager->priv->connection != NULL)
303 export_all (manager);
304  
305 g_mutex_unlock (&manager->priv->lock);
306  
307 g_object_notify (G_OBJECT (manager), "connection");
308 out:
309 ;
310 }
311  
312 /**
313 * g_dbus_object_manager_server_get_connection:
314 * @manager: A #GDBusObjectManagerServer
315 *
316 * Gets the #GDBusConnection used by @manager.
317 *
318 * Returns: (transfer full): A #GDBusConnection object or %NULL if
319 * @manager isn't exported on a connection. The returned object should
320 * be freed with g_object_unref().
321 *
322 * Since: 2.30
323 */
324 GDBusConnection *
325 g_dbus_object_manager_server_get_connection (GDBusObjectManagerServer *manager)
326 {
327 GDBusConnection *ret;
328 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), NULL);
329 g_mutex_lock (&manager->priv->lock);
330 ret = manager->priv->connection != NULL ? g_object_ref (manager->priv->connection) : NULL;
331 g_mutex_unlock (&manager->priv->lock);
332 return ret;
333 }
334  
335 /* ---------------------------------------------------------------------------------------------------- */
336  
337 static void
338 registration_data_export_interface (RegistrationData *data,
339 GDBusInterfaceSkeleton *interface_skeleton,
340 const gchar *object_path)
341 {
342 GDBusInterfaceInfo *info;
343 GError *error;
344  
345 info = g_dbus_interface_skeleton_get_info (interface_skeleton);
346 error = NULL;
347 if (data->manager->priv->connection != NULL)
348 {
349 if (!g_dbus_interface_skeleton_export (interface_skeleton,
350 data->manager->priv->connection,
351 object_path,
352 &error))
353 {
354 g_warning ("%s: Error registering object at %s with interface %s: %s",
355 G_STRLOC,
356 object_path,
357 info->name,
358 error->message);
359 g_error_free (error);
360 }
361 }
362  
363 g_assert (g_hash_table_lookup (data->map_iface_name_to_iface, info->name) == NULL);
364 g_hash_table_insert (data->map_iface_name_to_iface,
365 info->name,
366 g_object_ref (interface_skeleton));
367  
368 /* if we are already exported, then... */
369 if (data->exported)
370 {
371 const gchar *interfaces[2];
372 /* emit InterfacesAdded on the ObjectManager object */
373 interfaces[0] = info->name;
374 interfaces[1] = NULL;
375 g_dbus_object_manager_server_emit_interfaces_added (data->manager, data, interfaces, object_path);
376 }
377 }
378  
379 static void
380 registration_data_unexport_interface (RegistrationData *data,
381 GDBusInterfaceSkeleton *interface_skeleton)
382 {
383 GDBusInterfaceInfo *info;
384 GDBusInterfaceSkeleton *iface;
385  
386 info = g_dbus_interface_skeleton_get_info (interface_skeleton);
387 iface = g_hash_table_lookup (data->map_iface_name_to_iface, info->name);
388 g_assert (iface != NULL);
389  
390 if (data->manager->priv->connection != NULL)
391 g_dbus_interface_skeleton_unexport (iface);
392  
393 g_warn_if_fail (g_hash_table_remove (data->map_iface_name_to_iface, info->name));
394  
395 /* if we are already exported, then... */
396 if (data->exported)
397 {
398 const gchar *interfaces[2];
399 /* emit InterfacesRemoved on the ObjectManager object */
400 interfaces[0] = info->name;
401 interfaces[1] = NULL;
402 g_dbus_object_manager_server_emit_interfaces_removed (data->manager, data, interfaces);
403 }
404 }
405  
406 /* ---------------------------------------------------------------------------------------------------- */
407  
408 static void
409 on_interface_added (GDBusObject *object,
410 GDBusInterface *interface,
411 gpointer user_data)
412 {
413 RegistrationData *data = user_data;
414 const gchar *object_path;
415 g_mutex_lock (&data->manager->priv->lock);
416 object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
417 registration_data_export_interface (data, G_DBUS_INTERFACE_SKELETON (interface), object_path);
418 g_mutex_unlock (&data->manager->priv->lock);
419 }
420  
421 static void
422 on_interface_removed (GDBusObject *object,
423 GDBusInterface *interface,
424 gpointer user_data)
425 {
426 RegistrationData *data = user_data;
427 g_mutex_lock (&data->manager->priv->lock);
428 registration_data_unexport_interface (data, G_DBUS_INTERFACE_SKELETON (interface));
429 g_mutex_unlock (&data->manager->priv->lock);
430 }
431  
432 /* ---------------------------------------------------------------------------------------------------- */
433  
434  
435 static void
436 registration_data_free (RegistrationData *data)
437 {
438 GHashTableIter iter;
439 GDBusInterfaceSkeleton *iface;
440  
441 data->exported = FALSE;
442  
443 g_hash_table_iter_init (&iter, data->map_iface_name_to_iface);
444 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &iface))
445 {
446 if (data->manager->priv->connection != NULL)
447 g_dbus_interface_skeleton_unexport (iface);
448 }
449  
450 g_signal_handlers_disconnect_by_func (data->object, G_CALLBACK (on_interface_added), data);
451 g_signal_handlers_disconnect_by_func (data->object, G_CALLBACK (on_interface_removed), data);
452 g_object_unref (data->object);
453 g_hash_table_destroy (data->map_iface_name_to_iface);
454 g_free (data);
455 }
456  
457 /* ---------------------------------------------------------------------------------------------------- */
458  
459 static void
460 g_dbus_object_manager_server_export_unlocked (GDBusObjectManagerServer *manager,
461 GDBusObjectSkeleton *object,
462 const gchar *object_path)
463 {
464 RegistrationData *data;
465 GList *existing_interfaces;
466 GList *l;
467 GPtrArray *interface_names;
468  
469 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
470 g_return_if_fail (G_IS_DBUS_OBJECT (object));
471 g_return_if_fail (g_str_has_prefix (object_path, manager->priv->object_path_ending_in_slash));
472  
473 interface_names = g_ptr_array_new ();
474  
475 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
476 if (data != NULL)
477 g_dbus_object_manager_server_unexport_unlocked (manager, object_path);
478  
479 data = g_new0 (RegistrationData, 1);
480 data->object = g_object_ref (object);
481 data->manager = manager;
482 data->map_iface_name_to_iface = g_hash_table_new_full (g_str_hash,
483 g_str_equal,
484 NULL,
485 (GDestroyNotify) g_object_unref);
486  
487 g_signal_connect (object,
488 "interface-added",
489 G_CALLBACK (on_interface_added),
490 data);
491 g_signal_connect (object,
492 "interface-removed",
493 G_CALLBACK (on_interface_removed),
494 data);
495  
496 /* Register all known interfaces - note that data->exported is FALSE so
497 * we don't emit any InterfacesAdded signals.
498 */
499 existing_interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (object));
500 for (l = existing_interfaces; l != NULL; l = l->next)
501 {
502 GDBusInterfaceSkeleton *interface_skeleton = G_DBUS_INTERFACE_SKELETON (l->data);
503 registration_data_export_interface (data, interface_skeleton, object_path);
504 g_ptr_array_add (interface_names, g_dbus_interface_skeleton_get_info (interface_skeleton)->name);
505 }
506 g_list_free_full (existing_interfaces, g_object_unref);
507 g_ptr_array_add (interface_names, NULL);
508  
509 data->exported = TRUE;
510  
511 /* now emit InterfacesAdded() for all the interfaces */
512 g_dbus_object_manager_server_emit_interfaces_added (manager, data, (const gchar *const *) interface_names->pdata, object_path);
513 g_ptr_array_unref (interface_names);
514  
515 g_hash_table_insert (manager->priv->map_object_path_to_data,
516 g_strdup (object_path),
517 data);
518 }
519  
520 /**
521 * g_dbus_object_manager_server_export:
522 * @manager: A #GDBusObjectManagerServer.
523 * @object: A #GDBusObjectSkeleton.
524 *
525 * Exports @object on @manager.
526 *
527 * If there is already a #GDBusObject exported at the object path,
528 * then the old object is removed.
529 *
530 * The object path for @object must be in the hierarchy rooted by the
531 * object path for @manager.
532 *
533 * Note that @manager will take a reference on @object for as long as
534 * it is exported.
535 *
536 * Since: 2.30
537 */
538 void
539 g_dbus_object_manager_server_export (GDBusObjectManagerServer *manager,
540 GDBusObjectSkeleton *object)
541 {
542 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
543 g_mutex_lock (&manager->priv->lock);
544 g_dbus_object_manager_server_export_unlocked (manager, object,
545 g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
546 g_mutex_unlock (&manager->priv->lock);
547 }
548  
549 /**
550 * g_dbus_object_manager_server_export_uniquely:
551 * @manager: A #GDBusObjectManagerServer.
552 * @object: An object.
553 *
554 * Like g_dbus_object_manager_server_export() but appends a string of
555 * the form _N (with N being a natural number) to @object's object path
556 * if an object with the given path already exists. As such, the
557 * #GDBusObjectProxy:g-object-path property of @object may be modified.
558 *
559 * Since: 2.30
560 */
561 void
562 g_dbus_object_manager_server_export_uniquely (GDBusObjectManagerServer *manager,
563 GDBusObjectSkeleton *object)
564 {
565 gchar *orig_object_path;
566 gchar *object_path;
567 guint count;
568 gboolean modified;
569  
570 orig_object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
571  
572 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager));
573 g_return_if_fail (G_IS_DBUS_OBJECT (object));
574 g_return_if_fail (g_str_has_prefix (orig_object_path, manager->priv->object_path_ending_in_slash));
575  
576 g_mutex_lock (&manager->priv->lock);
577  
578 object_path = g_strdup (orig_object_path);
579 count = 1;
580 modified = FALSE;
581 while (TRUE)
582 {
583 RegistrationData *data;
584 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
585 if (data == NULL)
586 {
587 break;
588 }
589 g_free (object_path);
590 object_path = g_strdup_printf ("%s_%d", orig_object_path, count++);
591 modified = TRUE;
592 }
593  
594 g_dbus_object_manager_server_export_unlocked (manager, object, object_path);
595  
596 g_mutex_unlock (&manager->priv->lock);
597  
598 if (modified)
599 g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), object_path);
600  
601 g_free (object_path);
602 g_free (orig_object_path);
603  
604 }
605  
606 /**
607 * g_dbus_object_manager_server_is_exported:
608 * @manager: A #GDBusObjectManagerServer.
609 * @object: An object.
610 *
611 * Returns whether @object is currently exported on @manager.
612 *
613 * Returns: %TRUE if @object is exported
614 *
615 * Since: 2.34
616 **/
617 gboolean
618 g_dbus_object_manager_server_is_exported (GDBusObjectManagerServer *manager,
619 GDBusObjectSkeleton *object)
620 {
621 RegistrationData *data = NULL;
622 const gchar *object_path;
623 gboolean object_is_exported;
624  
625 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
626 g_return_val_if_fail (G_IS_DBUS_OBJECT (object), FALSE);
627  
628 g_mutex_lock (&manager->priv->lock);
629  
630 object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
631 if (object_path != NULL)
632 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
633 object_is_exported = (data != NULL);
634  
635 g_mutex_unlock (&manager->priv->lock);
636  
637 return object_is_exported;
638 }
639  
640 /* ---------------------------------------------------------------------------------------------------- */
641  
642 static gboolean
643 g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer *manager,
644 const gchar *object_path)
645 {
646 RegistrationData *data;
647 gboolean ret;
648  
649 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
650 g_return_val_if_fail (g_variant_is_object_path (object_path), FALSE);
651 g_return_val_if_fail (g_str_has_prefix (object_path, manager->priv->object_path_ending_in_slash), FALSE);
652  
653 ret = FALSE;
654  
655 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
656 if (data != NULL)
657 {
658 GPtrArray *interface_names;
659 GHashTableIter iter;
660 const gchar *iface_name;
661  
662 interface_names = g_ptr_array_new ();
663 g_hash_table_iter_init (&iter, data->map_iface_name_to_iface);
664 while (g_hash_table_iter_next (&iter, (gpointer) &iface_name, NULL))
665 g_ptr_array_add (interface_names, (gpointer) iface_name);
666 g_ptr_array_add (interface_names, NULL);
667 /* now emit InterfacesRemoved() for all the interfaces */
668 g_dbus_object_manager_server_emit_interfaces_removed (manager, data, (const gchar *const *) interface_names->pdata);
669 g_ptr_array_unref (interface_names);
670  
671 g_hash_table_remove (manager->priv->map_object_path_to_data, object_path);
672 ret = TRUE;
673 }
674  
675 return ret;
676 }
677  
678 /**
679 * g_dbus_object_manager_server_unexport:
680 * @manager: A #GDBusObjectManagerServer.
681 * @object_path: An object path.
682 *
683 * If @manager has an object at @path, removes the object. Otherwise
684 * does nothing.
685 *
686 * Note that @object_path must be in the hierarchy rooted by the
687 * object path for @manager.
688 *
689 * Returns: %TRUE if object at @object_path was removed, %FALSE otherwise.
690 *
691 * Since: 2.30
692 */
693 gboolean
694 g_dbus_object_manager_server_unexport (GDBusObjectManagerServer *manager,
695 const gchar *object_path)
696 {
697 gboolean ret;
698 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE);
699 g_mutex_lock (&manager->priv->lock);
700 ret = g_dbus_object_manager_server_unexport_unlocked (manager, object_path);
701 g_mutex_unlock (&manager->priv->lock);
702 return ret;
703 }
704  
705  
706 /* ---------------------------------------------------------------------------------------------------- */
707  
708 static const GDBusArgInfo manager_interfaces_added_signal_info_arg0 =
709 {
710 -1,
711 "object_path",
712 "o",
713 (GDBusAnnotationInfo**) NULL,
714 };
715  
716 static const GDBusArgInfo manager_interfaces_added_signal_info_arg1 =
717 {
718 -1,
719 "interfaces_and_properties",
720 "a{sa{sv}}",
721 (GDBusAnnotationInfo**) NULL,
722 };
723  
724 static const GDBusArgInfo * const manager_interfaces_added_signal_info_arg_pointers[] =
725 {
726 &manager_interfaces_added_signal_info_arg0,
727 &manager_interfaces_added_signal_info_arg1,
728 NULL
729 };
730  
731 static const GDBusSignalInfo manager_interfaces_added_signal_info =
732 {
733 -1,
734 "InterfacesAdded",
735 (GDBusArgInfo**) &manager_interfaces_added_signal_info_arg_pointers,
736 (GDBusAnnotationInfo**) NULL
737 };
738  
739 /* ---------- */
740  
741 static const GDBusArgInfo manager_interfaces_removed_signal_info_arg0 =
742 {
743 -1,
744 "object_path",
745 "o",
746 (GDBusAnnotationInfo**) NULL,
747 };
748  
749 static const GDBusArgInfo manager_interfaces_removed_signal_info_arg1 =
750 {
751 -1,
752 "interfaces",
753 "as",
754 (GDBusAnnotationInfo**) NULL,
755 };
756  
757 static const GDBusArgInfo * const manager_interfaces_removed_signal_info_arg_pointers[] =
758 {
759 &manager_interfaces_removed_signal_info_arg0,
760 &manager_interfaces_removed_signal_info_arg1,
761 NULL
762 };
763  
764 static const GDBusSignalInfo manager_interfaces_removed_signal_info =
765 {
766 -1,
767 "InterfacesRemoved",
768 (GDBusArgInfo**) &manager_interfaces_removed_signal_info_arg_pointers,
769 (GDBusAnnotationInfo**) NULL
770 };
771  
772 /* ---------- */
773  
774 static const GDBusSignalInfo * const manager_signal_info_pointers[] =
775 {
776 &manager_interfaces_added_signal_info,
777 &manager_interfaces_removed_signal_info,
778 NULL
779 };
780  
781 /* ---------- */
782  
783 static const GDBusArgInfo manager_get_all_method_info_out_arg0 =
784 {
785 -1,
786 "object_paths_interfaces_and_properties",
787 "a{oa{sa{sv}}}",
788 (GDBusAnnotationInfo**) NULL,
789 };
790  
791 static const GDBusArgInfo * const manager_get_all_method_info_out_arg_pointers[] =
792 {
793 &manager_get_all_method_info_out_arg0,
794 NULL
795 };
796  
797 static const GDBusMethodInfo manager_get_all_method_info =
798 {
799 -1,
800 "GetManagedObjects",
801 (GDBusArgInfo**) NULL,
802 (GDBusArgInfo**) &manager_get_all_method_info_out_arg_pointers,
803 (GDBusAnnotationInfo**) NULL
804 };
805  
806 static const GDBusMethodInfo * const manager_method_info_pointers[] =
807 {
808 &manager_get_all_method_info,
809 NULL
810 };
811  
812 /* ---------- */
813  
814 static const GDBusInterfaceInfo manager_interface_info =
815 {
816 -1,
817 "org.freedesktop.DBus.ObjectManager",
818 (GDBusMethodInfo **) manager_method_info_pointers,
819 (GDBusSignalInfo **) manager_signal_info_pointers,
820 (GDBusPropertyInfo **) NULL,
821 (GDBusAnnotationInfo **) NULL
822 };
823  
824 static void
825 manager_method_call (GDBusConnection *connection,
826 const gchar *sender,
827 const gchar *object_path,
828 const gchar *interface_name,
829 const gchar *method_name,
830 GVariant *parameters,
831 GDBusMethodInvocation *invocation,
832 gpointer user_data)
833 {
834 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (user_data);
835 GVariantBuilder array_builder;
836 GHashTableIter object_iter;
837 RegistrationData *data;
838  
839 g_mutex_lock (&manager->priv->lock);
840  
841 if (g_strcmp0 (method_name, "GetManagedObjects") == 0)
842 {
843 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a{oa{sa{sv}}}"));
844 g_hash_table_iter_init (&object_iter, manager->priv->map_object_path_to_data);
845 while (g_hash_table_iter_next (&object_iter, NULL, (gpointer) &data))
846 {
847 GVariantBuilder interfaces_builder;
848 GHashTableIter interface_iter;
849 GDBusInterfaceSkeleton *iface;
850 const gchar *iter_object_path;
851  
852 g_variant_builder_init (&interfaces_builder, G_VARIANT_TYPE ("a{sa{sv}}"));
853 g_hash_table_iter_init (&interface_iter, data->map_iface_name_to_iface);
854 while (g_hash_table_iter_next (&interface_iter, NULL, (gpointer) &iface))
855 {
856 GVariant *properties = g_dbus_interface_skeleton_get_properties (iface);
857 g_variant_builder_add (&interfaces_builder, "{s@a{sv}}",
858 g_dbus_interface_skeleton_get_info (iface)->name,
859 properties);
860 g_variant_unref (properties);
861 }
862 iter_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
863 g_variant_builder_add (&array_builder,
864 "{oa{sa{sv}}}",
865 iter_object_path,
866 &interfaces_builder);
867 }
868  
869 g_dbus_method_invocation_return_value (invocation,
870 g_variant_new ("(a{oa{sa{sv}}})",
871 &array_builder));
872 }
873 else
874 {
875 g_dbus_method_invocation_return_error (invocation,
876 G_DBUS_ERROR,
877 G_DBUS_ERROR_UNKNOWN_METHOD,
878 "Unknown method %s - only GetManagedObjects() is supported",
879 method_name);
880 }
881 g_mutex_unlock (&manager->priv->lock);
882 }
883  
884 static const GDBusInterfaceVTable manager_interface_vtable =
885 {
886 manager_method_call, /* handle_method_call */
887 NULL, /* get_property */
888 NULL /* set_property */
889 };
890  
891 /* ---------------------------------------------------------------------------------------------------- */
892  
893 static void
894 g_dbus_object_manager_server_constructed (GObject *object)
895 {
896 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (object);
897  
898 if (manager->priv->connection != NULL)
899 export_all (manager);
900  
901 if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->constructed != NULL)
902 G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->constructed (object);
903 }
904  
905 static void
906 g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager,
907 RegistrationData *data,
908 const gchar *const *interfaces,
909 const gchar *object_path)
910 {
911 GVariantBuilder array_builder;
912 GError *error;
913 guint n;
914  
915 if (data->manager->priv->connection == NULL)
916 goto out;
917  
918 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a{sa{sv}}"));
919 for (n = 0; interfaces[n] != NULL; n++)
920 {
921 GDBusInterfaceSkeleton *iface;
922 GVariant *properties;
923  
924 iface = g_hash_table_lookup (data->map_iface_name_to_iface, interfaces[n]);
925 g_assert (iface != NULL);
926 properties = g_dbus_interface_skeleton_get_properties (iface);
927 g_variant_builder_add (&array_builder, "{s@a{sv}}", interfaces[n], properties);
928 g_variant_unref (properties);
929 }
930  
931 error = NULL;
932 g_dbus_connection_emit_signal (data->manager->priv->connection,
933 NULL, /* destination_bus_name */
934 manager->priv->object_path,
935 manager_interface_info.name,
936 "InterfacesAdded",
937 g_variant_new ("(oa{sa{sv}})",
938 object_path,
939 &array_builder),
940 &error);
941 if (error)
942 {
943 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
944 g_warning ("Couldn't emit InterfacesAdded signal: %s", error->message);
945 g_error_free (error);
946 }
947 out:
948 ;
949 }
950  
951 static void
952 g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager,
953 RegistrationData *data,
954 const gchar *const *interfaces)
955 {
956 GVariantBuilder array_builder;
957 GError *error;
958 guint n;
959 const gchar *object_path;
960  
961 if (data->manager->priv->connection == NULL)
962 goto out;
963  
964 g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("as"));
965 for (n = 0; interfaces[n] != NULL; n++)
966 g_variant_builder_add (&array_builder, "s", interfaces[n]);
967  
968 error = NULL;
969 object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object));
970 g_dbus_connection_emit_signal (data->manager->priv->connection,
971 NULL, /* destination_bus_name */
972 manager->priv->object_path,
973 manager_interface_info.name,
974 "InterfacesRemoved",
975 g_variant_new ("(oas)",
976 object_path,
977 &array_builder),
978 &error);
979 if (error)
980 {
981 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
982 g_warning ("Couldn't emit InterfacesRemoved signal: %s", error->message);
983 g_error_free (error);
984 }
985 out:
986 ;
987 }
988  
989 /* ---------------------------------------------------------------------------------------------------- */
990  
991 static GList *
992 g_dbus_object_manager_server_get_objects (GDBusObjectManager *_manager)
993 {
994 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
995 GList *ret;
996 GHashTableIter iter;
997 RegistrationData *data;
998  
999 g_mutex_lock (&manager->priv->lock);
1000  
1001 ret = NULL;
1002 g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1003 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data))
1004 {
1005 ret = g_list_prepend (ret, g_object_ref (data->object));
1006 }
1007  
1008 g_mutex_unlock (&manager->priv->lock);
1009  
1010 return ret;
1011 }
1012  
1013 static const gchar *
1014 g_dbus_object_manager_server_get_object_path (GDBusObjectManager *_manager)
1015 {
1016 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
1017 return manager->priv->object_path;
1018 }
1019  
1020 static GDBusObject *
1021 g_dbus_object_manager_server_get_object (GDBusObjectManager *_manager,
1022 const gchar *object_path)
1023 {
1024 GDBusObjectManagerServer *manager = G_DBUS_OBJECT_MANAGER_SERVER (_manager);
1025 GDBusObject *ret;
1026 RegistrationData *data;
1027  
1028 ret = NULL;
1029  
1030 g_mutex_lock (&manager->priv->lock);
1031 data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path);
1032 if (data != NULL)
1033 ret = g_object_ref (data->object);
1034 g_mutex_unlock (&manager->priv->lock);
1035  
1036 return ret;
1037 }
1038  
1039 static GDBusInterface *
1040 g_dbus_object_manager_server_get_interface (GDBusObjectManager *_manager,
1041 const gchar *object_path,
1042 const gchar *interface_name)
1043 {
1044 GDBusInterface *ret;
1045 GDBusObject *object;
1046  
1047 ret = NULL;
1048  
1049 object = g_dbus_object_manager_get_object (_manager, object_path);
1050 if (object == NULL)
1051 goto out;
1052  
1053 ret = g_dbus_object_get_interface (object, interface_name);
1054 g_object_unref (object);
1055  
1056 out:
1057 return ret;
1058 }
1059  
1060 static void
1061 dbus_object_manager_interface_init (GDBusObjectManagerIface *iface)
1062 {
1063 iface->get_object_path = g_dbus_object_manager_server_get_object_path;
1064 iface->get_objects = g_dbus_object_manager_server_get_objects;
1065 iface->get_object = g_dbus_object_manager_server_get_object;
1066 iface->get_interface = g_dbus_object_manager_server_get_interface;
1067 }
1068  
1069 /* ---------------------------------------------------------------------------------------------------- */
1070  
1071 static void
1072 export_all (GDBusObjectManagerServer *manager)
1073 {
1074 GHashTableIter iter;
1075 const gchar *object_path;
1076 RegistrationData *data;
1077 GHashTableIter iface_iter;
1078 GDBusInterfaceSkeleton *iface;
1079 GError *error;
1080  
1081 g_return_if_fail (manager->priv->connection != NULL);
1082  
1083 error = NULL;
1084 g_warn_if_fail (manager->priv->manager_reg_id == 0);
1085 manager->priv->manager_reg_id = g_dbus_connection_register_object (manager->priv->connection,
1086 manager->priv->object_path,
1087 (GDBusInterfaceInfo *) &manager_interface_info,
1088 &manager_interface_vtable,
1089 manager,
1090 NULL, /* user_data_free_func */
1091 &error);
1092 if (manager->priv->manager_reg_id == 0)
1093 {
1094 g_warning ("%s: Error registering manager at %s: %s",
1095 G_STRLOC,
1096 manager->priv->object_path,
1097 error->message);
1098 g_error_free (error);
1099 }
1100  
1101 g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1102 while (g_hash_table_iter_next (&iter, (gpointer) &object_path, (gpointer) &data))
1103 {
1104 g_hash_table_iter_init (&iface_iter, data->map_iface_name_to_iface);
1105 while (g_hash_table_iter_next (&iface_iter, NULL, (gpointer) &iface))
1106 {
1107 g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface) == NULL);
1108 error = NULL;
1109 if (!g_dbus_interface_skeleton_export (iface,
1110 manager->priv->connection,
1111 object_path,
1112 &error))
1113 {
1114 g_warning ("%s: Error registering object at %s with interface %s: %s",
1115 G_STRLOC,
1116 object_path,
1117 g_dbus_interface_skeleton_get_info (iface)->name,
1118 error->message);
1119 g_error_free (error);
1120 }
1121 }
1122 }
1123 }
1124  
1125 static void
1126 unexport_all (GDBusObjectManagerServer *manager, gboolean only_manager)
1127 {
1128 GHashTableIter iter;
1129 RegistrationData *data;
1130 GHashTableIter iface_iter;
1131 GDBusInterfaceSkeleton *iface;
1132  
1133 g_return_if_fail (manager->priv->connection != NULL);
1134  
1135 g_warn_if_fail (manager->priv->manager_reg_id > 0);
1136 if (manager->priv->manager_reg_id > 0)
1137 {
1138 g_warn_if_fail (g_dbus_connection_unregister_object (manager->priv->connection,
1139 manager->priv->manager_reg_id));
1140 manager->priv->manager_reg_id = 0;
1141 }
1142 if (only_manager)
1143 goto out;
1144  
1145 g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data);
1146 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data))
1147 {
1148 g_hash_table_iter_init (&iface_iter, data->map_iface_name_to_iface);
1149 while (g_hash_table_iter_next (&iface_iter, NULL, (gpointer) &iface))
1150 {
1151 g_warn_if_fail (g_dbus_interface_skeleton_get_connection (iface) != NULL);
1152 g_dbus_interface_skeleton_unexport (iface);
1153 }
1154 }
1155 out:
1156 ;
1157 }
1158  
1159 /* ---------------------------------------------------------------------------------------------------- */