[evolution-data-server/dbus-hybrid: 8/9] Port libedata-book to DBus



commit 588f6518d28988ad185cb22fd132f494a917af14
Author: Ross Burton <ross linux intel com>
Date:   Mon Jun 15 08:54:43 2009 +0100

    Port libedata-book to DBus

 addressbook/libedata-book/Makefile.am              |   68 +-
 addressbook/libedata-book/e-book-backend-sync.h    |    1 -
 addressbook/libedata-book/e-book-backend.c         |   60 +-
 addressbook/libedata-book/e-book-backend.h         |    3 +-
 addressbook/libedata-book/e-data-book-factory.c    |  665 ++++-------
 addressbook/libedata-book/e-data-book-factory.h    |   51 +-
 addressbook/libedata-book/e-data-book-types.h      |   99 ++-
 addressbook/libedata-book/e-data-book-view.c       |  790 ++++++-------
 addressbook/libedata-book/e-data-book-view.h       |   48 +-
 addressbook/libedata-book/e-data-book.c            | 1293 ++++++++------------
 addressbook/libedata-book/e-data-book.h            |  156 ++--
 addressbook/libedata-book/glib-gen.mak             |   42 +
 addressbook/libedata-book/libedata-book.pc.in      |    5 +-
 addressbook/libedata-book/opid.c                   |   75 ++
 addressbook/libedata-book/opid.h                   |   28 +
 ...ome.evolution.dataserver.AddressBook.service.in |    3 +
 16 files changed, 1540 insertions(+), 1847 deletions(-)
---
diff --git a/addressbook/libedata-book/Makefile.am b/addressbook/libedata-book/Makefile.am
index 2865c39..9eb5b9f 100644
--- a/addressbook/libedata-book/Makefile.am
+++ b/addressbook/libedata-book/Makefile.am
@@ -1,36 +1,27 @@
 INCLUDES =						\
 	-DG_LOG_DOMAIN=\"libedata-book\"		\
+	-DLIBEXECDIR=\"$(libexecdir)\"			\
 	-I$(top_srcdir)					\
 	-I$(top_builddir)				\
 	-I$(top_srcdir)/addressbook			\
 	-I$(top_builddir)/addressbook			\
 	$(DB_CFLAGS)					\
-        $(EVOLUTION_ADDRESSBOOK_CFLAGS)
+	$(EVOLUTION_ADDRESSBOOK_CFLAGS)
 
-# The corba stubs and skels
-CORBA_GENERATED_C =				\
-	Evolution-DataServer-Addressbook-common.c		\
-	Evolution-DataServer-Addressbook-skels.c		\
-	Evolution-DataServer-Addressbook-stubs.c
-CORBA_GENERATED_H =			\
-	Evolution-DataServer-Addressbook.h
-
-CORBA_GENERATED = $(CORBA_GENERATED_C) $(CORBA_GENERATED_H)
+# The library
+lib_LTLIBRARIES = libedata-book-1.2.la
 
-idls =						\
-	$(srcdir)/../idl/Evolution-DataServer-Addressbook.idl
+DBUS_GENERATED_H = e-data-book-glue.h e-data-book-factory-glue.h e-data-book-view-glue.h
 
-idl_flags = $(IDL_INCLUDES)
+include glib-gen.mak
+glib_enum_headers=e-data-book-types.h
+glib_enum_define=E_DATA_BOOK
+glib_enum_prefix=e_data_book
 
-$(CORBA_GENERATED_H): $(idls)
-	$(ORBIT_IDL) $(idl_flags) $(srcdir)/../idl/Evolution-DataServer-Addressbook.idl
-$(CORBA_GENERATED_C): $(CORBA_GENERATED_H)
-
-# The library
-lib_LTLIBRARIES = libedata-book-1.2.la
+ENUM_GENERATED = e-data-book-enumtypes.h e-data-book-enumtypes.c
 
 libedata_book_1_2_la_SOURCES =				\
-	$(CORBA_GENERATED_C)				\
+	$(DBUS_GENERATED_H)				\
 	e-book-backend-factory.c			\
 	e-book-backend-sexp.c				\
 	e-book-backend-summary.c			\
@@ -38,10 +29,11 @@ libedata_book_1_2_la_SOURCES =				\
 	e-book-backend-db-cache.c                       \
 	e-book-backend-sync.c				\
 	e-book-backend.c				\
-	e-data-book-factory.c				\
 	e-data-book-view.c				\
 	e-data-book.c					\
-	ximian-vcard.h
+	ximian-vcard.h					\
+	opid.c opid.h					\
+	$(ENUM_GENERATED)
 
 libedata_book_1_2_la_LIBADD =					\
 	$(top_builddir)/addressbook/libebook/libebook-1.2.la	\
@@ -56,7 +48,6 @@ libedata_book_1_2_la_LDFLAGS = \
 libedata_bookincludedir = $(privincludedir)/libedata-book
 
 libedata_bookinclude_HEADERS =				\
-	$(CORBA_GENERATED_H)				\
 	e-book-backend-factory.h			\
 	e-book-backend-sexp.h				\
 	e-book-backend-summary.h			\
@@ -75,12 +66,37 @@ libedata_bookinclude_HEADERS =				\
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libedata-book-$(API_VERSION).pc
 
-BUILT_SOURCES = $(CORBA_GENERATED)
-CLEANFILES = $(BUILT_SOURCES)
+service_in_files = org.gnome.evolution.dataserver.AddressBook.service.in
+servicedir = $(datadir)/dbus-1/services
+service_DATA = $(service_in_files:.service.in=.service)
+ EVO_SUBST_SERVICE_RULE@
+
+BUILT_SOURCES = $(DBUS_GENERATED_H)
+CLEANFILES = $(BUILT_SOURCES) $(service_DATA)
 DISTCLEANFILES = $(pkgconfig_DATA)
 
 EXTRA_DIST = 						\
-	$(pkgconfig_DATA:-$(API_VERSION).pc=.pc.in)
+	e-data-book-factory.xml				\
+	e-data-book-view.xml				\
+	e-data-book.xml					\
+	$(pkgconfig_DATA:-$(API_VERSION).pc=.pc.in)	\
+	$(service_in_files)
 
 dist-hook:
 	cd $(distdir); rm -f $(BUILT_SOURCES)
+
+%-glue.h: %.xml
+	dbus-binding-tool --mode=glib-server --output=$@ --prefix=$(subst -,_,$*) $^
+
+%-bindings.h: %.xml
+	dbus-binding-tool --mode=glib-client --output=$@ --prefix=$(subst -,_,$*) $^
+
+
+DBUS_BINDINGS = e-data-book-factory-bindings.h e-data-book-bindings.h e-data-book-view-bindings.h
+BUILT_SOURCES += $(DBUS_BINDINGS) $(ENUM_GENERATED)
+
+factorydir = $(libexecdir)
+factory_PROGRAMS = e-addressbook-factory
+
+e_addressbook_factory_SOURCES = e-data-book-factory.c e-data-book-factory.h
+e_addressbook_factory_LDADD = libedata-book-1.2.la
diff --git a/addressbook/libedata-book/e-book-backend-sync.h b/addressbook/libedata-book/e-book-backend-sync.h
index b51d461..589fa62 100644
--- a/addressbook/libedata-book/e-book-backend-sync.h
+++ b/addressbook/libedata-book/e-book-backend-sync.h
@@ -6,7 +6,6 @@
 #define __E_BOOK_BACKEND_SYNC_H__
 
 #include <glib.h>
-#include <libedata-book/Evolution-DataServer-Addressbook.h>
 #include <libedata-book/e-data-book-types.h>
 #include <libedata-book/e-book-backend.h>
 
diff --git a/addressbook/libedata-book/e-book-backend.c b/addressbook/libedata-book/e-book-backend.c
index 2468180..bb2a866 100644
--- a/addressbook/libedata-book/e-book-backend.c
+++ b/addressbook/libedata-book/e-book-backend.c
@@ -9,6 +9,7 @@
 #include <config.h>
 
 #include "e-data-book-view.h"
+#include "e-data-book.h"
 #include "e-book-backend.h"
 
 struct _EBookBackendPrivate {
@@ -571,12 +572,7 @@ e_book_backend_add_client (EBookBackend      *backend,
 	g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), FALSE);
 	g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
 
-	bonobo_object_set_immortal (BONOBO_OBJECT (book), TRUE);
-
 	g_object_weak_ref (G_OBJECT (book), book_destroy_cb, backend);
-
-	ORBit_small_listen_for_broken (e_data_book_get_listener (book), G_CALLBACK (listener_died_cb), book);
-
 	g_mutex_lock (backend->priv->clients_mutex);
 	backend->priv->clients = g_list_prepend (backend->priv->clients, book);
 	g_mutex_unlock (backend->priv->clients_mutex);
