/* Callback used when a backend loses its last connected client */
static void
backend_last_client_gone_cb (EBookBackend *backend, gpointer data)
{
	EDataBookFactory *factory;
	ESource *source;
	gchar *uri;

	factory = E_DATA_BOOK_FACTORY (data);

	/* Remove the backend from the active server map */

	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);
	}

	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);
}
static EDataBookFactory *
book_backend_factory_get_data_factory (EBackendFactory *factory)
{
	EExtensible *extensible;

	extensible = e_extension_get_extensible (E_EXTENSION (factory));

	return E_DATA_BOOK_FACTORY (extensible);
}
static void
e_data_book_factory_finalize (GObject *object)
{
	EDataBookFactory *factory = E_DATA_BOOK_FACTORY (object);
	EDataBookFactoryPrivate *priv = factory->priv;

	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);

	if (G_OBJECT_CLASS (e_data_book_factory_parent_class)->finalize)
		G_OBJECT_CLASS (e_data_book_factory_parent_class)->finalize (object);
}
static void
e_data_book_factory_dispose (GObject *object)
{
	EDataBookFactory *factory = E_DATA_BOOK_FACTORY (object);
	EDataBookFactoryPrivate *priv = factory->priv;

	g_hash_table_remove_all (priv->active_server_map);
	g_hash_table_remove_all (priv->backends);

	if (priv->registered) {
		bonobo_activation_active_server_unregister (
			priv->iid, bonobo_object_corba_objref (
			BONOBO_OBJECT (factory)));
		priv->registered = FALSE;
	}

	if (G_OBJECT_CLASS (e_data_book_factory_parent_class)->dispose)
		G_OBJECT_CLASS (e_data_book_factory_parent_class)->dispose (object);
}
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)
{
	EDataBookFactory      *factory = E_DATA_BOOK_FACTORY (bonobo_object (servant));
	GNOME_Evolution_Addressbook_Book corba_book;
	EBookBackend *backend;
	EDataBook *book = NULL;
	ESource *source;
	gchar *uri;

	printf ("impl_GNOME_Evolution_Addressbook_BookFactory_getBook\n");

	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;
	}

	uri = e_source_get_uri (source);
	if (!uri) {
		g_object_unref (source);
		CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
				     ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported,
				     NULL);
		return CORBA_OBJECT_NIL;
	}
	printf (" + %s\n", uri);

	/* Look up the backend and create one if needed */
	g_mutex_lock (factory->priv->map_mutex);

	backend = g_hash_table_lookup (factory->priv->active_server_map, uri);

	if (!backend) {
		EBookBackendFactory*  backend_factory;

		backend_factory = e_data_book_factory_lookup_backend_factory (factory, uri);

		if (backend_factory == NULL) {
			CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
					     ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported,
					     NULL);

			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_free (uri);

	if (backend) {
		g_mutex_unlock (factory->priv->map_mutex);

		book = e_data_book_new (backend, source, listener);

		e_book_backend_add_client (backend, book);
		e_book_backend_set_mode (backend, factory->priv->mode);
		corba_book = bonobo_object_corba_objref (BONOBO_OBJECT (book));
	}
	else {
		/* probably need a more descriptive exception here */
		CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
				     ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported,
				     NULL);
		g_mutex_unlock (factory->priv->map_mutex);

		corba_book = CORBA_OBJECT_NIL;
	}

	g_object_unref (source);
	if (book)
		printf (" => %p\n", book);
	return corba_book;
}