diff options
author | Ross Burton <ross@linux.intel.com> | 2009-06-15 08:54:43 +0100 |
---|---|---|
committer | Ross Burton <ross@linux.intel.com> | 2009-08-17 13:01:53 +0100 |
commit | f296cb9c794c649f431a8d1210bd92d91086fc5d (patch) | |
tree | b99a3ffe832d0e55c7218a0114f1fc6178732148 | |
parent | 84a1355a10557a912676d92a53167a070cb5dabc (diff) | |
download | evolution-data-server-f296cb9c794c649f431a8d1210bd92d91086fc5d.tar.gz |
Port libedata-book to DBus
-rw-r--r-- | addressbook/libedata-book/Makefile.am | 60 | ||||
-rw-r--r-- | addressbook/libedata-book/e-book-backend-sync.h | 1 | ||||
-rw-r--r-- | addressbook/libedata-book/e-book-backend.c | 60 | ||||
-rw-r--r-- | addressbook/libedata-book/e-book-backend.h | 3 | ||||
-rw-r--r-- | addressbook/libedata-book/e-data-book-factory.c | 663 | ||||
-rw-r--r-- | addressbook/libedata-book/e-data-book-factory.h | 51 | ||||
-rw-r--r-- | addressbook/libedata-book/e-data-book-types.h | 99 | ||||
-rw-r--r-- | addressbook/libedata-book/e-data-book-view.c | 790 | ||||
-rw-r--r-- | addressbook/libedata-book/e-data-book-view.h | 47 | ||||
-rw-r--r-- | addressbook/libedata-book/e-data-book.c | 1289 | ||||
-rw-r--r-- | addressbook/libedata-book/e-data-book.h | 157 | ||||
-rw-r--r-- | addressbook/libedata-book/glib-gen.mak | 42 | ||||
-rw-r--r-- | addressbook/libedata-book/libedata-book.pc.in | 5 | ||||
-rw-r--r-- | addressbook/libedata-book/opid.c | 75 | ||||
-rw-r--r-- | addressbook/libedata-book/opid.h | 28 | ||||
-rw-r--r-- | addressbook/libedata-book/org.gnome.evolution.dataserver.AddressBook.service.in | 3 |
16 files changed, 1533 insertions, 1840 deletions
diff --git a/addressbook/libedata-book/Makefile.am b/addressbook/libedata-book/Makefile.am index 6389ce4ba..cf8f0b88a 100644 --- a/addressbook/libedata-book/Makefile.am +++ b/addressbook/libedata-book/Makefile.am @@ -1,36 +1,29 @@ AM_CPPFLAGS = \ -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 +%-glue.h: %.xml + dbus-binding-tool --mode=glib-server --output=$@ --prefix=$(subst -,_,$*) $^ -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 +31,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 +50,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 +68,27 @@ 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) $(ENUM_GENERATED) +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) + +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 b51d46181..589fa62d4 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 7ef6da85d..61460e24c 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 6ece62e8d..27d03b7ce 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 5f1410a93..a3bd588eb 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) -{ - 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) +e_data_book_factory_class_init (EDataBookFactoryClass *e_data_book_factory_class) { - 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; - - 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); - } + 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 (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,336 +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); - canonical_uri = e_data_book_factory_canonicalize_uri (uri); - if (canonical_uri == NULL) - return NULL; + g_return_val_if_fail (E_IS_DATA_BOOK_FACTORY (factory), NULL); + g_return_val_if_fail (uri != NULL, 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; + 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; +} - backend = e_book_backend_factory_new_backend (backend_factory); - if (!backend) - return NULL; +static void +my_remove (char *key, GObject *dead) +{ + g_mutex_lock (factory->priv->books_lock); + g_hash_table_remove (factory->priv->books, key); + g_mutex_unlock (factory->priv->books_lock); - g_hash_table_insert (book_factory->priv->active_server_map, - g_strdup (uri), - backend); + g_free (key); - g_signal_connect (backend, "last_client_gone", - G_CALLBACK (backend_last_client_gone_cb), - book_factory); + /* 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); + } +} - return backend; +static void +book_closed_cb (EDataBook *book, const char *client) +{ + GList *list; + + 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); } -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 +impl_BookFactory_getBook(EDataBookFactory *factory, const char *IN_uri, DBusGMethodInvocation *context) { - EDataBookFactory *factory = E_DATA_BOOK_FACTORY (bonobo_object (servant)); - GNOME_Evolution_Addressbook_Book corba_book; - EBookBackend *backend; - EDataBook *book = NULL; + EDataBook *book; + EDataBookFactoryPrivate *priv = factory->priv; ESource *source; - gchar *uri; - - printf ("impl_GNOME_Evolution_Addressbook_BookFactory_getBook\n"); + char *path, *sender; + GList *list; - 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 (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; } - 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; + /* Remove a pending exit */ + if (priv->exit_timeout) { + g_source_remove (priv->exit_timeout); + priv->exit_timeout = 0; } - 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); - - g_mutex_unlock (factory->priv->map_mutex); - - g_free (uri); - return CORBA_OBJECT_NIL; - } - backend = e_data_book_factory_launch_backend (factory, backend_factory, listener, uri); + 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); - g_free (uri); - - if (backend) { - g_mutex_unlock (factory->priv->map_mutex); + /* 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); - book = e_data_book_new (backend, source, listener); + g_mutex_unlock (priv->books_lock); - 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; - } - - g_object_unref (source); - if (book) - printf (" => %p\n", (gpointer) book); - return corba_book; + dbus_g_method_return (context, path); } static void -e_data_book_factory_construct (EDataBookFactory *factory) +name_owner_changed (DBusGProxy *proxy, + const char *name, + const char *prev_owner, + const char *new_owner, + EDataBookFactory *factory) { - /* nothing to do here.. */ + 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); + } } -/** - * e_data_book_factory_new: - * - * Create a new #EDataBookFactory. - * - * Return value: A new #EDataBookFactory. - **/ -EDataBookFactory * -e_data_book_factory_new (void) +/* Convenience function to print an error and exit */ +static void +die (const char *prefix, GError *error) { - 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); - - e_data_book_factory_construct (factory); - - return factory; + g_error("%s: %s", prefix, error->message); + g_error_free (error); + exit(1); } -/** - * 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) -{ - 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; - } +#define E_DATA_BOOK_FACTORY_SERVICE_NAME "org.gnome.evolution.dataserver.AddressBook" - g_free (tmp_iid); - return FALSE; -} -static void -set_backend_online_status (gpointer key, gpointer value, gpointer data) +int +main (int argc, char **argv) { - EBookBackend *backend; + GError *error = NULL; + DBusGProxy *bus_proxy; + guint32 request_name_ret; - backend = E_BOOK_BACKEND (value); - e_book_backend_set_mode (backend, GPOINTER_TO_INT (data)); -} + g_type_init (); + if (!g_thread_supported ()) g_thread_init (NULL); + dbus_g_thread_init (); -/** - * 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; + loop = g_main_loop_new (NULL, FALSE); - 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); - -} -static void -e_data_book_factory_init (EDataBookFactory *factory) -{ - GHashTable *active_server_map; - GHashTable *backends; + /* 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); - active_server_map = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); + bus_proxy = dbus_g_proxy_new_for_name (connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); - backends = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) NULL); + 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); - factory->priv = g_new0 (EDataBookFactoryPrivate, 1); + if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + g_error ("Got result code %u from requesting name", request_name_ret); + exit (1); + } - factory->priv->map_mutex = g_mutex_new(); - factory->priv->active_server_map = active_server_map; - factory->priv->backends = backends; - factory->priv->registered = FALSE; -} + 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_dispose (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_hash_table_remove_all (priv->active_server_map); - g_hash_table_remove_all (priv->backends); + g_main_loop_run (loop); - if (priv->registered) { - bonobo_activation_active_server_unregister ( - priv->iid, bonobo_object_corba_objref ( - BONOBO_OBJECT (factory))); - priv->registered = FALSE; - } + dbus_g_connection_unref (connection); - if (G_OBJECT_CLASS (e_data_book_factory_parent_class)->dispose) - G_OBJECT_CLASS (e_data_book_factory_parent_class)->dispose (object); + return 0; } -static void -e_data_book_factory_finalize (GObject *object) +/* Stolen from http://cvs.gnome.org/viewcvs/NetworkManager/utils/nm-utils.c */ +static gchar *nm_dbus_escape_object_path (const gchar *utf8_string) { - EDataBookFactory *factory = E_DATA_BOOK_FACTORY (object); - EDataBookFactoryPrivate *priv = factory->priv; + const gchar *p; + GString *string; - 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); + g_return_val_if_fail (utf8_string != NULL, NULL); + g_return_val_if_fail (g_utf8_validate (utf8_string, -1, NULL), NULL); - if (G_OBJECT_CLASS (e_data_book_factory_parent_class)->finalize) - G_OBJECT_CLASS (e_data_book_factory_parent_class)->finalize (object); -} + string = g_string_sized_new ((strlen (utf8_string) + 1) * 2); -static void -e_data_book_factory_class_init (EDataBookFactoryClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - POA_GNOME_Evolution_Addressbook_BookFactory__epv *epv; - - e_data_book_factory_parent_class = g_type_class_peek_parent (klass); + for (p = utf8_string; *p != '\0'; p = g_utf8_next_char (p)) + { + gunichar character; - object_class->dispose = e_data_book_factory_dispose; - object_class->finalize = e_data_book_factory_finalize; + character = g_utf8_get_char (p); - 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); + 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 = &klass->epv; + g_string_append_printf (string, "_%x_", character); + } - epv->getBook = impl_GNOME_Evolution_Addressbook_BookFactory_getBook; + return g_string_free (string, FALSE); } - -BONOBO_TYPE_FUNC_FULL ( - EDataBookFactory, - GNOME_Evolution_Addressbook_BookFactory, - BONOBO_TYPE_OBJECT, - e_data_book_factory) diff --git a/addressbook/libedata-book/e-data-book-factory.h b/addressbook/libedata-book/e-data-book-factory.h index 01048c614..d90a061e1 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 30ced269e..618fb7b72 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 94ef8a651..c3861dd34 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 1bdfafac1..160a44338 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,21 +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, @@ -55,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); @@ -70,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 224cd8974..4d770cf81 100644 --- a/addressbook/libedata-book/e-data-book.c +++ b/addressbook/libedata-book/e-data-book.c @@ -1,1012 +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 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"); - - e_book_backend_remove (e_data_book_get_backend (book), book, opid); -} +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_getContact (PortableServer_Servant servant, - const CORBA_long opid, - const CORBA_char *id, - CORBA_Environment *ev) -{ - EDataBook *book = E_DATA_BOOK (bonobo_object (servant)); - - printf ("impl_GNOME_Evolution_Addressbook_Book_getContact\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_get_contact (e_data_book_get_backend (book), book, opid, id); + g_object_unref (op->book); + g_slice_free (OperationData, op); } -static void -impl_GNOME_Evolution_Addressbook_Book_getContactList (PortableServer_Servant servant, - const CORBA_long opid, - const CORBA_char *query, - 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_getContactList\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_list (e_data_book_get_backend (book), book, opid, query); + return data; } -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) -{ - 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 void -impl_GNOME_Evolution_Addressbook_Book_addContact (PortableServer_Servant servant, - const CORBA_long opid, - const CORBA_char *vcard, - 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_create_contact (e_data_book_get_backend (book), book, opid, vcard); + 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_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); -} +/* Generate the GObject boilerplate */ +G_DEFINE_TYPE(EDataBook, e_data_book, G_TYPE_OBJECT) 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)); + GObjectClass *object_class = G_OBJECT_CLASS (e_data_book_class); - 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; -} + 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; - - CORBA_exception_init (&ev); - GNOME_Evolution_Addressbook_BookListener_notifyBookRemoved (book->priv->listener, opid, status, &ev); + OperationData *op; - 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; - - CORBA_exception_init (&ev); + DBusGMethodInvocation *context = opid_fetch (opid); - GNOME_Evolution_Addressbook_BookListener_notifyAuthenticationResult ( - book->priv->listener, opid, status, &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)); - 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; - - CORBA_exception_init (&ev); + DBusGMethodInvocation *context = opid_fetch (opid); - num_auth_methods = g_list_length (auth_methods); + 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; - 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); + sender = dbus_g_method_get_sender (context); - priv = book->priv; + book->closed_cb (book, sender); - CORBA_exception_init (&ev); - book->priv->listener = CORBA_Object_duplicate (listener, &ev); + g_free (sender); - if (ev._major != CORBA_NO_EXCEPTION) { - g_message ("e_data_book_construct(): could not duplicate the listener"); - CORBA_exception_free (&ev); - return; - } - - CORBA_exception_free (&ev); - - g_object_ref (source); + g_object_unref (book); - 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; - - e_data_book_parent_class = g_type_class_peek_parent (klass); + DBusGMethodInvocation *context = opid_fetch (opid); - object_class->dispose = e_data_book_dispose; - - epv = &klass->epv; + if (status == E_DATA_BOOK_STATUS_SUCCESS) { + char **array; + GList *l; + int i = 0; - 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; + array = g_new0 (char*, g_list_length (list) + 1); + for (l = list; l != NULL; l = l->next) { + array[i++] = l->data; + } -} + dbus_g_method_return (context, array); -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 5b26b7815..d7c9d7dca 100644 --- a/addressbook/libedata-book/e-data-book.h +++ b/addressbook/libedata-book/e-data-book.h @@ -1,109 +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; }; -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); +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, + 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 000000000..f510d80b1 --- /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 8ab451e2d..d99e1b82d 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 000000000..127e0c18a --- /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 000000000..20bbf1af0 --- /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 000000000..092831154 --- /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 |