@@ -629,29 +625,7 @@ e_book_backend_remove_client (EBookBackend *backend,
 gboolean
 e_book_backend_has_out_of_proc_clients (EBookBackend *backend)
 {
-	GList *l;
-
-	g_mutex_lock (backend->priv->clients_mutex);
-
-	if (!backend->priv->clients) {
-		g_mutex_unlock (backend->priv->clients_mutex);
-
-		return FALSE;
-	}
-
-	for (l = backend->priv->clients; l; l = l->next) {
-		if (ORBit_small_get_connection_status (e_data_book_get_listener (l->data)) != ORBIT_CONNECTION_IN_PROC) {
-			g_mutex_unlock (backend->priv->clients_mutex);
-
-			return TRUE;
-		}
-	}
-
-	g_mutex_unlock (backend->priv->clients_mutex);
-
-	/* If we get here, all remaining clients are in proc */
-
-	return FALSE;
+	return TRUE;
 }
 
 /**
@@ -815,13 +789,13 @@ e_book_backend_sync (EBookBackend *backend)
  *
  * Return value: A new #GNOME_Evolution_Addressbook_BookChangeItem.
  **/
-GNOME_Evolution_Addressbook_BookChangeItem*
-e_book_backend_change_add_new     (const gchar *vcard)
+EDataBookChange *
+e_book_backend_change_add_new     (const char *vcard)
 {
-	GNOME_Evolution_Addressbook_BookChangeItem* new_change = GNOME_Evolution_Addressbook_BookChangeItem__alloc();
+  EDataBookChange *new_change = g_new (EDataBookChange, 1);
 
-	new_change->changeType= GNOME_Evolution_Addressbook_ContactAdded;
-	new_change->vcard = CORBA_string_dup (vcard);
+	new_change->change_type = E_DATA_BOOK_BACKEND_CHANGE_ADDED;
+	new_change->vcard = g_strdup (vcard);
 
 	return new_change;
 }
@@ -835,13 +809,13 @@ e_book_backend_change_add_new     (const gchar *vcard)
  *
  * Return value: A new #GNOME_Evolution_Addressbook_BookChangeItem.
  **/
-GNOME_Evolution_Addressbook_BookChangeItem*
-e_book_backend_change_modify_new  (const gchar *vcard)
+EDataBookChange *
+e_book_backend_change_modify_new  (const char *vcard)
 {
-	GNOME_Evolution_Addressbook_BookChangeItem* new_change = GNOME_Evolution_Addressbook_BookChangeItem__alloc();
+  EDataBookChange *new_change = g_new (EDataBookChange, 1);
 
-	new_change->changeType= GNOME_Evolution_Addressbook_ContactModified;
-	new_change->vcard = CORBA_string_dup (vcard);
+	new_change->change_type = E_DATA_BOOK_BACKEND_CHANGE_MODIFIED;
+	new_change->vcard = g_strdup (vcard);
 
 	return new_change;
 }
@@ -855,13 +829,13 @@ e_book_backend_change_modify_new  (const gchar *vcard)
  *
  * Return value: A new #GNOME_Evolution_Addressbook_BookChangeItem.
  **/
-GNOME_Evolution_Addressbook_BookChangeItem*
-e_book_backend_change_delete_new  (const gchar *vcard)
+EDataBookChange *
+e_book_backend_change_delete_new  (const char *vcard)
 {
-	GNOME_Evolution_Addressbook_BookChangeItem* new_change = GNOME_Evolution_Addressbook_BookChangeItem__alloc();
+  EDataBookChange *new_change = g_new (EDataBookChange, 1);
 
-	new_change->changeType= GNOME_Evolution_Addressbook_ContactDeleted;
-	new_change->vcard = CORBA_string_dup (vcard);
+	new_change->change_type = E_DATA_BOOK_BACKEND_CHANGE_DELETED;
+	new_change->vcard = g_strdup (vcard);
 
 	return new_change;
 }
diff --git a/addressbook/libedata-book/e-book-backend.h b/addressbook/libedata-book/e-book-backend.h
index 3f4beee..276d8c3 100644
--- a/addressbook/libedata-book/e-book-backend.h
+++ b/addressbook/libedata-book/e-book-backend.h
@@ -25,9 +25,10 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <libebook/e-contact.h>
-#include <libedata-book/Evolution-DataServer-Addressbook.h>
 #include <libedata-book/e-data-book-types.h>
 #include <libedata-book/e-data-book.h>
+#include <libedataserver/e-list.h>
+#include <libedataserver/e-source.h>
 
 G_BEGIN_DECLS
 
diff --git a/addressbook/libedata-book/e-data-book-factory.c b/addressbook/libedata-book/e-data-book-factory.c
index 21f2266..a3bd588 100644
--- a/addressbook/libedata-book/e-data-book-factory.c
+++ b/addressbook/libedata-book/e-data-book-factory.c
@@ -1,82 +1,87 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
  *
- * Author:
- *   Nat Friedman (nat ximian com)
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
  *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ross Burton <ross linux intel com>
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-#endif
-
+#include <stdlib.h>
 #include <string.h>
-
-#include <bonobo-activation/bonobo-activation.h>
-#include <bonobo/bonobo-main.h>
-#include <bonobo/bonobo-arg.h>
-#include "libebackend/e-data-server-module.h"
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <dbus/dbus-protocol.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <libebackend/e-data-server-module.h>
+#include "e-book-backend-factory.h"
 #include "e-data-book-factory.h"
+#include "e-data-book.h"
+#include "e-book-backend.h"
+#include "e-book-backend-factory.h"
 
-#include <backends/groupwise/e-book-backend-groupwise.h>
+static void impl_BookFactory_getBook(EDataBookFactory *factory, const char *IN_uri, DBusGMethodInvocation *context);
+#include "e-data-book-factory-glue.h"
 
-#define DEFAULT_E_DATA_BOOK_FACTORY_OAF_ID "OAFIID:GNOME_Evolution_DataServer_BookFactory:" BASE_VERSION
+static gchar *nm_dbus_escape_object_path (const gchar *utf8_string);
 
-static BonoboObjectClass          *e_data_book_factory_parent_class;
+static GMainLoop *loop;
+static EDataBookFactory *factory;
+extern DBusGConnection *connection;
 
-typedef struct {
-	gchar                                     *uri;
-	GNOME_Evolution_Addressbook_BookListener  listener;
-} EDataBookFactoryQueuedRequest;
+/* Convenience macro to test and set a GError/return on failure */
+#define g_set_error_val_if_fail(test, returnval, error, domain, code) G_STMT_START{ \
+		if G_LIKELY (test) {} else {				\
+			g_set_error (error, domain, code, #test);	\
+			g_warning(#test " failed");			\
+			return (returnval);				\
+		}							\
+	}G_STMT_END
 
-struct _EDataBookFactoryPrivate {
-	GMutex *map_mutex;
+G_DEFINE_TYPE(EDataBookFactory, e_data_book_factory, G_TYPE_OBJECT);
+
+#define E_DATA_BOOK_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_DATA_BOOK_FACTORY, EDataBookFactoryPrivate))
 
+struct _EDataBookFactoryPrivate {
+	/* TODO: as the factory is not threaded these locks could be removed */
+	GMutex *backend_lock;
 	GHashTable *backends;
-	GHashTable *active_server_map;
 
-	/* OAFIID of the factory */
-	gchar *iid;
+	GMutex *books_lock;
+	/* A hash of object paths for book URIs to EDataBooks */
+	GHashTable *books;
 
-	/* Whether the factory has been registered with OAF yet */
-	guint       registered : 1;
+	GMutex *connections_lock;
+	/* This is a hash of client addresses to GList* of EDataBooks */
+	GHashTable *connections;
 
-	gint mode;
+	guint exit_timeout;
 };
 
-/* Signal IDs */
-enum {
-	LAST_BOOK_GONE,
-	LAST_SIGNAL
-};
-
-static guint factory_signals[LAST_SIGNAL];
-
-static gchar *
-e_data_book_factory_canonicalize_uri (const gchar *uri)
+/* Create the EDataBookFactory error quark */
+GQuark
+e_data_book_factory_error_quark (void)
 {
-	/* FIXME: What do I do here? */
-
-	return g_strdup (uri);
-}
-
-static gchar *
-e_data_book_factory_extract_proto_from_uri (const gchar *uri)
-{
-	gchar *proto;
-	gchar *p;
-
-	p = strchr (uri, ':');
-
-	if (p == NULL)
-		return NULL;
-
-	proto = g_malloc0 (p - uri + 1);
-
-	strncpy (proto, uri, p - uri);
-
-	return proto;
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("e_data_book_factory_error");
+	return quark;
 }
 
 /**
@@ -86,7 +91,7 @@ e_data_book_factory_extract_proto_from_uri (const gchar *uri)
  *
  * Registers @backend_factory with @factory.
  **/
-void
+static void
 e_data_book_factory_register_backend (EDataBookFactory      *book_factory,
 				      EBookBackendFactory   *backend_factory)
 {
@@ -106,46 +111,6 @@ e_data_book_factory_register_backend (EDataBookFactory      *book_factory,
 			     g_strdup (proto), backend_factory);
 }
 
-static void
-out_of_proc_check (gpointer key, gpointer value, gpointer data)
-{
-	gboolean *out_of_proc = data;
-
-	if ((*out_of_proc))
-	    return;
-
-	*out_of_proc = e_book_backend_has_out_of_proc_clients (value);
-}
-
-/**
- * e_data_book_factory_get_n_backends:
- * @factory: An addressbook factory.
- *
- * Queries the number of running addressbook backends in an addressbook factory.
- *
- * Return value: Number of running backends.
- **/
-gint
-e_data_book_factory_get_n_backends (EDataBookFactory *factory)
-{
-	gint n_backends;
-	gboolean out_of_proc = FALSE;
-
-	g_return_val_if_fail (factory != NULL, -1);
-	g_return_val_if_fail (E_IS_DATA_BOOK_FACTORY (factory), -1);
-
-	g_mutex_lock (factory->priv->map_mutex);
-	g_hash_table_foreach (factory->priv->active_server_map, out_of_proc_check, &out_of_proc);
-
-	if (!out_of_proc)
-		n_backends = 0;
-	else
-		n_backends = g_hash_table_size (factory->priv->active_server_map);
-	g_mutex_unlock (factory->priv->map_mutex);
-
-	return n_backends;
-}
-
 /**
  * e_data_book_factory_register_backends:
  * @book_factory: an #EDataBookFactory
@@ -153,7 +118,7 @@ e_data_book_factory_get_n_backends (EDataBookFactory *factory)
  * Register the backends supported by the Evolution Data Server,
  * with @book_factory.
  **/
-void
+static void
 e_data_book_factory_register_backends (EDataBookFactory *book_factory)
 {
 	GList *factories, *f;
@@ -166,72 +131,47 @@ e_data_book_factory_register_backends (EDataBookFactory *book_factory)
 	}
 
 	e_data_server_extension_list_free (factories);
+	e_data_server_module_remove_unused ();
 }
 
 static void
-dump_active_server_map_entry (gpointer key, gpointer value, gpointer data)
+e_data_book_factory_class_init (EDataBookFactoryClass *e_data_book_factory_class)
 {
-	gchar *uri;
-	EBookBackend *backend;
-
-	uri = key;
-	backend = E_BOOK_BACKEND (value);
-
-	g_message ("  %s: %p", uri, (gpointer) backend);
-}
-
-/**
- * e_data_book_factory_dump_active_backends:
- * @factory: an #EDataBookFactory
- *
- * Dump the list of active backends registered with @factory
- * to stdout. This is a debugging function.
- **/
-void
-e_data_book_factory_dump_active_backends (EDataBookFactory *factory)
-{
-	g_message ("Active PAS backends");
-
-	g_mutex_lock (factory->priv->map_mutex);
-	g_hash_table_foreach (factory->priv->active_server_map,
-			      dump_active_server_map_entry,
-			      NULL);
-	g_mutex_unlock (factory->priv->map_mutex);
+	g_type_class_add_private (e_data_book_factory_class, sizeof (EDataBookFactoryPrivate));
+	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (e_data_book_factory_class), &dbus_glib_e_data_book_factory_object_info);
 }
 
-/* Callback used when a backend loses its last connected client */
+/* Instance init */
 static void
-backend_last_client_gone_cb (EBookBackend *backend, gpointer data)
+e_data_book_factory_init (EDataBookFactory *factory)
 {
-	EDataBookFactory *factory;
-	ESource *source;
-	gchar *uri;
+	factory->priv = E_DATA_BOOK_FACTORY_GET_PRIVATE (factory);
 
-	factory = E_DATA_BOOK_FACTORY (data);
+	factory->priv->backend_lock = g_mutex_new ();
+	factory->priv->backends = g_hash_table_new (g_str_hash, g_str_equal);
 
-	/* Remove the backend from the active server map */
+	factory->priv->books_lock = g_mutex_new ();
+	factory->priv->books = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
-	source = e_book_backend_get_source (backend);
-	if (source)
-		uri = e_source_get_uri (source);
-	else
-		uri = NULL;
+	factory->priv->connections_lock = g_mutex_new ();
+	factory->priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
-	if (uri) {
-		g_mutex_lock (factory->priv->map_mutex);
-		g_hash_table_remove (factory->priv->active_server_map, uri);
-		g_mutex_unlock (factory->priv->map_mutex);
-	}
-
-	if (g_hash_table_size (factory->priv->active_server_map) == 0) {
-		/* Notify upstream if there are no more backends */
-		g_signal_emit (G_OBJECT (factory), factory_signals[LAST_BOOK_GONE], 0);
-	}
-
-	g_free (uri);
+	e_data_server_module_init ();
+	e_data_book_factory_register_backends (factory);
 }
 
-
+/* TODO: write dispose to kill hash */
+static char *
+e_data_book_factory_extract_proto_from_uri (const char *uri)
+{
+	char *proto, *p;
+	p = strchr (uri, ':');
+	if (p == NULL)
+		return NULL;
+	proto = g_malloc0 (p - uri + 1);
+	strncpy (proto, uri, p - uri);
+	return proto;
+}
 
 static EBookBackendFactory*
 e_data_book_factory_lookup_backend_factory (EDataBookFactory *factory,
@@ -239,338 +179,219 @@ e_data_book_factory_lookup_backend_factory (EDataBookFactory *factory,
 {
 	EBookBackendFactory *backend_factory;
 	gchar                *proto;
-	gchar                *canonical_uri;
 
-	g_assert (factory != NULL);
-	g_assert (E_IS_DATA_BOOK_FACTORY (factory));
-	g_assert (uri != NULL);
+	g_return_val_if_fail (E_IS_DATA_BOOK_FACTORY (factory), NULL);
+	g_return_val_if_fail (uri != NULL, NULL);
 
-	canonical_uri = e_data_book_factory_canonicalize_uri (uri);
-	if (canonical_uri == NULL)
-		return NULL;
-
-	proto = e_data_book_factory_extract_proto_from_uri (canonical_uri);
+	proto = e_data_book_factory_extract_proto_from_uri (uri);
 	if (proto == NULL) {
-		g_free (canonical_uri);
+		g_warning ("Cannot extract protocol from URI %s", uri);
 		return NULL;
 	}
 
 	backend_factory = g_hash_table_lookup (factory->priv->backends, proto);
 
 	g_free (proto);
-	g_free (canonical_uri);
 
 	return backend_factory;
 }
 
-static EBookBackend *
-e_data_book_factory_launch_backend (EDataBookFactory      *book_factory,
-				    EBookBackendFactory   *backend_factory,
-				    GNOME_Evolution_Addressbook_BookListener listener,
-				    const gchar          *uri)
+static char *
+make_path_name (const char* uri)
 {
-	EBookBackend          *backend;
-
-	backend = e_book_backend_factory_new_backend (backend_factory);
-	if (!backend)
-		return NULL;
-
-	g_hash_table_insert (book_factory->priv->active_server_map,
-			     g_strdup (uri),
-			     backend);
-
-	g_signal_connect (backend, "last_client_gone",
-			  G_CALLBACK (backend_last_client_gone_cb),
-			  book_factory);
-
-	return backend;
+	char *s, *path;
+	s = nm_dbus_escape_object_path (uri);
+	path = g_strdup_printf ("/org/gnome/evolution/dataserver/addressbook/%s", s);
+	g_free (s);
+	return path;
 }
 
-static GNOME_Evolution_Addressbook_Book
-impl_GNOME_Evolution_Addressbook_BookFactory_getBook (PortableServer_Servant        servant,
-						      const CORBA_char             *source_xml,
-						      const GNOME_Evolution_Addressbook_BookListener listener,
-						      CORBA_Environment            *ev)
+static void
+my_remove (char *key, GObject *dead)
 {
-	EDataBookFactory      *factory = E_DATA_BOOK_FACTORY (bonobo_object (servant));
-	GNOME_Evolution_Addressbook_Book corba_book;
-	EBookBackend *backend;
-	EDataBook *book = NULL;
-	ESource *source;
-	gchar *uri;
+	g_mutex_lock (factory->priv->books_lock);
+	g_hash_table_remove (factory->priv->books, key);
+	g_mutex_unlock (factory->priv->books_lock);
 
-	printf ("impl_GNOME_Evolution_Addressbook_BookFactory_getBook\n");
+	g_free (key);
 
-	source = e_source_new_from_standalone_xml (source_xml);
-	if (!source) {
-		CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
-				     ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported,
-				     NULL);
-		return CORBA_OBJECT_NIL;
+	/* If there are no open books, start a timer to quit */
+	if (factory->priv->exit_timeout == 0 && g_hash_table_size (factory->priv->books) == 0) {
+		factory->priv->exit_timeout = g_timeout_add (10000, (GSourceFunc)g_main_loop_quit, loop);
 	}
+}
 
-	uri = e_source_get_uri (source);
-	if (!uri) {
-		g_object_unref (source);
-		CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
-				     ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported,
-				     NULL);
-		return CORBA_OBJECT_NIL;
-	}
-	printf (" + %s\n", uri);
-
-	/* Look up the backend and create one if needed */
-	g_mutex_lock (factory->priv->map_mutex);
-
-	backend = g_hash_table_lookup (factory->priv->active_server_map, uri);
-
-	if (!backend) {
-		EBookBackendFactory*  backend_factory;
-
-		backend_factory = e_data_book_factory_lookup_backend_factory (factory, uri);
-
-		if (backend_factory == NULL) {
-			CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
-					     ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported,
-					     NULL);
+static void
+book_closed_cb (EDataBook *book, const char *client)
+{
+	GList *list;
 
-			g_mutex_unlock (factory->priv->map_mutex);
+	list = g_hash_table_lookup (factory->priv->connections, client);
+	list = g_list_remove (list, book);
+	g_hash_table_insert (factory->priv->connections, g_strdup (client), list);
+}
 
-			g_free (uri);
-			return CORBA_OBJECT_NIL;
-		}
+static void
+impl_BookFactory_getBook(EDataBookFactory *factory, const char *IN_uri, DBusGMethodInvocation *context)
+{
+	EDataBook *book;
+	EDataBookFactoryPrivate *priv = factory->priv;
+	ESource *source;
+	char *path, *sender;
+	GList *list;
 
-		backend = e_data_book_factory_launch_backend (factory, backend_factory, listener, uri);
+	if (IN_uri == NULL || IN_uri[0] == '\0') {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_NO_SUCH_BOOK, _("Empty URI")));
+		return;
 	}
 
-	g_free (uri);
-
-	if (backend) {
-		g_mutex_unlock (factory->priv->map_mutex);
-
-		book = e_data_book_new (backend, source, listener);
-
-		e_book_backend_add_client (backend, book);
-		e_book_backend_set_mode (backend, factory->priv->mode);
-		corba_book = bonobo_object_corba_objref (BONOBO_OBJECT (book));
-	}
-	else {
-		/* probably need a more descriptive exception here */
-		CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
-				     ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported,
-				     NULL);
-		g_mutex_unlock (factory->priv->map_mutex);
-
-		corba_book = CORBA_OBJECT_NIL;
+	/* Remove a pending exit */
+	if (priv->exit_timeout) {
+		g_source_remove (priv->exit_timeout);
+		priv->exit_timeout = 0;
 	}
 
+	g_mutex_lock (priv->books_lock);
+
+	source = e_source_new_with_absolute_uri ("", IN_uri);
+	path = make_path_name (IN_uri);
+	book = g_hash_table_lookup (priv->books, path);
+	if (book == NULL) {
+		EBookBackend *backend = NULL;
+		backend = e_book_backend_factory_new_backend (e_data_book_factory_lookup_backend_factory (factory, IN_uri));
+		book = e_data_book_new (backend, source, book_closed_cb);
+		e_book_backend_set_mode (backend, 2); /* TODO: very odd */
+		g_hash_table_insert (priv->books, g_strdup(path), book);
+		dbus_g_connection_register_g_object (connection, path, G_OBJECT (book));
+		g_object_weak_ref (G_OBJECT (book), (GWeakNotify)my_remove, g_strdup (path));
+		g_object_unref (backend); /* The book takes a reference to the backend */
+	} else {
+		g_object_ref (book);
+	}
 	g_object_unref (source);
-	if (book)
-		printf (" => %p\n", (gpointer) book);
-	return corba_book;
-}
-
-static void
-e_data_book_factory_construct (EDataBookFactory *factory)
-{
-	/* nothing to do here.. */
-}
-
-/**
- * e_data_book_factory_new:
- *
- * Create a new #EDataBookFactory.
- *
- * Return value: A new #EDataBookFactory.
- **/
-EDataBookFactory *
-e_data_book_factory_new (void)
-{
-	static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
-	static PortableServer_POA poa = NULL;
-	EDataBookFactory *factory;
-
-	g_static_mutex_lock (&mutex);
-	if (poa == NULL)
-		poa = bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL);
-	g_static_mutex_unlock (&mutex);
 
-	factory = g_object_new (E_TYPE_DATA_BOOK_FACTORY, "poa", poa, NULL);
+	/* Update the hash of open connections */
+	g_mutex_lock (priv->connections_lock);
+	sender = dbus_g_method_get_sender (context);
+	list = g_hash_table_lookup (priv->connections, sender);
+	list = g_list_prepend (list, book);
+	g_hash_table_insert (priv->connections, sender, list);
+	g_mutex_unlock (priv->connections_lock);
 
-	e_data_book_factory_construct (factory);
+	g_mutex_unlock (priv->books_lock);
 
-	return factory;
+	dbus_g_method_return (context, path);
 }
 
-/**
- * e_data_book_factory_activate:
- * @factory: an #EDataBookFactory
- * @iid: the OAF ID of the factory to activate
- *
- * Activates the factory specified by @iid, using Bonobo.
- *
- * Return value: %TRUE for success, %FALSE otherwise.
- **/
-gboolean
-e_data_book_factory_activate (EDataBookFactory *factory, const gchar *iid)
+static void
+name_owner_changed (DBusGProxy *proxy,
+                    const char *name,
+                    const char *prev_owner,
+                    const char *new_owner,
+                    EDataBookFactory *factory)
 {
-	EDataBookFactoryPrivate *priv;
-	Bonobo_RegistrationResult result;
-	gchar *tmp_iid;
-
-	g_return_val_if_fail (factory != NULL, FALSE);
-	g_return_val_if_fail (E_IS_DATA_BOOK_FACTORY (factory), FALSE);
-
-	priv = factory->priv;
-
-	g_return_val_if_fail (!priv->registered, FALSE);
-
-	/* if iid is NULL, use the default factory OAFIID */
-	if (iid)
-		tmp_iid = g_strdup (iid);
-	else
-		tmp_iid = g_strdup (DEFAULT_E_DATA_BOOK_FACTORY_OAF_ID);
-
-	result = bonobo_activation_active_server_register (tmp_iid, bonobo_object_corba_objref (BONOBO_OBJECT (factory)));
-
-	switch (result) {
-	case Bonobo_ACTIVATION_REG_SUCCESS:
-		priv->registered = TRUE;
-		priv->iid = tmp_iid;
-		return TRUE;
-	case Bonobo_ACTIVATION_REG_NOT_LISTED:
-		g_message ("Error registering the PAS factory: not listed");
-		break;
-	case Bonobo_ACTIVATION_REG_ALREADY_ACTIVE:
-		g_message ("Error registering the PAS factory: already active");
-		break;
-	case Bonobo_ACTIVATION_REG_ERROR:
-	default:
-		g_message ("Error registering the PAS factory: generic error");
-		break;
+	if (strcmp (new_owner, "") == 0 && strcmp (name, prev_owner) == 0) {
+		char *key;
+		GList *list = NULL;
+		g_mutex_lock (factory->priv->connections_lock);
+		if (g_hash_table_lookup_extended (factory->priv->connections, prev_owner, (gpointer)&key, (gpointer)&list)) {
+			g_list_foreach (list, (GFunc)g_object_unref, NULL);
+			g_list_free (list);
+			g_hash_table_remove (factory->priv->connections, prev_owner);
+		}
+		g_mutex_unlock (factory->priv->connections_lock);
 	}
-
-	g_free (tmp_iid);
-	return FALSE;
 }
+
+/* Convenience function to print an error and exit */
 static void
-set_backend_online_status (gpointer key, gpointer value, gpointer data)
+die (const char *prefix, GError *error)
 {
-	EBookBackend *backend;
-
-	backend = E_BOOK_BACKEND (value);
-	e_book_backend_set_mode (backend, GPOINTER_TO_INT (data));
+	g_error("%s: %s", prefix, error->message);
+	g_error_free (error);
+	exit(1);
 }
 
-/**
- * e_data_book_factory_set_backend_mode:
- * @factory: an #EDataBookFactory
- * @mode: a connection status
- *
- * Sets all the backends associated with @factory to be either online
- * or offline. @mode should be passed as 1 for offline, or 2 for
- * online.
- **/
-void
-e_data_book_factory_set_backend_mode (EDataBookFactory *factory, gint mode)
-{
-	EDataBookFactoryPrivate *priv = factory->priv;
-
-
-	g_mutex_lock (priv->map_mutex);
-	priv->mode = mode;
-	g_hash_table_foreach (priv->active_server_map, set_backend_online_status, GINT_TO_POINTER (priv->mode));
-	g_mutex_unlock (priv->map_mutex);
+#define E_DATA_BOOK_FACTORY_SERVICE_NAME "org.gnome.evolution.dataserver.AddressBook"
 
-}
-static void
-e_data_book_factory_init (EDataBookFactory *factory)
+int
+main (int argc, char **argv)
 {
-	GHashTable *active_server_map;
-	GHashTable *backends;
+	GError *error = NULL;
+	DBusGProxy *bus_proxy;
+	guint32 request_name_ret;
 
-	active_server_map = g_hash_table_new_full (
-		g_str_hash, g_str_equal,
-		(GDestroyNotify) g_free,
-		(GDestroyNotify) g_object_unref);
+	g_type_init ();
+	if (!g_thread_supported ()) g_thread_init (NULL);
+	dbus_g_thread_init ();
 
-	backends = g_hash_table_new_full (
-		g_str_hash, g_str_equal,
-		(GDestroyNotify) g_free,
-		(GDestroyNotify) NULL);
+	loop = g_main_loop_new (NULL, FALSE);
 
-	factory->priv = g_new0 (EDataBookFactoryPrivate, 1);
+	/* Obtain a connection to the session bus */
+	connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+	if (connection == NULL)
+		die ("Failed to open connection to bus", error);
 
-	factory->priv->map_mutex         = g_mutex_new();
-	factory->priv->active_server_map = active_server_map;
-	factory->priv->backends          = backends;
-	factory->priv->registered        = FALSE;
-}
-
-static void
-e_data_book_factory_dispose (GObject *object)
-{
-	EDataBookFactory *factory = E_DATA_BOOK_FACTORY (object);
-	EDataBookFactoryPrivate *priv = factory->priv;
+	bus_proxy = dbus_g_proxy_new_for_name (connection,
+					       DBUS_SERVICE_DBUS,
+					       DBUS_PATH_DBUS,
+					       DBUS_INTERFACE_DBUS);
 
-	g_hash_table_remove_all (priv->active_server_map);
-	g_hash_table_remove_all (priv->backends);
+	if (!org_freedesktop_DBus_request_name (bus_proxy, E_DATA_BOOK_FACTORY_SERVICE_NAME,
+						0, &request_name_ret, &error))
+		die ("Failed to get name", error);
 
-	if (priv->registered) {
-		bonobo_activation_active_server_unregister (
-			priv->iid, bonobo_object_corba_objref (
-			BONOBO_OBJECT (factory)));
-		priv->registered = FALSE;
+	if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+		g_error ("Got result code %u from requesting name", request_name_ret);
+		exit (1);
 	}
 
-	if (G_OBJECT_CLASS (e_data_book_factory_parent_class)->dispose)
-		G_OBJECT_CLASS (e_data_book_factory_parent_class)->dispose (object);
-}
+	factory = g_object_new (E_TYPE_DATA_BOOK_FACTORY, NULL);
+	dbus_g_connection_register_g_object (connection,
+					     "/org/gnome/evolution/dataserver/addressbook/BookFactory",
+					     G_OBJECT (factory));
 
-static void
-e_data_book_factory_finalize (GObject *object)
-{
-	EDataBookFactory *factory = E_DATA_BOOK_FACTORY (object);
-	EDataBookFactoryPrivate *priv = factory->priv;
+	dbus_g_proxy_add_signal (bus_proxy, "NameOwnerChanged",
+				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (bus_proxy, "NameOwnerChanged", G_CALLBACK (name_owner_changed), factory, NULL);
+
+	g_main_loop_run (loop);
 
-	g_mutex_free (priv->map_mutex);
-	g_hash_table_destroy (priv->active_server_map);
-	g_hash_table_destroy (priv->backends);
-	g_free (priv->iid);
-	g_free (priv);
+	dbus_g_connection_unref (connection);
 
-	if (G_OBJECT_CLASS (e_data_book_factory_parent_class)->finalize)
-		G_OBJECT_CLASS (e_data_book_factory_parent_class)->finalize (object);
+	return 0;
 }
 
-static void
-e_data_book_factory_class_init (EDataBookFactoryClass *klass)
+/* Stolen from http://cvs.gnome.org/viewcvs/NetworkManager/utils/nm-utils.c */
+static gchar *nm_dbus_escape_object_path (const gchar *utf8_string)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	POA_GNOME_Evolution_Addressbook_BookFactory__epv *epv;
+	const gchar *p;
+	GString *string;
 
-	e_data_book_factory_parent_class = g_type_class_peek_parent (klass);
+	g_return_val_if_fail (utf8_string != NULL, NULL);
+	g_return_val_if_fail (g_utf8_validate (utf8_string, -1, NULL), NULL);
 
-	object_class->dispose = e_data_book_factory_dispose;
-	object_class->finalize = e_data_book_factory_finalize;
+	string = g_string_sized_new ((strlen (utf8_string) + 1) * 2);
 
-	factory_signals[LAST_BOOK_GONE] =
-		g_signal_new ("last_book_gone",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_FIRST,
-			      G_STRUCT_OFFSET (EDataBookFactoryClass, last_book_gone),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
+	for (p = utf8_string; *p != '\0'; p = g_utf8_next_char (p))
+		{
+			gunichar character;
 
+			character = g_utf8_get_char (p);
 
-	epv = &klass->epv;
+			if (((character >= ((gunichar) 'a')) &&
+			     (character <= ((gunichar) 'z'))) ||
+			    ((character >= ((gunichar) 'A')) &&
+			     (character <= ((gunichar) 'Z'))) ||
+			    ((character >= ((gunichar) '0')) &&
+			     (character <= ((gunichar) '9'))))
+				{
+					g_string_append_c (string, (gchar) character);
+					continue;
+				}
 
-	epv->getBook = impl_GNOME_Evolution_Addressbook_BookFactory_getBook;
-}
+			g_string_append_printf (string, "_%x_", character);
+		}
 
-BONOBO_TYPE_FUNC_FULL (
-		       EDataBookFactory,
-		       GNOME_Evolution_Addressbook_BookFactory,
-		       BONOBO_TYPE_OBJECT,
-		       e_data_book_factory)
+	return g_string_free (string, FALSE);
+}
diff --git a/addressbook/libedata-book/e-data-book-factory.h b/addressbook/libedata-book/e-data-book-factory.h
index 01048c6..d90a061 100644
--- a/addressbook/libedata-book/e-data-book-factory.h
+++ b/addressbook/libedata-book/e-data-book-factory.h
@@ -1,15 +1,28 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <bonobo/bonobo-object.h>
-#include <libedata-book/Evolution-DataServer-Addressbook.h>
-#include <libedata-book/e-book-backend.h>
-#include <libedata-book/e-book-backend-factory.h>
-
 #ifndef __E_DATA_BOOK_FACTORY_H__
 #define __E_DATA_BOOK_FACTORY_H__
 
+#include <glib-object.h>
+
 G_BEGIN_DECLS
 
 #define E_TYPE_DATA_BOOK_FACTORY        (e_data_book_factory_get_type ())
@@ -22,34 +35,22 @@ G_BEGIN_DECLS
 typedef struct _EDataBookFactoryPrivate EDataBookFactoryPrivate;
 
 typedef struct {
-	BonoboObject            parent_object;
+	GObject parent;
 	EDataBookFactoryPrivate *priv;
 } EDataBookFactory;
 
 typedef struct {
-	BonoboObjectClass parent_class;
-
-	POA_GNOME_Evolution_Addressbook_BookFactory__epv epv;
-
-	/* Notification signals */
-	void (* last_book_gone) (EDataBookFactory *factory);
+	GObjectClass parent;
 } EDataBookFactoryClass;
 
-EDataBookFactory *e_data_book_factory_new                  (void);
-
-void              e_data_book_factory_register_backend     (EDataBookFactory    *factory,
-							    EBookBackendFactory *backend_factory);
-
-gint               e_data_book_factory_get_n_backends       (EDataBookFactory    *factory);
-
-void		  e_data_book_factory_register_backends    (EDataBookFactory    *factory);
-
-void              e_data_book_factory_dump_active_backends (EDataBookFactory    *factory);
+typedef enum {
+	E_DATA_BOOK_FACTORY_ERROR_GENERIC
+} EDataBookFactoryError;
 
-gboolean          e_data_book_factory_activate             (EDataBookFactory    *factory, const gchar *iid);
-void              e_data_book_factory_set_backend_mode             (EDataBookFactory    *factory, gint mode);
+GQuark e_data_book_factory_error_quark (void);
+#define E_DATA_BOOK_FACTORY_ERROR e_data_book_factory_error_quark ()
 
-GType             e_data_book_factory_get_type             (void);
+GType e_data_book_factory_get_type (void);
 
 G_END_DECLS
 
diff --git a/addressbook/libedata-book/e-data-book-types.h b/addressbook/libedata-book/e-data-book-types.h
index 30ced26..618fb7b 100644
--- a/addressbook/libedata-book/e-data-book-types.h
+++ b/addressbook/libedata-book/e-data-book-types.h
@@ -1,11 +1,24 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * Blanket header containing the typedefs for object types used in the
- * PAS stuff, so we can disentangle the #includes.
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
  *
- * Author: Chris Toshok <toshok ximian com>
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
  *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Chris Toshok <toshok ximian com>
+ * Author: Ross Burton <ross linux intel com>
  */
 
 #ifndef __E_DATA_BOOK_TYPES_H__
@@ -31,6 +44,84 @@ typedef struct _EBookBackendSyncClass   EBookBackendSyncClass;
 typedef struct _EDataBook        EDataBook;
 typedef struct _EDataBookClass   EDataBookClass;
 
+typedef enum {
+	E_DATA_BOOK_STATUS_SUCCESS,
+	E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
+	E_DATA_BOOK_STATUS_PERMISSION_DENIED,
+	E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND,
+	E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS,
+	E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED,
+	E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED,
+	E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD,
+	E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD,
+	E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE,
+	E_DATA_BOOK_STATUS_NO_SUCH_BOOK,
+	E_DATA_BOOK_STATUS_BOOK_REMOVED,
+	E_DATA_BOOK_STATUS_OFFLINE_UNAVAILABLE,
+	E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED,
+	E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED,
+	E_DATA_BOOK_STATUS_INVALID_QUERY,
+	E_DATA_BOOK_STATUS_QUERY_REFUSED,
+	E_DATA_BOOK_STATUS_COULD_NOT_CANCEL,
+	E_DATA_BOOK_STATUS_OTHER_ERROR,
+	E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION,
+	E_DATA_BOOK_STATUS_NO_SPACE,
+} EDataBookStatus;
+
+/* Some hacks so the backends compile without change */
+#define GNOME_Evolution_Addressbook_CallStatus EDataBookStatus
+#define GNOME_Evolution_Addressbook_BookMode EDataBookMode
+
+#define GNOME_Evolution_Addressbook_Success E_DATA_BOOK_STATUS_SUCCESS
+#define GNOME_Evolution_Addressbook_RepositoryOffline E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE
+#define GNOME_Evolution_Addressbook_PermissionDenied E_DATA_BOOK_STATUS_PERMISSION_DENIED
+#define GNOME_Evolution_Addressbook_ContactNotFound E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND
+#define GNOME_Evolution_Addressbook_ContactIdAlreadyExists E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS
+#define GNOME_Evolution_Addressbook_AuthenticationFailed E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED
+#define GNOME_Evolution_Addressbook_AuthenticationRequired E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED
+#define GNOME_Evolution_Addressbook_UnsupportedField E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD
+#define GNOME_Evolution_Addressbook_UnsupportedAuthenticationMethod E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD
+#define GNOME_Evolution_Addressbook_TLSNotAvailable E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE
+#define GNOME_Evolution_Addressbook_NoSuchBook E_DATA_BOOK_STATUS_NO_SUCH_BOOK
+#define GNOME_Evolution_Addressbook_BookRemoved E_DATA_BOOK_STATUS_BOOK_REMOVED
+#define GNOME_Evolution_Addressbook_OfflineUnavailable E_DATA_BOOK_STATUS_BOOK_REMOVED
+#define GNOME_Evolution_Addressbook_SearchSizeLimitExceeded E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED
+#define GNOME_Evolution_Addressbook_SearchTimeLimitExceeded E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED
+#define GNOME_Evolution_Addressbook_InvalidQuery E_DATA_BOOK_STATUS_INVALID_QUERY
+#define GNOME_Evolution_Addressbook_QueryRefused E_DATA_BOOK_STATUS_QUERY_REFUSED
+#define GNOME_Evolution_Addressbook_CouldNotCancel E_DATA_BOOK_STATUS_COULD_NOT_CANCEL
+#define GNOME_Evolution_Addressbook_OtherError E_DATA_BOOK_STATUS_OTHER_ERROR
+#define GNOME_Evolution_Addressbook_InvalidServerVersion E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION
+#define GNOME_Evolution_Addressbook_NoSpace E_DATA_BOOK_STATUS_NO_SPACE
+
+typedef enum {
+	E_DATA_BOOK_MODE_LOCAL,
+	E_DATA_BOOK_MODE_REMOTE,
+	E_DATA_BOOK_MODE_ANY,
+} EDataBookMode;
+
+#define GNOME_Evolution_Addressbook_MODE_LOCAL E_DATA_BOOK_MODE_LOCAL
+#define GNOME_Evolution_Addressbook_MODE_REMOTE E_DATA_BOOK_MODE_REMOTE
+#define GNOME_Evolution_Addressbook_MODE_ANY E_DATA_BOOK_MODE_ANY
+
+typedef enum {
+	E_DATA_BOOK_BACKEND_CHANGE_ADDED,
+	E_DATA_BOOK_BACKEND_CHANGE_DELETED,
+	E_DATA_BOOK_BACKEND_CHANGE_MODIFIED
+} EDataBookChangeType;
+
+typedef struct {
+	EDataBookChangeType change_type;
+	char *vcard;
+} EDataBookChange;
+
+/* Transition typedef */
+typedef EDataBookChange GNOME_Evolution_Addressbook_BookChangeItem;
+
+#define GNOME_Evolution_Addressbook_ContactAdded E_DATA_BOOK_BACKEND_CHANGE_ADDED
+#define GNOME_Evolution_Addressbook_ContactDeleted E_DATA_BOOK_BACKEND_CHANGE_DELETED
+#define GNOME_Evolution_Addressbook_ContactModified E_DATA_BOOK_BACKEND_CHANGE_MODIFIED
+
 G_END_DECLS
 
 #endif /* __E_DATA_BOOK_TYPES_H__ */
diff --git a/addressbook/libedata-book/e-data-book-view.c b/addressbook/libedata-book/e-data-book-view.c
index 94ef8a6..c3861dd 100644
--- a/addressbook/libedata-book/e-data-book-view.c
+++ b/addressbook/libedata-book/e-data-book-view.c
@@ -1,8 +1,23 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * pas-book-view.c
- *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ross Burton <ross linux intel com>
  */
 
 #ifdef HAVE_CONFIG_H
@@ -10,218 +25,244 @@
 #endif
 
 #include <string.h>
-#include <glib.h>
-#include <bonobo/bonobo-main.h>
-#include "e-book-backend.h"
-#include "e-book-backend-sexp.h"
+#include <dbus/dbus.h>
+#include <libebook/e-contact.h>
 #include "e-data-book-view.h"
 
-#define d(x)
-
-static BonoboObjectClass *e_data_book_view_parent_class;
+extern DBusGConnection *connection;
 
-struct _EDataBookViewPrivate {
-	GNOME_Evolution_Addressbook_BookViewListener  listener;
+static gboolean impl_BookView_start (EDataBookView *view, GError **error);
+static gboolean impl_BookView_stop (EDataBookView *view, GError **error);
+static gboolean impl_BookView_dispose (EDataBookView *view, GError **eror);
 
-#define DEFAULT_INITIAL_THRESHOLD 20
-#define DEFAULT_THRESHOLD_MAX 3000
+#include "e-data-book-view-glue.h"
 
-	GMutex *mutex;
+static void reset_array (GArray *array);
 
-	GMutex *pending_mutex;
+G_DEFINE_TYPE (EDataBookView, e_data_book_view, G_TYPE_OBJECT);
+#define E_DATA_BOOK_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_DATA_BOOK_VIEW, EDataBookViewPrivate))
 
-	CORBA_sequence_GNOME_Evolution_Addressbook_VCard adds;
-	gint next_threshold;
-	gint threshold_max;
-	gint threshold_min;
-
-	CORBA_sequence_GNOME_Evolution_Addressbook_VCard changes;
-	CORBA_sequence_GNOME_Evolution_Addressbook_ContactId removes;
+#define THRESHOLD 32
 
+struct _EDataBookViewPrivate {
+	EDataBook *book;
 	EBookBackend *backend;
-	gchar *card_query;
+
+	char* card_query;
 	EBookBackendSExp *card_sexp;
+	int max_results;
+
+	gboolean running;
+	GMutex *pending_mutex;
+
+	GArray *adds;
+	GArray *changes;
+	GArray *removes;
+
 	GHashTable *ids;
+	guint idle_id;
+};
 
-	gint max_results;
+enum {
+	CONTACTS_ADDED,
+	CONTACTS_CHANGED,
+	CONTACTS_REMOVED,
+	STATUS_MESSAGE,
+	COMPLETE,
+	LAST_SIGNAL
 };
 
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void e_data_book_view_dispose (GObject *object);
+static void e_data_book_view_finalize (GObject *object);
+
 static void
-view_listener_died_cb (gpointer cnx, gpointer user_data)
+e_data_book_view_class_init (EDataBookViewClass *klass)
 {
-	EDataBookView *book_view = E_DATA_BOOK_VIEW (user_data);
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-	if (book_view) {
-		e_book_backend_stop_book_view (e_data_book_view_get_backend (book_view), book_view);
-		bonobo_object_unref (book_view);
-	}
+	object_class->dispose = e_data_book_view_dispose;
+	object_class->finalize = e_data_book_view_finalize;
+
+	signals[CONTACTS_ADDED] =
+		g_signal_new ("contacts-added",
+			      G_OBJECT_CLASS_TYPE (klass),
+			      G_SIGNAL_RUN_LAST,
+			      0, NULL, NULL,
+			      g_cclosure_marshal_VOID__BOXED,
+			      G_TYPE_NONE, 1, G_TYPE_STRV);
+
+	signals[CONTACTS_CHANGED] =
+		g_signal_new ("contacts-changed",
+			      G_OBJECT_CLASS_TYPE (klass),
+			      G_SIGNAL_RUN_LAST,
+			      0, NULL, NULL,
+			      g_cclosure_marshal_VOID__BOXED,
+			      G_TYPE_NONE, 1, G_TYPE_STRV);
+
+	signals[CONTACTS_REMOVED] =
+		g_signal_new ("contacts-removed",
+			      G_OBJECT_CLASS_TYPE (klass),
+			      G_SIGNAL_RUN_LAST,
+			      0, NULL, NULL,
+			      g_cclosure_marshal_VOID__BOXED,
+			      G_TYPE_NONE, 1, G_TYPE_STRV);
+
+	signals[STATUS_MESSAGE] =
+		g_signal_new ("status-message",
+			      G_OBJECT_CLASS_TYPE (klass),
+			      G_SIGNAL_RUN_LAST,
+			      0, NULL, NULL,
+			      g_cclosure_marshal_VOID__STRING,
+			      G_TYPE_NONE, 1, G_TYPE_STRING);
+
+	signals[COMPLETE] =
+		g_signal_new ("complete",
+			      G_OBJECT_CLASS_TYPE (klass),
+			      G_SIGNAL_RUN_LAST,
+			      0, NULL, NULL,
+			      g_cclosure_marshal_VOID__UINT,
+			      G_TYPE_NONE, 1, G_TYPE_UINT);
+
+	g_type_class_add_private (klass, sizeof (EDataBookViewPrivate));
+
+	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_e_data_book_view_object_info);
 }
 
 static void
-send_pending_adds (EDataBookView *book_view, gboolean reset)
+e_data_book_view_init (EDataBookView *book_view)
 {
-	CORBA_Environment ev;
-	CORBA_sequence_GNOME_Evolution_Addressbook_VCard *adds;
-
-	adds = &book_view->priv->adds;
-	if (adds->_length == 0)
-		return;
+	EDataBookViewPrivate *priv = E_DATA_BOOK_VIEW_GET_PRIVATE (book_view);
+	book_view->priv = priv;
 
-	CORBA_exception_init (&ev);
+	priv->running = FALSE;
+	priv->pending_mutex = g_mutex_new ();
 
-	GNOME_Evolution_Addressbook_BookViewListener_notifyContactsAdded (
-		book_view->priv->listener, adds, &ev);
+	priv->adds = g_array_sized_new (TRUE, TRUE, sizeof (char*), THRESHOLD);
+	priv->changes = g_array_sized_new (TRUE, TRUE, sizeof (char*), THRESHOLD);
+	priv->removes = g_array_sized_new (TRUE, TRUE, sizeof (char*), THRESHOLD);
 
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("send_pending_adds: Exception signaling BookViewListener!\n");
-	}
+	priv->ids = g_hash_table_new_full (g_str_hash, g_str_equal,
+					   g_free, NULL);
+}
 
-	CORBA_exception_free (&ev);
+static void
+book_destroyed_cb (gpointer data, GObject *dead)
+{
+	EDataBookView *view = E_DATA_BOOK_VIEW (data);
+	EDataBookViewPrivate *priv = view->priv;
 
-	CORBA_free (adds->_buffer);
-	adds->_buffer = NULL;
-	adds->_maximum = 0;
-	adds->_length = 0;
+	/* The book has just died, so unset the pointer so we don't try and remove a
+	   dead weak reference. */
+	view->priv->book = NULL;
 
-	if (reset)
-		book_view->priv->next_threshold = book_view->priv->threshold_min;
+	/* If the view is running stop it here. */
+	if (priv->running) {
+		e_book_backend_stop_book_view (priv->backend, view);
+		priv->running = FALSE;
+	}
 }
 
 static void
-send_pending_changes (EDataBookView *book_view)
+send_pending_adds (EDataBookView *view)
 {
-	CORBA_Environment ev;
-	CORBA_sequence_GNOME_Evolution_Addressbook_VCard *changes;
+	EDataBookViewPrivate *priv = view->priv;
 
-	changes = &book_view->priv->changes;
-	if (changes->_length == 0)
+	if (priv->adds->len == 0)
 		return;
 
-	CORBA_exception_init (&ev);
-
-	GNOME_Evolution_Addressbook_BookViewListener_notifyContactsChanged (
-		book_view->priv->listener, changes, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("send_pending_changes: Exception signaling BookViewListener!\n");
-	}
-
-	CORBA_exception_free (&ev);
-
-	CORBA_free (changes->_buffer);
-	changes->_buffer = NULL;
-	changes->_maximum = 0;
-	changes->_length = 0;
+	g_signal_emit (view, signals[CONTACTS_ADDED], 0, priv->adds->data);
+	reset_array (priv->adds);
 }
 
 static void
-send_pending_removes (EDataBookView *book_view)
+send_pending_changes (EDataBookView *view)
 {
-	CORBA_Environment ev;
-	CORBA_sequence_GNOME_Evolution_Addressbook_VCard *removes;
+	EDataBookViewPrivate *priv = view->priv;
 
-	removes = &book_view->priv->removes;
-	if (removes->_length == 0)
+	if (priv->changes->len == 0)
 		return;
 
-	CORBA_exception_init (&ev);
-
-	GNOME_Evolution_Addressbook_BookViewListener_notifyContactsRemoved (
-		book_view->priv->listener, removes, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("send_pending_removes: Exception signaling BookViewListener!\n");
-	}
+	g_signal_emit (view, signals[CONTACTS_CHANGED], 0, priv->changes->data);
+	reset_array (priv->changes);
+}
 
-	CORBA_exception_free (&ev);
+static void
+send_pending_removes (EDataBookView *view)
+{
+	EDataBookViewPrivate *priv = view->priv;
 
-	CORBA_free (removes->_buffer);
-	removes->_buffer = NULL;
-	removes->_maximum = 0;
-	removes->_length = 0;
-}
+	if (priv->removes->len == 0)
+		return;
 
-#define MAKE_REALLOC(type)						\
-static void								\
-CORBA_sequence_ ## type ## _realloc (CORBA_sequence_ ## type *seq,	\
-				     CORBA_unsigned_long      new_max)	\
-{									\
-	type *new_buf;							\
-	gint i;								\
-	new_buf = CORBA_sequence_ ## type ## _allocbuf (new_max);	\
-	for (i = 0; i < seq->_maximum; i ++)				\
-		new_buf[i] = CORBA_string_dup (seq->_buffer[i]);	\
-	CORBA_free (seq->_buffer);					\
-	seq->_buffer = new_buf;						\
-	seq->_maximum = new_max;					\
+	g_signal_emit (view, signals[CONTACTS_REMOVED], 0, priv->removes->data);
+	reset_array (priv->removes);
 }
 
-MAKE_REALLOC (GNOME_Evolution_Addressbook_VCard)
-MAKE_REALLOC (GNOME_Evolution_Addressbook_ContactId)
-
+/*
+ * Queue @vcard to be sent as a change notification. This takes ownership of
+ * @vcard.
+ */
 static void
-notify_change (EDataBookView *book_view, const gchar *vcard)
+notify_change (EDataBookView *view, char *vcard)
 {
-	CORBA_sequence_GNOME_Evolution_Addressbook_VCard *changes;
+	EDataBookViewPrivate *priv = view->priv;
+	send_pending_adds (view);
+	send_pending_removes (view);
 
-	send_pending_adds (book_view, TRUE);
-	send_pending_removes (book_view);
+	g_array_append_val (priv->changes, vcard);
+}
 
-	changes = &book_view->priv->changes;
+/*
+ * Queue @id to be sent as a change notification. This takes ownership of @id.
+ */
+static void
+notify_remove (EDataBookView *view, char *id)
+{
+	EDataBookViewPrivate *priv = view->priv;
 
-	if (changes->_length == changes->_maximum) {
-		CORBA_sequence_GNOME_Evolution_Addressbook_VCard_realloc (
-			changes, 2 * (changes->_maximum + 1));
-	}
+	send_pending_adds (view);
+	send_pending_changes (view);
 
-	changes->_buffer[changes->_length++] = CORBA_string_dup (vcard);
+	g_array_append_val (priv->removes, id);
+	g_hash_table_remove (priv->ids, id);
 }
 
+/*
+ * Queue @id and @vcard to be sent as a change notification. This takes ownership of
+ * @vcard but not @id.
+ */
 static void
-notify_remove (EDataBookView *book_view, const gchar *id)
+notify_add (EDataBookView *view, const char *id, char *vcard)
 {
-	CORBA_sequence_GNOME_Evolution_Addressbook_ContactId *removes;
-
-	send_pending_adds (book_view, TRUE);
-	send_pending_changes (book_view);
-
-	removes = &book_view->priv->removes;
+	EDataBookViewPrivate *priv = view->priv;
+	send_pending_changes (view);
+	send_pending_removes (view);
 
-	if (removes->_length == removes->_maximum) {
-		CORBA_sequence_GNOME_Evolution_Addressbook_ContactId_realloc (
-			removes, 2 * (removes->_maximum + 1));
+	if (priv->adds->len == THRESHOLD) {
+		send_pending_adds (view);
 	}
-
-	removes->_buffer[removes->_length++] = CORBA_string_dup (id);
-	g_hash_table_remove (book_view->priv->ids, id);
+	g_array_append_val (priv->adds, vcard);
+	g_hash_table_insert (priv->ids, g_strdup (id),
+			     GUINT_TO_POINTER (1));
 }
 
 static void
-notify_add (EDataBookView *book_view, const gchar *id, const gchar *vcard)
+reset_array (GArray *array)
 {
-	CORBA_sequence_GNOME_Evolution_Addressbook_VCard *adds;
-	EDataBookViewPrivate *priv = book_view->priv;
-
-	send_pending_changes (book_view);
-	send_pending_removes (book_view);
-
-	adds = &priv->adds;
-
-	if (adds->_length == adds->_maximum) {
-		send_pending_adds (book_view, FALSE);
-
-		adds->_buffer = CORBA_sequence_GNOME_Evolution_Addressbook_VCard_allocbuf (priv->next_threshold);
-		adds->_maximum = priv->next_threshold;
-
-		if (priv->next_threshold < priv->threshold_max) {
-			priv->next_threshold = MIN (2 * priv->next_threshold,
-						    priv->threshold_max);
+	gint i = 0;
+	gchar *tmp = NULL;
+
+	/* Free stored strings */
+	for (i = 0; i < array->len; i++)
+		{
+			tmp = g_array_index (array, gchar *, i);
+			g_free (tmp);
 		}
-	}
 
-	adds->_buffer[adds->_length++] = CORBA_string_dup (vcard);
-	g_hash_table_insert (book_view->priv->ids, g_strdup (id),
-			     GUINT_TO_POINTER (1));
+	/* Force the array size to 0 */
+	g_array_set_size (array, 0);
 }
 
 /**
@@ -237,24 +278,24 @@ notify_add (EDataBookView *book_view, const gchar *id, const gchar *vcard)
  **/
 void
 e_data_book_view_notify_update (EDataBookView *book_view,
-			     EContact    *contact)
+                                EContact      *contact)
 {
+	EDataBookViewPrivate *priv = book_view->priv;
 	gboolean currently_in_view, want_in_view;
-	const gchar *id=NULL;
+	const gchar *id;
 	gchar *vcard;
 
-	g_mutex_lock (book_view->priv->pending_mutex);
+	if (!priv->running)
+		return;
+
+	g_mutex_lock (priv->pending_mutex);
 
 	id = e_contact_get_const (contact, E_CONTACT_UID);
-	if (!id) {
-		g_mutex_unlock (book_view->priv->pending_mutex);
-		return;
-	}
 
 	currently_in_view =
-		g_hash_table_lookup (book_view->priv->ids, id) != NULL;
-	want_in_view = e_book_backend_sexp_match_contact (
-		book_view->priv->card_sexp, contact);
+		g_hash_table_lookup (priv->ids, id) != NULL;
+	want_in_view =
+		e_book_backend_sexp_match_contact (priv->card_sexp, contact);
 
 	if (want_in_view) {
 		vcard = e_vcard_to_string (E_VCARD (contact),
@@ -264,15 +305,13 @@ e_data_book_view_notify_update (EDataBookView *book_view,
 			notify_change (book_view, vcard);
 		else
 			notify_add (book_view, id, vcard);
-
-		g_free (vcard);
 	} else {
 		if (currently_in_view)
-			notify_remove (book_view, id);
+			notify_remove (book_view, g_strdup (id));
 		/* else nothing; we're removing a card that wasn't there */
 	}
 
-	g_mutex_unlock (book_view->priv->pending_mutex);
+	g_mutex_unlock (priv->pending_mutex);
 }
 
 /**
@@ -291,25 +330,22 @@ e_data_book_view_notify_update (EDataBookView *book_view,
 void
 e_data_book_view_notify_update_vcard (EDataBookView *book_view, gchar *vcard)
 {
+	EDataBookViewPrivate *priv = book_view->priv;
 	gboolean currently_in_view, want_in_view;
-	const gchar *id = NULL;
+	const gchar *id;
 	EContact *contact;
 
-	g_mutex_lock (book_view->priv->pending_mutex);
+	if (!priv->running)
+		return;
+
+	g_mutex_lock (priv->pending_mutex);
 
 	contact = e_contact_new_from_vcard (vcard);
 	id = e_contact_get_const (contact, E_CONTACT_UID);
-	if (!id) {
-		free (vcard);
-		g_object_unref (contact);
-		g_mutex_unlock (book_view->priv->pending_mutex);
-		return;
-	}
-
 	currently_in_view =
-		g_hash_table_lookup (book_view->priv->ids, id) != NULL;
+		g_hash_table_lookup (priv->ids, id) != NULL;
 	want_in_view =
-		e_book_backend_sexp_match_contact (book_view->priv->card_sexp, contact);
+		e_book_backend_sexp_match_contact (priv->card_sexp, contact);
 
 	if (want_in_view) {
 		if (currently_in_view)
@@ -318,12 +354,15 @@ e_data_book_view_notify_update_vcard (EDataBookView *book_view, gchar *vcard)
 			notify_add (book_view, id, vcard);
 	} else {
 		if (currently_in_view)
-			notify_remove (book_view, id);
+			notify_remove (book_view, g_strdup (id));
+		else
+			/* else nothing; we're removing a card that wasn't there */
+			g_free (vcard);
 	}
-
-	g_free (vcard);
+	/* Do this last so that id is still valid when notify_ is called */
 	g_object_unref (contact);
-	g_mutex_unlock (book_view->priv->pending_mutex);
+
+	g_mutex_unlock (priv->pending_mutex);
 }
 
 /**
@@ -349,20 +388,23 @@ e_data_book_view_notify_update_vcard (EDataBookView *book_view, gchar *vcard)
 void
 e_data_book_view_notify_update_prefiltered_vcard (EDataBookView *book_view, const gchar *id, gchar *vcard)
 {
+	EDataBookViewPrivate *priv = book_view->priv;
 	gboolean currently_in_view;
 
-	g_mutex_lock (book_view->priv->pending_mutex);
+	if (!priv->running)
+		return;
+
+	g_mutex_lock (priv->pending_mutex);
 
 	currently_in_view =
-		g_hash_table_lookup (book_view->priv->ids, id) != NULL;
+		g_hash_table_lookup (priv->ids, id) != NULL;
 
 	if (currently_in_view)
 		notify_change (book_view, vcard);
 	else
 		notify_add (book_view, id, vcard);
 
-	g_free (vcard);
-	g_mutex_unlock (book_view->priv->pending_mutex);
+	g_mutex_unlock (priv->pending_mutex);
 }
 
 /**
@@ -374,15 +416,19 @@ e_data_book_view_notify_update_prefiltered_vcard (EDataBookView *book_view, cons
  * was removed from @book_view.
  **/
 void
-e_data_book_view_notify_remove (EDataBookView *book_view,
-			     const gchar  *id)
+e_data_book_view_notify_remove (EDataBookView *book_view, const gchar *id)
 {
-	g_mutex_lock (book_view->priv->pending_mutex);
+	EDataBookViewPrivate *priv = E_DATA_BOOK_VIEW_GET_PRIVATE (book_view);
+
+	if (!priv->running)
+		return;
 
-	if (g_hash_table_lookup (book_view->priv->ids, id))
-		notify_remove (book_view, id);
+	g_mutex_lock (priv->pending_mutex);
 
-	g_mutex_unlock (book_view->priv->pending_mutex);
+	if (g_hash_table_lookup (priv->ids, id))
+		notify_remove (book_view, g_strdup (id));
+
+	g_mutex_unlock (priv->pending_mutex);
 }
 
 /**
@@ -395,29 +441,25 @@ e_data_book_view_notify_remove (EDataBookView *book_view,
  * in sync with the backend's.
  **/
 void
-e_data_book_view_notify_complete (EDataBookView *book_view,
-			       GNOME_Evolution_Addressbook_CallStatus status)
+e_data_book_view_notify_complete (EDataBookView *book_view, EDataBookStatus status)
 {
-	CORBA_Environment ev;
+	EDataBookViewPrivate *priv = book_view->priv;
+
+	if (!priv->running)
+		return;
 
-	g_mutex_lock (book_view->priv->pending_mutex);
+	g_mutex_lock (priv->pending_mutex);
 
-	send_pending_adds (book_view, TRUE);
+	send_pending_adds (book_view);
 	send_pending_changes (book_view);
 	send_pending_removes (book_view);
 
-	g_mutex_unlock (book_view->priv->pending_mutex);
-
-	CORBA_exception_init (&ev);
+	g_mutex_unlock (priv->pending_mutex);
 
-	GNOME_Evolution_Addressbook_BookViewListener_notifySequenceComplete (
-		book_view->priv->listener, status, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_data_book_view_notify_complete: Exception signaling BookViewListener!\n");
-	}
+	/* We're done now, so tell the backend to stop?  TODO: this is a bit different to
+	   how the CORBA backend works... */
 
-	CORBA_exception_free (&ev);
+	g_signal_emit (book_view, signals[COMPLETE], 0, status);
 }
 
 /**
@@ -430,86 +472,160 @@ e_data_book_view_notify_complete (EDataBookView *book_view,
  * reporting.
  **/
 void
-e_data_book_view_notify_status_message (EDataBookView *book_view,
-				     const gchar  *message)
+e_data_book_view_notify_status_message (EDataBookView *book_view, const gchar *message)
 {
-	CORBA_Environment ev;
+	EDataBookViewPrivate *priv = E_DATA_BOOK_VIEW_GET_PRIVATE (book_view);
 
-	CORBA_exception_init (&ev);
+	if (!priv->running)
+		return;
 
-	GNOME_Evolution_Addressbook_BookViewListener_notifyProgress (
-		book_view->priv->listener, message, 0, &ev);
+	g_signal_emit (book_view, signals[STATUS_MESSAGE], 0, message);
+}
 
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_data_book_view_notify_status_message: Exception signaling BookViewListener!\n");
-	}
+/**
+ * e_data_book_view_new:
+ * @book: The #EDataBook to search
+ * @path: The object path that this book view should have
+ * @card_query: The query as a string
+ * @card_sexp: The query as an #EBookBackendSExp
+ * @max_results: The maximum number of results to return
+ *
+ * Create a new #EDataBookView for the given #EBook, filtering on #card_sexp,
+ * and place it on DBus at the object path #path.
+ */
+EDataBookView *
+e_data_book_view_new (EDataBook *book, const gchar *path, const gchar *card_query, EBookBackendSExp *card_sexp, gint max_results)
+{
+	EDataBookView *view;
+	EDataBookViewPrivate *priv;
 
-	CORBA_exception_free (&ev);
+	view = g_object_new (E_TYPE_DATA_BOOK_VIEW, NULL);
+	priv = view->priv;
+
+	priv->book = book;
+	/* Attach a weak reference to the book, so if it dies the book view is destroyed too */
+	g_object_weak_ref (G_OBJECT (priv->book), book_destroyed_cb, view);
+	priv->backend = g_object_ref (e_data_book_get_backend (book));
+	priv->card_query = g_strdup (card_query);
+	priv->card_sexp = card_sexp;
+	priv->max_results = max_results;
+
+	dbus_g_connection_register_g_object (connection, path, G_OBJECT (view));
+
+	return view;
 }
 
 static void
-e_data_book_view_construct (EDataBookView                *book_view,
-			    EBookBackend                 *backend,
-			    GNOME_Evolution_Addressbook_BookViewListener  listener,
-			    const gchar                   *card_query,
-			    EBookBackendSExp             *card_sexp,
-			    gint                           max_results)
+e_data_book_view_dispose (GObject *object)
 {
-	EDataBookViewPrivate *priv;
-	CORBA_Environment ev;
+	EDataBookView *book_view = E_DATA_BOOK_VIEW (object);
+	EDataBookViewPrivate *priv = book_view->priv;
 
-	g_return_if_fail (book_view != NULL);
-	g_return_if_fail (listener != CORBA_OBJECT_NIL);
+	if (priv->book) {
+		/* Remove the weak reference */
+		g_object_weak_unref (G_OBJECT (priv->book), book_destroyed_cb, book_view);
+		priv->book = NULL;
+	}
 
-	priv = book_view->priv;
+	if (priv->backend) {
+		e_book_backend_remove_book_view (priv->backend, book_view);
+		g_object_unref (priv->backend);
+		priv->backend = NULL;
+	}
 
-	CORBA_exception_init (&ev);
+	if (priv->card_sexp) {
+		g_object_unref (priv->card_sexp);
+		priv->card_sexp = NULL;
+	}
 
-	priv->listener = bonobo_object_dup_ref (listener, &ev);
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning("Unable to duplicate listener object in pas-book-view.c\n");
-		CORBA_exception_free (&ev);
-		return;
+	if (priv->idle_id) {
+		g_source_remove (priv->idle_id);
+		priv->idle_id = 0;
 	}
 
-	CORBA_exception_free (&ev);
+	G_OBJECT_CLASS (e_data_book_view_parent_class)->dispose (object);
+}
 
-	priv->backend = backend;
-	priv->card_query = g_strdup (card_query);
-	priv->card_sexp = card_sexp;
-	priv->max_results = max_results;
+static void
+e_data_book_view_finalize (GObject *object)
+{
+	EDataBookView *book_view = E_DATA_BOOK_VIEW (object);
+	EDataBookViewPrivate *priv = book_view->priv;
 
-	ORBit_small_listen_for_broken (e_data_book_view_get_listener (book_view), G_CALLBACK (view_listener_died_cb), book_view);
+	reset_array (priv->adds);
+	reset_array (priv->changes);
+	reset_array (priv->removes);
+	g_array_free (priv->adds, TRUE);
+	g_array_free (priv->changes, TRUE);
+	g_array_free (priv->removes, TRUE);
+
+	g_free (priv->card_query);
+
+	g_mutex_free (priv->pending_mutex);
+
+	g_hash_table_destroy (priv->ids);
+
+	G_OBJECT_CLASS (e_data_book_view_parent_class)->finalize (object);
 }
 
-static void
-impl_GNOME_Evolution_Addressbook_BookView_start (PortableServer_Servant servant,
-						 CORBA_Environment *ev)
+static gboolean
+bookview_idle_start (gpointer data)
 {
-	EDataBookView *view = E_DATA_BOOK_VIEW (bonobo_object (servant));
+	EDataBookView *book_view = data;
+
+	book_view->priv->running = TRUE;
+	book_view->priv->idle_id = 0;
 
-	e_book_backend_start_book_view (e_data_book_view_get_backend (view), view);
+	e_book_backend_start_book_view (book_view->priv->backend, book_view);
+	return FALSE;
 }
 
-static void
-impl_GNOME_Evolution_Addressbook_BookView_stop (PortableServer_Servant servant,
-						CORBA_Environment *ev)
+static gboolean
+impl_BookView_start (EDataBookView *book_view, GError **error)
 {
-	EDataBookView *view = E_DATA_BOOK_VIEW (bonobo_object (servant));
+	book_view->priv->idle_id = g_idle_add (bookview_idle_start, book_view);
+	return TRUE;
+}
+
+static gboolean
+bookview_idle_stop (gpointer data)
+{
+	EDataBookView *book_view = data;
+
+	e_book_backend_stop_book_view (book_view->priv->backend, book_view);
 
-	e_book_backend_stop_book_view (e_data_book_view_get_backend (view), view);
+	book_view->priv->running = FALSE;
+	book_view->priv->idle_id = 0;
+
+	return FALSE;
 }
 
-static void
-impl_GNOME_Evolution_Addressbook_BookView_dispose (PortableServer_Servant servant,
-						   CORBA_Environment *ev)
+static gboolean
+impl_BookView_stop (EDataBookView *book_view, GError **error)
 {
-	EDataBookView *view = E_DATA_BOOK_VIEW (bonobo_object (servant));
+	if (book_view->priv->idle_id)
+		g_source_remove (book_view->priv->idle_id);
 
-	d(printf("in impl_GNOME_Evolution_Addressbook_BookView_dispose\n"));
-	ORBit_small_unlisten_for_broken (e_data_book_view_get_listener (view), G_CALLBACK (view_listener_died_cb));
+	book_view->priv->idle_id = g_idle_add (bookview_idle_stop, book_view);
+	return TRUE;
+}
 
-	bonobo_object_unref (view);
+static gboolean
+impl_BookView_dispose (EDataBookView *book_view, GError **eror)
+{
+	g_object_unref (book_view);
+
+	return TRUE;
+}
+
+void
+e_data_book_view_set_thresholds (EDataBookView *book_view,
+                                 int minimum_grouping_threshold,
+                                 int maximum_grouping_threshold)
+{
+	g_return_if_fail (E_IS_DATA_BOOK_VIEW (book_view));
+
+	g_debug ("e_data_book_view_set_thresholds does nothing in eds-dbus");
 }
 
 /**
@@ -524,7 +640,7 @@ impl_GNOME_Evolution_Addressbook_BookView_dispose (PortableServer_Servant servan
 const gchar *
 e_data_book_view_get_card_query (EDataBookView *book_view)
 {
-	g_return_val_if_fail (book_view, NULL);
+	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
 
 	return book_view->priv->card_query;
 }
@@ -580,93 +696,6 @@ e_data_book_view_get_backend (EDataBookView *book_view)
 }
 
 /**
- * e_data_book_view_get_mutex:
- * @book_view: an #EDataBookView
- *
- * Gets the internal mutex of @book_view.
- *
- * Return value: The #GMutex for @book_view.
- **/
-GMutex*
-e_data_book_view_get_mutex (EDataBookView *book_view)
-{
-	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
-
-	return book_view->priv->mutex;
-}
-
-/**
- * e_data_book_view_get_listener:
- * @book_view: an #EDataBookView
- *
- * Gets the CORBA listener that @book_view is dispatching
- * events to.
- *
- * Return value: The CORBA book view listener.
- **/
-GNOME_Evolution_Addressbook_BookViewListener
-e_data_book_view_get_listener (EDataBookView  *book_view)
-{
-	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), CORBA_OBJECT_NIL);
-
-	return book_view->priv->listener;
-}
-
-/**
- * e_data_book_view_set_thresholds:
- * @book_view: an #EDataBookView
- * @minimum_grouping_threshold: the minimum threshold
- * @maximum_grouping_threshold: the maximum threshold
- *
- * Sets the thresholds for grouping add events together
- * for efficiency reasons. The minimum threshold specifies
- * how many adds must be grouped (as long as there are
- * pending adds), and the maximum threshold specifies
- * the maximum number of adds that can be grouped.
- **/
-void
-e_data_book_view_set_thresholds (EDataBookView *book_view,
-				 gint minimum_grouping_threshold,
-				 gint maximum_grouping_threshold)
-{
-	book_view->priv->threshold_min = minimum_grouping_threshold;
-	book_view->priv->threshold_max = maximum_grouping_threshold;
-}
-
-/**
- * e_data_book_view_new:
- * @backend: an #EBookBackend to view
- * @listener: a CORBA listener to reveive notifications
- * @card_query: an s-expression representing the query
- * @card_sexp:
- * @max_results: the maximum number of results for the query
- *
- * Return value: A new #EDataBookView.
- **/
-EDataBookView *
-e_data_book_view_new (EBookBackend *backend,
-		      GNOME_Evolution_Addressbook_BookViewListener  listener,
-		      const gchar *card_query,
-		      EBookBackendSExp *card_sexp,
-		      gint max_results)
-{
-	static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
-	static PortableServer_POA poa = NULL;
-	EDataBookView *book_view;
-
-	g_static_mutex_lock (&mutex);
-	if (poa == NULL)
-		poa = bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_OBJECT, NULL);
-	g_static_mutex_unlock (&mutex);
-
-	book_view = g_object_new (E_TYPE_DATA_BOOK_VIEW, "poa", poa, NULL);
-
-	e_data_book_view_construct (book_view, backend, listener, card_query, card_sexp, max_results);
-
-	return book_view;
-}
-
-/**
  * e_data_book_view_ref
  * @book_view: an #EBookView
  *
@@ -676,7 +705,7 @@ e_data_book_view_new (EBookBackend *backend,
 void
 e_data_book_view_ref (EDataBookView *book_view)
 {
-	bonobo_object_ref (book_view);
+	g_object_ref (book_view);
 }
 
 /**
@@ -689,78 +718,5 @@ e_data_book_view_ref (EDataBookView *book_view)
 void
 e_data_book_view_unref (EDataBookView *book_view)
 {
-	bonobo_object_unref (book_view);
+	g_object_unref (book_view);
 }
-
-static void
-e_data_book_view_dispose (GObject *object)
-{
-	EDataBookView *book_view = E_DATA_BOOK_VIEW (object);
-
-	d(printf ("disposing of EDataBookView\n"));
-	if (book_view->priv) {
-		bonobo_object_release_unref (book_view->priv->listener, NULL);
-
-		if (book_view->priv->adds._buffer)
-			CORBA_free (book_view->priv->adds._buffer);
-		if (book_view->priv->changes._buffer)
-			CORBA_free (book_view->priv->changes._buffer);
-		if (book_view->priv->removes._buffer)
-			CORBA_free (book_view->priv->removes._buffer);
-
-		g_free (book_view->priv->card_query);
-		g_object_unref (book_view->priv->card_sexp);
-
-		g_mutex_free (book_view->priv->pending_mutex);
-
-		g_mutex_free (book_view->priv->mutex);
-
-		g_hash_table_destroy (book_view->priv->ids);
-
-		g_free (book_view->priv);
-		book_view->priv = NULL;
-	}
-
-	if (G_OBJECT_CLASS (e_data_book_view_parent_class)->dispose)
-		G_OBJECT_CLASS (e_data_book_view_parent_class)->dispose (object);
-}
-
-static void
-e_data_book_view_class_init (EDataBookViewClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	POA_GNOME_Evolution_Addressbook_BookView__epv *epv;
-
-	e_data_book_view_parent_class = g_type_class_peek_parent (klass);
-
-	object_class->dispose = e_data_book_view_dispose;
-
-	epv = &klass->epv;
-
-	epv->start                = impl_GNOME_Evolution_Addressbook_BookView_start;
-	epv->stop                 = impl_GNOME_Evolution_Addressbook_BookView_stop;
-	epv->dispose              = impl_GNOME_Evolution_Addressbook_BookView_dispose;
-
-}
-
-static void
-e_data_book_view_init (EDataBookView *book_view)
-{
-	book_view->priv = g_new0 (EDataBookViewPrivate, 1);
-
-	book_view->priv->pending_mutex = g_mutex_new();
-	book_view->priv->mutex = g_mutex_new();
-
-	book_view->priv->threshold_min = DEFAULT_INITIAL_THRESHOLD;
-	book_view->priv->threshold_max = DEFAULT_THRESHOLD_MAX;
-	book_view->priv->next_threshold = book_view->priv->threshold_min;
-
-	book_view->priv->ids = g_hash_table_new_full (g_str_hash, g_str_equal,
-						      g_free, NULL);
-}
-
-BONOBO_TYPE_FUNC_FULL (
-		       EDataBookView,
-		       GNOME_Evolution_Addressbook_BookView,
-		       BONOBO_TYPE_OBJECT,
-		       e_data_book_view)
diff --git a/addressbook/libedata-book/e-data-book-view.h b/addressbook/libedata-book/e-data-book-view.h
index b5cc864..160a443 100644
--- a/addressbook/libedata-book/e-data-book-view.h
+++ b/addressbook/libedata-book/e-data-book-view.h
@@ -1,23 +1,35 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * A wrapper object which exports the GNOME_Evolution_Addressbook_Book CORBA interface
- * and which maintains a request queue.
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
  *
- * Author:
- *   Nat Friedman (nat ximian com)
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
  *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Nat Friedman <nat ximian com>
+ * Author: Ross Burton <ross linux intel com>
  */
 
 #ifndef __E_DATA_BOOK_VIEW_H__
 #define __E_DATA_BOOK_VIEW_H__
 
-#include <bonobo/bonobo-object.h>
 #include <glib.h>
 #include <glib-object.h>
 #include <libebook/e-contact.h>
-#include <libedata-book/Evolution-DataServer-Addressbook.h>
 #include <libedata-book/e-data-book-types.h>
+#include <libedata-book/e-book-backend.h>
+#include <libedata-book/e-book-backend-sexp.h>
 
 G_BEGIN_DECLS
 
@@ -31,22 +43,19 @@ G_BEGIN_DECLS
 typedef struct _EDataBookViewPrivate EDataBookViewPrivate;
 
 struct _EDataBookView {
-	BonoboObject     parent_object;
+	GObject parent;
 	EDataBookViewPrivate *priv;
 };
 
 struct _EDataBookViewClass {
-	BonoboObjectClass parent_class;
-
-	POA_GNOME_Evolution_Addressbook_BookView__epv epv;
+	GObjectClass parent;
 };
 
-
-EDataBookView *e_data_book_view_new                  (EBookBackend                 *backend,
-						      GNOME_Evolution_Addressbook_BookViewListener  listener,
-						      const gchar                   *card_query,
-						      EBookBackendSExp             *card_sexp,
-						      gint                           max_results);
+EDataBookView *e_data_book_view_new                  (EDataBook        *book,
+						      const gchar       *path,
+						      const gchar       *card_query,
+						      EBookBackendSExp *card_sexp,
+						      gint               max_results);
 
 void              e_data_book_view_set_thresholds    (EDataBookView *book_view,
 						      gint minimum_grouping_threshold,
@@ -56,9 +65,6 @@ const gchar *       e_data_book_view_get_card_query    (EDataBookView
 EBookBackendSExp* e_data_book_view_get_card_sexp     (EDataBookView                *book_view);
 gint               e_data_book_view_get_max_results   (EDataBookView                *book_view);
 EBookBackend*     e_data_book_view_get_backend       (EDataBookView                *book_view);
-GNOME_Evolution_Addressbook_BookViewListener e_data_book_view_get_listener (EDataBookView  *book_view);
-GMutex*           e_data_book_view_get_mutex         (EDataBookView                *book_view);
-
 void         e_data_book_view_notify_update          (EDataBookView                *book_view,
 						      EContact                     *contact);
 
@@ -71,7 +77,7 @@ void         e_data_book_view_notify_update_prefiltered_vcard (EDataBookView
 void         e_data_book_view_notify_remove          (EDataBookView                *book_view,
 						      const gchar                   *id);
 void         e_data_book_view_notify_complete        (EDataBookView                *book_view,
-						      GNOME_Evolution_Addressbook_CallStatus);
+						      EDataBookStatus               status);
 void         e_data_book_view_notify_status_message  (EDataBookView                *book_view,
 						      const gchar                   *message);
 void         e_data_book_view_ref                    (EDataBookView                *book_view);
diff --git a/addressbook/libedata-book/e-data-book.c b/addressbook/libedata-book/e-data-book.c
index 9c7c8bb..4d770cf 100644
--- a/addressbook/libedata-book/e-data-book.c
+++ b/addressbook/libedata-book/e-data-book.c
@@ -1,1016 +1,697 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * pas-book.c
- *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ross Burton <ross linux intel com>
  */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <bonobo/bonobo-main.h>
-#include <bonobo/bonobo-arg.h>
-#include "libedataserver/e-list.h"
-#include <libebook/e-contact.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include "e-data-book-enumtypes.h"
+#include "e-data-book-factory.h"
+#include "e-data-book.h"
 #include "e-data-book-view.h"
-#include "e-book-backend.h"
 #include "e-book-backend-sexp.h"
-#include "e-data-book.h"
-
-static BonoboObjectClass *e_data_book_parent_class;
-POA_GNOME_Evolution_Addressbook_Book__vepv e_data_book_vepv;
-
-struct _EDataBookPrivate {
-	EBookBackend                               *backend;
-	GNOME_Evolution_Addressbook_BookListener  listener;
-	ESource                                    *source;
+#include "opid.h"
+
+DBusGConnection *connection;
+
+/* DBus glue */
+static void impl_AddressBook_Book_open(EDataBook *book, gboolean only_if_exists, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_remove(EDataBook *book, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_getContact(EDataBook *book, const char *IN_uid, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_getContactList(EDataBook *book, const char *query, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_authenticateUser(EDataBook *book, const char *IN_user, const char *IN_passwd, const char *IN_auth_method, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_addContact(EDataBook *book, const char *IN_vcard, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_modifyContact(EDataBook *book, const char *IN_vcard, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_removeContacts(EDataBook *book, const char **IN_uids, DBusGMethodInvocation *context);
+static gboolean impl_AddressBook_Book_getStaticCapabilities(EDataBook *book, char **OUT_capabilities, GError **error);
+static void impl_AddressBook_Book_getSupportedFields(EDataBook *book, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_getRequiredFields(EDataBook *book, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_getSupportedAuthMethods(EDataBook *book, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_getBookView (EDataBook *book, const char *search, const guint max_results, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_getChanges(EDataBook *book, const char *IN_change_id, DBusGMethodInvocation *context);
+static gboolean impl_AddressBook_Book_cancelOperation(EDataBook *book, GError **error);
+static void impl_AddressBook_Book_close(EDataBook *book, DBusGMethodInvocation *context);
+#include "e-data-book-glue.h"
+
+static void return_status_and_list (guint32 opid, EDataBookStatus status, GList *list, gboolean free_data);
+
+enum {
+	WRITABLE,
+	CONNECTION,
+	AUTH_REQUIRED,
+	LAST_SIGNAL
 };
 
-static void
-impl_GNOME_Evolution_Addressbook_Book_open (PortableServer_Servant servant,
-					    const CORBA_long opid,
-					    const CORBA_boolean only_if_exists,
-					    CORBA_Environment *ev)
-{
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
-	printf ("impl_GNOME_Evolution_Addressbook_Book_open (%p)\n", (gpointer) book);
-
-	e_book_backend_open (e_data_book_get_backend (book), book, opid, only_if_exists);
-}
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static GThreadPool *op_pool;
+
+typedef enum {
+	OP_OPEN,
+	OP_AUTHENTICATE,
+	OP_ADD_CONTACT,
+	OP_GET_CONTACT,
+	OP_GET_CONTACTS,
+	OP_MODIFY_CONTACT,
+	OP_REMOVE_CONTACTS,
+	OP_GET_CHANGES,
+} OperationID;
+
+typedef struct {
+	OperationID op;
+	guint32 id; /* operation id */
+	EDataBook *book; /* book */
+	union {
+		/* OP_OPEN */
+		gboolean only_if_exists;
+		/* OP_AUTHENTICATE */
+		struct {
+			char *username;
+			char *password;
+			char *method;
+		} auth;
+		/* OP_ADD_CONTACT */
+		/* OP_MODIFY_CONTACT */
+		char *vcard;
+		/* OP_GET_CONTACT */
+		char *uid;
+		/* OP_GET_CONTACTS */
+		char *query;
+		/* OP_MODIFY_CONTACT */
+		char **vcards;
+		/* OP_REMOVE_CONTACTS */
+		GList *ids;
+		/* OP_GET_CHANGES */
+		char *change_id;
+	};
+} OperationData;
 
 static void
-impl_GNOME_Evolution_Addressbook_Book_remove (PortableServer_Servant servant,
-					      const CORBA_long opid,
-					      CORBA_Environment *ev)
-{
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
-	printf ("impl_GNOME_Evolution_Addressbook_Book_remove\n");
+operation_thread (gpointer data, gpointer user_data)
+{
+	OperationData *op = data;
+	EBookBackend *backend;
+
+	backend = e_data_book_get_backend (op->book);
+
+	switch (op->op) {
+	case OP_OPEN:
+		e_book_backend_open (backend, op->book, op->id, op->only_if_exists);
+		break;
+	case OP_AUTHENTICATE:
+		e_book_backend_authenticate_user (backend, op->book, op->id,
+						  op->auth.username,
+						  op->auth.password,
+						  op->auth.method);
+		g_free (op->auth.username);
+		g_free (op->auth.password);
+		g_free (op->auth.method);
+		break;
+	case OP_ADD_CONTACT:
+		e_book_backend_create_contact (backend, op->book, op->id, op->vcard);
+		g_free (op->vcard);
+		break;
+	case OP_GET_CONTACT:
+		e_book_backend_get_contact (backend, op->book, op->id, op->uid);
+		g_free (op->uid);
+		break;
+	case OP_GET_CONTACTS:
+		e_book_backend_get_contact_list (backend, op->book, op->id, op->query);
+		g_free (op->query);
+		break;
+	case OP_MODIFY_CONTACT:
+		e_book_backend_modify_contact (backend, op->book, op->id, op->vcard);
+		g_free (op->vcard);
+		break;
+	case OP_REMOVE_CONTACTS:
+		e_book_backend_remove_contacts (backend, op->book, op->id, op->ids);
+		g_list_foreach (op->ids, (GFunc)g_free, NULL);
+		g_list_free (op->ids);
+		break;
+	case OP_GET_CHANGES:
+		e_book_backend_get_changes (backend, op->book, op->id, op->change_id);
+		g_free (op->change_id);
+		break;
+	}
 
-	e_book_backend_remove (e_data_book_get_backend (book), book, opid);
+	g_object_unref (op->book);
+	g_slice_free (OperationData, op);
 }
 
-static void
-impl_GNOME_Evolution_Addressbook_Book_getContact (PortableServer_Servant servant,
-						  const CORBA_long opid,
-						  const CORBA_char *id,
-						  CORBA_Environment *ev)
+static OperationData *
+op_new (OperationID op, EDataBook *book, DBusGMethodInvocation *context)
 {
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
+	OperationData *data;
 
-	printf ("impl_GNOME_Evolution_Addressbook_Book_getContact\n");
+	data = g_slice_new0 (OperationData);
+	data->op = op;
+	data->book = g_object_ref (book);
+	data->id = opid_store (context);
 
-	e_book_backend_get_contact (e_data_book_get_backend (book), book, opid, id);
+	return data;
 }
 
-static void
-impl_GNOME_Evolution_Addressbook_Book_getContactList (PortableServer_Servant servant,
-						      const CORBA_long opid,
-						      const CORBA_char *query,
-						      CORBA_Environment *ev)
-{
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
-	printf ("impl_GNOME_Evolution_Addressbook_Book_getContactList\n");
-
-	e_book_backend_get_contact_list (e_data_book_get_backend (book), book, opid, query);
-}
 
-static void
-impl_GNOME_Evolution_Addressbook_Book_authenticateUser (PortableServer_Servant servant,
-							const CORBA_long opid,
-							const gchar * user,
-							const gchar * passwd,
-							const gchar * auth_method,
-							CORBA_Environment *ev)
+/* Create the EDataBook error quark */
+GQuark
+e_data_book_error_quark (void)
 {
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
-	e_book_backend_authenticate_user (e_data_book_get_backend (book), book,
-					  opid, user, passwd, auth_method);
+	static GQuark quark = 0;
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("e-data-book-error");
+	return quark;
 }
 
-static void
-impl_GNOME_Evolution_Addressbook_Book_addContact (PortableServer_Servant servant,
-						  const CORBA_long opid,
-						  const CORBA_char *vcard,
-						  CORBA_Environment *ev)
-{
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
 
-	e_book_backend_create_contact (e_data_book_get_backend (book), book, opid, vcard);
-}
+/* Generate the GObject boilerplate */
+G_DEFINE_TYPE(EDataBook, e_data_book, G_TYPE_OBJECT)
 
 static void
-impl_GNOME_Evolution_Addressbook_Book_removeContacts (PortableServer_Servant servant,
-						      const CORBA_long opid,
-						      const GNOME_Evolution_Addressbook_ContactIdList *ids,
-						      CORBA_Environment *ev)
-{
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-	gint i;
-	GList *id_list = NULL;
-
-	for (i = 0; i < ids->_length; i ++)
-		id_list = g_list_append (id_list, ids->_buffer[i]);
-
-	e_book_backend_remove_contacts (e_data_book_get_backend (book), book, opid, id_list);
-
-	g_list_free (id_list);
-}
-
-static void
-impl_GNOME_Evolution_Addressbook_Book_modifyContact (PortableServer_Servant servant,
-						     const CORBA_long opid,
-						     const CORBA_char *vcard,
-						     CORBA_Environment *ev)
+e_data_book_dispose (GObject *object)
 {
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
-	e_book_backend_modify_contact (e_data_book_get_backend (book), book, opid, vcard);
-}
-
-static void
-impl_GNOME_Evolution_Addressbook_Book_getBookView (PortableServer_Servant servant,
-						   const CORBA_long opid,
-						   const GNOME_Evolution_Addressbook_BookViewListener listener,
-						   const CORBA_char *search,
-						   const GNOME_Evolution_Addressbook_stringlist* requested_fields,
-						   const CORBA_long max_results,
-						   CORBA_Environment *ev)
-{
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-	EBookBackend *backend = e_data_book_get_backend (book);
-	EBookBackendSExp *card_sexp;
-	EDataBookView *view;
-
-	g_warning ("impl_GNOME_Evolution_Addressbook_Book_getBookView (%s)\n", search);
-
-	/* we handle this entirely here, since it doesn't require any
-	   backend involvement now that we have e_data_book_view_start to
-	   actually kick off the search. */
+	EDataBook *book = E_DATA_BOOK (object);
 
-	card_sexp = e_book_backend_sexp_new (search);
-	if (!card_sexp) {
-		e_data_book_respond_get_book_view (book, opid, GNOME_Evolution_Addressbook_InvalidQuery, NULL);
-		return;
+	if (book->backend) {
+		g_object_unref (book->backend);
+		book->backend = NULL;
 	}
 
-	/* XXX still need to add requested_fields here */
-	view = e_data_book_view_new (backend, listener, search, card_sexp, max_results);
-
-	if (!view) {
-		g_object_unref (card_sexp);
-		e_data_book_respond_get_book_view (book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
-		return;
+	if (book->source) {
+		g_object_unref (book->source);
+		book->source = NULL;
 	}
 
-	e_book_backend_add_book_view (backend, view);
-
-	e_data_book_respond_get_book_view (book, opid, GNOME_Evolution_Addressbook_Success, view);
+	G_OBJECT_CLASS (e_data_book_parent_class)->dispose (object);
 }
 
-
 static void
-impl_GNOME_Evolution_Addressbook_Book_getChanges (PortableServer_Servant servant,
-						  const CORBA_long opid,
-						  const CORBA_char *change_id,
-						  CORBA_Environment *ev)
+e_data_book_class_init (EDataBookClass *e_data_book_class)
 {
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
-	e_book_backend_get_changes (e_data_book_get_backend (book), book, opid, change_id);
-}
-
-static gchar *
-impl_GNOME_Evolution_Addressbook_Book_getStaticCapabilities (PortableServer_Servant servant,
-							     CORBA_Environment *ev)
-{
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-	gchar *temp;
-	gchar *ret_val;
-
-	temp = e_book_backend_get_static_capabilities (book->priv->backend);
-	ret_val = CORBA_string_dup(temp);
-	g_free(temp);
-	return ret_val;
-}
+	GObjectClass *object_class = G_OBJECT_CLASS (e_data_book_class);
 
+	object_class->dispose = e_data_book_dispose;
 
+	signals[WRITABLE] =
+		g_signal_new ("writable",
+			      G_OBJECT_CLASS_TYPE (e_data_book_class),
+			      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+			      0,
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__BOOLEAN,
+			      G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+	signals[CONNECTION] =
+		g_signal_new ("connection",
+			      G_OBJECT_CLASS_TYPE (e_data_book_class),
+			      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+			      0,
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__BOOLEAN,
+			      G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+	signals[AUTH_REQUIRED] =
+		g_signal_new ("auth-required",
+			      G_OBJECT_CLASS_TYPE (e_data_book_class),
+			      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+			      0,
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+
+	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (e_data_book_class), &dbus_glib_e_data_book_object_info);
+
+	dbus_g_error_domain_register (E_DATA_BOOK_ERROR, NULL, E_TYPE_DATA_BOOK_STATUS);
+
+	op_pool = g_thread_pool_new (operation_thread, NULL, 10, FALSE, NULL);
+	/* Kill threads which don't do anything for 10 seconds */
+	g_thread_pool_set_max_idle_time (10 * 1000);
+}
+
+/* Instance init */
 static void
-impl_GNOME_Evolution_Addressbook_Book_getRequiredFields (PortableServer_Servant servant,
-							  const CORBA_long opid,
-							  CORBA_Environment *ev)
-
+e_data_book_init (EDataBook *ebook)
 {
-
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
-	e_book_backend_get_required_fields (e_data_book_get_backend (book), book, opid);
-
 }
 
-static void
-impl_GNOME_Evolution_Addressbook_Book_getSupportedFields (PortableServer_Servant servant,
-							  const CORBA_long opid,
-							  CORBA_Environment *ev)
+EDataBook *
+e_data_book_new (EBookBackend *backend, ESource *source, EDataBookClosedCallback closed_cb)
 {
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
-	e_book_backend_get_supported_fields (e_data_book_get_backend (book), book, opid);
+	EDataBook *book;
+	book = g_object_new (E_TYPE_DATA_BOOK, NULL);
+	book->backend = g_object_ref (backend);
+	book->source = g_object_ref (source);
+	book->closed_cb = closed_cb;
+	return book;
 }
 
-static void
-impl_GNOME_Evolution_Addressbook_Book_getSupportedAuthMethods (PortableServer_Servant servant,
-							       const CORBA_long opid,
-							       CORBA_Environment *ev)
+ESource*
+e_data_book_get_source (EDataBook *book)
 {
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
+	g_return_val_if_fail (book != NULL, NULL);
 
-	e_book_backend_get_supported_auth_methods (e_data_book_get_backend (book), book, opid);
+	return book->source;
 }
 
-static GNOME_Evolution_Addressbook_CallStatus
-impl_GNOME_Evolution_Addressbook_Book_cancelOperation (PortableServer_Servant servant,
-						       CORBA_Environment *ev)
+EBookBackend*
+e_data_book_get_backend (EDataBook *book)
 {
-	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
+	g_return_val_if_fail (book != NULL, NULL);
 
-	return e_book_backend_cancel_operation (e_data_book_get_backend (book), book);
+	return book->backend;
 }
 
-
-/**
- * e_data_book_get_backend:
- * @book: an #EDataBook
- *
- * Gets the #EBookBackend being used to store data for @book.
- *
- * Return value: The #EBookBackend being used.
- **/
-EBookBackend *
-e_data_book_get_backend (EDataBook *book)
+static void
+impl_AddressBook_Book_open(EDataBook *book, gboolean only_if_exists, DBusGMethodInvocation *context)
 {
-	g_return_val_if_fail (book && E_IS_DATA_BOOK (book), NULL);
+	OperationData *op;
 
-	return book->priv->backend;
+	op = op_new (OP_OPEN, book, context);
+	op->only_if_exists = only_if_exists;
+	g_thread_pool_push (op_pool, op, NULL);
 }
 
-/**
- * e_data_book_get_listener:
- * @book: an #EDataBook
- *
- * Gets the CORBA listener associated with @book.
- *
- * Return value: A #GNOME_Evolution_Addressbook_BookListener.
- **/
-GNOME_Evolution_Addressbook_BookListener
-e_data_book_get_listener (EDataBook *book)
+void
+e_data_book_respond_open (EDataBook *book, guint opid, EDataBookStatus status)
 {
-	g_return_val_if_fail (book && E_IS_DATA_BOOK (book), CORBA_OBJECT_NIL);
+	DBusGMethodInvocation *context = opid_fetch (opid);
 
-	return book->priv->listener;
+	if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot open book")));
+	} else {
+		dbus_g_method_return (context);
+	}
 }
 
-/**
- * e_data_book_get_source:
- * @book: an #EDataBook
- *
- * Gets the #ESource associated with @book.
- *
- * Return value: An #ESource.
- **/
-ESource *
-e_data_book_get_source (EDataBook *book)
+static void
+impl_AddressBook_Book_remove(EDataBook *book, DBusGMethodInvocation *context)
 {
-	return book->priv->source;
+	e_book_backend_remove (book->backend, book, opid_store (context));
 }
 
-/**
- * e_data_book_respond_open:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- *
- * Respond to an 'open' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
 void
-e_data_book_respond_open (EDataBook                              *book,
-			  guint32                                 opid,
-			  GNOME_Evolution_Addressbook_CallStatus  status)
+e_data_book_respond_remove (EDataBook *book, guint opid, EDataBookStatus status)
 {
-	CORBA_Environment ev;
+	DBusGMethodInvocation *context = opid_fetch (opid);
 
-	CORBA_exception_init (&ev);
-	GNOME_Evolution_Addressbook_BookListener_notifyBookOpened (book->priv->listener, opid, status, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_data_book_respond_open: Exception "
-			   "responding to BookListener!\n");
+	if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot remove book")));
+	} else {
+		dbus_g_method_return (context);
 	}
-
-	CORBA_exception_free (&ev);
 }
 
-/**
- * e_data_book_respond_remove:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- *
- * Respond to a 'remove' request to remove all of @book's data,
- * specified by @opid, indicating @status as the outcome.
- **/
-void
-e_data_book_respond_remove (EDataBook                           *book,
-			    guint32                              opid,
-			    GNOME_Evolution_Addressbook_CallStatus  status)
+static void
+impl_AddressBook_Book_getContact (EDataBook *book, const char *IN_uid, DBusGMethodInvocation *context)
 {
-	CORBA_Environment ev;
+	OperationData *op;
 
-	CORBA_exception_init (&ev);
-	GNOME_Evolution_Addressbook_BookListener_notifyBookRemoved (book->priv->listener, opid, status, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_data_book_respond_remove: Exception "
-			   "responding to BookListener!\n");
+	if (IN_uid == NULL) {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, _("Cannot get contact")));
+		return;
 	}
 
-	CORBA_exception_free (&ev);
+	op = op_new (OP_GET_CONTACT, book, context);
+	op->uid = g_strdup (IN_uid);
+	g_thread_pool_push (op_pool, op, NULL);
 }
 
-/**
- * e_data_book_respond_create:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @contact: the contact created, or %NULL
- *
- * Respond to a 'create' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
 void
-e_data_book_respond_create (EDataBook                              *book,
-			    guint32                                 opid,
-			    GNOME_Evolution_Addressbook_CallStatus  status,
-			    EContact                               *contact)
+e_data_book_respond_get_contact (EDataBook *book, guint32 opid, EDataBookStatus status, const gchar *vcard)
 {
-	CORBA_Environment ev;
+	DBusGMethodInvocation *context = opid_fetch (opid);
 
-	if (status == GNOME_Evolution_Addressbook_Success) {
-		e_book_backend_notify_update (book->priv->backend, contact);
-		e_book_backend_notify_complete (book->priv->backend);
+	if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot get contact")));
+	} else {
+		dbus_g_method_return (context, vcard);
 	}
+}
 
-	CORBA_exception_init (&ev);
-
-	GNOME_Evolution_Addressbook_BookListener_notifyContactCreated (
-		book->priv->listener, opid, status,
-		status == GNOME_Evolution_Addressbook_Success ? e_contact_get_const (contact, E_CONTACT_UID) : "",
-		&ev);
+static void
+impl_AddressBook_Book_getContactList (EDataBook *book, const char *query, DBusGMethodInvocation *context)
+{
+	OperationData *op;
 
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_data_book_respond_create: Exception "
-			   "responding to BookListener!\n");
+	if (query == NULL || query[0] == '\0') {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_INVALID_QUERY, _("Empty query")));
+		return;
 	}
 
-	CORBA_exception_free (&ev);
+	op = op_new (OP_GET_CONTACTS, book, context);
+	op->query = g_strdup (query);
+	g_thread_pool_push (op_pool, op, NULL);
 }
 
-/**
- * e_data_book_respond_remove_contacts:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @ids: a list of contact IDs removed
- *
- * Respond to a 'remove contacts' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
 void
-e_data_book_respond_remove_contacts (EDataBook                              *book,
-				     guint32                                 opid,
-				     GNOME_Evolution_Addressbook_CallStatus  status,
-				     GList                                  *ids)
+e_data_book_respond_get_contact_list (EDataBook *book, guint32 opid, EDataBookStatus status, GList *cards)
 {
-	CORBA_Environment ev;
-	GList *i;
-
-	CORBA_exception_init (&ev);
-
-	if (ids) {
-		for (i = ids; i; i = i->next)
-			e_book_backend_notify_remove (book->priv->backend, i->data);
-		e_book_backend_notify_complete (book->priv->backend);
-	}
-
-	GNOME_Evolution_Addressbook_BookListener_notifyContactsRemoved (
-		book->priv->listener, opid, status, &ev);
+	return_status_and_list (opid, status, cards, TRUE);
+}
 
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_data_book_respond_remove: Exception "
-			   "responding to BookListener!\n");
-	}
+static void
+impl_AddressBook_Book_authenticateUser(EDataBook *book, const char *IN_user, const char *IN_passwd, const char *IN_auth_method, DBusGMethodInvocation *context)
+{
+	OperationData *op;
 
-	CORBA_exception_free (&ev);
+	op = op_new (OP_AUTHENTICATE, book, context);
+	op->auth.username = g_strdup (IN_user);
+	op->auth.password = g_strdup (IN_passwd);
+	op->auth.method = g_strdup (IN_auth_method);
+	g_thread_pool_push (op_pool, op, NULL);
 }
 
-/**
- * e_data_book_respond_modify:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @contact: the modified #EContact
- *
- * Respond to a 'modify' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
 void
-e_data_book_respond_modify (EDataBook                              *book,
-			    guint32                                 opid,
-			    GNOME_Evolution_Addressbook_CallStatus  status,
-			    EContact                               *contact)
+e_data_book_respond_authenticate_user (EDataBook *book, guint32 opid, EDataBookStatus status)
 {
-	CORBA_Environment ev;
+	DBusGMethodInvocation *context = opid_fetch (opid);
 
-	if (status == GNOME_Evolution_Addressbook_Success) {
-		e_book_backend_notify_update (book->priv->backend, contact);
-		e_book_backend_notify_complete (book->priv->backend);
+	if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot authenticate user")));
+	} else {
+		dbus_g_method_return (context);
 	}
+}
 
-	CORBA_exception_init (&ev);
-
-	GNOME_Evolution_Addressbook_BookListener_notifyContactModified (
-		book->priv->listener, opid, status, &ev);
+static void
+impl_AddressBook_Book_addContact (EDataBook *book, const char *IN_vcard, DBusGMethodInvocation *context)
+{
+	OperationData *op;
 
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_data_book_respond_modify: Exception "
-			   "responding to BookListener!\n");
+	if (IN_vcard == NULL || IN_vcard[0] == '\0') {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_INVALID_QUERY, _("Cannot add contact")));
+		return;
 	}
 
-	CORBA_exception_free (&ev);
+	op = op_new (OP_ADD_CONTACT, book, context);
+	op->vcard = g_strdup (IN_vcard);
+	g_thread_pool_push (op_pool, op, NULL);
 }
 
-/**
- * e_data_book_respond_authenticate_user:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- *
- * Respond to an 'authenticate' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
 void
-e_data_book_respond_authenticate_user (EDataBook                              *book,
-				       guint32                                 opid,
-				       GNOME_Evolution_Addressbook_CallStatus  status)
+e_data_book_respond_create (EDataBook *book, guint32 opid, EDataBookStatus status, EContact *contact)
 {
-	CORBA_Environment ev;
+	DBusGMethodInvocation *context = opid_fetch (opid);
 
-	CORBA_exception_init (&ev);
+	if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot add contact")));
+	} else {
+		e_book_backend_notify_update (e_data_book_get_backend (book), contact);
+		e_book_backend_notify_complete (e_data_book_get_backend (book));
 
-	GNOME_Evolution_Addressbook_BookListener_notifyAuthenticationResult (
-		book->priv->listener, opid, status, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_data_book_respond_authenticate_user: Exception "
-			   "responding to BookListener!\n");
+		dbus_g_method_return (context, e_contact_get_const (contact, E_CONTACT_UID));
 	}
-
-	CORBA_exception_free (&ev);
 }
 
-/**
- * e_data_book_respond_get_required_fields:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @fields: a list of required field names
- *
- * Respond to a 'get required fields' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
-void
-e_data_book_respond_get_required_fields (EDataBook                              *book,
-					  guint32                                 opid,
-					  GNOME_Evolution_Addressbook_CallStatus  status,
-					  GList                                  *fields)
+static void
+impl_AddressBook_Book_modifyContact (EDataBook *book, const char *IN_vcard, DBusGMethodInvocation *context)
 {
+	OperationData *op;
 
-	CORBA_Environment ev;
-	GNOME_Evolution_Addressbook_stringlist stringlist;
-	gint num_fields;
-	gint i;
-	GList *iter;
-
-	CORBA_exception_init (&ev);
-
-	num_fields = g_list_length (fields);
-
-	stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_fields);
-	stringlist._maximum = num_fields;
-	stringlist._length = num_fields;
-
-	for (i = 0, iter = fields; iter; iter = iter->next, i ++) {
-		stringlist._buffer[i] = CORBA_string_dup ((gchar *)iter->data);
+	if (IN_vcard == NULL) {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_INVALID_QUERY, _("Cannot modify contact")));
+		return;
 	}
 
-	printf ("calling GNOME_Evolution_Addressbook_BookListener_notifyRequiredFields\n");
-
-	GNOME_Evolution_Addressbook_BookListener_notifyRequiredFields (
-			book->priv->listener, opid, status,
-			&stringlist,
-			&ev);
-
-	CORBA_exception_free (&ev);
-
-	CORBA_free(stringlist._buffer);
+	op = op_new (OP_MODIFY_CONTACT, book, context);
+	op->vcard = g_strdup (IN_vcard);
+	g_thread_pool_push (op_pool, op, NULL);
 }
 
-/**
- * e_data_book_respond_get_supported_fields:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @fields: a list of supported field names
- *
- * Respond to a 'get supported fields' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
 void
-e_data_book_respond_get_supported_fields (EDataBook                              *book,
-					  guint32                                 opid,
-					  GNOME_Evolution_Addressbook_CallStatus  status,
-					  GList                                  *fields)
+e_data_book_respond_modify (EDataBook *book, guint32 opid, EDataBookStatus status, EContact *contact)
 {
-	CORBA_Environment ev;
-	GNOME_Evolution_Addressbook_stringlist stringlist;
-	gint num_fields;
-	gint i;
-	GList *iter;
+	DBusGMethodInvocation *context = opid_fetch (opid);
 
-	CORBA_exception_init (&ev);
+	if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot modify contact")));
+	} else {
+		e_book_backend_notify_update (e_data_book_get_backend (book), contact);
+		e_book_backend_notify_complete (e_data_book_get_backend (book));
 
-	num_fields = g_list_length (fields);
+		dbus_g_method_return (context);
+	}
+}
 
-	stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_fields);
-	stringlist._maximum = num_fields;
-	stringlist._length = num_fields;
+static void
+impl_AddressBook_Book_removeContacts(EDataBook *book, const char **IN_uids, DBusGMethodInvocation *context)
+{
+	OperationData *op;
 
-	for (i = 0, iter = fields; iter; iter = iter->next, i ++) {
-		stringlist._buffer[i] = CORBA_string_dup ((gchar *)iter->data);
+	/* Allow an empty array to be removed */
+	if (IN_uids == NULL) {
+		dbus_g_method_return (context);
+		return;
 	}
 
-	printf ("calling GNOME_Evolution_Addressbook_BookListener_notifySupportedFields\n");
-
-	GNOME_Evolution_Addressbook_BookListener_notifySupportedFields (
-			book->priv->listener, opid, status,
-			&stringlist,
-			&ev);
+	op = op_new (OP_REMOVE_CONTACTS, book, context);
 
-	CORBA_exception_free (&ev);
+	for (; *IN_uids; IN_uids++) {
+		op->ids = g_list_prepend (op->ids, g_strdup (*IN_uids));
+	}
 
-	CORBA_free(stringlist._buffer);
+	g_thread_pool_push (op_pool, op, NULL);
 }
 
-/**
- * e_data_book_respond_get_supported_auth_methods:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @auth_methods: a list of names for supported auth methods
- *
- * Respond to a 'get supported auth methods' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
 void
-e_data_book_respond_get_supported_auth_methods (EDataBook                              *book,
-						guint32                                 opid,
-						GNOME_Evolution_Addressbook_CallStatus  status,
-						GList                                  *auth_methods)
+e_data_book_respond_remove_contacts (EDataBook *book, guint32 opid, EDataBookStatus status, GList *ids)
 {
-	CORBA_Environment ev;
-	GNOME_Evolution_Addressbook_stringlist stringlist;
-	gint num_auth_methods;
-	GList *iter;
-	gint i;
+	DBusGMethodInvocation *context = opid_fetch (opid);
 
-	CORBA_exception_init (&ev);
+	if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot remove contacts")));
+	} else {
+		GList *i;
 
-	num_auth_methods = g_list_length (auth_methods);
-
-	stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_auth_methods);
-	stringlist._maximum = num_auth_methods;
-	stringlist._length = num_auth_methods;
+		for (i = ids; i; i = i->next)
+			e_book_backend_notify_remove (e_data_book_get_backend (book), i->data);
+		e_book_backend_notify_complete (e_data_book_get_backend (book));
 
-	for (i = 0, iter = auth_methods; iter; iter = iter->next, i ++) {
-		stringlist._buffer[i] = CORBA_string_dup ((gchar *)iter->data);
+		dbus_g_method_return (context);
 	}
+}
 
-	GNOME_Evolution_Addressbook_BookListener_notifySupportedAuthMethods (
-			book->priv->listener, opid, status,
-			&stringlist,
-			&ev);
-
-	CORBA_exception_free (&ev);
-
-	CORBA_free(stringlist._buffer);
+static gboolean
+impl_AddressBook_Book_getStaticCapabilities(EDataBook *book, char **OUT_capabilities, GError **error)
+{
+	*OUT_capabilities = e_book_backend_get_static_capabilities (e_data_book_get_backend (book));
+	return TRUE;
 }
 
 static void
-view_destroy(gpointer data, GObject *where_object_was)
+impl_AddressBook_Book_getSupportedFields(EDataBook *book, DBusGMethodInvocation *context)
 {
-	EDataBook           *book = (EDataBook *)data;
-	e_book_backend_remove_book_view (book->priv->backend, (EDataBookView*)where_object_was);
+	e_book_backend_get_supported_fields (e_data_book_get_backend (book), book, opid_store (context));
 }
 
-/**
- * e_data_book_respond_get_book_view:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @book_view: the #EDataBookView created
- *
- * Respond to a 'get book view' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
 void
-e_data_book_respond_get_book_view (EDataBook                              *book,
-				   guint32                                 opid,
-				   GNOME_Evolution_Addressbook_CallStatus  status,
-				   EDataBookView                          *book_view)
+e_data_book_respond_get_supported_fields (EDataBook *book, guint32 opid, EDataBookStatus status, GList *fields)
 {
-	CORBA_Environment ev;
-	CORBA_Object      object = CORBA_OBJECT_NIL;
-
-	printf ("e_data_book_respond_get_book_view\n");
-
-	CORBA_exception_init (&ev);
-
-	if (book_view) {
-		object = bonobo_object_corba_objref(BONOBO_OBJECT(book_view));
-
-		g_object_weak_ref (G_OBJECT (book_view), view_destroy, book);
-	}
-
-	GNOME_Evolution_Addressbook_BookListener_notifyViewRequested (
-		book->priv->listener, opid, status, object, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_data_book_respond_get_book_view: Exception "
-			   "responding to BookListener!\n");
-	}
-
-	CORBA_exception_free (&ev);
+	return_status_and_list (opid, status, fields, FALSE);
 }
 
-/**
- * e_data_book_respond_get_contact:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @vcard: the found VCard, or %NULL
- *
- * Respond to a 'get contact' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
-void
-e_data_book_respond_get_contact (EDataBook                              *book,
-				 guint32                                 opid,
-				 GNOME_Evolution_Addressbook_CallStatus  status,
-				 const gchar                            *vcard)
+static void
+impl_AddressBook_Book_getRequiredFields(EDataBook *book, DBusGMethodInvocation *context)
 {
-	CORBA_Environment ev;
-
-	CORBA_exception_init (&ev);
-
-	GNOME_Evolution_Addressbook_BookListener_notifyContactRequested (book->priv->listener,
-									 opid,
-									 status,
-									 vcard,
-									 &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION)
-		g_message ("could not notify listener of get-contact response");
-
-	CORBA_exception_free (&ev);
+	e_book_backend_get_required_fields (e_data_book_get_backend (book), book, opid_store (context));
 }
 
-/**
- * e_data_book_respond_get_contact_list:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @card_list: a list of VCard strings
- *
- * Respond to a 'get contact list' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
 void
-e_data_book_respond_get_contact_list (EDataBook                              *book,
-				      guint32                                 opid,
-				      GNOME_Evolution_Addressbook_CallStatus  status,
-				      GList                                  *card_list)
+e_data_book_respond_get_required_fields (EDataBook *book, guint32 opid, EDataBookStatus status, GList *fields)
 {
-	CORBA_Environment ev;
-	GNOME_Evolution_Addressbook_stringlist stringlist;
-	gint num_cards;
-	gint i;
-	GList *l;
-
-	CORBA_exception_init (&ev);
-
-	num_cards = g_list_length (card_list);
-
-	stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_cards);
-	stringlist._maximum = num_cards;
-	stringlist._length = num_cards;
-
-	for (i = 0, l = card_list; l; l = l->next, i ++)
-		stringlist._buffer[i] = CORBA_string_dup (l->data);
-
-	g_list_foreach (card_list, (GFunc)g_free, NULL);
-	g_list_free (card_list);
-
-
-	GNOME_Evolution_Addressbook_BookListener_notifyContactListRequested (book->priv->listener,
-									     opid,
-									     status,
-									     &stringlist,
-									     &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION)
-		g_message ("could not notify listener of get-contact-list response");
-
-	CORBA_exception_free (&ev);
+	return_status_and_list (opid, status, fields, FALSE);
+}
 
-	CORBA_free(stringlist._buffer);
+static void
+impl_AddressBook_Book_getSupportedAuthMethods(EDataBook *book, DBusGMethodInvocation *context)
+{
+	e_book_backend_get_supported_auth_methods (e_data_book_get_backend (book), book, opid_store (context));
 }
 
-/**
- * e_data_book_respond_get_changes:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @changes: a list of GNOME_Evolution_Addressbook_BookChangeItem items
- *
- * Respond to a 'get changes' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
 void
-e_data_book_respond_get_changes (EDataBook                              *book,
-				 guint32                                 opid,
-				 GNOME_Evolution_Addressbook_CallStatus  status,
-				 GList                                  *changes)
+e_data_book_respond_get_supported_auth_methods (EDataBook *book, guint32 opid, EDataBookStatus status, GList *auth_methods)
 {
-	CORBA_Environment ev;
-	GNOME_Evolution_Addressbook_BookChangeList changelist;
-	gint num_changes;
-	gint i;
-	GList *l;
+	return_status_and_list (opid, status, auth_methods, FALSE);
+}
 
-	CORBA_exception_init (&ev);
+static char*
+construct_bookview_path (void)
+{
+	static volatile guint counter = 1;
 
-	num_changes = g_list_length (changes);
+	return g_strdup_printf ("/org/gnome/evolution/dataserver/addressbook/BookView/%d/%d",
+				getpid (),
+				g_atomic_int_exchange_and_add ((int*)&counter, 1));
+}
 
-	changelist._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_BookChangeItem_allocbuf (num_changes);
-	changelist._maximum = num_changes;
-	changelist._length = num_changes;
+static void
+impl_AddressBook_Book_getBookView (EDataBook *book, const char *search, const guint max_results, DBusGMethodInvocation *context)
+{
+	EBookBackend *backend = e_data_book_get_backend (book);
+	EBookBackendSExp *card_sexp;
+	EDataBookView *book_view;
+	char *path;
 
-	for (i = 0, l = changes; l; l = l->next, i ++) {
-		GNOME_Evolution_Addressbook_BookChangeItem *change = (GNOME_Evolution_Addressbook_BookChangeItem*)l->data;
-		changelist._buffer[i] = *change;
-		changelist._buffer[i].vcard = CORBA_string_dup (change->vcard);
+	card_sexp = e_book_backend_sexp_new (search);
+	if (!card_sexp) {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_INVALID_QUERY, _("Invalid query")));
+		return;
 	}
 
-	g_list_foreach (changes, (GFunc)CORBA_free, NULL);
-	g_list_free (changes);
+	path = construct_bookview_path ();
+	book_view = e_data_book_view_new (book, path, search, card_sexp, max_results);
 
-	GNOME_Evolution_Addressbook_BookListener_notifyChangesRequested (book->priv->listener,
-									 opid,
-									 status,
-									 &changelist,
-									 &ev);
+	e_book_backend_add_book_view (backend, book_view);
 
-	if (ev._major != CORBA_NO_EXCEPTION)
-		g_message ("could not notify listener of get-changes response");
+	dbus_g_method_return (context, path);
+	g_free (path);
+}
 
-	CORBA_exception_free (&ev);
+static void
+impl_AddressBook_Book_getChanges(EDataBook *book, const char *IN_change_id, DBusGMethodInvocation *context)
+{
+	OperationData *op;
 
-	CORBA_free(changelist._buffer);
+	op = op_new (OP_GET_CHANGES, book, context);
+	op->change_id = g_strdup (IN_change_id);
+	g_thread_pool_push (op_pool, op, NULL);
 }
 
-/**
- * e_data_book_report_writable:
- * @book: an #EDataBook
- * @writable: %TRUE if @book is writeable, %FALSE otherwise
- *
- * Notify listeners that @book's writeable status has changed
- * to @writable.
- **/
 void
-e_data_book_report_writable (EDataBook                           *book,
-			     gboolean                           writable)
+e_data_book_respond_get_changes (EDataBook *book, guint32 opid, EDataBookStatus status, GList *changes)
 {
-	CORBA_Environment ev;
+	DBusGMethodInvocation *context = opid_fetch (opid);
 
-	CORBA_exception_init (&ev);
+	if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot get changes")));
+	} else {
+		/* The DBus interface to this is a(us), an array of structs of unsigned ints
+		   and strings.  In dbus-glib this is a GPtrArray of GValueArray of unsigned
+		   int and strings. */
+		GPtrArray *array;
 
-	GNOME_Evolution_Addressbook_BookListener_notifyWritable (
-		book->priv->listener, (CORBA_boolean) writable, &ev);
+		array = g_ptr_array_new ();
 
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_data_book_report_writable: Exception "
-			   "responding to BookListener!\n");
-	}
+		while (changes != NULL) {
+			EDataBookChange *change = (EDataBookChange *) changes->data;
+			GValueArray *vals;
 
-	CORBA_exception_free (&ev);
-}
+			vals = g_value_array_new (2);
 
-/**
- * e_data_book_report_connection_status:
- * @book: an #EDataBook
- * @is_online: %TRUE if the book is connected, %FALSE otherwise
- *
- * Notify listeners that @book's online status has changed
- * to @is_online.
- **/
-void
-e_data_book_report_connection_status (EDataBook   *book,
-				      gboolean    is_online)
-{
-	CORBA_Environment ev;
+			g_value_array_append (vals, NULL);
+			g_value_init (g_value_array_get_nth (vals, 0), G_TYPE_UINT);
+			g_value_set_uint (g_value_array_get_nth (vals, 0), change->change_type);
 
-	CORBA_exception_init (&ev);
+			g_value_array_append (vals, NULL);
+			g_value_init (g_value_array_get_nth (vals, 1), G_TYPE_STRING);
+			g_value_take_string (g_value_array_get_nth (vals, 1), change->vcard);
+			/* Now change->vcard is owned by the GValue */
 
-	GNOME_Evolution_Addressbook_BookListener_notifyConnectionStatus (
-		book->priv->listener, (CORBA_boolean) is_online, &ev);
+			g_free (change);
+			changes = g_list_remove (changes, change);
+		}
 
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_data_book_report_connection_status: Exception "
-			   "responding to BookListener!\n");
+		dbus_g_method_return (context, array);
+		g_ptr_array_foreach (array, (GFunc)g_value_array_free, NULL);
+		g_ptr_array_free (array, TRUE);
 	}
-
-	CORBA_exception_free (&ev);
-
 }
 
-/**
- * e_data_book_report_connection_status:
- * @book: an #EDataBook
- *
- * Notify listeners that @book requires authentication.
- **/
-void
-e_data_book_report_auth_required (EDataBook *book)
+static gboolean
+impl_AddressBook_Book_cancelOperation(EDataBook *book, GError **error)
 {
-
-	CORBA_Environment ev;
-
-	CORBA_exception_init (&ev);
-
-	GNOME_Evolution_Addressbook_BookListener_notifyAuthRequired (
-			 book->priv->listener,  &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("e_data_book_report_auth_required: Exception "
-			   "responding to BookListener!\n");
+	if (!e_book_backend_cancel_operation (e_data_book_get_backend (book), book)) {
+		g_set_error (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_COULD_NOT_CANCEL, "Failed to cancel operation");
+		return FALSE;
 	}
 
-	CORBA_exception_free (&ev);
-
+	return TRUE;
 }
 
 static void
-e_data_book_construct (EDataBook                *book,
-		       EBookBackend             *backend,
-		       ESource *source,
-		       GNOME_Evolution_Addressbook_BookListener listener)
+impl_AddressBook_Book_close(EDataBook *book, DBusGMethodInvocation *context)
 {
-	EDataBookPrivate *priv;
-	CORBA_Environment ev;
+	char *sender;
 
-	g_return_if_fail (book != NULL);
-	g_return_if_fail (source != NULL);
-
-	priv = book->priv;
+	sender = dbus_g_method_get_sender (context);
 
-	CORBA_exception_init (&ev);
-	book->priv->listener = CORBA_Object_duplicate (listener, &ev);
+	book->closed_cb (book, sender);
 
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_message ("e_data_book_construct(): could not duplicate the listener");
-		CORBA_exception_free (&ev);
-		return;
-	}
+	g_free (sender);
 
-	CORBA_exception_free (&ev);
+	g_object_unref (book);
 
-	g_object_ref (source);
-
-	priv->backend   = g_object_ref(backend);
-	priv->source    = source;
+	dbus_g_method_return (context);
 }
 
-/**
- * e_data_book_new:
- * @backend: an #EBookBackend
- * @source: an #ESource
- * @listener: a #GNOME_Evolution_Addressbook_BookListener CORBA object
- *
- * Create a new #EDataBook using @backend for storage, @source as the
- * storage location and @listener for reporting status.
- *
- * Return value: A new #EDataBook.
- **/
-EDataBook *
-e_data_book_new (EBookBackend                               *backend,
-		 ESource *source,
-		 GNOME_Evolution_Addressbook_BookListener  listener)
+void
+e_data_book_report_writable (EDataBook *book, gboolean writable)
 {
-	static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
-	static PortableServer_POA poa = NULL;
-	EDataBook *book;
-
-	g_static_mutex_lock (&mutex);
-	if (poa == NULL)
-		poa = bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL);
-	g_static_mutex_unlock (&mutex);
-
-	book = g_object_new (E_TYPE_DATA_BOOK, "poa", poa, NULL);
-
-	e_data_book_construct (book, backend, source, listener);
+	g_return_if_fail (book != NULL);
 
-	return book;
+	g_signal_emit (book, signals[WRITABLE], 0, writable);
 }
 
-static void
-e_data_book_dispose (GObject *object)
+void
+e_data_book_report_connection_status (EDataBook *book, gboolean connected)
 {
-	EDataBook *book = E_DATA_BOOK (object);
-
-	if (book->priv) {
-		CORBA_Environment ev;
-
-		CORBA_exception_init (&ev);
-		CORBA_Object_release (book->priv->listener, &ev);
-
-		if (ev._major != CORBA_NO_EXCEPTION)
-			g_message ("e_data_book_construct(): could not release the listener");
+	g_return_if_fail (book != NULL);
 
-		CORBA_exception_free (&ev);
+	g_signal_emit (book, signals[CONNECTION], 0, connected);
+}
 
-		g_object_unref (book->priv->source);
-		g_object_unref (book->priv->backend);
-		g_free (book->priv);
-		book->priv = NULL;
-	}
+void
+e_data_book_report_auth_required (EDataBook *book)
+{
+	g_return_if_fail (book != NULL);
 
-	if (G_OBJECT_CLASS (e_data_book_parent_class)->dispose)
-		G_OBJECT_CLASS (e_data_book_parent_class)->dispose (object);
+	g_signal_emit (book, signals[AUTH_REQUIRED], 0);
 }
 
 static void
-e_data_book_class_init (EDataBookClass *klass)
+return_status_and_list (guint32 opid, EDataBookStatus status, GList *list, gboolean free_data)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	POA_GNOME_Evolution_Addressbook_Book__epv *epv;
+	DBusGMethodInvocation *context = opid_fetch (opid);
 
-	e_data_book_parent_class = g_type_class_peek_parent (klass);
+	if (status == E_DATA_BOOK_STATUS_SUCCESS) {
+		char **array;
+		GList *l;
+		int i = 0;
 
-	object_class->dispose = e_data_book_dispose;
+		array = g_new0 (char*, g_list_length (list) + 1);
+		for (l = list; l != NULL; l = l->next) {
+			array[i++] = l->data;
+		}
 
-	epv = &klass->epv;
+		dbus_g_method_return (context, array);
 
-	epv->open                    = impl_GNOME_Evolution_Addressbook_Book_open;
-	epv->remove                  = impl_GNOME_Evolution_Addressbook_Book_remove;
-	epv->getContact              = impl_GNOME_Evolution_Addressbook_Book_getContact;
-	epv->getContactList          = impl_GNOME_Evolution_Addressbook_Book_getContactList;
-	epv->authenticateUser        = impl_GNOME_Evolution_Addressbook_Book_authenticateUser;
-	epv->addContact              = impl_GNOME_Evolution_Addressbook_Book_addContact;
-	epv->removeContacts          = impl_GNOME_Evolution_Addressbook_Book_removeContacts;
-	epv->modifyContact           = impl_GNOME_Evolution_Addressbook_Book_modifyContact;
-	epv->getStaticCapabilities   = impl_GNOME_Evolution_Addressbook_Book_getStaticCapabilities;
-	epv->getSupportedFields      = impl_GNOME_Evolution_Addressbook_Book_getSupportedFields;
-	epv->getRequiredFields       = impl_GNOME_Evolution_Addressbook_Book_getRequiredFields;
-	epv->getSupportedAuthMethods = impl_GNOME_Evolution_Addressbook_Book_getSupportedAuthMethods;
-	epv->getBookView             = impl_GNOME_Evolution_Addressbook_Book_getBookView;
-	epv->getChanges              = impl_GNOME_Evolution_Addressbook_Book_getChanges;
-	epv->cancelOperation         = impl_GNOME_Evolution_Addressbook_Book_cancelOperation;
-
-}
-
-static void
-e_data_book_init (EDataBook *book)
-{
-	book->priv                = g_new0 (EDataBookPrivate, 1);
+		if (free_data) {
+			g_strfreev (array);
+		} else {
+			g_free (array);
+		}
+	} else {
+		dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot complete operation")));
+	}
 }
-
-BONOBO_TYPE_FUNC_FULL (
-		       EDataBook,
-		       GNOME_Evolution_Addressbook_Book,
-		       BONOBO_TYPE_OBJECT,
-		       e_data_book)
diff --git a/addressbook/libedata-book/e-data-book.h b/addressbook/libedata-book/e-data-book.h
index 6d891d7..d7c9d7d 100644
--- a/addressbook/libedata-book/e-data-book.h
+++ b/addressbook/libedata-book/e-data-book.h
@@ -1,110 +1,112 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * A wrapper object which exports the GNOME_Evolution_Addressbook_Book CORBA interface
- * and which maintains a request queue.
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
  *
- * Author:
- *   Nat Friedman (nat ximian com)
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
  *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ross Burton <ross linux intel com>
  */
 
 #ifndef __E_DATA_BOOK_H__
 #define __E_DATA_BOOK_H__
 
-#include <bonobo/bonobo-object.h>
-#include "libedataserver/e-list.h"
-#include "libedataserver/e-source.h"
-#include <libedata-book/Evolution-DataServer-Addressbook.h>
-#include <libedata-book/e-data-book-types.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include <libedataserver/e-source.h>
+#include "e-book-backend.h"
+#include "e-data-book-types.h"
 
 G_BEGIN_DECLS
 
 #define E_TYPE_DATA_BOOK        (e_data_book_get_type ())
 #define E_DATA_BOOK(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_DATA_BOOK, EDataBook))
-#define E_DATA_BOOK_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), E_TYPE_DATA_BOOK, EDataBookClass))
+#define E_DATA_BOOK_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST ((k), E_TYPE_DATA_BOOK, EDataBookClass))
 #define E_IS_DATA_BOOK(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_DATA_BOOK))
 #define E_IS_DATA_BOOK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_DATA_BOOK))
 #define E_DATA_BOOK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), E_TYPE_DATA_BOOK, EDataBookClass))
 
-typedef struct _EDataBookPrivate EDataBookPrivate;
+typedef void (* EDataBookClosedCallback) (EDataBook *book, const char *client);
 
 struct _EDataBook {
-	BonoboObject       parent_object;
-	EDataBookPrivate    *priv;
+	GObject parent;
+	EBookBackend *backend;
+	ESource *source;
+	/* TODO: move to private data */
+	EDataBookClosedCallback closed_cb;
 };
 
 struct _EDataBookClass {
-	BonoboObjectClass parent_class;
-
-	POA_GNOME_Evolution_Addressbook_Book__epv epv;
-
-	/* Padding for future expansion */
-	void (*_pas_reserved0) (void);
-	void (*_pas_reserved1) (void);
-	void (*_pas_reserved2) (void);
-	void (*_pas_reserved3) (void);
-	void (*_pas_reserved4) (void);
+	GObjectClass parent;
 };
 
+GQuark e_data_book_error_quark (void);
+#define E_DATA_BOOK_ERROR e_data_book_error_quark ()
 
-EDataBook                *e_data_book_new                    (EBookBackend                               *backend,
-							      ESource                                  *source,
-							 GNOME_Evolution_Addressbook_BookListener  listener);
-GNOME_Evolution_Addressbook_BookListener e_data_book_get_listener (EDataBook                         *book);
+EDataBook                *e_data_book_new                    (EBookBackend *backend,
+							      ESource *source,
+							 EDataBookClosedCallback closed_cb);
 EBookBackend             *e_data_book_get_backend            (EDataBook                                *book);
 ESource                *e_data_book_get_source             (EDataBook                                *book);
 
-void                    e_data_book_respond_open           (EDataBook                                *book,
-							    guint32                                   opid,
-							    GNOME_Evolution_Addressbook_CallStatus    status);
-void                    e_data_book_respond_remove         (EDataBook                                *book,
-							    guint32                                   opid,
-							    GNOME_Evolution_Addressbook_CallStatus  status);
-void                    e_data_book_respond_create         (EDataBook                                *book,
-							    guint32                                   opid,
-							    GNOME_Evolution_Addressbook_CallStatus  status,
-							    EContact                               *contact);
-void                    e_data_book_respond_remove_contacts (EDataBook                                *book,
-							     guint32                                   opid,
-							     GNOME_Evolution_Addressbook_CallStatus  status,
-							     GList                                  *ids);
-void                    e_data_book_respond_modify         (EDataBook                                *book,
-							    guint32                                   opid,
-							    GNOME_Evolution_Addressbook_CallStatus  status,
-							    EContact                               *contact);
-void                    e_data_book_respond_authenticate_user (EDataBook                                *book,
-							       guint32                                   opid,
-							       GNOME_Evolution_Addressbook_CallStatus  status);
-void                    e_data_book_respond_get_supported_fields (EDataBook                              *book,
-								  guint32                                 opid,
-								  GNOME_Evolution_Addressbook_CallStatus  status,
-								  GList                                  *fields);
-void                    e_data_book_respond_get_required_fields (EDataBook                              *book,
-								  guint32                                 opid,
-								  GNOME_Evolution_Addressbook_CallStatus  status,
-								  GList                                  *fields);
-void                    e_data_book_respond_get_supported_auth_methods (EDataBook                              *book,
-									guint32                                 opid,
-									GNOME_Evolution_Addressbook_CallStatus  status,
-									GList                                  *fields);
-
-void                    e_data_book_respond_get_book_view  (EDataBook                              *book,
-							    guint32                                 opid,
-							    GNOME_Evolution_Addressbook_CallStatus  status,
-							    EDataBookView                          *book_view);
-void                    e_data_book_respond_get_contact    (EDataBook                              *book,
-							    guint32                                 opid,
-							    GNOME_Evolution_Addressbook_CallStatus  status,
-							    const gchar                            *vcard);
-void                    e_data_book_respond_get_contact_list (EDataBook                              *book,
-							      guint32                                 opid,
-							      GNOME_Evolution_Addressbook_CallStatus  status,
+void                    e_data_book_respond_open           (EDataBook *book,
+							    guint32 opid,
+							    EDataBookStatus status);
+void                    e_data_book_respond_remove         (EDataBook *book,
+							    guint32 opid,
+							    EDataBookStatus status);
+void                    e_data_book_respond_create         (EDataBook *book,
+							    guint32 opid,
+							    EDataBookStatus status,
+							    EContact *contact);
+void                    e_data_book_respond_remove_contacts (EDataBook *book,
+							     guint32 opid,
+							     EDataBookStatus  status,
+							     GList *ids);
+void                    e_data_book_respond_modify         (EDataBook *book,
+							    guint32 opid,
+							    EDataBookStatus status,
+							    EContact *contact);
+void                    e_data_book_respond_authenticate_user (EDataBook *book,
+							       guint32 opid,
+							       EDataBookStatus status);
+void                    e_data_book_respond_get_supported_fields (EDataBook *book,
+								  guint32 opid,
+								  EDataBookStatus status,
+								  GList *fields);
+void                    e_data_book_respond_get_required_fields (EDataBook *book,
+								  guint32 opid,
+								  EDataBookStatus status,
+								  GList *fields);
+void                    e_data_book_respond_get_supported_auth_methods (EDataBook *book,
+									guint32 opid,
+									EDataBookStatus status,
+									GList *fields);
+
+void                    e_data_book_respond_get_contact (EDataBook *book,
+							    guint32 opid,
+							    EDataBookStatus status,
+							    const gchar *vcard);
+void                    e_data_book_respond_get_contact_list (EDataBook *book,
+							      guint32 opid,
+							      EDataBookStatus status,
 							      GList *cards);
-void                    e_data_book_respond_get_changes    (EDataBook                              *book,
-							    guint32                                 opid,
-							    GNOME_Evolution_Addressbook_CallStatus  status,
-							    GList                                  *changes);
+void                    e_data_book_respond_get_changes    (EDataBook *book,
+							    guint32 opid,
+							    EDataBookStatus status,
+							    GList *changes);
 
 void                    e_data_book_report_writable        (EDataBook                         *book,
 							    gboolean                           writable);
diff --git a/addressbook/libedata-book/glib-gen.mak b/addressbook/libedata-book/glib-gen.mak
new file mode 100644
index 0000000..f510d80
--- /dev/null
+++ b/addressbook/libedata-book/glib-gen.mak
@@ -0,0 +1,42 @@
+# these are the variables your Makefile.am should set
+# the example is based on the colorbalance interface
+
+#glib_enum_headers=$(colorbalance_headers)
+#glib_enum_define=GST_COLOR_BALANCE
+#glib_enum_prefix=gst_color_balance
+
+# these are all the rules generating the relevant files
+%-marshal.h: %-marshal.list
+	glib-genmarshal --header --prefix=$(glib_enum_prefix)_marshal $^ > $*-marshal.h.tmp
+	mv $*-marshal.h.tmp $*-marshal.h
+
+%-marshal.c: %-marshal.list
+	echo "#include \"$*-marshal.h\"" >> $*-marshal.c.tmp
+	glib-genmarshal --body --prefix=$(glib_enum_prefix)_marshal $^ >> $*-marshal.c.tmp
+	mv $*-marshal.c.tmp $*-marshal.c
+
+%-enumtypes.h: $(glib_enum_headers)
+	glib-mkenums \
+	--fhead "#ifndef __$(glib_enum_define)_ENUM_TYPES_H__\n#define __$(glib_enum_define)_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
+	--fprod "/* enumerations from \"@filename \" */\n" \
+	--vhead "GType @enum_name _get_type (void);\n#define E_TYPE_ ENUMSHORT@ (@enum_name _get_type())\n"         \
+	--ftail "G_END_DECLS\n\n#endif /* __$(glib_enum_define)_ENUM_TYPES_H__ */" \
+	$^ > $@
+
+%-enumtypes.c: $(glib_enum_headers)
+	@if test "x$(glib_enum_headers)" == "x"; then echo "ERROR: glib_enum_headers is empty, please fix Makefile"; exit 1; fi
+	glib-mkenums \
+	--fhead "#include <$*.h>\n#include \"$*-enumtypes.h\"" \
+	--fprod "\n/* enumerations from \"@filename \" */" \
+	--vhead "GType\n enum_name@_get_type (void)\n{\n  static GType etype = 0;\n  if (etype == 0) {\n    static const G Type@Value values[] = {"     \
+	--vprod "      { @VALUENAME@, \"@VALUENAME \", \"@valuenick \" }," \
+	--vtail "      { 0, NULL, NULL }\n    };\n    etype = g_ type@_register_static (\"@EnumName \", values);\n  }\n  return etype;\n}\n" \
+	$^ > $@
+
+# a hack rule to make sure .Plo files exist because they get include'd
+# from Makefile's
+.deps/%-marshal.Plo:
+	touch $@
+
+.deps/%-enumtypes.Plo:
+	touch $@
diff --git a/addressbook/libedata-book/libedata-book.pc.in b/addressbook/libedata-book/libedata-book.pc.in
index 8ab451e..d99e1b8 100644
--- a/addressbook/libedata-book/libedata-book.pc.in
+++ b/addressbook/libedata-book/libedata-book.pc.in
@@ -5,14 +5,11 @@ includedir= includedir@
 datarootdir= datarootdir@
 datadir= datadir@
 
-idldir= idldir@
-IDL_INCLUDES=-I${idldir} @IDL_INCLUDES@
-
 privincludedir= privincludedir@
 
 Name: libedatabook
 Description: Backend library for evolution address books
 Version: @VERSION@
-Requires: libbonobo-2.0 >= @LIBBONOBO_REQUIRED@ libedataserver-1.2 libebackend-1.2 libebook-1.2
+Requires: libedataserver-1.2 libebook-1.2 dbus-glib-1
 Libs: -L${libdir} -ledata-book-1.2
 Cflags: -I${privincludedir}
diff --git a/addressbook/libedata-book/opid.c b/addressbook/libedata-book/opid.c
new file mode 100644
index 0000000..127e0c1
--- /dev/null
+++ b/addressbook/libedata-book/opid.c
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ross Burton <ross linux intel com>
+ */
+
+#include "opid.h"
+
+G_LOCK_DEFINE_STATIC (lock);
+static int counter = 0;
+static GHashTable *hash = NULL;
+
+static void
+opid_init (void)
+{
+	counter = 1;
+	hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+}
+
+guint32
+opid_store (gpointer p)
+{
+	int id;
+
+	g_return_val_if_fail (p, 0);
+
+	G_LOCK (lock);
+
+	if (G_UNLIKELY (hash == NULL))
+		opid_init ();
+
+	do {
+		id = counter++;
+	} while (g_hash_table_lookup (hash, GINT_TO_POINTER (id)) != NULL);
+
+	g_hash_table_insert (hash, GINT_TO_POINTER (id), p);
+
+	G_UNLOCK (lock);
+
+	return id;
+}
+
+gpointer
+opid_fetch (guint32 id)
+{
+	gpointer p;
+
+	G_LOCK (lock);
+
+	if (G_UNLIKELY (hash == NULL))
+		opid_init ();
+
+	p = g_hash_table_lookup (hash, GINT_TO_POINTER (id));
+
+	g_hash_table_remove (hash, GINT_TO_POINTER (id));
+
+	G_UNLOCK (lock);
+
+	return p;
+}
diff --git a/addressbook/libedata-book/opid.h b/addressbook/libedata-book/opid.h
new file mode 100644
index 0000000..20bbf1a
--- /dev/null
+++ b/addressbook/libedata-book/opid.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ross Burton <ross linux intel com>
+ */
+
+#include <glib.h>
+
+/* Stupid EDS internal API */
+
+guint32 opid_store (gpointer p);
+
+gpointer opid_fetch (guint32 id);
diff --git a/addressbook/libedata-book/org.gnome.evolution.dataserver.AddressBook.service.in b/addressbook/libedata-book/org.gnome.evolution.dataserver.AddressBook.service.in
new file mode 100644
index 0000000..0928311
--- /dev/null
+++ b/addressbook/libedata-book/org.gnome.evolution.dataserver.AddressBook.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gnome.evolution.dataserver.AddressBook
+Exec= LIBEXECDIR@/e-addressbook-factory



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]