[evolution-data-server] Rework how CamelServices are added to CamelSession.



commit e0ac4d79705c8b51783c71b362499f38c15ee496
Author: Matthew Barnes <mbarnes redhat com>
Date:   Tue Apr 19 15:32:47 2011 -0400

    Rework how CamelServices are added to CamelSession.
    
    * Give CamelServices a simple unique ID string.  That will be its
      identity from now on, not its URL.
    
    * Split adding a CamelService and retrieving a CamelService into two
      separate operations.  Adding a CamelService requires both a UID and
      CamelURL (for now), retrieving a CamelService just requires the UID.
    
    * CamelService now implements the GInitable interface, replacing its
      construct() method.

 camel/camel-disco-store.c                          |   35 +-
 camel/camel-offline-store.c                        |   38 +-
 camel/camel-provider.c                             |    6 -
 camel/camel-provider.h                             |    2 -
 camel/camel-sasl-popb4smtp.c                       |   54 ++-
 camel/camel-service.c                              |  593 ++++++++++++++------
 camel/camel-service.h                              |   14 +-
 camel/camel-session.c                              |  409 +++++++++-----
 camel/camel-session.h                              |   37 +-
 camel/camel-store.c                                |  150 +++---
 camel/camel-vee-store.c                            |   32 +-
 camel/providers/groupwise/camel-groupwise-folder.c |   11 +-
 camel/providers/groupwise/camel-groupwise-store.c  |  283 ++++++----
 camel/providers/groupwise/camel-groupwise-store.h  |    1 -
 .../groupwise/camel-groupwise-transport.c          |   71 ++-
 .../groupwise/camel-groupwise-transport.h          |   10 +-
 camel/providers/imap/camel-imap-folder.c           |   10 +-
 camel/providers/imap/camel-imap-store.c            |  304 ++++++-----
 camel/providers/imap/camel-imap-store.h            |    2 +-
 camel/providers/imapx/camel-imapx-store.c          |  140 ++++--
 camel/providers/imapx/camel-imapx-store.h          |    2 +-
 camel/providers/imapx/test-imapx.c                 |    8 +-
 camel/providers/local/camel-local-store.c          |   99 ++--
 camel/providers/local/camel-mh-store.c             |   32 +-
 camel/providers/local/camel-spool-store.c          |  134 +++--
 camel/providers/nntp/camel-nntp-folder.c           |   17 +-
 camel/providers/nntp/camel-nntp-store.c            |   71 ++-
 camel/providers/nntp/camel-nntp-store.h            |    2 +-
 camel/providers/pop3/camel-pop3-store.c            |   21 +-
 docs/reference/camel/camel-sections.txt            |   13 +-
 .../reference/camel/tmpl/camel-cipher-context.sgml |   10 +
 docs/reference/camel/tmpl/camel-provider.sgml      |    2 -
 docs/reference/camel/tmpl/camel-service.sgml       |   32 +-
 docs/reference/camel/tmpl/camel-session.sgml       |   40 +-
 docs/reference/camel/tmpl/camel-unused.sgml        |   80 +++
 35 files changed, 1683 insertions(+), 1082 deletions(-)
---
diff --git a/camel/camel-disco-store.c b/camel/camel-disco-store.c
index d6e6306..fb3c1db 100644
--- a/camel/camel-disco-store.c
+++ b/camel/camel-disco-store.c
@@ -38,25 +38,25 @@
 
 G_DEFINE_TYPE (CamelDiscoStore, camel_disco_store, CAMEL_TYPE_STORE)
 
-static gboolean
-disco_store_construct (CamelService *service,
-                       CamelSession *session,
-                       CamelProvider *provider,
-                       CamelURL *url,
-                       GError **error)
+static void
+disco_store_constructed (GObject *object)
 {
-	CamelServiceClass *service_class;
-	CamelDiscoStore *disco = CAMEL_DISCO_STORE (service);
+	CamelDiscoStore *disco;
+	CamelService *service;
+	CamelSession *session;
 
-	/* Chain up to parent's construct() method. */
-	service_class = CAMEL_SERVICE_CLASS (camel_disco_store_parent_class);
-	if (!service_class->construct (service, session, provider, url, error))
-		return FALSE;
+	disco = CAMEL_DISCO_STORE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (camel_disco_store_parent_class)->constructed (object);
 
-	disco->status = camel_session_get_online (session) ?
-		CAMEL_DISCO_STORE_ONLINE : CAMEL_DISCO_STORE_OFFLINE;
+	service = CAMEL_SERVICE (object);
+	session = camel_service_get_session (service);
 
-	return TRUE;
+	if (camel_session_get_online (session))
+		disco->status = CAMEL_DISCO_STORE_ONLINE;
+	else
+		disco->status = CAMEL_DISCO_STORE_OFFLINE;
 }
 
 static void
@@ -311,11 +311,14 @@ disco_store_set_status (CamelDiscoStore *disco_store,
 static void
 camel_disco_store_class_init (CamelDiscoStoreClass *class)
 {
+	GObjectClass *object_class;
 	CamelServiceClass *service_class;
 	CamelStoreClass *store_class;
 
+	object_class = G_OBJECT_CLASS (class);
+	object_class->constructed = disco_store_constructed;
+
 	service_class = CAMEL_SERVICE_CLASS (class);
-	service_class->construct = disco_store_construct;
 	service_class->cancel_connect = disco_store_cancel_connect;
 	service_class->connect_sync = disco_store_connect_sync;
 	service_class->disconnect_sync = disco_store_disconnect_sync;
diff --git a/camel/camel-offline-store.c b/camel/camel-offline-store.c
index eb4e608..e5f5b12 100644
--- a/camel/camel-offline-store.c
+++ b/camel/camel-offline-store.c
@@ -31,49 +31,47 @@
 #include "camel-offline-store.h"
 #include "camel-session.h"
 
+#define CAMEL_OFFLINE_STORE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), CAMEL_TYPE_OFFLINE_STORE, CamelOfflineStorePrivate))
+
 struct _CamelOfflineStorePrivate {
 	gboolean online;
 };
 
 G_DEFINE_TYPE (CamelOfflineStore, camel_offline_store, CAMEL_TYPE_STORE)
 
-static gboolean
-offline_store_construct (CamelService *service,
-                         CamelSession *session,
-                         CamelProvider *provider,
-                         CamelURL *url,
-                         GError **error)
+static void
+offline_store_constructed (GObject *object)
 {
-	CamelOfflineStore *store = CAMEL_OFFLINE_STORE (service);
-	CamelServiceClass *service_class;
+	CamelOfflineStorePrivate *priv;
+	CamelSession *session;
 
-	/* Chain up to parent's construct() method. */
-	service_class = CAMEL_SERVICE_CLASS (camel_offline_store_parent_class);
-	if (!service_class->construct (service, session, provider, url, error))
-		return FALSE;
+	priv = CAMEL_OFFLINE_STORE_GET_PRIVATE (object);
 
-	store->priv->online = camel_session_get_online (session);
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (camel_offline_store_parent_class)->
+		constructed (object);
 
-	return TRUE;
+	session = camel_service_get_session (CAMEL_SERVICE (object));
+	priv->online = camel_session_get_online (session);
 }
 
 static void
 camel_offline_store_class_init (CamelOfflineStoreClass *class)
 {
-	CamelServiceClass *service_class;
+	GObjectClass *object_class;
 
 	g_type_class_add_private (class, sizeof (CamelOfflineStorePrivate));
 
-	service_class = CAMEL_SERVICE_CLASS (class);
-	service_class->construct = offline_store_construct;
+	object_class = G_OBJECT_CLASS (class);
+	object_class->constructed = offline_store_constructed;
 }
 
 static void
 camel_offline_store_init (CamelOfflineStore *store)
 {
-	store->priv = G_TYPE_INSTANCE_GET_PRIVATE (
-		store, CAMEL_TYPE_OFFLINE_STORE, CamelOfflineStorePrivate);
-	store->priv->online = TRUE;
+	store->priv = CAMEL_OFFLINE_STORE_GET_PRIVATE (store);
 }
 
 /**
diff --git a/camel/camel-provider.c b/camel/camel-provider.c
index edea3ae..67f45bf 100644
--- a/camel/camel-provider.c
+++ b/camel/camel-provider.c
@@ -243,12 +243,6 @@ camel_provider_register (CamelProvider *provider)
 		return;
 	}
 
-	for (i = 0; i < CAMEL_NUM_PROVIDER_TYPES; i++) {
-		if (provider->object_types[i])
-			provider->service_cache[i] = camel_object_bag_new (provider->url_hash, provider->url_equal,
-									   (CamelCopyFunc)camel_url_copy, (GFreeFunc)camel_url_free);
-	}
-
 	/* Translate all strings here */
 #define P_(string) dgettext (provider->translation_domain, string)
 
diff --git a/camel/camel-provider.h b/camel/camel-provider.h
index e98dd8c..8645685 100644
--- a/camel/camel-provider.h
+++ b/camel/camel-provider.h
@@ -223,8 +223,6 @@ typedef struct {
 	/* GList of CamelServiceAuthTypes the provider supports */
 	GList *authtypes;
 
-	CamelObjectBag *service_cache[CAMEL_NUM_PROVIDER_TYPES];
-
 	GHashFunc url_hash;
 	GCompareFunc url_equal;
 
diff --git a/camel/camel-sasl-popb4smtp.c b/camel/camel-sasl-popb4smtp.c
index 24caa99..0f2de6e 100644
--- a/camel/camel-sasl-popb4smtp.c
+++ b/camel/camel-sasl-popb4smtp.c
@@ -65,33 +65,57 @@ sasl_popb4smtp_challenge_sync (CamelSasl *sasl,
                                GCancellable *cancellable,
                                GError **error)
 {
-	gchar *popuri;
 	CamelService *service;
 	CamelSession *session;
-	CamelStore *store;
 	time_t now, *timep;
+	const gchar *type_name;
+	const gchar *uid;
+	gchar *pop_uid;
 
 	service = camel_sasl_get_service (sasl);
 	session = camel_service_get_session (service);
+	uid = camel_service_get_uid (service);
+
 	camel_sasl_set_authenticated (sasl, FALSE);
 
-	popuri = camel_session_get_password (
-		session, service, NULL, _("POP Source URI"),
-		"popb4smtp_uri", 0, error);
+	pop_uid = camel_session_get_password (
+		session, service, NULL, _("POP Source UID"),
+		"popb4smtp_uid", 0, error);
+
+	if (pop_uid != NULL)
+		service = camel_session_get_service (session, pop_uid);
+	else
+		service = NULL;
+
+	if (service == NULL) {
+		g_set_error (
+			error, CAMEL_SERVICE_ERROR,
+			CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+			_("POP Before SMTP authentication "
+			  "using an unknown transport"));
+		g_free (pop_uid);
+		return NULL;
+	}
+
+	type_name = G_OBJECT_TYPE_NAME (service);
 
-	if (popuri == NULL) {
+	if (!CAMEL_IS_STORE (service)) {
 		g_set_error (
 			error, CAMEL_SERVICE_ERROR,
 			CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
-			_("POP Before SMTP authentication using an unknown transport"));
+			_("POP Before SMTP authentication attempted "
+			  "with a %s service"), type_name);
+		g_free (pop_uid);
 		return NULL;
 	}
 
-	if (g_ascii_strncasecmp(popuri, "pop:", 4) != 0) {
+	if (strstr (type_name, "POP") == NULL) {
 		g_set_error (
 			error, CAMEL_SERVICE_ERROR,
 			CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
-			_("POP Before SMTP authentication using a non-POP source"));
+			_("POP Before SMTP authentication attempted "
+			  "with a %s service"), type_name);
+		g_free (pop_uid);
 		return NULL;
 	}
 
@@ -101,24 +125,22 @@ sasl_popb4smtp_challenge_sync (CamelSasl *sasl,
 	/* need to lock around the whole thing until finished with timep */
 
 	POPB4SMTP_LOCK (lock);
-	timep = g_hash_table_lookup (poplast, popuri);
+	timep = g_hash_table_lookup (poplast, pop_uid);
 	if (timep) {
 		if ((*timep + POPB4SMTP_TIMEOUT) > now) {
 			camel_sasl_set_authenticated (sasl, TRUE);
 			POPB4SMTP_UNLOCK (lock);
-			g_free (popuri);
+			g_free (pop_uid);
 			return NULL;
 		}
 	} else {
 		timep = g_malloc0 (sizeof (*timep));
-		g_hash_table_insert (poplast, g_strdup (popuri), timep);
+		g_hash_table_insert (poplast, g_strdup (pop_uid), timep);
 	}
 
 	/* connect to pop session */
-	store = camel_session_get_store (session, popuri, error);
-	if (store) {
+	if (camel_service_connect_sync (service, error)) {
 		camel_sasl_set_authenticated (sasl, TRUE);
-		g_object_unref (store);
 		*timep = now;
 	} else {
 		camel_sasl_set_authenticated (sasl, FALSE);
@@ -127,7 +149,7 @@ sasl_popb4smtp_challenge_sync (CamelSasl *sasl,
 
 	POPB4SMTP_UNLOCK (lock);
 
-	g_free (popuri);
+	g_free (pop_uid);
 
 	return NULL;
 }
diff --git a/camel/camel-service.c b/camel/camel-service.c
index e844cb8..181c910 100644
--- a/camel/camel-service.c
+++ b/camel/camel-service.c
@@ -32,6 +32,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <glib/gstdio.h>
 #include <glib/gi18n-lib.h>
 
 #include <libedataserver/e-data-server-util.h>
@@ -44,11 +45,18 @@
 #define d(x)
 #define w(x)
 
+#define CAMEL_SERVICE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), CAMEL_TYPE_SERVICE, CamelServicePrivate))
+
 struct _CamelServicePrivate {
-	CamelSession *session;
 	CamelProvider *provider;
+	CamelSession *session;
 	CamelURL *url;
 
+	gchar *user_data_dir;
+	gchar *uid;
+
 	GCancellable *connect_op;
 	CamelServiceConnectionStatus status;
 
@@ -56,166 +64,284 @@ struct _CamelServicePrivate {
 	GStaticMutex connect_op_lock;	/* for locking the connection_op */
 };
 
-G_DEFINE_ABSTRACT_TYPE (CamelService, camel_service, CAMEL_TYPE_OBJECT)
+enum {
+	PROP_0,
+	PROP_PROVIDER,
+	PROP_SESSION,
+	PROP_UID,
+	PROP_URL
+};
 
-static void
-service_finalize (GObject *object)
+/* Forward Declarations */
+static void camel_service_initable_init (GInitableIface *interface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (
+	CamelService, camel_service, CAMEL_TYPE_OBJECT,
+	G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, camel_service_initable_init))
+
+static gchar *
+service_find_old_data_dir (CamelService *service)
 {
-	CamelService *service = CAMEL_SERVICE (object);
+	CamelProvider *provider;
+	CamelSession *session;
+	CamelURL *url;
+	GString *path;
+	gboolean allows_host;
+	gboolean allows_user;
+	gboolean needs_host;
+	gboolean needs_path;
+	gboolean needs_user;
+	const gchar *base_dir;
+	gchar *old_data_dir;
+
+	provider = camel_service_get_provider (service);
+	session = camel_service_get_session (service);
+	url = camel_service_get_camel_url (service);
 
-	if (service->priv->status == CAMEL_SERVICE_CONNECTED)
-		CAMEL_SERVICE_GET_CLASS (service)->disconnect_sync (
-			service, TRUE, NULL, NULL);
+	allows_host = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_HOST);
+	allows_user = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_USER);
+
+	needs_host = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_HOST);
+	needs_path = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_PATH);
+	needs_user = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_USER);
+
+	/* This function reproduces the way service data directories used
+	 * to be determined before we moved to just using the UID.  If the
+	 * old data directory exists, try renaming it to the new form.
+	 *
+	 * A virtual class method was used to determine the directory path,
+	 * but no known CamelProviders ever overrode the default algorithm
+	 * below.  So this should work for everyone. */
+
+	path = g_string_new (provider->protocol);
+
+	if (allows_user) {
+		g_string_append_c (path, '/');
+		if (url->user != NULL)
+			g_string_append (path, url->user);
+		if (allows_host) {
+			g_string_append_c (path, '@');
+			if (url->host != NULL)
+				g_string_append (path, url->host);
+			if (url->port) {
+				g_string_append_c (path, ':');
+				g_string_append_printf (path, "%d", url->port);
+			}
+		} else if (!needs_user) {
+			g_string_append_c (path, '@');
+		}
 
-	if (service->priv->url)
-		camel_url_free (service->priv->url);
+	} else if (allows_host) {
+		g_string_append_c (path, '/');
+		if (!needs_host)
+			g_string_append_c (path, '@');
+		if (url->host != NULL)
+			g_string_append (path, url->host);
+		if (url->port) {
+			g_string_append_c (path, ':');
+			g_string_append_printf (path, "%d", url->port);
+		}
+	}
 
-	if (service->priv->session)
-		g_object_unref (service->priv->session);
+	if (needs_path) {
+		if (*url->path != '/')
+			g_string_append_c (path, '/');
+		g_string_append (path, url->path);
+	}
 
-	g_static_rec_mutex_free (&service->priv->connect_lock);
-	g_static_mutex_free (&service->priv->connect_op_lock);
+	base_dir = camel_session_get_user_data_dir (session);
+	old_data_dir = g_build_filename (base_dir, path->str, NULL);
 
-	/* Chain up to parent's finalize() method. */
-	G_OBJECT_CLASS (camel_service_parent_class)->finalize (object);
-}
+	g_string_free (path, TRUE);
 
-static gboolean
-service_construct (CamelService *service,
-                   CamelSession *session,
-                   CamelProvider *provider,
-                   CamelURL *url,
-                   GError **error)
-{
-	gchar *err, *url_string;
-
-	if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_USER) &&
-	    (url->user == NULL || url->user[0] == '\0')) {
-		err = _("URL '%s' needs a username component");
-		goto fail;
-	} else if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_HOST) &&
-		   (url->host == NULL || url->host[0] == '\0')) {
-		err = _("URL '%s' needs a host component");
-		goto fail;
-	} else if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_PATH) &&
-		   (url->path == NULL || url->path[0] == '\0')) {
-		err = _("URL '%s' needs a path component");
-		goto fail;
+	if (!g_file_test (old_data_dir, G_FILE_TEST_IS_DIR)) {
+		g_free (old_data_dir);
+		old_data_dir = NULL;
 	}
 
+	return old_data_dir;
+}
+
+static void
+service_set_provider (CamelService *service,
+                      CamelProvider *provider)
+{
+	g_return_if_fail (provider != NULL);
+	g_return_if_fail (service->priv->provider == NULL);
+
 	service->priv->provider = provider;
-	service->priv->url = camel_url_copy (url);
+}
+
+static void
+service_set_session (CamelService *service,
+                     CamelSession *session)
+{
+	g_return_if_fail (CAMEL_IS_SESSION (session));
+	g_return_if_fail (service->priv->session == NULL);
+
 	service->priv->session = g_object_ref (session);
+}
 
-	service->priv->status = CAMEL_SERVICE_DISCONNECTED;
+static void
+service_set_uid (CamelService *service,
+                 const gchar *uid)
+{
+	g_return_if_fail (uid != NULL);
+	g_return_if_fail (service->priv->uid == NULL);
 
-	return TRUE;
+	service->priv->uid = g_strdup (uid);
+}
 
-fail:
-	url_string = camel_url_to_string (url, CAMEL_URL_HIDE_PASSWORD);
-	g_set_error (
-		error, CAMEL_SERVICE_ERROR,
-		CAMEL_SERVICE_ERROR_URL_INVALID,
-		err, url_string);
-	g_free (url_string);
+static void
+service_set_url (CamelService *service,
+                 CamelURL *url)
+{
+	g_return_if_fail (url != NULL);
+	g_return_if_fail (service->priv->url == NULL);
 
-	return FALSE;
+	service->priv->url = camel_url_copy (url);
 }
 
-static gchar *
-service_get_name (CamelService *service,
-                  gboolean brief)
+static void
+service_set_property (GObject *object,
+                      guint property_id,
+                      const GValue *value,
+                      GParamSpec *pspec)
 {
-	g_warning (
-		"%s does not implement CamelServiceClass::get_name()",
-		G_OBJECT_TYPE_NAME (service));
+	switch (property_id) {
+		case PROP_PROVIDER:
+			service_set_provider (
+				CAMEL_SERVICE (object),
+				g_value_get_pointer (value));
+			return;
+
+		case PROP_SESSION:
+			service_set_session (
+				CAMEL_SERVICE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_UID:
+			service_set_uid (
+				CAMEL_SERVICE (object),
+				g_value_get_string (value));
+			return;
+
+		case PROP_URL:
+			service_set_url (
+				CAMEL_SERVICE (object),
+				g_value_get_boxed (value));
+			return;
+	}
 
-	return g_strdup (G_OBJECT_TYPE_NAME (service));
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 }
 
-static gchar *
-service_get_path (CamelService *service)
-{
-	CamelProvider *prov = service->priv->provider;
-	CamelURL *url = service->priv->url;
-	GString *use_path1 = NULL, *use_path2 = NULL;
-	gchar *ret_path = NULL;
-
-	/* A sort of ad-hoc default implementation that works for our
-	 * current set of services.
-	 */
-
-	if (CAMEL_PROVIDER_ALLOWS (prov, CAMEL_URL_PART_USER)) {
-		use_path1 = g_string_new ("");
-
-		if (CAMEL_PROVIDER_ALLOWS (prov, CAMEL_URL_PART_HOST)) {
-			g_string_append_printf (use_path1, "%s %s",
-						url->user ? url->user : "",
-						url->host ? url->host : "");
-
-			if (url->port)
-				g_string_append_printf (use_path1, ":%d", url->port);
-		} else {
-			g_string_append_printf (use_path1, "%s%s", url->user ? url->user : "",
-						CAMEL_PROVIDER_NEEDS (prov, CAMEL_URL_PART_USER) ? "" : "@");
-		}
+static void
+service_get_property (GObject *object,
+                      guint property_id,
+                      GValue *value,
+                      GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_PROVIDER:
+			g_value_set_pointer (
+				value, camel_service_get_provider (
+				CAMEL_SERVICE (object)));
+			return;
+
+		case PROP_SESSION:
+			g_value_set_object (
+				value, camel_service_get_session (
+				CAMEL_SERVICE (object)));
+			return;
+
+		case PROP_UID:
+			g_value_set_string (
+				value, camel_service_get_uid (
+				CAMEL_SERVICE (object)));
+			return;
+
+		case PROP_URL:
+			g_value_set_boxed (
+				value, camel_service_get_url (
+				CAMEL_SERVICE (object)));
+			return;
+	}
 
-		e_filename_make_safe (use_path1->str);
-	} else if (CAMEL_PROVIDER_ALLOWS (prov, CAMEL_URL_PART_HOST)) {
-		use_path1 = g_string_new ("");
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
 
-		g_string_append_printf (use_path1, "%s%s",
-					CAMEL_PROVIDER_NEEDS (prov, CAMEL_URL_PART_HOST) ? "" : "@",
-					url->host ? url->host : "");
+static void
+service_dispose (GObject *object)
+{
+	CamelServicePrivate *priv;
 
-		if (url->port)
-			g_string_append_printf (use_path1, ":%d", url->port);
+	priv = CAMEL_SERVICE_GET_PRIVATE (object);
 
-		e_filename_make_safe (use_path1->str);
+	if (priv->session != NULL) {
+		g_object_unref (priv->session);
+		priv->session = NULL;
 	}
 
-	if (CAMEL_PROVIDER_NEEDS (prov, CAMEL_URL_PART_PATH) && url->path && *url->path) {
-		use_path2 = g_string_new (*url->path == '/' ? url->path + 1 : url->path);
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (camel_service_parent_class)->dispose (object);
+}
 
-		/* fix directory separators, if needed */
-		if (G_DIR_SEPARATOR != '/') {
-			gchar **elems = g_strsplit (use_path2->str, "/", -1);
+static void
+service_finalize (GObject *object)
+{
+	CamelServicePrivate *priv;
 
-			if (elems) {
-				gint ii;
+	priv = CAMEL_SERVICE_GET_PRIVATE (object);
 
-				g_string_truncate (use_path2, 0);
+	if (priv->status == CAMEL_SERVICE_CONNECTED)
+		CAMEL_SERVICE_GET_CLASS (object)->disconnect_sync (
+			CAMEL_SERVICE (object), TRUE, NULL, NULL);
 
-				for (ii = 0; elems[ii]; ii++) {
-					gchar *elem = elems[ii];
+	if (priv->url != NULL)
+		camel_url_free (priv->url);
 
-					if (*elem) {
-						e_filename_make_safe (elem);
+	g_free (priv->user_data_dir);
+	g_free (priv->uid);
 
-						if (use_path2->len)
-							g_string_append_c (use_path2, G_DIR_SEPARATOR);
-						g_string_append (use_path2, elem);
-					}
-				}
+	g_static_rec_mutex_free (&priv->connect_lock);
+	g_static_mutex_free (&priv->connect_op_lock);
 
-				g_strfreev (elems);
-			}
-		}
-	}
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (camel_service_parent_class)->finalize (object);
+}
 
-	if (!use_path1 && use_path2) {
-		use_path1 = use_path2;
-		use_path2 = NULL;
-	}
+static void
+service_constructed (GObject *object)
+{
+	CamelService *service;
+	CamelSession *session;
+	const gchar *base_data_dir;
+	const gchar *uid;
 
-	ret_path = g_build_filename (service->priv->provider->protocol, use_path1 ? use_path1->str : NULL, use_path2 ? use_path2->str : NULL, NULL);
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (camel_service_parent_class)->constructed (object);
 
-	if (use_path1)
-		g_string_free (use_path1, TRUE);
-	if (use_path2)
-		g_string_free (use_path2, TRUE);
+	service = CAMEL_SERVICE (object);
+	session = camel_service_get_session (service);
 
-	return ret_path;
+	uid = camel_service_get_uid (service);
+	base_data_dir = camel_session_get_user_data_dir (session);
+
+	service->priv->user_data_dir =
+		g_build_filename (base_data_dir, uid, NULL);
+}
+
+static gchar *
+service_get_name (CamelService *service,
+                  gboolean brief)
+{
+	g_warning (
+		"%s does not implement CamelServiceClass::get_name()",
+		G_OBJECT_TYPE_NAME (service));
+
+	return g_strdup (G_OBJECT_TYPE_NAME (service));
 }
 
 static void
@@ -253,6 +379,76 @@ service_query_auth_types_sync (CamelService *service,
 	return NULL;
 }
 
+static gboolean
+service_initable_init (GInitable *initable,
+                       GCancellable *cancellable,
+                       GError **error)
+{
+	CamelProvider *provider;
+	CamelService *service;
+	CamelURL *url;
+	gboolean success = FALSE;
+	const gchar *new_data_dir;
+	gchar *old_data_dir;
+	gchar *url_string;
+
+	service = CAMEL_SERVICE (initable);
+	url = camel_service_get_camel_url (service);
+	provider = camel_service_get_provider (service);
+
+	url_string = camel_url_to_string (url, CAMEL_URL_HIDE_PASSWORD);
+
+	if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_USER)) {
+		if (url->user == NULL || *url->user == '\0') {
+			g_set_error (
+				error, CAMEL_SERVICE_ERROR,
+				CAMEL_SERVICE_ERROR_URL_INVALID,
+				_("URL '%s' needs a user component"),
+				url_string);
+			goto exit;
+		}
+	}
+
+	if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_HOST)) {
+		if (url->host == NULL || *url->host == '\0') {
+			g_set_error (
+				error, CAMEL_SERVICE_ERROR,
+				CAMEL_SERVICE_ERROR_URL_INVALID,
+				_("URL '%s' needs a host component"),
+				url_string);
+			goto exit;
+		}
+	}
+
+	if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_PATH)) {
+		if (url->path == NULL || *url->path == '\0') {
+			g_set_error (
+				error, CAMEL_SERVICE_ERROR,
+				CAMEL_SERVICE_ERROR_URL_INVALID,
+				_("URL '%s' needs a path component"),
+				url_string);
+			goto exit;
+		}
+	}
+
+	new_data_dir = camel_service_get_user_data_dir (service);
+	old_data_dir = service_find_old_data_dir (service);
+
+	/* If the old data directory name exists, try renaming
+	 * it to the new data directory.  Failure is non-fatal. */
+	if (old_data_dir != NULL) {
+		g_rename (old_data_dir, new_data_dir);
+		g_free (old_data_dir);
+	}
+
+	success = TRUE;
+
+exit:
+	g_free (url_string);
+
+	return success;
+}
+
 static void
 camel_service_class_init (CamelServiceClass *class)
 {
@@ -261,22 +457,78 @@ camel_service_class_init (CamelServiceClass *class)
 	g_type_class_add_private (class, sizeof (CamelServicePrivate));
 
 	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = service_set_property;
+	object_class->get_property = service_get_property;
+	object_class->dispose = service_dispose;
 	object_class->finalize = service_finalize;
+	object_class->constructed = service_constructed;
 
-	class->construct = service_construct;
 	class->get_name = service_get_name;
-	class->get_path = service_get_path;
 	class->cancel_connect = service_cancel_connect;
 	class->connect_sync = service_connect_sync;
 	class->disconnect_sync = service_disconnect_sync;
 	class->query_auth_types_sync = service_query_auth_types_sync;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_PROVIDER,
+		g_param_spec_pointer (
+			"provider",
+			"Provider",
+			"The CamelProvider for the service",
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SESSION,
+		g_param_spec_object (
+			"session",
+			"Session",
+			"A CamelSession instance",
+			CAMEL_TYPE_SESSION,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_UID,
+		g_param_spec_string (
+			"uid",
+			"UID",
+			"The unique identity of the service",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_URL,
+		g_param_spec_boxed (
+			"url",
+			"URL",
+			"The CamelURL for the service",
+			CAMEL_TYPE_URL,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+camel_service_initable_init (GInitableIface *interface)
+{
+	interface->init = service_initable_init;
 }
 
 static void
 camel_service_init (CamelService *service)
 {
-	service->priv = G_TYPE_INSTANCE_GET_PRIVATE (
-		service, CAMEL_TYPE_SERVICE, CamelServicePrivate);
+	service->priv = CAMEL_SERVICE_GET_PRIVATE (service);
+
+	service->priv->status = CAMEL_SERVICE_DISCONNECTED;
 
 	g_static_rec_mutex_init (&service->priv->connect_lock);
 	g_static_mutex_init (&service->priv->connect_op_lock);
@@ -296,40 +548,6 @@ camel_service_error_quark (void)
 }
 
 /**
- * camel_service_construct:
- * @service: a #CamelService
- * @session: the #CamelSession for @service
- * @provider: the #CamelProvider associated with @service
- * @url: the default URL for the service (may be %NULL)
- * @error: return location for a #GError, or %NULL
- *
- * Constructs a #CamelService initialized with the given parameters.
- *
- * Returns: %TRUE on success, %FALSE on failure
- **/
-gboolean
-camel_service_construct (CamelService *service,
-                         CamelSession *session,
-                         CamelProvider *provider,
-                         CamelURL *url,
-                         GError **error)
-{
-	CamelServiceClass *class;
-	gboolean success;
-
-	g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
-	g_return_val_if_fail (CAMEL_IS_SESSION (session), FALSE);
-
-	class = CAMEL_SERVICE_GET_CLASS (service);
-	g_return_val_if_fail (class->construct != NULL, FALSE);
-
-	success = class->construct (service, session, provider, url, error);
-	CAMEL_CHECK_GERROR (service, construct, success, error);
-
-	return success;
-}
-
-/**
  * camel_service_cancel_connect:
  * @service: a #CamelService
  *
@@ -354,6 +572,27 @@ camel_service_cancel_connect (CamelService *service)
 }
 
 /**
+ * camel_service_get_user_data_dir:
+ * @service: a #CamelService
+ *
+ * Returns the base directory under which to store user-specific data
+ * for @service.  The directory is formed by appending the directory
+ * returned by camel_session_get_user_data_dir() with the service's
+ * #CamelService:uid value.
+ *
+ * Returns: the base directory for @service
+ *
+ * Since: 3.2
+ **/
+const gchar *
+camel_service_get_user_data_dir (CamelService *service)
+{
+	g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
+
+	return service->priv->user_data_dir;
+}
+
+/**
  * camel_service_get_name:
  * @service: a #CamelService
  * @brief: whether or not to use a briefer form
@@ -381,29 +620,19 @@ camel_service_get_name (CamelService *service,
 }
 
 /**
- * camel_service_get_path:
+ * camel_service_get_provider:
  * @service: a #CamelService
  *
- * This gets a valid UNIX relative path describing @service, which
- * is guaranteed to be different from the path returned for any
- * different service. This path MUST start with the name of the
- * provider, followed by a "/", but after that, it is up to the
- * provider.
+ * Gets the #CamelProvider associated with the service.
  *
- * Returns: the path, which the caller must free
+ * Returns: the #CamelProvider
  **/
-gchar *
-camel_service_get_path (CamelService *service)
+CamelProvider *
+camel_service_get_provider (CamelService *service)
 {
-	CamelServiceClass *class;
-
 	g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
-	g_return_val_if_fail (service->priv->url, NULL);
 
-	class = CAMEL_SERVICE_GET_CLASS (service);
-	g_return_val_if_fail (class->get_path != NULL, NULL);
-
-	return class->get_path (service);
+	return service->priv->provider;
 }
 
 /**
@@ -412,7 +641,7 @@ camel_service_get_path (CamelService *service)
  *
  * Gets the #CamelSession associated with the service.
  *
- * Returns: the session
+ * Returns: the #CamelSession
  **/
 CamelSession *
 camel_service_get_session (CamelService *service)
@@ -423,19 +652,21 @@ camel_service_get_session (CamelService *service)
 }
 
 /**
- * camel_service_get_provider:
+ * camel_service_get_uid:
  * @service: a #CamelService
  *
- * Gets the #CamelProvider associated with the service.
+ * Gets the unique identifier string associated with the service.
  *
- * Returns: the provider
+ * Returns: the UID string
+ *
+ * Since: 3.2
  **/
-CamelProvider *
-camel_service_get_provider (CamelService *service)
+const gchar *
+camel_service_get_uid (CamelService *service)
 {
 	g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
 
-	return service->priv->provider;
+	return service->priv->uid;
 }
 
 /**
diff --git a/camel/camel-service.h b/camel/camel-service.h
index fd37ce0..f70472c 100644
--- a/camel/camel-service.h
+++ b/camel/camel-service.h
@@ -107,14 +107,8 @@ struct _CamelService {
 struct _CamelServiceClass {
 	CamelObjectClass parent_class;
 
-	gboolean	(*construct)		(CamelService *service,
-						 struct _CamelSession *session,
-						 CamelProvider *provider,
-						 CamelURL *url,
-						 GError **error);
 	gchar *		(*get_name)		(CamelService *service,
 						 gboolean brief);
-	gchar *		(*get_path)		(CamelService *service);
 	void		(*cancel_connect)	(CamelService *service);
 
 	gboolean	(*connect_sync)		(CamelService *service,
@@ -141,17 +135,13 @@ typedef struct {
 
 GType		camel_service_get_type		(void);
 GQuark		camel_service_error_quark	(void) G_GNUC_CONST;
-gboolean	camel_service_construct		(CamelService *service,
-						 struct _CamelSession *session,
-						 CamelProvider *provider,
-						 CamelURL *url,
-						 GError **error);
+const gchar *	camel_service_get_user_data_dir	(CamelService *service);
 gchar *		camel_service_get_name		(CamelService *service,
 						 gboolean brief);
-gchar *		camel_service_get_path		(CamelService *service);
 CamelProvider *	camel_service_get_provider	(CamelService *service);
 struct _CamelSession *
 		camel_service_get_session	(CamelService *service);
+const gchar *	camel_service_get_uid		(CamelService *service);
 CamelURL *	camel_service_get_camel_url	(CamelService *service);
 gchar *		camel_service_get_url		(CamelService *service);
 void		camel_service_cancel_connect	(CamelService *service);
diff --git a/camel/camel-session.c b/camel/camel-session.c
index 20b2a0d..85701b0 100644
--- a/camel/camel-session.c
+++ b/camel/camel-session.c
@@ -47,17 +47,23 @@
 #include "camel-folder.h"
 #include "camel-mime-message.h"
 
+#define CAMEL_SESSION_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), CAMEL_TYPE_SESSION, CamelSessionPrivate))
+
 #define d(x)
 
 struct _CamelSessionPrivate {
 	GMutex *lock;		/* for locking everything basically */
 	GMutex *thread_lock;	/* locking threads */
 
+	gchar *user_data_dir;
+
 	gint thread_id;
 	GHashTable *thread_active;
 	GThreadPool *thread_pool;
 
-	GHashTable *thread_msg_op;
+	GHashTable *services;
 	GHashTable *junk_headers;
 
 	gchar *socks_proxy_host;
@@ -73,7 +79,7 @@ enum {
 	PROP_CHECK_JUNK,
 	PROP_NETWORK_AVAILABLE,
 	PROP_ONLINE,
-	PROP_STORAGE_PATH
+	PROP_USER_DATA_DIR,
 };
 
 G_DEFINE_TYPE (CamelSession, camel_session, CAMEL_TYPE_OBJECT)
@@ -93,6 +99,16 @@ cs_thread_status (CamelOperation *operation,
 }
 
 static void
+session_set_user_data_dir (CamelSession *session,
+                           const gchar *user_data_dir)
+{
+	g_return_if_fail (user_data_dir != NULL);
+	g_return_if_fail (session->priv->user_data_dir == NULL);
+
+	session->priv->user_data_dir = g_strdup (user_data_dir);
+}
+
+static void
 session_set_property (GObject *object,
                       guint property_id,
                       const GValue *value,
@@ -116,6 +132,12 @@ session_set_property (GObject *object,
 				CAMEL_SESSION (object),
 				g_value_get_boolean (value));
 			return;
+
+		case PROP_USER_DATA_DIR:
+			session_set_user_data_dir (
+				CAMEL_SESSION (object),
+				g_value_get_string (value));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -145,33 +167,54 @@ session_get_property (GObject *object,
 				value, camel_session_get_online (
 				CAMEL_SESSION (object)));
 			return;
+
+		case PROP_USER_DATA_DIR:
+			g_value_set_string (
+				value, camel_session_get_user_data_dir (
+				CAMEL_SESSION (object)));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 }
 
 static void
+session_dispose (GObject *object)
+{
+	CamelSessionPrivate *priv;
+
+	priv = CAMEL_SESSION_GET_PRIVATE (object);
+
+	g_hash_table_remove_all (priv->services);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (camel_session_parent_class)->dispose (object);
+}
+
+static void
 session_finalize (GObject *object)
 {
-	CamelSession *session = CAMEL_SESSION (object);
-	GThreadPool *thread_pool = session->priv->thread_pool;
+	CamelSessionPrivate *priv;
+
+	priv = CAMEL_SESSION_GET_PRIVATE (object);
 
-	g_hash_table_destroy (session->priv->thread_active);
+	g_free (priv->user_data_dir);
 
-	if (thread_pool != NULL) {
+	g_hash_table_destroy (priv->services);
+	g_hash_table_destroy (priv->thread_active);
+
+	if (priv->thread_pool != NULL) {
 		/* there should be no unprocessed tasks */
-		g_assert (g_thread_pool_unprocessed (thread_pool) == 0);
-		g_thread_pool_free (thread_pool, FALSE, FALSE);
+		g_assert (g_thread_pool_unprocessed (priv->thread_pool) == 0);
+		g_thread_pool_free (priv->thread_pool, FALSE, FALSE);
 	}
 
-	g_free (session->storage_path);
-
-	g_mutex_free (session->priv->lock);
-	g_mutex_free (session->priv->thread_lock);
+	g_mutex_free (priv->lock);
+	g_mutex_free (priv->thread_lock);
 
-	if (session->priv->junk_headers) {
-		g_hash_table_remove_all (session->priv->junk_headers);
-		g_hash_table_destroy (session->priv->junk_headers);
+	if (priv->junk_headers) {
+		g_hash_table_remove_all (priv->junk_headers);
+		g_hash_table_destroy (priv->junk_headers);
 	}
 
 	/* Chain up to parent's finalize() method. */
@@ -179,87 +222,74 @@ session_finalize (GObject *object)
 }
 
 static CamelService *
-session_get_service (CamelSession *session,
+session_add_service (CamelSession *session,
+                     const gchar *uid,
                      const gchar *url_string,
                      CamelProviderType type,
                      GError **error)
 {
 	CamelURL *url;
-	CamelProvider *provider;
 	CamelService *service;
+	CamelProvider *provider;
+	GType service_type = G_TYPE_INVALID;
+
+	service = g_hash_table_lookup (session->priv->services, uid);
+	if (CAMEL_IS_SERVICE (service))
+		return service;
+
+	g_debug ("%s: Entering", G_STRFUNC);
 
 	url = camel_url_new (url_string, error);
-	if (!url)
+	if (url == NULL)
 		return NULL;
 
-	/* We need to look up the provider so we can then lookup
-	   the service in the provider's cache */
+	/* Try to find a suitable CamelService subclass. */
 	provider = camel_provider_get (url->protocol, error);
-	if (provider && !provider->object_types[type]) {
+	if (provider != NULL)
+		service_type = provider->object_types[type];
+
+	if (service_type == G_TYPE_INVALID) {
 		g_set_error (
 			error, CAMEL_SERVICE_ERROR,
 			CAMEL_SERVICE_ERROR_URL_INVALID,
 			_("No provider available for protocol '%s'"),
 			url->protocol);
-		provider = NULL;
+		camel_url_free (url);
+		return NULL;
 	}
 
-	if (!provider) {
+	if (!g_type_is_a (service_type, CAMEL_TYPE_SERVICE)) {
+		g_set_error (
+			error, CAMEL_SERVICE_ERROR,
+			CAMEL_SERVICE_ERROR_INVALID,
+			_("Invalid GType registered for protocol '%s'"),
+			url->protocol);
 		camel_url_free (url);
 		return NULL;
 	}
 
-	/* If the provider doesn't use paths but the URL contains one,
-	 * ignore it.
-	 */
-	if (url->path && !CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_PATH))
+	/* If the provider does not use paths but the URL contains one,
+	 * ignore it. */
+	if (!CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_PATH))
 		camel_url_set_path (url, NULL);
 
-	/* Now look up the service in the provider's cache */
-	service = camel_object_bag_reserve (provider->service_cache[type], url);
-	if (service == NULL) {
-		service = g_object_new (provider->object_types[type], NULL);
-		if (!camel_service_construct (service, session, provider, url, error)) {
-			g_object_unref (service);
-			service = NULL;
-			camel_object_bag_abort (provider->service_cache[type], url);
-		} else {
-			camel_object_bag_add (provider->service_cache[type], url, service);
-		}
-	}
+	service = g_initable_new (
+		service_type, NULL, error,
+		"provider", provider, "session",
+		session, "uid", uid, "url", url, NULL);
 
-	camel_url_free (url);
-
-	return service;
-}
-
-static gchar *
-session_get_storage_path (CamelSession *session,
-                          CamelService *service,
-                          GError **error)
-{
-	gchar *service_path;
-	gchar *storage_path;
+	/* The hash table takes ownership of the new CamelService. */
+	if (service != NULL)
+		g_hash_table_insert (
+			session->priv->services,
+			g_strdup (uid), service);
 
-	service_path = camel_service_get_path (service);
-	storage_path = g_build_filename (
-		session->storage_path, service_path, NULL);
-	g_free (service_path);
+	if (service != NULL)
+		g_debug ("%s: Adding %s (%s)", G_STRFUNC, uid, url_string);
 
-	if (g_access (storage_path, F_OK) == 0)
-		return storage_path;
-
-	if (g_mkdir_with_parents (storage_path, S_IRWXU) == -1) {
-		g_set_error (
-			error, G_IO_ERROR,
-			g_io_error_from_errno (errno),
-			_("Could not create directory %s:\n%s"),
-			storage_path, g_strerror (errno));
-		g_free (storage_path);
-		storage_path = NULL;
-	}
+	camel_url_free (url);
 
-	return storage_path;
+	return service;
 }
 
 static gpointer
@@ -378,10 +408,10 @@ camel_session_class_init (CamelSessionClass *class)
 	object_class = G_OBJECT_CLASS (class);
 	object_class->set_property = session_set_property;
 	object_class->get_property = session_get_property;
+	object_class->dispose = session_dispose;
 	object_class->finalize = session_finalize;
 
-	class->get_service = session_get_service;
-	class->get_storage_path = session_get_storage_path;
+	class->add_service = session_add_service;
 	class->thread_msg_new = session_thread_msg_new;
 	class->thread_msg_free = session_thread_msg_free;
 	class->thread_queue = session_thread_queue;
@@ -397,7 +427,8 @@ camel_session_class_init (CamelSessionClass *class)
 			"Check incoming messages for junk",
 			FALSE,
 			G_PARAM_READWRITE |
-			G_PARAM_CONSTRUCT));
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
 
 	g_object_class_install_property (
 		object_class,
@@ -408,7 +439,8 @@ camel_session_class_init (CamelSessionClass *class)
 			"Whether the network is available",
 			TRUE,
 			G_PARAM_READWRITE |
-			G_PARAM_CONSTRUCT));
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
 
 	g_object_class_install_property (
 		object_class,
@@ -419,58 +451,92 @@ camel_session_class_init (CamelSessionClass *class)
 			"Whether the shell is online",
 			TRUE,
 			G_PARAM_READWRITE |
-			G_PARAM_CONSTRUCT));
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_USER_DATA_DIR,
+		g_param_spec_string (
+			"user-data-dir",
+			"User Data Directory",
+			"User-specific base directory for mail data",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
 }
 
 static void
 camel_session_init (CamelSession *session)
 {
-	session->priv = G_TYPE_INSTANCE_GET_PRIVATE (
-		session, CAMEL_TYPE_SESSION, CamelSessionPrivate);
+	GHashTable *services;
+
+	services = g_hash_table_new_full (
+		(GHashFunc) g_str_hash,
+		(GEqualFunc) g_str_equal,
+		(GDestroyNotify) g_free,
+		(GDestroyNotify) g_object_unref);
+
+	session->priv = CAMEL_SESSION_GET_PRIVATE (session);
+
 	session->priv->lock = g_mutex_new ();
 	session->priv->thread_lock = g_mutex_new ();
 	session->priv->thread_id = 1;
 	session->priv->thread_active = g_hash_table_new (NULL, NULL);
 	session->priv->thread_pool = NULL;
+	session->priv->services = services;
 	session->priv->junk_headers = NULL;
 }
 
 /**
- * camel_session_construct:
- * @session: a #CamelSession object to construct
- * @storage_path: path to a directory the session can use for
- * persistent storage. (This directory must already exist.)
+ * camel_session_get_user_data_dir:
+ * @session: a #CamelSession
+ *
+ * Returns the base directory under which to store user-specific mail data.
  *
- * Constructs @session.
+ * Returns: the base directory for mail data
+ *
+ * Since: 3.2
  **/
-void
-camel_session_construct (CamelSession *session, const gchar *storage_path)
+const gchar *
+camel_session_get_user_data_dir (CamelSession *session)
 {
-	session->storage_path = g_strdup (storage_path);
+	g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
+
+	return session->priv->user_data_dir;
 }
 
 /**
- * camel_session_get_service:
- * @session: a #CamelSession object
- * @url_string: a #CamelURL describing the service to get
+ * camel_session_add_service:
+ * @session: a #CamelSession
+ * @uid: a unique identifier string
+ * @uri_string: a URI string describing the service
  * @type: the provider type (#CAMEL_PROVIDER_STORE or
- * #CAMEL_PROVIDER_TRANSPORT) to get, since some URLs may be able
- * to specify either type.
+ * #CAMEL_PROVIDER_TRANSPORT) to get, since some URLs may be able to
+ * specify either type
  * @error: return location for a #GError, or %NULL
  *
- * This resolves a #CamelURL into a #CamelService, including loading the
- * provider library for that service if it has not already been loaded.
+ * Instantiates a new #CamelService for @session.  The @uid identifies the
+ * service for future lookup.  The @uri_string describes which provider to
+ * use, authentication details, provider-specific options, etc.  The @type
+ * explicitly designates the service as a #CamelStore or #CamelTransport.
+ *
+ * If the given @uid has already been added, the existing #CamelService
+ * with that @uid is returned regardless of whether it agrees with the
+ * given @uri_string and @type.
+ *
+ * If the @uri_string is invalid or no #CamelProvider is available to
+ * handle the @uri_string, the function sets @error and returns %NULL.
  *
- * Services are cached, and asking for "the same" @url_string multiple
- * times will return the same CamelService (with its reference count
- * incremented by one each time). What constitutes "the same" URL
- * depends in part on the provider.
+ * Returns: a #CamelService instance, or %NULL
  *
- * Returns: the requested #CamelService, or %NULL
+ * Since: 3.2
  **/
 CamelService *
-camel_session_get_service (CamelSession *session,
-                           const gchar *url_string,
+camel_session_add_service (CamelSession *session,
+                           const gchar *uid,
+                           const gchar *uri_string,
                            CamelProviderType type,
                            GError **error)
 {
@@ -478,15 +544,16 @@ camel_session_get_service (CamelSession *session,
 	CamelService *service;
 
 	g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
-	g_return_val_if_fail (url_string != NULL, NULL);
+	g_return_val_if_fail (uid != NULL, NULL);
+	g_return_val_if_fail (uri_string != NULL, NULL);
 
 	class = CAMEL_SESSION_GET_CLASS (session);
-	g_return_val_if_fail (class->get_service != NULL, NULL);
+	g_return_val_if_fail (class->add_service != NULL, NULL);
 
 	camel_session_lock (session, CAMEL_SESSION_SESSION_LOCK);
 
-	service = class->get_service (session, url_string, type, error);
-	CAMEL_CHECK_GERROR (session, get_service, service != NULL, error);
+	service = class->add_service (session, uid, uri_string, type, error);
+	CAMEL_CHECK_GERROR (session, add_service, service != NULL, error);
 
 	camel_session_unlock (session, CAMEL_SESSION_SESSION_LOCK);
 
@@ -494,81 +561,111 @@ camel_session_get_service (CamelSession *session,
 }
 
 /**
- * camel_session_get_service_connected:
- * @session: a #CamelSession object
- * @url_string: a #CamelURL describing the service to get
- * @type: the provider type
- * @error: return location for a #GError, or %NULL
+ * camel_session_get_service:
+ * @session: a #CamelSession
+ * @uid: a unique identifier string
  *
- * This works like camel_session_get_service(), but also ensures that
- * the returned service will have been successfully connected (via
- * camel_service_connect().)
+ * Looks up a #CamelService by its unique identifier string.  The service
+ * must have been previously added using camel_session_add_service().
  *
- * Returns: the requested #CamelService, or %NULL
+ * Returns: a #CamelService instance, or %NULL
  **/
 CamelService *
-camel_session_get_service_connected (CamelSession *session,
-                                     const gchar *url_string,
-                                     CamelProviderType type,
-                                     GError **error)
+camel_session_get_service (CamelSession *session,
+                           const gchar *uid)
 {
 	CamelService *service;
-	CamelServiceConnectionStatus status;
 
-	service = camel_session_get_service (session, url_string, type, error);
-	if (service == NULL)
-		return NULL;
+	g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
+	g_return_val_if_fail (uid != NULL, NULL);
+
+	camel_session_lock (session, CAMEL_SESSION_SESSION_LOCK);
+
+	service = g_hash_table_lookup (session->priv->services, uid);
+
+	camel_session_unlock (session, CAMEL_SESSION_SESSION_LOCK);
+
+	return service;
+}
+
+/**
+ * camel_session_get_service_by_url:
+ * @session: a #CamelSession
+ * @url: a #CamelURL
+ *
+ * Looks up a #CamelService by trying to match its #CamelURL against
+ * the given @url.  The service must have been previously added using
+ * camel_session_add_service().
+ *
+ * Note this function is significantly slower than camel_session_get_service().
+ *
+ * Returns: a #CamelService instance, or %NULL
+ *
+ * Since: 3.2
+ **/
+CamelService *
+camel_session_get_service_by_url (CamelSession *session,
+                                  CamelURL *url)
+{
+	CamelService *match = NULL;
+	GList *list, *iter;
+
+	g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
+	g_return_val_if_fail (url != NULL, NULL);
+
+	list = camel_session_list_services (session);
+
+	for (iter = list; iter != NULL; iter = g_list_next (iter)) {
+		CamelProvider *provider;
+		CamelService *service;
+		CamelURL *service_url;
 
-	/* FIXME This blocks.  Need to take a GCancellable. */
-	status = camel_service_get_connection_status (service);
-	if (status != CAMEL_SERVICE_CONNECTED) {
-		if (!camel_service_connect_sync (service, error)) {
-			g_object_unref (service);
-			return NULL;
+		service = CAMEL_SERVICE (iter->data);
+		provider = camel_service_get_provider (service);
+		service_url = camel_service_get_camel_url (service);
+
+		if (provider->url_equal == NULL)
+			continue;
+
+		if (provider->url_equal (url, service_url)) {
+			match = service;
+			break;
 		}
 	}
 
-	return service;
+	g_list_free (list);
+
+	return match;
 }
 
 /**
- * camel_session_get_storage_path:
- * @session: a #CamelSession object
- * @service: a #CamelService
- * @error: return location for a #GError, or %NULL
+ * camel_session_list_services:
+ * @session: a #CamelSession
  *
- * This returns the path to a directory which the service can use for
- * its own purposes. Data stored there will remain between Evolution
- * sessions. No code outside of that service should ever touch the
- * files in this directory. If the directory does not exist, it will
- * be created.
+ * Returns a list of all #CamelService objects previously added using
+ * camel_session_add_service().  Free the returned list using g_list_free().
  *
- * Returns: the path (which the caller must free), or %NULL if an error
- * occurs.
+ * Returns: an unsorted list of #CamelService objects
  **/
-gchar *
-camel_session_get_storage_path (CamelSession *session,
-                                CamelService *service,
-                                GError **error)
+GList *
+camel_session_list_services (CamelSession *session)
 {
-	CamelSessionClass *class;
-	gchar *storage_path;
+	GList *list;
 
 	g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
-	g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
 
-	class = CAMEL_SESSION_GET_CLASS (session);
-	g_return_val_if_fail (class->get_storage_path != NULL, NULL);
+	camel_session_lock (session, CAMEL_SESSION_SESSION_LOCK);
 
-	storage_path = class->get_storage_path (session, service, error);
-	CAMEL_CHECK_GERROR (session, get_storage_path, storage_path != NULL, error);
+	list = g_hash_table_get_values (session->priv->services);
 
-	return storage_path;
+	camel_session_unlock (session, CAMEL_SESSION_SESSION_LOCK);
+
+	return list;
 }
 
 /**
  * camel_session_get_password:
- * @session: a #CamelSession object
+ * @session: a #CamelSession
  * @service: the #CamelService this query is being made by
  * @domain: domain of password request.  May be null to use the default.
  * @prompt: prompt to provide to user
@@ -626,7 +723,7 @@ camel_session_get_password (CamelSession *session,
 
 /**
  * camel_session_forget_password:
- * @session: a #CamelSession object
+ * @session: a #CamelSession
  * @service: the #CamelService rejecting the password
  * @item: an identifier, unique within this service, for the information
  * @error: return location for a #GError, or %NULL
@@ -666,7 +763,7 @@ camel_session_forget_password (CamelSession *session,
 
 /**
  * camel_session_alert_user:
- * @session: a #CamelSession object
+ * @session: a #CamelSession
  * @type: the type of alert (info, warning, or error)
  * @prompt: the message for the user
  * @cancel: whether or not to provide a "Cancel" option in addition to
@@ -795,7 +892,7 @@ camel_session_set_online (CamelSession *session,
 
 /**
  * camel_session_get_filter_driver:
- * @session: a #CamelSession object
+ * @session: a #CamelSession
  * @type: the type of filter (eg, "incoming")
  * @error: return location for a #GError, or %NULL
  *
@@ -823,7 +920,7 @@ camel_session_get_filter_driver (CamelSession *session,
 
 /**
  * camel_session_thread_msg_new:
- * @session: a #CamelSession object
+ * @session: a #CamelSession
  * @ops: thread operations
  * @size: number of bytes
  *
@@ -854,7 +951,7 @@ camel_session_thread_msg_new (CamelSession *session,
 
 /**
  * camel_session_thread_msg_free:
- * @session: a #CamelSession object
+ * @session: a #CamelSession
  * @msg: a #CamelSessionThreadMsg
  *
  * Free a @msg.  Note that the message must have been allocated using
@@ -877,7 +974,7 @@ camel_session_thread_msg_free (CamelSession *session,
 
 /**
  * camel_session_thread_queue:
- * @session: a #CamelSession object
+ * @session: a #CamelSession
  * @msg: a #CamelSessionThreadMsg
  * @flags: queue type flags, currently 0.
  *
@@ -905,7 +1002,7 @@ camel_session_thread_queue (CamelSession *session,
 
 /**
  * camel_session_thread_wait:
- * @session: a #CamelSession object
+ * @session: a #CamelSession
  * @id: id of the operation to wait on
  *
  * Wait on an operation to complete (by id).
diff --git a/camel/camel-session.h b/camel/camel-session.h
index 59893fa..0d40c35 100644
--- a/camel/camel-session.h
+++ b/camel/camel-session.h
@@ -89,7 +89,6 @@ struct _CamelSession {
 	CamelObject parent;
 	CamelSessionPrivate *priv;
 
-	gchar *storage_path;
 	CamelJunkPlugin *junk_plugin;
 };
 
@@ -99,13 +98,11 @@ typedef struct _CamelSessionThreadMsg CamelSessionThreadMsg;
 struct _CamelSessionClass {
 	CamelObjectClass parent_class;
 
-	CamelService *	(*get_service)		(CamelSession *session,
+	CamelService *	(*add_service)		(CamelSession *session,
+						 const gchar *uid,
 						 const gchar *url_string,
 						 CamelProviderType type,
 						 GError **error);
-	gchar *		(*get_storage_path)	(CamelSession *session,
-						 CamelService *service,
-						 GError **error);
 	gchar *		(*get_password)		(CamelSession *session,
 						 CamelService *service,
 						 const gchar *domain,
@@ -153,36 +150,24 @@ struct _CamelSessionClass {
 };
 
 GType		camel_session_get_type		(void);
-void		camel_session_construct		(CamelSession *session,
-						 const gchar *storage_path);
-
+const gchar *	camel_session_get_user_data_dir	(CamelSession *session);
 void            camel_session_set_socks_proxy   (CamelSession *session,
 						 const gchar *socks_host,
 						 gint socks_port);
 void            camel_session_get_socks_proxy   (CamelSession *session,
 						 gchar **host_ret,
 						 gint *port_ret);
-
-CamelService *	camel_session_get_service	(CamelSession *session,
-						 const gchar *url_string,
+CamelService *	camel_session_add_service	(CamelSession *session,
+						 const gchar *uid,
+						 const gchar *uri_string,
 						 CamelProviderType type,
 						 GError **error);
-CamelService *	camel_session_get_service_connected
+CamelService *	camel_session_get_service	(CamelSession *session,
+						 const gchar *uid);
+CamelService *	camel_session_get_service_by_url
 						(CamelSession *session,
-						 const gchar *url_string,
-						 CamelProviderType type,
-						 GError **error);
-
-#define camel_session_get_store(session, url_string, error) \
-	((CamelStore *) camel_session_get_service_connected \
-	(session, url_string, CAMEL_PROVIDER_STORE, error))
-#define camel_session_get_transport(session, url_string, error) \
-	((CamelTransport *) camel_session_get_service_connected \
-	(session, url_string, CAMEL_PROVIDER_TRANSPORT, error))
-
-gchar *		camel_session_get_storage_path	(CamelSession *session,
-						 CamelService *service,
-						 GError **error);
+						 CamelURL *url);
+GList *		camel_session_list_services	(CamelSession *session);
 gchar *		camel_session_get_password	(CamelSession *session,
 						 CamelService *service,
 						 const gchar *domain,
diff --git a/camel/camel-store.c b/camel/camel-store.c
index 1f0b5ee..92132ef 100644
--- a/camel/camel-store.c
+++ b/camel/camel-store.c
@@ -27,6 +27,7 @@
 #include <config.h>
 #endif
 
+#include <errno.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -44,6 +45,10 @@
 #define d(x)
 #define w(x)
 
+#define CAMEL_STORE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), CAMEL_TYPE_STORE, CamelStorePrivate))
+
 typedef struct _AsyncContext AsyncContext;
 typedef struct _SignalData SignalData;
 
@@ -81,8 +86,15 @@ enum {
 };
 
 static guint signals[LAST_SIGNAL];
+static GInitableIface *parent_initable_interface;
+
+/* Forward Declarations */
+static void camel_store_initable_init (GInitableIface *interface);
 
-G_DEFINE_ABSTRACT_TYPE (CamelStore, camel_store, CAMEL_TYPE_SERVICE)
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (
+	CamelStore, camel_store, CAMEL_TYPE_SERVICE,
+	G_IMPLEMENT_INTERFACE (
+		G_TYPE_INITABLE, camel_store_initable_init))
 
 static void
 async_context_free (AsyncContext *async_context)
@@ -259,76 +271,6 @@ store_constructed (GObject *object)
 }
 
 static gboolean
-store_construct (CamelService *service,
-                 CamelSession *session,
-                 CamelProvider *provider,
-                 CamelURL *url,
-                 GError **error)
-{
-	CamelServiceClass *service_class;
-	CamelStore *store = CAMEL_STORE (service);
-	gchar *store_db_path, *store_path = NULL;
-
-	/* Chain up to parent's construct() method. */
-	service_class = CAMEL_SERVICE_CLASS (camel_store_parent_class);
-	if (!service_class->construct (service, session, provider, url, error))
-		return FALSE;
-
-	store_db_path = g_build_filename (url->path, CAMEL_DB_FILE, NULL);
-
-	if (!url->path || strlen (store_db_path) < 2) {
-		store_path = camel_session_get_storage_path (session, service, error);
-
-		g_free (store_db_path);
-		store_db_path = g_build_filename (store_path, CAMEL_DB_FILE, NULL);
-	}
-
-	if (!g_file_test (url->path ? url->path : store_path, G_FILE_TEST_EXISTS)) {
-		/* Cache might be blown. Recreate. */
-		g_mkdir_with_parents (url->path ? url->path : store_path, S_IRWXU);
-	}
-
-	g_free (store_path);
-
-	/* This is for reading from the store */
-	store->cdb_r = camel_db_open (store_db_path, NULL);
-	if (camel_debug("sqlite"))
-		printf("store_db_path %s\n", store_db_path);
-	if (store->cdb_r == NULL) {
-		gchar *store_path;
-
-		if (camel_debug("sqlite"))
-			g_print ("Failure for store_db_path : [%s]\n", store_db_path);
-		g_free (store_db_path);
-
-		store_path =  camel_session_get_storage_path (session, service, NULL);
-		store_db_path = g_build_filename (store_path, CAMEL_DB_FILE, NULL);
-		g_free (store_path);
-
-		store->cdb_r = camel_db_open (store_db_path, NULL);
-		if (store->cdb_r == NULL) {
-			g_print("Retry with %s failed\n", store_db_path);
-			g_free (store_db_path);
-			return FALSE;
-		}
-	}
-	g_free (store_db_path);
-
-	if (camel_db_create_folders_table (store->cdb_r, error)) {
-		g_warning ("something went wrong terribly during db creation \n");
-		return FALSE;
-	}
-
-	/* This is for writing to the store */
-	store->cdb_w = camel_db_clone (store->cdb_r, error);
-
-	if (camel_url_get_param(url, "filter"))
-		store->flags |= CAMEL_STORE_FILTER_INBOX;
-
-	return TRUE;
-}
-
-static gboolean
 store_can_refresh_folder (CamelStore *store,
                           CamelFolderInfo *info,
                           GError **error)
@@ -1246,11 +1188,61 @@ store_noop_finish (CamelStore *store,
 	return !g_simple_async_result_propagate_error (simple, error);
 }
 
+static gboolean
+store_initable_init (GInitable *initable,
+                     GCancellable *cancellable,
+                     GError **error)
+{
+	CamelStore *store;
+	CamelService *service;
+	CamelSession *session;
+	CamelURL *url;
+	const gchar *user_data_dir;
+	gchar *filename;
+
+	store = CAMEL_STORE (initable);
+
+	/* Chain up to parent interface's init() method. */
+	if (!parent_initable_interface->init (initable, cancellable, error))
+		return FALSE;
+
+	service = CAMEL_SERVICE (initable);
+	url = camel_service_get_camel_url (service);
+	session = camel_service_get_session (service);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
+	if (g_mkdir_with_parents (user_data_dir, S_IRWXU) == -1) {
+		g_set_error_literal (
+			error, G_FILE_ERROR,
+			g_file_error_from_errno (errno),
+			g_strerror (errno));
+		return FALSE;
+	}
+
+	/* This is for reading from the store */
+	filename = g_build_filename (user_data_dir, CAMEL_DB_FILE, NULL);
+	store->cdb_r = camel_db_open (filename, error);
+	g_free (filename);
+
+	if (store->cdb_r == NULL)
+		return FALSE;
+
+	if (camel_db_create_folders_table (store->cdb_r, error))
+		return FALSE;
+
+	/* This is for writing to the store */
+	store->cdb_w = camel_db_clone (store->cdb_r, error);
+
+	if (camel_url_get_param (url, "filter"))
+		store->flags |= CAMEL_STORE_FILTER_INBOX;
+
+	return TRUE;
+}
+
 static void
 camel_store_class_init (CamelStoreClass *class)
 {
 	GObjectClass *object_class;
-	CamelServiceClass *service_class;
 
 	g_type_class_add_private (class, sizeof (CamelStorePrivate));
 
@@ -1258,9 +1250,6 @@ camel_store_class_init (CamelStoreClass *class)
 	object_class->finalize = store_finalize;
 	object_class->constructed = store_constructed;
 
-	service_class = CAMEL_SERVICE_CLASS (class);
-	service_class->construct = store_construct;
-
 	class->hash_folder_name = g_str_hash;
 	class->compare_folder_name = g_str_equal;
 	class->can_refresh_folder = store_can_refresh_folder;
@@ -1359,10 +1348,17 @@ camel_store_class_init (CamelStoreClass *class)
 }
 
 static void
+camel_store_initable_init (GInitableIface *interface)
+{
+	parent_initable_interface = g_type_interface_peek_parent (interface);
+
+	interface->init = store_initable_init;
+}
+
+static void
 camel_store_init (CamelStore *store)
 {
-	store->priv = G_TYPE_INSTANCE_GET_PRIVATE (
-		store, CAMEL_TYPE_STORE, CamelStorePrivate);
+	store->priv = CAMEL_STORE_GET_PRIVATE (store);
 
 	/* set vtrash and vjunk on by default */
 	store->flags = CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK;
diff --git a/camel/camel-vee-store.c b/camel/camel-vee-store.c
index 4ebed62..bca8ae0 100644
--- a/camel/camel-vee-store.c
+++ b/camel/camel-vee-store.c
@@ -115,37 +115,29 @@ vee_store_finalize (GObject *object)
 	G_OBJECT_CLASS (camel_vee_store_parent_class)->finalize (object);
 }
 
-static gboolean
-vee_store_construct (CamelService *service,
-                     CamelSession *session,
-                     CamelProvider *provider,
-                     CamelURL *url,
-                     GError **error)
+static void
+vee_store_constructed (GObject *object)
 {
-	CamelServiceClass *service_class;
-	CamelStore *store;
 	CamelVeeStore *vee_store;
 
-	store = CAMEL_STORE (service);
-	vee_store = CAMEL_VEE_STORE (service);
+	vee_store = CAMEL_VEE_STORE (object);
 
-	/* Chain up to parent's construct() method. */
-	service_class = CAMEL_SERVICE_CLASS (camel_vee_store_parent_class);
-	if (!service_class->construct (service, session, provider, url, error))
-		return FALSE;
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (camel_vee_store_parent_class)->constructed (object);
 
-	/* Set up unmatched folder */
 #ifndef VEE_UNMATCHED_ENABLE
+	/* Set up unmatched folder */
 	vee_store->unmatched_uids = g_hash_table_new (g_str_hash, g_str_equal);
 	vee_store->folder_unmatched = g_object_new (
 		CAMEL_TYPE_VEE_FOLDER,
 		"full-name", CAMEL_UNMATCHED_NAME,
-		"name", _("Unmatched"), "parent-store", store, NULL);
-	camel_vee_folder_construct (vee_store->folder_unmatched, CAMEL_STORE_FOLDER_PRIVATE);
-	camel_db_create_vfolder (store->cdb_r, _("Unmatched"), NULL);
+		"name", _("Unmatched"), "parent-store", vee_store, NULL);
+	camel_vee_folder_construct (
+		vee_store->folder_unmatched, CAMEL_STORE_FOLDER_PRIVATE);
+	camel_db_create_vfolder (
+		CAMEL_STORE (vee_store)->cdb_r, _("Unmatched"), NULL);
 #endif
 
-	return TRUE;
 }
 
 static gchar *
@@ -470,9 +462,9 @@ camel_vee_store_class_init (CamelVeeStoreClass *class)
 
 	object_class = G_OBJECT_CLASS (class);
 	object_class->finalize = vee_store_finalize;
+	object_class->constructed = vee_store_constructed;
 
 	service_class = CAMEL_SERVICE_CLASS (class);
-	service_class->construct = vee_store_construct;
 	service_class->get_name = vee_store_get_name;
 
 	store_class = CAMEL_STORE_CLASS (class);
diff --git a/camel/providers/groupwise/camel-groupwise-folder.c b/camel/providers/groupwise/camel-groupwise-folder.c
index 2982f4e..b9bfd16 100644
--- a/camel/providers/groupwise/camel-groupwise-folder.c
+++ b/camel/providers/groupwise/camel-groupwise-folder.c
@@ -355,19 +355,20 @@ static void
 groupwise_folder_rename (CamelFolder *folder, const gchar *new)
 {
 	CamelGroupwiseFolder *gw_folder;
-	CamelGroupwiseStore *gw_store;
 	CamelStore *parent_store;
-	gchar *folder_dir, *summary_path, *state_file, *storage_path;
+	CamelService *service;
+	const gchar *user_data_dir;
+	gchar *folder_dir, *summary_path, *state_file;
 	gchar *folders;
 
 	parent_store = camel_folder_get_parent_store (folder);
 
 	gw_folder = CAMEL_GROUPWISE_FOLDER (folder);
-	gw_store = CAMEL_GROUPWISE_STORE (parent_store);
 
-	storage_path = storage_path_lookup (gw_store->priv);
+	service = CAMEL_SERVICE (parent_store);
+	user_data_dir = camel_service_get_user_data_dir (service);
 
-	folders = g_strconcat (storage_path, "/folders", NULL);
+	folders = g_strconcat (user_data_dir, "/folders", NULL);
 	folder_dir = e_path_to_physical (folders, new);
 	g_free (folders);
 
diff --git a/camel/providers/groupwise/camel-groupwise-store.c b/camel/providers/groupwise/camel-groupwise-store.c
index 7f2e06f..cd3f607 100644
--- a/camel/providers/groupwise/camel-groupwise-store.c
+++ b/camel/providers/groupwise/camel-groupwise-store.c
@@ -41,6 +41,7 @@
 #include "camel-groupwise-store-summary.h"
 #include "camel-groupwise-store.h"
 #include "camel-groupwise-summary.h"
+#include "camel-groupwise-transport.h"
 #include "camel-groupwise-utils.h"
 
 #ifdef G_OS_WIN32
@@ -62,7 +63,6 @@ struct _CamelGroupwiseStorePrivate {
 	gchar *use_ssl;
 
 	gchar *base_url;
-	gchar *storage_path;
 
 	GHashTable *id_hash; /*get names from ids*/
 	GHashTable *name_hash;/*get ids from names*/
@@ -71,88 +71,18 @@ struct _CamelGroupwiseStorePrivate {
 };
 
 extern CamelServiceAuthType camel_groupwise_password_authtype; /*for the query_auth_types function*/
+
+static GInitableIface *parent_initable_interface;
+
 static CamelFolderInfo *convert_to_folder_info (CamelGroupwiseStore *store, EGwContainer *container, const gchar *url, GCancellable *cancellable, GError **error);
 static gboolean groupwise_folders_sync (CamelGroupwiseStore *store, GCancellable *cancellable, GError **error);
 static gint match_path (const gchar *path, const gchar *name);
+static void camel_groupwise_store_initable_init (GInitableIface *interface);
 
-G_DEFINE_TYPE (CamelGroupwiseStore, camel_groupwise_store, CAMEL_TYPE_OFFLINE_STORE)
-
-static gboolean
-groupwise_store_construct (CamelService *service,
-                           CamelSession *session,
-                           CamelProvider *provider,
-                           CamelURL *url,
-                           GError **error)
-{
-	CamelServiceClass *service_class;
-	CamelGroupwiseStore *groupwise_store = CAMEL_GROUPWISE_STORE (service);
-	CamelStore *store = CAMEL_STORE (service);
-	const gchar *property_value;
-	CamelGroupwiseStorePrivate *priv = groupwise_store->priv;
-	gchar *path = NULL;
-
-	d(printf ("\nin groupwise store constrcut\n"));
-
-	/* Chain up to parent's construct() method. */
-	service_class = CAMEL_SERVICE_CLASS (camel_groupwise_store_parent_class);
-	if (!service_class->construct (service, session, provider, url, error))
-		return FALSE;
-
-	if (!(url->host || url->user)) {
-		g_set_error (
-			error, CAMEL_SERVICE_ERROR,
-			CAMEL_SERVICE_ERROR_INVALID,
-			_("Host or user not available in url"));
-	}
-
-	/*storage path*/
-	priv->storage_path = camel_session_get_storage_path (session, service, error);
-	if (!priv->storage_path)
-		return FALSE;
-
-	/*store summary*/
-	path = g_alloca (strlen (priv->storage_path) + 32);
-	sprintf (path, "%s/.summary", priv->storage_path);
-	groupwise_store->summary = camel_groupwise_store_summary_new ();
-	camel_store_summary_set_filename ((CamelStoreSummary *)groupwise_store->summary, path);
-	camel_store_summary_touch ((CamelStoreSummary *)groupwise_store->summary);
-	camel_store_summary_load ((CamelStoreSummary *) groupwise_store->summary);
-
-	/*host and user*/
-	priv->server_name = g_strdup (url->host);
-	priv->user = g_strdup (url->user);
-
-	/*base url*/
-	priv->base_url = camel_url_to_string (
-		url, CAMEL_URL_HIDE_PASSWORD |
-		CAMEL_URL_HIDE_PARAMS | CAMEL_URL_HIDE_AUTH);
-
-	/*soap port*/
-	property_value =  camel_url_get_param (url, "soap_port");
-	if (property_value == NULL)
-		priv->port = g_strdup ("7191");
-	else if (strlen (property_value) == 0)
-		priv->port = g_strdup ("7191");
-	else
-		priv->port = g_strdup (property_value);
-
-	/*filter*/
-	if (camel_url_get_param (url, "filter"))
-		store->flags |= CAMEL_STORE_FILTER_INBOX;
-
-	/*Hash Table*/
-	priv->id_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-	priv->name_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-	priv->parent_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-
-	/*ssl*/
-	priv->use_ssl = g_strdup (camel_url_get_param (url, "use_ssl"));
-
-	store->flags &= ~CAMEL_STORE_VJUNK;
-	store->flags &= ~CAMEL_STORE_VTRASH;
-
-	return TRUE;
-}
+G_DEFINE_TYPE_WITH_CODE (
+	CamelGroupwiseStore, camel_groupwise_store, CAMEL_TYPE_OFFLINE_STORE,
+	G_IMPLEMENT_INTERFACE (
+		G_TYPE_INITABLE, camel_groupwise_store_initable_init))
 
 static guint
 groupwise_hash_folder_name (gconstpointer key)
@@ -302,6 +232,7 @@ groupwise_connect_sync (CamelService *service,
 	CamelProvider *provider;
 	CamelSession *session;
 	CamelURL *url;
+	const gchar *user_data_dir;
 
 	d("in groupwise store connect\n");
 
@@ -309,16 +240,11 @@ groupwise_connect_sync (CamelService *service,
 	session = camel_service_get_session (service);
 	provider = camel_service_get_provider (service);
 	status = camel_service_get_connection_status (service);
+	user_data_dir = camel_service_get_user_data_dir (service);
 
 	if (status == CAMEL_SERVICE_DISCONNECTED)
 		return FALSE;
 
-	if (!priv) {
-		store->priv = g_new0 (CamelGroupwiseStorePrivate, 1);
-		priv = store->priv;
-		camel_service_construct (service, session, provider, url, error);
-	}
-
 	camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	if (priv->cnc) {
@@ -343,7 +269,8 @@ groupwise_connect_sync (CamelService *service,
 
 	}
 
-	ns = camel_groupwise_store_summary_namespace_new (store->summary, priv->storage_path, '/');
+	ns = camel_groupwise_store_summary_namespace_new (
+		store->summary, user_data_dir, '/');
 	camel_groupwise_store_summary_namespace_set (store->summary, ns);
 
 	if (camel_store_summary_count ((CamelStoreSummary *)store->summary) == 0) {
@@ -395,9 +322,6 @@ groupwise_disconnect_cleanup (CamelService *service, gboolean clean, GError **er
 			priv->base_url = NULL;
 		}
 
-		if (priv->storage_path)
-			g_free (priv->storage_path);
-
 		if (groupwise_store->root_container)
 			g_free (groupwise_store->root_container);
 
@@ -518,12 +442,16 @@ groupwise_build_folder_info (CamelGroupwiseStore *gw_store, const gchar *parent_
 static void
 groupwise_forget_folder (CamelGroupwiseStore *gw_store, const gchar *folder_name, GError **error)
 {
-	CamelGroupwiseStorePrivate *priv = gw_store->priv;
+	CamelService *service;
+	const gchar *user_data_dir;
 	gchar *state_file;
 	gchar *folder_dir, *storage_path;
 	CamelFolderInfo *fi;
 
-	storage_path = g_strdup_printf ("%s/folders", priv->storage_path);
+	service = CAMEL_SERVICE (gw_store);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
+	storage_path = g_strdup_printf ("%s/folders", user_data_dir);
 	folder_dir = e_path_to_physical (storage_path,folder_name);
 
 	if (g_access (folder_dir, F_OK) != 0) {
@@ -553,14 +481,18 @@ groupwise_get_folder_from_disk (CamelStore *store,
                                 GCancellable *cancellable,
                                 GError **error)
 {
-	CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (store);
-	CamelGroupwiseStorePrivate *priv = gw_store->priv;
 	CamelFolder *folder;
+	CamelService *service;
+	const gchar *user_data_dir;
 	gchar *folder_dir, *storage_path;
 
-	storage_path = g_strdup_printf("%s/folders", priv->storage_path);
+	service = CAMEL_SERVICE (store);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
+	storage_path = g_strdup_printf ("%s/folders", user_data_dir);
 	folder_dir = e_path_to_physical (storage_path, folder_name);
 	g_free (storage_path);
+
 	if (!folder_dir || g_access (folder_dir, F_OK) != 0) {
 		g_free (folder_dir);
 		g_set_error (
@@ -586,17 +518,22 @@ groupwise_store_get_folder_sync (CamelStore *store,
 	CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (store);
 	CamelGroupwiseStorePrivate *priv = gw_store->priv;
 	CamelFolder *folder;
+	CamelService *service;
 	CamelGroupwiseSummary *summary;
 	gchar *container_id, *folder_dir, *storage_path;
 	EGwConnectionStatus status;
 	GList *list = NULL;
 	gboolean done = FALSE, all_ok = TRUE;
+	const gchar *user_data_dir;
 	const gchar *position = E_GW_CURSOR_POSITION_END;
 	gint count = 0, cursor, summary_count = 0;
 	CamelStoreInfo *si = NULL;
 	guint total = 0;
 	GError *local_error = NULL;
 
+	service = CAMEL_SERVICE (store);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
 	folder = groupwise_get_folder_from_disk (
 		store, folder_name, flags, cancellable, &local_error);
 	if (folder) {
@@ -611,30 +548,30 @@ groupwise_store_get_folder_sync (CamelStore *store,
 	} else
 		g_clear_error (&local_error);
 
-	camel_service_lock (CAMEL_SERVICE (gw_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+	camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	groupwise_store_set_current_folder (gw_store, NULL);
 
 	if (!camel_groupwise_store_connected (gw_store, cancellable, error)) {
-		camel_service_unlock (CAMEL_SERVICE (gw_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+		camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 		return NULL;
 	}
 
 	if (!E_IS_GW_CONNECTION ( priv->cnc)) {
-		if (!groupwise_connect_sync (CAMEL_SERVICE (store), cancellable, error)) {
-			camel_service_unlock (CAMEL_SERVICE (gw_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+		if (!groupwise_connect_sync (service, cancellable, error)) {
+			camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 			return NULL;
 		}
 	}
 
 	container_id =	g_strdup (g_hash_table_lookup (priv->name_hash, folder_name));
 
-	storage_path = g_strdup_printf("%s/folders", priv->storage_path);
+	storage_path = g_strdup_printf ("%s/folders", user_data_dir);
 	folder_dir = e_path_to_physical (storage_path, folder_name);
 	g_free (storage_path);
 	folder = camel_gw_folder_new (store, folder_name, folder_dir, cancellable, NULL);
 	if (!folder) {
-		camel_service_unlock (CAMEL_SERVICE (gw_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+		camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 		g_set_error (
 			error, CAMEL_SERVICE_ERROR,
 			CAMEL_SERVICE_ERROR_INVALID,
@@ -668,7 +605,7 @@ groupwise_store_get_folder_sync (CamelStore *store,
 				&cursor);
 
 		if (status != E_GW_CONNECTION_STATUS_OK) {
-			camel_service_unlock (CAMEL_SERVICE (gw_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+			camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 			g_free (container_id);
 			return NULL;
 		}
@@ -731,7 +668,7 @@ groupwise_store_get_folder_sync (CamelStore *store,
 	groupwise_store_set_current_folder (gw_store, folder);
 
 	g_free (container_id);
-	camel_service_unlock (CAMEL_SERVICE (gw_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+	camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	return folder;
 }
@@ -1326,10 +1263,15 @@ groupwise_store_rename_folder_sync (CamelStore *store,
 {
 	CamelGroupwiseStore *groupwise_store = CAMEL_GROUPWISE_STORE (store);
 	CamelGroupwiseStorePrivate  *priv = groupwise_store->priv;
+	CamelService *service;
+	const gchar *user_data_dir;
 	gchar *oldpath, *newpath, *storepath;
 	const gchar *container_id;
 	gchar *temp_new = NULL;
 
+	service = CAMEL_SERVICE (store);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
 	if (groupwise_is_system_folder (old_name)) {
 		g_set_error (
 			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
@@ -1338,10 +1280,10 @@ groupwise_store_rename_folder_sync (CamelStore *store,
 		return FALSE;
 	}
 
-	camel_service_lock (CAMEL_SERVICE (groupwise_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+	camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	if (!camel_groupwise_store_connected (groupwise_store, cancellable, error)) {
-		camel_service_unlock (CAMEL_SERVICE (groupwise_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+		camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 		return FALSE;
 	}
 
@@ -1360,7 +1302,7 @@ groupwise_store_rename_folder_sync (CamelStore *store,
 			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
 			_("Cannot rename GroupWise folder '%s' to '%s'"),
 			old_name, new_name);
-		camel_service_unlock (CAMEL_SERVICE (groupwise_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+		camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 		return FALSE;
 	}
 
@@ -1370,7 +1312,7 @@ groupwise_store_rename_folder_sync (CamelStore *store,
 	g_hash_table_remove (priv->name_hash, old_name);
 	/*FIXME:Update all the id in the parent_hash*/
 
-	storepath = g_strdup_printf ("%s/folders", priv->storage_path);
+	storepath = g_strdup_printf ("%s/folders", user_data_dir);
 	oldpath = e_path_to_physical (storepath, old_name);
 	newpath = e_path_to_physical (storepath, new_name);
 	g_free (storepath);
@@ -1383,7 +1325,7 @@ groupwise_store_rename_folder_sync (CamelStore *store,
 
 	g_free (oldpath);
 	g_free (newpath);
-	camel_service_unlock (CAMEL_SERVICE (groupwise_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+	camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	return TRUE;
 }
@@ -1426,12 +1368,6 @@ cnc_lookup (CamelGroupwiseStorePrivate *priv)
 	return priv->cnc;
 }
 
-gchar *
-storage_path_lookup (CamelGroupwiseStorePrivate *priv)
-{
-	return priv->storage_path;
-}
-
 const gchar *
 groupwise_base_url_lookup (CamelGroupwiseStorePrivate *priv)
 {
@@ -1449,7 +1385,15 @@ groupwise_store_get_trash_folder_sync (CamelStore *store,
 		store, "Trash", 0, cancellable, error);
 	if (folder) {
 		CamelObject *object = CAMEL_OBJECT (folder);
-		 gchar *state = g_build_filename((CAMEL_GROUPWISE_STORE(store))->priv->storage_path, "folders", "Trash", "cmeta", NULL);
+		CamelService *service;
+		const gchar *user_data_dir;
+		gchar *state;
+
+		service = CAMEL_SERVICE (store);
+		user_data_dir = camel_service_get_user_data_dir (service);
+
+		state = g_build_filename (
+			user_data_dir, "folders", "Trash", "cmeta", NULL);
 
 		camel_object_set_state_filename (object, state);
 		g_free (state);
@@ -1559,7 +1503,6 @@ groupwise_store_finalize (GObject *object)
 	g_free (groupwise_store->priv->port);
 	g_free (groupwise_store->priv->use_ssl);
 	g_free (groupwise_store->priv->base_url);
-	g_free (groupwise_store->priv->storage_path);
 	g_free (groupwise_store->root_container);
 
 	if (groupwise_store->priv->id_hash != NULL)
@@ -1575,6 +1518,107 @@ groupwise_store_finalize (GObject *object)
 	G_OBJECT_CLASS (camel_groupwise_store_parent_class)->finalize (object);
 }
 
+static gboolean
+groupwise_store_initable_init (GInitable *initable,
+                               GCancellable *cancellable,
+                               GError **error)
+{
+	CamelGroupwiseStore *groupwise_store;
+	CamelService *transport;
+	CamelService *service;
+	CamelSession *session;
+	CamelURL *url;
+	const gchar *property_value;
+	const gchar *user_data_dir;
+	const gchar *store_uid;
+	gchar *transport_uid;
+	gchar *uri_string;
+	gchar *path = NULL;
+
+	groupwise_store = CAMEL_GROUPWISE_STORE (initable);
+
+	/* Chain up to parent interface's init() method. */
+	if (!parent_initable_interface->init (initable, cancellable, error))
+		return FALSE;
+
+	service = CAMEL_SERVICE (initable);
+	url = camel_service_get_camel_url (service);
+	session = camel_service_get_session (service);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
+	if (!(url->host || url->user)) {
+		g_set_error (
+			error, CAMEL_SERVICE_ERROR,
+			CAMEL_SERVICE_ERROR_INVALID,
+			_("Host or user not available in url"));
+	}
+
+	/*store summary*/
+	path = g_alloca (strlen (user_data_dir) + 32);
+	sprintf (path, "%s/.summary", user_data_dir);
+	groupwise_store->summary = camel_groupwise_store_summary_new ();
+	camel_store_summary_set_filename ((CamelStoreSummary *)groupwise_store->summary, path);
+	camel_store_summary_touch ((CamelStoreSummary *)groupwise_store->summary);
+	camel_store_summary_load ((CamelStoreSummary *) groupwise_store->summary);
+
+	/*host and user*/
+	groupwise_store->priv->server_name = g_strdup (url->host);
+	groupwise_store->priv->user = g_strdup (url->user);
+
+	/*base url*/
+	groupwise_store->priv->base_url = camel_url_to_string (
+		url, CAMEL_URL_HIDE_PASSWORD |
+		CAMEL_URL_HIDE_PARAMS | CAMEL_URL_HIDE_AUTH);
+
+	/*soap port*/
+	property_value =  camel_url_get_param (url, "soap_port");
+	if (property_value == NULL)
+		groupwise_store->priv->port = g_strdup ("7191");
+	else if (strlen (property_value) == 0)
+		groupwise_store->priv->port = g_strdup ("7191");
+	else
+		groupwise_store->priv->port = g_strdup (property_value);
+
+	/*filter*/
+	if (camel_url_get_param (url, "filter"))
+		CAMEL_STORE (groupwise_store)->flags |= CAMEL_STORE_FILTER_INBOX;
+
+	/*Hash Table*/
+	groupwise_store->priv->id_hash =
+		g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+	groupwise_store->priv->name_hash =
+		g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+	groupwise_store->priv->parent_hash =
+		g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+	/*ssl*/
+	groupwise_store->priv->use_ssl =
+		g_strdup (camel_url_get_param (url, "use_ssl"));
+
+	CAMEL_STORE (groupwise_store)->flags &= ~CAMEL_STORE_VJUNK;
+	CAMEL_STORE (groupwise_store)->flags &= ~CAMEL_STORE_VTRASH;
+
+	/* Add a corresponding CamelGroupwiseTransport. */
+
+	store_uid = camel_service_get_uid (service);
+	transport_uid = g_strconcat (store_uid, "-transport", NULL);
+	uri_string = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
+
+	transport = camel_session_add_service (
+		session, transport_uid, uri_string,
+		CAMEL_PROVIDER_TRANSPORT, error);
+
+	g_free (transport_uid);
+	g_free (uri_string);
+
+	if (transport != NULL)
+		camel_groupwise_transport_set_store (
+			CAMEL_GROUPWISE_TRANSPORT (transport),
+			groupwise_store);
+
+	return (transport != NULL);
+}
+
 static void
 camel_groupwise_store_class_init (CamelGroupwiseStoreClass *class)
 {
@@ -1589,7 +1633,6 @@ camel_groupwise_store_class_init (CamelGroupwiseStoreClass *class)
 	object_class->finalize = groupwise_store_finalize;
 
 	service_class = CAMEL_SERVICE_CLASS (class);
-	service_class->construct = groupwise_store_construct;
 	service_class->get_name = groupwise_get_name;
 	service_class->connect_sync = groupwise_connect_sync;
 	service_class->disconnect_sync = groupwise_disconnect_sync;
@@ -1609,6 +1652,14 @@ camel_groupwise_store_class_init (CamelGroupwiseStoreClass *class)
 }
 
 static void
+camel_groupwise_store_initable_init (GInitableIface *interface)
+{
+	parent_initable_interface = g_type_interface_peek_parent (interface);
+
+	interface->init = groupwise_store_initable_init;
+}
+
+static void
 camel_groupwise_store_init (CamelGroupwiseStore *groupwise_store)
 {
 	groupwise_store->priv = G_TYPE_INSTANCE_GET_PRIVATE (
diff --git a/camel/providers/groupwise/camel-groupwise-store.h b/camel/providers/groupwise/camel-groupwise-store.h
index 7e901c3..6a72357 100644
--- a/camel/providers/groupwise/camel-groupwise-store.h
+++ b/camel/providers/groupwise/camel-groupwise-store.h
@@ -86,7 +86,6 @@ const gchar *	camel_groupwise_store_folder_lookup
 						(CamelGroupwiseStore *store,
 						 const gchar *container_id);
 EGwConnection *	cnc_lookup			(CamelGroupwiseStorePrivate *priv);
-gchar *		storage_path_lookup		(CamelGroupwiseStorePrivate *priv);
 const gchar *	groupwise_base_url_lookup	(CamelGroupwiseStorePrivate *priv);
 CamelFolderInfo *
 		create_junk_folder		(CamelStore *store);
diff --git a/camel/providers/groupwise/camel-groupwise-transport.c b/camel/providers/groupwise/camel-groupwise-transport.c
index 6f2876d..54b3af9 100644
--- a/camel/providers/groupwise/camel-groupwise-transport.c
+++ b/camel/providers/groupwise/camel-groupwise-transport.c
@@ -36,8 +36,33 @@
 
 #define REPLY_VIEW "default message attachments threading"
 
+#define CAMEL_GROUPWISE_TRANSPORT_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), CAMEL_TYPE_GROUPWISE_TRANSPORT, CamelGroupwiseTransportPrivate))
+
 G_DEFINE_TYPE (CamelGroupwiseTransport, camel_groupwise_transport, CAMEL_TYPE_TRANSPORT)
 
+struct _CamelGroupwiseTransportPrivate {
+	CamelGroupwiseStore *store;
+};
+
+static void
+groupwise_transport_dispose (GObject *object)
+{
+	CamelGroupwiseTransportPrivate *priv;
+
+	priv = CAMEL_GROUPWISE_TRANSPORT_GET_PRIVATE (object);
+
+	if (priv->store != NULL) {
+		g_object_unref (priv->store);
+		priv->store = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (camel_groupwise_transport_parent_class)->
+		dispose (object);
+}
+
 static gchar *
 groupwise_transport_get_name (CamelService *service,
                               gboolean brief)
@@ -72,17 +97,14 @@ groupwise_send_to_sync (CamelTransport *transport,
                         GCancellable *cancellable,
                         GError **error)
 {
+	CamelGroupwiseTransportPrivate *priv;
 	CamelService *service;
 	CamelSession *session;
-	CamelStore *store = NULL;
 	CamelURL *service_url;
-	CamelGroupwiseStore *groupwise_store = NULL;
-	CamelGroupwiseStorePrivate *priv = NULL;
 	EGwItem *item ,*temp_item=NULL;
 	EGwConnection *cnc = NULL;
 	EGwConnectionStatus status = 0;
 	GSList *sent_item_list = NULL;
-	gchar *url = NULL;
 	gchar *reply_request = NULL;
 	EGwItemLinkInfo *info = NULL;
 
@@ -94,31 +116,16 @@ groupwise_send_to_sync (CamelTransport *transport,
 		return FALSE;
 	}
 
+	priv = CAMEL_GROUPWISE_TRANSPORT_GET_PRIVATE (transport);
+
 	service = CAMEL_SERVICE (transport);
 	session = camel_service_get_session (service);
 	service_url = camel_service_get_camel_url (service);
 
-	url = camel_url_to_string (
-		service_url, CAMEL_URL_HIDE_PASSWORD |
-		CAMEL_URL_HIDE_PARAMS | CAMEL_URL_HIDE_AUTH);
-
 	camel_operation_push_message (cancellable, _("Sending Message") );
 
 	/*camel groupwise store and cnc*/
-	store = camel_session_get_store (session, url, NULL);
-	g_free (url);
-	if (!store) {
-		g_warning ("ERROR: Could not get a pointer to the store");
-		g_set_error (
-			error, CAMEL_STORE_ERROR,
-			CAMEL_STORE_ERROR_INVALID,
-			_("Cannot get folder: Invalid operation on this store"));
-		return FALSE;
-	}
-	groupwise_store = CAMEL_GROUPWISE_STORE (store);
-	priv = groupwise_store->priv;
-
-	cnc = cnc_lookup (priv);
+	cnc = cnc_lookup (priv->store->priv);
 	if (!cnc) {
 		g_warning ("||| Eh!!! Failure |||\n");
 		camel_operation_pop_message (cancellable);
@@ -185,9 +192,16 @@ groupwise_send_to_sync (CamelTransport *transport,
 static void
 camel_groupwise_transport_class_init (CamelGroupwiseTransportClass *class)
 {
+	GObjectClass *object_class;
 	CamelServiceClass *service_class;
 	CamelTransportClass *transport_class;
 
+	g_type_class_add_private (
+		class, sizeof (CamelGroupwiseTransportPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->dispose = groupwise_transport_dispose;
+
 	service_class = CAMEL_SERVICE_CLASS (class);
 	service_class->get_name = groupwise_transport_get_name;
 	service_class->connect_sync = groupwise_transport_connect_sync;
@@ -197,6 +211,17 @@ camel_groupwise_transport_class_init (CamelGroupwiseTransportClass *class)
 }
 
 static void
-camel_groupwise_transport_init (CamelGroupwiseTransport *groupwise_transport)
+camel_groupwise_transport_init (CamelGroupwiseTransport *transport)
 {
+	transport->priv = CAMEL_GROUPWISE_TRANSPORT_GET_PRIVATE (transport);
+}
+
+void
+camel_groupwise_transport_set_store (CamelGroupwiseTransport *transport,
+                                     CamelGroupwiseStore *store)
+{
+	g_return_if_fail (CAMEL_IS_GROUPWISE_TRANSPORT (transport));
+	g_return_if_fail (CAMEL_IS_GROUPWISE_STORE (store));
+
+	transport->priv->store = g_object_ref (store);
 }
diff --git a/camel/providers/groupwise/camel-groupwise-transport.h b/camel/providers/groupwise/camel-groupwise-transport.h
index 9abf71a..ee9d21c 100644
--- a/camel/providers/groupwise/camel-groupwise-transport.h
+++ b/camel/providers/groupwise/camel-groupwise-transport.h
@@ -24,7 +24,7 @@
 #ifndef CAMEL_GROUPWISE_TRANSPORT_H
 #define CAMEL_GROUPWISE_TRANSPORT_H
 
-#include <camel/camel.h>
+#include "camel-groupwise-store.h"
 
 /* Standard GObject macros */
 #define CAMEL_TYPE_GROUPWISE_TRANSPORT \
@@ -49,17 +49,21 @@ G_BEGIN_DECLS
 
 typedef struct _CamelGroupwiseTransport CamelGroupwiseTransport;
 typedef struct _CamelGroupwiseTransportClass CamelGroupwiseTransportClass;
+typedef struct _CamelGroupwiseTransportPrivate CamelGroupwiseTransportPrivate;
 
 struct _CamelGroupwiseTransport {
 	CamelTransport parent;
-	gboolean connected;
+	CamelGroupwiseTransportPrivate *priv;
 };
 
 struct _CamelGroupwiseTransportClass {
 	CamelTransportClass parent_class;
 };
 
-GType camel_groupwise_transport_get_type (void);
+GType		camel_groupwise_transport_get_type (void);
+void		camel_groupwise_transport_set_store
+					(CamelGroupwiseTransport *transport,
+					 CamelGroupwiseStore *store);
 
 G_END_DECLS
 
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index c4bd8c5..77519cd 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -629,18 +629,22 @@ imap_get_filename (CamelFolder *folder,
 static void
 imap_rename (CamelFolder *folder, const gchar *new)
 {
+	CamelService *service;
 	CamelStore *parent_store;
 	CamelImapFolder *imap_folder = (CamelImapFolder *)folder;
-	CamelImapStore *imap_store;
+	const gchar *user_data_dir;
 	gchar *folder_dir, *summary_path, *state_file;
 	gchar *folders;
 
 	parent_store = camel_folder_get_parent_store (folder);
-	imap_store = CAMEL_IMAP_STORE (parent_store);
 
-	folders = g_strconcat (imap_store->storage_path, "/folders", NULL);
+	service = CAMEL_SERVICE (parent_store);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
+	folders = g_strconcat (user_data_dir, "/folders", NULL);
 	folder_dir = imap_path_to_physical (folders, new);
 	g_free (folders);
+
 	summary_path = g_strdup_printf("%s/summary", folder_dir);
 
 	CAMEL_IMAP_FOLDER_REC_LOCK (folder, cache_lock);
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 74c1fc8..dc8cd8e 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -136,7 +136,15 @@ static struct {
 
 extern CamelServiceAuthType camel_imap_password_authtype;
 
-G_DEFINE_TYPE (CamelImapStore, camel_imap_store, CAMEL_TYPE_OFFLINE_STORE)
+static GInitableIface *parent_initable_interface;
+
+/* Forward Declarations */
+static void camel_imap_store_initable_init (GInitableIface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	CamelImapStore, camel_imap_store, CAMEL_TYPE_OFFLINE_STORE,
+	G_IMPLEMENT_INTERFACE (
+		G_TYPE_INITABLE, camel_imap_store_initable_init))
 
 static void
 parse_capability (CamelImapStore *store, gchar *capa)
@@ -910,7 +918,6 @@ imap_store_finalize (GObject *object)
 	camel_service_disconnect_sync (CAMEL_SERVICE (imap_store), TRUE, NULL);
 
 	g_free (imap_store->base_url);
-	g_free (imap_store->storage_path);
 	g_free (imap_store->users_namespace);
 	g_free (imap_store->custom_headers);
 	g_free (imap_store->real_trash_path);
@@ -920,110 +927,6 @@ imap_store_finalize (GObject *object)
 	G_OBJECT_CLASS (camel_imap_store_parent_class)->finalize (object);
 }
 
-static gboolean
-imap_store_construct (CamelService *service,
-                      CamelSession *session,
-                      CamelProvider *provider,
-                      CamelURL *url,
-                      GError **error)
-{
-	CamelServiceClass *service_class;
-	CamelImapStore *imap_store = CAMEL_IMAP_STORE (service);
-	CamelStore *store = CAMEL_STORE (service);
-	gchar *tmp;
-	CamelURL *summary_url;
-
-	/* Chain up to parent's construct() method. */
-	service_class = CAMEL_SERVICE_CLASS (camel_imap_store_parent_class);
-	if (!service_class->construct (service, session, provider, url, error))
-		return FALSE;
-
-	imap_store->storage_path = camel_session_get_storage_path (session, service, error);
-	if (!imap_store->storage_path)
-		return FALSE;
-
-	/* FIXME */
-	imap_store->base_url = camel_url_to_string (
-		url, CAMEL_URL_HIDE_PASSWORD |
-		CAMEL_URL_HIDE_PARAMS | CAMEL_URL_HIDE_AUTH);
-
-	imap_store->parameters = 0;
-	if (camel_url_get_param (url, "use_lsub"))
-		imap_store->parameters |= IMAP_PARAM_SUBSCRIPTIONS;
-	if (camel_url_get_param (url, "override_namespace") && camel_url_get_param (url, "namespace")) {
-		imap_store->parameters |= IMAP_PARAM_OVERRIDE_NAMESPACE;
-		g_free (imap_store->users_namespace);
-		imap_store->users_namespace = g_strdup (camel_url_get_param (url, "namespace"));
-	}
-	if (camel_url_get_param (url, "check_all"))
-		imap_store->parameters |= IMAP_PARAM_CHECK_ALL;
-	if (camel_url_get_param (url, "check_lsub"))
-		imap_store->parameters |= IMAP_PARAM_CHECK_LSUB;
-	if (camel_url_get_param (url, "filter")) {
-		imap_store->parameters |= IMAP_PARAM_FILTER_INBOX;
-		store->flags |= CAMEL_STORE_FILTER_INBOX;
-	}
-	if (camel_url_get_param (url, "filter_junk"))
-		imap_store->parameters |= IMAP_PARAM_FILTER_JUNK;
-	if (camel_url_get_param (url, "filter_junk_inbox"))
-		imap_store->parameters |= IMAP_PARAM_FILTER_JUNK_INBOX;
-
-	imap_store->headers = IMAP_FETCH_MAILING_LIST_HEADERS;
-	if (camel_url_get_param (url, "all_headers"))
-		imap_store->headers = IMAP_FETCH_ALL_HEADERS;
-	else if (camel_url_get_param (url, "basic_headers"))
-		imap_store->headers = IMAP_FETCH_MINIMAL_HEADERS;
-
-	if (camel_url_get_param (url, "imap_custom_headers")) {
-		imap_store->custom_headers = g_strdup(camel_url_get_param (url, "imap_custom_headers"));
-	}
-
-	imap_store->real_trash_path = g_strdup (camel_url_get_param (url, "real_trash_path"));
-	imap_store->real_junk_path = g_strdup (camel_url_get_param (url, "real_junk_path"));
-
-	if (imap_store->real_trash_path && !*imap_store->real_trash_path) {
-		g_free (imap_store->real_trash_path);
-		imap_store->real_trash_path = NULL;
-	}
-
-	if (imap_store->real_trash_path && *imap_store->real_trash_path)
-		store->flags &= ~CAMEL_STORE_VTRASH;
-
-	if (imap_store->real_junk_path && !*imap_store->real_junk_path) {
-		g_free (imap_store->real_junk_path);
-		imap_store->real_junk_path = NULL;
-	}
-
-	if (imap_store->real_junk_path && *imap_store->real_junk_path) {
-		store->flags &= ~CAMEL_STORE_VJUNK;
-		store->flags |= CAMEL_STORE_REAL_JUNK_FOLDER;
-	}
-
-	/* setup/load the store summary */
-	tmp = alloca (strlen (imap_store->storage_path)+32);
-	sprintf(tmp, "%s/.ev-store-summary", imap_store->storage_path);
-	imap_store->summary = camel_imap_store_summary_new ();
-	camel_store_summary_set_filename ((CamelStoreSummary *)imap_store->summary, tmp);
-	summary_url = camel_url_new (imap_store->base_url, NULL);
-	camel_store_summary_set_uri_base ((CamelStoreSummary *)imap_store->summary, summary_url);
-	camel_url_free (summary_url);
-	if (camel_store_summary_load ((CamelStoreSummary *)imap_store->summary) == 0) {
-		CamelImapStoreSummary *is = imap_store->summary;
-
-		if (is->namespace) {
-			/* if namespace has changed, clear folder list */
-			if (imap_store->users_namespace && strcmp (imap_store->users_namespace, is->namespace->full_name) != 0) {
-				camel_store_summary_clear ((CamelStoreSummary *)is);
-			}
-		}
-
-		imap_store->capabilities = is->capabilities;
-		imap_set_server_level (imap_store);
-	}
-
-	return TRUE;
-}
-
 static gchar *
 imap_store_get_name (CamelService *service,
                      gboolean brief)
@@ -1313,6 +1216,110 @@ imap_store_query_auth_types_sync (CamelService *service,
 	return g_list_prepend (sasl_types, &camel_imap_password_authtype);
 }
 
+static gboolean
+imap_store_initable_init (GInitable *initable,
+                          GCancellable *cancellable,
+                          GError **error)
+{
+	CamelImapStore *imap_store;
+	CamelService *service;
+	CamelURL *summary_url;
+	CamelURL *url;
+	const gchar *user_data_dir;
+	gchar *tmp;
+
+	imap_store = CAMEL_IMAP_STORE (initable);
+
+	/* Chain up to parent interface's init() method. */
+	if (!parent_initable_interface->init (initable, cancellable, error))
+		return FALSE;
+
+	service = CAMEL_SERVICE (initable);
+	url = camel_service_get_camel_url (service);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
+	/* FIXME */
+	imap_store->base_url = camel_url_to_string (
+		url, CAMEL_URL_HIDE_PASSWORD |
+		CAMEL_URL_HIDE_PARAMS | CAMEL_URL_HIDE_AUTH);
+
+	imap_store->parameters = 0;
+	if (camel_url_get_param (url, "use_lsub"))
+		imap_store->parameters |= IMAP_PARAM_SUBSCRIPTIONS;
+	if (camel_url_get_param (url, "override_namespace") && camel_url_get_param (url, "namespace")) {
+		imap_store->parameters |= IMAP_PARAM_OVERRIDE_NAMESPACE;
+		g_free (imap_store->users_namespace);
+		imap_store->users_namespace = g_strdup (camel_url_get_param (url, "namespace"));
+	}
+	if (camel_url_get_param (url, "check_all"))
+		imap_store->parameters |= IMAP_PARAM_CHECK_ALL;
+	if (camel_url_get_param (url, "check_lsub"))
+		imap_store->parameters |= IMAP_PARAM_CHECK_LSUB;
+	if (camel_url_get_param (url, "filter")) {
+		imap_store->parameters |= IMAP_PARAM_FILTER_INBOX;
+		CAMEL_STORE (imap_store)->flags |= CAMEL_STORE_FILTER_INBOX;
+	}
+	if (camel_url_get_param (url, "filter_junk"))
+		imap_store->parameters |= IMAP_PARAM_FILTER_JUNK;
+	if (camel_url_get_param (url, "filter_junk_inbox"))
+		imap_store->parameters |= IMAP_PARAM_FILTER_JUNK_INBOX;
+
+	imap_store->headers = IMAP_FETCH_MAILING_LIST_HEADERS;
+	if (camel_url_get_param (url, "all_headers"))
+		imap_store->headers = IMAP_FETCH_ALL_HEADERS;
+	else if (camel_url_get_param (url, "basic_headers"))
+		imap_store->headers = IMAP_FETCH_MINIMAL_HEADERS;
+
+	if (camel_url_get_param (url, "imap_custom_headers")) {
+		imap_store->custom_headers = g_strdup(camel_url_get_param (url, "imap_custom_headers"));
+	}
+
+	imap_store->real_trash_path = g_strdup (camel_url_get_param (url, "real_trash_path"));
+	imap_store->real_junk_path = g_strdup (camel_url_get_param (url, "real_junk_path"));
+
+	if (imap_store->real_trash_path && !*imap_store->real_trash_path) {
+		g_free (imap_store->real_trash_path);
+		imap_store->real_trash_path = NULL;
+	}
+
+	if (imap_store->real_trash_path && *imap_store->real_trash_path)
+		CAMEL_STORE (imap_store)->flags &= ~CAMEL_STORE_VTRASH;
+
+	if (imap_store->real_junk_path && !*imap_store->real_junk_path) {
+		g_free (imap_store->real_junk_path);
+		imap_store->real_junk_path = NULL;
+	}
+
+	if (imap_store->real_junk_path && *imap_store->real_junk_path) {
+		CAMEL_STORE (imap_store)->flags &= ~CAMEL_STORE_VJUNK;
+		CAMEL_STORE (imap_store)->flags |= CAMEL_STORE_REAL_JUNK_FOLDER;
+	}
+
+	/* setup/load the store summary */
+	tmp = alloca (strlen (user_data_dir) + 32);
+	sprintf(tmp, "%s/.ev-store-summary", user_data_dir);
+	imap_store->summary = camel_imap_store_summary_new ();
+	camel_store_summary_set_filename ((CamelStoreSummary *)imap_store->summary, tmp);
+	summary_url = camel_url_new (imap_store->base_url, NULL);
+	camel_store_summary_set_uri_base ((CamelStoreSummary *)imap_store->summary, summary_url);
+	camel_url_free (summary_url);
+	if (camel_store_summary_load ((CamelStoreSummary *)imap_store->summary) == 0) {
+		CamelImapStoreSummary *is = imap_store->summary;
+
+		if (is->namespace) {
+			/* if namespace has changed, clear folder list */
+			if (imap_store->users_namespace && strcmp (imap_store->users_namespace, is->namespace->full_name) != 0) {
+				camel_store_summary_clear ((CamelStoreSummary *)is);
+			}
+		}
+
+		imap_store->capabilities = is->capabilities;
+		imap_set_server_level (imap_store);
+	}
+
+	return TRUE;
+}
+
 static void
 camel_imap_store_class_init (CamelImapStoreClass *class)
 {
@@ -1325,7 +1332,6 @@ camel_imap_store_class_init (CamelImapStoreClass *class)
 	object_class->finalize = imap_store_finalize;
 
 	service_class = CAMEL_SERVICE_CLASS (class);
-	service_class->construct = imap_store_construct;
 	service_class->get_name = imap_store_get_name;
 	service_class->connect_sync = imap_store_connect_sync;
 	service_class->disconnect_sync = imap_store_disconnect_sync;
@@ -1350,6 +1356,14 @@ camel_imap_store_class_init (CamelImapStoreClass *class)
 }
 
 static void
+camel_imap_store_initable_init (GInitableIface *interface)
+{
+	parent_initable_interface = g_type_interface_peek_parent (interface);
+
+	interface->init = imap_store_initable_init;
+}
+
+static void
 camel_imap_store_init (CamelImapStore *imap_store)
 {
 	imap_store->istream = NULL;
@@ -1455,6 +1469,8 @@ imap_folder_effectively_unsubscribed (CamelImapStore *imap_store,
 static void
 imap_forget_folder (CamelImapStore *imap_store, const gchar *folder_name, GError **error)
 {
+	CamelService *service;
+	const gchar *user_data_dir;
 	gchar *state_file;
 	gchar *journal_file;
 	gchar *folder_dir, *storage_path;
@@ -1467,7 +1483,10 @@ imap_forget_folder (CamelImapStore *imap_store, const gchar *folder_name, GError
 	else
 		name = folder_name;
 
-	storage_path = g_strdup_printf ("%s/folders", imap_store->storage_path);
+	service = CAMEL_SERVICE (imap_store);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
+	storage_path = g_strdup_printf ("%s/folders", user_data_dir);
 	folder_dir = imap_path_to_physical (storage_path, folder_name);
 	g_free (storage_path);
 	if (g_access (folder_dir, F_OK) != 0) {
@@ -1607,7 +1626,15 @@ imap_store_get_trash_folder_sync (CamelStore *store,
 
 	if (folder) {
 		CamelObject *object = CAMEL_OBJECT (folder);
-		gchar *state = g_build_filename(((CamelImapStore *)store)->storage_path, "system", "Trash.cmeta", NULL);
+		CamelService *service;
+		const gchar *user_data_dir;
+		gchar *state;
+
+		service = CAMEL_SERVICE (store);
+		user_data_dir = camel_service_get_user_data_dir (service);
+
+		state = g_build_filename (
+			user_data_dir, "system", "Trash.cmeta", NULL);
 
 		camel_object_set_state_filename (object, state);
 		g_free (state);
@@ -1645,7 +1672,15 @@ imap_store_get_junk_folder_sync (CamelStore *store,
 
 	if (folder) {
 		CamelObject *object = CAMEL_OBJECT (folder);
-		gchar *state = g_build_filename(((CamelImapStore *)store)->storage_path, "system", "Junk.cmeta", NULL);
+		CamelService *service;
+		const gchar *user_data_dir;
+		gchar *state;
+
+		service = CAMEL_SERVICE (store);
+		user_data_dir = camel_service_get_user_data_dir (service);
+
+		state = g_build_filename (
+			user_data_dir, "system", "Junk.cmeta", NULL);
 
 		camel_object_set_state_filename (object, state);
 		g_free (state);
@@ -1792,9 +1827,14 @@ imap_store_get_folder_sync (CamelStore *store,
 	CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
 	CamelImapResponse *response;
 	CamelFolder *new_folder;
+	CamelService *service;
+	const gchar *user_data_dir;
 	gchar *folder_dir, *storage_path;
 	GError *local_error = NULL;
 
+	service = CAMEL_SERVICE (store);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
 	/* Try to get it locally first, if it is, then the client will
 	   force a select when necessary */
 	new_folder = get_folder_offline (store, folder_name, flags, &local_error);
@@ -1811,10 +1851,10 @@ imap_store_get_folder_sync (CamelStore *store,
 		return NULL;
 	}
 
-	camel_service_lock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+	camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	if (!camel_imap_store_connected (imap_store, error)) {
-		camel_service_unlock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+		camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 		return NULL;
 	}
 
@@ -1832,7 +1872,7 @@ imap_store_get_folder_sync (CamelStore *store,
 		const gchar *c;
 
 		if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			camel_service_unlock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+			camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 			g_propagate_error (error, local_error);
 			return NULL;
 		}
@@ -1840,7 +1880,7 @@ imap_store_get_folder_sync (CamelStore *store,
 		g_clear_error (&local_error);
 
 		if (!(flags & CAMEL_STORE_FOLDER_CREATE)) {
-			camel_service_unlock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+			camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 			g_set_error (
 				error, CAMEL_STORE_ERROR,
 				CAMEL_STORE_ERROR_NO_FOLDER,
@@ -1854,7 +1894,7 @@ imap_store_get_folder_sync (CamelStore *store,
 			c++;
 
 		if (*c != '\0') {
-			camel_service_unlock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+			camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 			g_set_error (
 				error, CAMEL_FOLDER_ERROR,
 				CAMEL_FOLDER_ERROR_INVALID_PATH,
@@ -1877,7 +1917,7 @@ imap_store_get_folder_sync (CamelStore *store,
 			gint i;
 
 			if (!(response = camel_imap_command (imap_store, NULL, cancellable, error, "LIST \"\" %G", parent_real))) {
-				camel_service_unlock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+				camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 				g_free (parent_name);
 				g_free (parent_real);
 				return NULL;
@@ -1923,7 +1963,7 @@ imap_store_get_folder_sync (CamelStore *store,
 						error, CAMEL_FOLDER_ERROR,
 						CAMEL_FOLDER_ERROR_INVALID_STATE,
 						_("The parent folder is not allowed to contain subfolders"));
-					camel_service_unlock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+					camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 					g_free (parent_name);
 					g_free (parent_real);
 					return NULL;
@@ -1932,7 +1972,7 @@ imap_store_get_folder_sync (CamelStore *store,
 				/* delete the old parent and recreate it */
 				if (!imap_store_delete_folder_sync (
 					store, parent_name, cancellable, error)) {
-					camel_service_unlock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+					camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 					g_free (parent_name);
 					g_free (parent_real);
 					return NULL;
@@ -1945,7 +1985,7 @@ imap_store_get_folder_sync (CamelStore *store,
 				g_free (name);
 
 				if (!response) {
-					camel_service_unlock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+					camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 					g_free (parent_name);
 					g_free (parent_real);
 					return NULL;
@@ -1969,7 +2009,7 @@ imap_store_get_folder_sync (CamelStore *store,
 		}
 		g_free (folder_real);
 		if (!response) {
-			camel_service_unlock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+			camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 			return NULL;
 		}
 	} else if (flags & CAMEL_STORE_FOLDER_EXCL) {
@@ -1980,12 +2020,12 @@ imap_store_get_folder_sync (CamelStore *store,
 
 		camel_imap_response_free_without_processing (imap_store, response);
 
-		camel_service_unlock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+		camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 		return NULL;
 	}
 
-	storage_path = g_strdup_printf("%s/folders", imap_store->storage_path);
+	storage_path = g_strdup_printf("%s/folders", user_data_dir);
 	folder_dir = imap_path_to_physical (storage_path, folder_name);
 	g_free (storage_path);
 	new_folder = camel_imap_folder_new (store, folder_name, folder_dir, error);
@@ -2003,7 +2043,7 @@ imap_store_get_folder_sync (CamelStore *store,
 	}
 	camel_imap_response_free_without_processing (imap_store, response);
 
-	camel_service_unlock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+	camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	return new_folder;
 }
@@ -2015,6 +2055,11 @@ get_folder_offline (CamelStore *store, const gchar *folder_name,
 	CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
 	CamelFolder *new_folder = NULL;
 	CamelStoreInfo *si;
+	CamelService *service;
+	const gchar *user_data_dir;
+
+	service = CAMEL_SERVICE (store);
+	user_data_dir = camel_service_get_user_data_dir (service);
 
 	si = camel_store_summary_path ((CamelStoreSummary *)imap_store->summary, folder_name);
 	if (si) {
@@ -2030,7 +2075,7 @@ get_folder_offline (CamelStore *store, const gchar *folder_name,
 		if (!g_ascii_strcasecmp (folder_name, "INBOX"))
 			folder_name = "INBOX";
 
-		storage_path = g_strdup_printf("%s/folders", imap_store->storage_path);
+		storage_path = g_strdup_printf("%s/folders", user_data_dir);
 		folder_dir = imap_path_to_physical (storage_path, folder_name);
 		g_free (storage_path);
 		new_folder = camel_imap_folder_new (store, folder_name, folder_dir, error);
@@ -2172,10 +2217,15 @@ imap_store_rename_folder_sync (CamelStore *store,
 {
 	CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
 	CamelImapResponse *response;
+	CamelService *service;
+	const gchar *user_data_dir;
 	gchar *oldpath, *newpath, *storage_path;
 	gboolean success = TRUE;
 
-	camel_service_lock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+	service = CAMEL_SERVICE (store);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
+	camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	if (!camel_imap_store_connected (imap_store, error)) {
 		success = FALSE;
@@ -2220,7 +2270,7 @@ imap_store_rename_folder_sync (CamelStore *store,
 		manage_subscriptions (
 			store, new_name_in, TRUE, cancellable);
 
-	storage_path = g_strdup_printf("%s/folders", imap_store->storage_path);
+	storage_path = g_strdup_printf("%s/folders", user_data_dir);
 	oldpath = imap_path_to_physical (storage_path, old_name);
 	newpath = imap_path_to_physical (storage_path, new_name_in);
 
@@ -2256,7 +2306,7 @@ imap_store_rename_folder_sync (CamelStore *store,
 	g_free (newpath);
 fail:
 	imap_store->renaming = FALSE;
-	camel_service_unlock (CAMEL_SERVICE (imap_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+	camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	return success;
 }
diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h
index eacacae..59024a0 100644
--- a/camel/providers/imap/camel-imap-store.h
+++ b/camel/providers/imap/camel-imap-store.h
@@ -153,7 +153,7 @@ struct _CamelImapStore {
 	/* Information about the server */
 	CamelImapServerLevel server_level;
 	guint32 capabilities, parameters;
-	gchar *users_namespace, dir_sep, *base_url, *storage_path;
+	gchar *users_namespace, dir_sep, *base_url;
 	GHashTable *authtypes;
 
 	time_t refresh_stamp;
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index 5ccb1b4..bb644ad 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -50,7 +50,15 @@
 
 #define FINFO_REFRESH_INTERVAL 60
 
-G_DEFINE_TYPE (CamelIMAPXStore, camel_imapx_store, CAMEL_TYPE_OFFLINE_STORE)
+static GInitableIface *parent_initable_interface;
+
+/* Forward Declarations */
+static void camel_imapx_store_initable_init (GInitableIface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	CamelIMAPXStore, camel_imapx_store, CAMEL_TYPE_OFFLINE_STORE,
+	G_IMPLEMENT_INTERFACE (
+		G_TYPE_INITABLE, camel_imapx_store_initable_init))
 
 static guint
 imapx_name_hash (gconstpointer key)
@@ -142,44 +150,6 @@ imapx_store_finalize (GObject *object)
 	G_OBJECT_CLASS (camel_imapx_store_parent_class)->finalize (object);
 }
 
-static gboolean
-imapx_construct (CamelService *service,
-                 CamelSession *session,
-                 CamelProvider *provider,
-                 CamelURL *url,
-                 GError **error)
-{
-	gchar *summary;
-	CamelIMAPXStore *store = (CamelIMAPXStore *)service;
-	CamelServiceClass *service_class;
-
-	service_class = CAMEL_SERVICE_CLASS (camel_imapx_store_parent_class);
-	if (!service_class->construct (service, session, provider, url, error))
-		return FALSE;
-
-	store->base_url = camel_url_to_string (
-		url, CAMEL_URL_HIDE_PASSWORD |
-		CAMEL_URL_HIDE_PARAMS | CAMEL_URL_HIDE_AUTH);
-	imapx_parse_receiving_options (store, url);
-
-	store->summary = camel_imapx_store_summary_new ();
-	store->storage_path = camel_session_get_storage_path (session, service, error);
-
-	if (store->storage_path == NULL)
-		return FALSE;
-
-	summary = g_build_filename(store->storage_path, ".ev-store-summary", NULL);
-	camel_store_summary_set_filename ((CamelStoreSummary *)store->summary, summary);
-	/* FIXME: need to remove params, passwords, etc */
-	camel_store_summary_set_uri_base (
-		(CamelStoreSummary *)store->summary, url);
-	camel_store_summary_load ((CamelStoreSummary *)store->summary);
-
-	g_free (summary);
-
-	return TRUE;
-}
-
 static gchar *
 imapx_get_name (CamelService *service, gboolean brief)
 {
@@ -324,6 +294,11 @@ get_folder_offline (CamelStore *store, const gchar *folder_name,
 	CamelIMAPXStore *imapx_store = CAMEL_IMAPX_STORE (store);
 	CamelFolder *new_folder = NULL;
 	CamelStoreInfo *si;
+	CamelService *service;
+	const gchar *user_data_dir;
+
+	service = CAMEL_SERVICE (store);
+	user_data_dir = camel_service_get_user_data_dir (service);
 
 	si = camel_store_summary_path ((CamelStoreSummary *)imapx_store->summary, folder_name);
 	if (si) {
@@ -339,7 +314,7 @@ get_folder_offline (CamelStore *store, const gchar *folder_name,
 		if (!g_ascii_strcasecmp (folder_name, "INBOX"))
 			folder_name = "INBOX";
 
-		storage_path = g_strdup_printf("%s/folders", imapx_store->storage_path);
+		storage_path = g_strdup_printf("%s/folders", user_data_dir);
 		folder_dir = imapx_path_to_physical (storage_path, folder_name);
 		g_free (storage_path);
 		/* FIXME */
@@ -587,8 +562,13 @@ imapx_delete_folder_from_cache (CamelIMAPXStore *istore, const gchar *folder_nam
 	gchar *state_file;
 	gchar *folder_dir, *storage_path;
 	CamelFolderInfo *fi;
+	CamelService *service;
+	const gchar *user_data_dir;
 
-	storage_path = g_strdup_printf ("%s/folders", istore->storage_path);
+	service = CAMEL_SERVICE (istore);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
+	storage_path = g_strdup_printf ("%s/folders", user_data_dir);
 	folder_dir = imapx_path_to_physical (storage_path, folder_name);
 	g_free (storage_path);
 	if (g_access (folder_dir, F_OK) != 0) {
@@ -1262,7 +1242,15 @@ imapx_store_get_junk_folder_sync (CamelStore *store,
 
 	if (folder) {
 		CamelObject *object = CAMEL_OBJECT (folder);
-		gchar *state = g_build_filename(((CamelIMAPXStore *)store)->storage_path, "system", "Junk.cmeta", NULL);
+		CamelService *service;
+		const gchar *user_data_dir;
+		gchar *state;
+
+		service = CAMEL_SERVICE (store);
+		user_data_dir = camel_service_get_user_data_dir (service);
+
+		state = g_build_filename (
+			user_data_dir, "system", "Junk.cmeta", NULL);
 
 		camel_object_set_state_filename (object, state);
 		g_free (state);
@@ -1286,7 +1274,15 @@ imapx_store_get_trash_folder_sync (CamelStore *store,
 
 	if (folder) {
 		CamelObject *object = CAMEL_OBJECT (folder);
-		gchar *state = g_build_filename(((CamelIMAPXStore *)store)->storage_path, "system", "Trash.cmeta", NULL);
+		CamelService *service;
+		const gchar *user_data_dir;
+		gchar *state;
+
+		service = CAMEL_SERVICE (store);
+		user_data_dir = camel_service_get_user_data_dir (service);
+
+		state = g_build_filename (
+			user_data_dir, "system", "Trash.cmeta", NULL);
 
 		camel_object_set_state_filename (object, state);
 		g_free (state);
@@ -1433,9 +1429,14 @@ imapx_store_rename_folder_sync (CamelStore *store,
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *) store;
 	CamelIMAPXServer *server;
+	CamelService *service;
+	const gchar *user_data_dir;
 	gchar *oldpath, *newpath, *storage_path;
 	gboolean success = FALSE;
 
+	service = CAMEL_SERVICE (store);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
 	if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store))) {
 		g_set_error (
 			error, CAMEL_SERVICE_ERROR,
@@ -1468,7 +1469,7 @@ imapx_store_rename_folder_sync (CamelStore *store,
 		success = imapx_subscribe_folder (
 			store, new, FALSE, cancellable, error);
 
-	storage_path = g_strdup_printf("%s/folders", istore->storage_path);
+	storage_path = g_strdup_printf("%s/folders", user_data_dir);
 	oldpath = imapx_path_to_physical (storage_path, old);
 	newpath = imapx_path_to_physical (storage_path, new);
 	g_free (storage_path);
@@ -1532,6 +1533,48 @@ imapx_store_noop_sync (CamelStore *store,
 	return success;
 }
 
+static gboolean
+imapx_store_initable_init (GInitable *initable,
+                           GCancellable *cancellable,
+                           GError **error)
+{
+	CamelIMAPXStore *store;
+	CamelService *service;
+	CamelSession *session;
+	CamelURL *url;
+	const gchar *user_data_dir;
+	gchar *summary;
+
+	store = CAMEL_IMAPX_STORE (initable);
+
+	/* Chain up to parent interface's init() method. */
+	if (!parent_initable_interface->init (initable, cancellable, error))
+		return FALSE;
+
+	service = CAMEL_SERVICE (initable);
+	url = camel_service_get_camel_url (service);
+	session = camel_service_get_session (service);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
+	store->base_url = camel_url_to_string (
+		url, CAMEL_URL_HIDE_PASSWORD |
+		CAMEL_URL_HIDE_PARAMS | CAMEL_URL_HIDE_AUTH);
+	imapx_parse_receiving_options (store, url);
+
+	store->summary = camel_imapx_store_summary_new ();
+
+	summary = g_build_filename (user_data_dir, ".ev-store-summary", NULL);
+	camel_store_summary_set_filename ((CamelStoreSummary *)store->summary, summary);
+	/* FIXME: need to remove params, passwords, etc */
+	camel_store_summary_set_uri_base (
+		(CamelStoreSummary *)store->summary, url);
+	camel_store_summary_load ((CamelStoreSummary *)store->summary);
+
+	g_free (summary);
+
+	return TRUE;
+}
+
 static void
 camel_imapx_store_class_init (CamelIMAPXStoreClass *class)
 {
@@ -1543,7 +1586,6 @@ camel_imapx_store_class_init (CamelIMAPXStoreClass *class)
 	object_class->finalize = imapx_store_finalize;
 
 	service_class = CAMEL_SERVICE_CLASS (class);
-	service_class->construct = imapx_construct;
 	service_class->get_name = imapx_get_name;
 	service_class->connect_sync = imapx_connect_sync;
 	service_class->disconnect_sync = imapx_disconnect_sync;
@@ -1568,6 +1610,14 @@ camel_imapx_store_class_init (CamelIMAPXStoreClass *class)
 }
 
 static void
+camel_imapx_store_initable_init (GInitableIface *interface)
+{
+	parent_initable_interface = g_type_interface_peek_parent (interface);
+
+	interface->init = imapx_store_initable_init;
+}
+
+static void
 camel_imapx_store_init (CamelIMAPXStore *istore)
 {
 	CamelStore *store = CAMEL_STORE (istore);
diff --git a/camel/providers/imapx/camel-imapx-store.h b/camel/providers/imapx/camel-imapx-store.h
index be5ce65..b4dcbe6 100644
--- a/camel/providers/imapx/camel-imapx-store.h
+++ b/camel/providers/imapx/camel-imapx-store.h
@@ -70,7 +70,7 @@ struct _CamelIMAPXStore {
 	CamelIMAPXConnManager *con_man;
 
 	CamelIMAPXStoreSummary *summary; /* in-memory list of folders */
-	gchar *namespace, dir_sep, *base_url, *storage_path;
+	gchar *namespace, dir_sep, *base_url;
 
 	guint32 rec_options;
 
diff --git a/camel/providers/imapx/test-imapx.c b/camel/providers/imapx/test-imapx.c
index 7f3d270..20c2b66 100644
--- a/camel/providers/imapx/test-imapx.c
+++ b/camel/providers/imapx/test-imapx.c
@@ -41,10 +41,12 @@ main (gint argc, gchar *argv[])
 	camel_init ("/tmp/test-camel-imapx", TRUE);
 	camel_provider_init ();
 
-	session = g_object_new (CAMEL_TYPE_SESSION, NULL);
-	camel_session_construct (session, "/tmp/test-camel-imapx");
+	session = g_object_new (
+		CAMEL_TYPE_SESSION,
+		"user-data-dir", "/tmp/test-camel-imapx", NULL);
 
-	service = camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, NULL);
+	service = camel_session_add_service (
+		session, "text-imapx", uri, CAMEL_PROVIDER_STORE, NULL);
 	camel_service_connect_sync (service, NULL);
 
 	camel_store_get_folder_info_sync (
diff --git a/camel/providers/local/camel-local-store.c b/camel/providers/local/camel-local-store.c
index 7d81a29..5b88d9c 100644
--- a/camel/providers/local/camel-local-store.c
+++ b/camel/providers/local/camel-local-store.c
@@ -39,7 +39,6 @@
 
 #define d(x)
 
-static gboolean construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, GError **error);
 static CamelFolder *local_store_get_folder_sync (CamelStore *store, const gchar *folder_name, CamelStoreGetFolderFlags flags, GCancellable *cancellable, GError **error);
 static gchar *get_name (CamelService *service, gboolean brief);
 static CamelFolder *local_store_get_inbox_folder_sync (CamelStore *store, GCancellable *cancellable, GError **error);
@@ -57,6 +56,54 @@ static gchar *local_get_meta_path (CamelLocalStore *lf, const gchar *full_name,
 G_DEFINE_TYPE (CamelLocalStore, camel_local_store, CAMEL_TYPE_STORE)
 
 static void
+local_store_constructed (GObject *object)
+{
+	CamelLocalStore *local_store;
+	CamelService *service;
+	CamelURL *url;
+	gchar *local_store_path;
+	gchar *local_store_uri;
+	gint len;
+
+	local_store = CAMEL_LOCAL_STORE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (camel_local_store_parent_class)->constructed (object);
+
+	service = CAMEL_SERVICE (object);
+	url = camel_service_get_camel_url (service);
+
+	len = strlen (url->path);
+	if (!G_IS_DIR_SEPARATOR (url->path[len - 1]))
+		local_store->toplevel_dir = g_strdup_printf ("%s/", url->path);
+	else
+		local_store->toplevel_dir = g_strdup (url->path);
+
+	local_store->is_main_store = FALSE;
+
+	local_store_path = g_build_filename (
+		e_get_user_data_dir (), "mail", "local", NULL);
+	local_store_uri = g_filename_to_uri (local_store_path, NULL, NULL);
+	if (local_store_uri) {
+		CamelProvider *provider;
+		CamelURL *local_store_url = camel_url_new (local_store_uri, NULL);
+
+		provider = camel_service_get_provider (service);
+		camel_url_set_protocol (local_store_url, url->protocol);
+		camel_url_set_host (local_store_url, url->host);
+
+		local_store->is_main_store =
+			provider && provider->url_equal ?
+			provider->url_equal (url, local_store_url) :
+			camel_url_equal (url, local_store_url);
+		camel_url_free (local_store_url);
+	}
+
+	g_free (local_store_uri);
+	g_free (local_store_path);
+}
+
+static void
 local_store_finalize (GObject *object)
 {
 	CamelLocalStore *local_store = CAMEL_LOCAL_STORE (object);
@@ -76,9 +123,9 @@ camel_local_store_class_init (CamelLocalStoreClass *class)
 
 	object_class = G_OBJECT_CLASS (class);
 	object_class->finalize = local_store_finalize;
+	object_class->constructed = local_store_constructed;
 
 	service_class = CAMEL_SERVICE_CLASS (class);
-	service_class->construct = construct;
 	service_class->get_name = get_name;
 
 	store_class = CAMEL_STORE_CLASS (class);
@@ -102,54 +149,6 @@ camel_local_store_init (CamelLocalStore *local_store)
 {
 }
 
-static gboolean
-construct (CamelService *service,
-           CamelSession *session,
-           CamelProvider *provider,
-           CamelURL *url,
-           GError **error)
-{
-	CamelLocalStore *local_store = CAMEL_LOCAL_STORE (service);
-	CamelServiceClass *service_class;
-	gint len;
-	gchar *local_store_path, *local_store_uri;
-
-	/* Chain up to parent's construct() method. */
-	service_class = CAMEL_SERVICE_CLASS (camel_local_store_parent_class);
-	if (!service_class->construct (service, session, provider, url, error))
-		return FALSE;
-
-	len = strlen (url->path);
-	if (!G_IS_DIR_SEPARATOR (url->path[len - 1]))
-		local_store->toplevel_dir = g_strdup_printf ("%s/", url->path);
-	else
-		local_store->toplevel_dir = g_strdup (url->path);
-
-	local_store->is_main_store = FALSE;
-
-	local_store_path = g_build_filename (e_get_user_data_dir (), "mail", "local", NULL);
-	local_store_uri = g_filename_to_uri (local_store_path, NULL, NULL);
-	if (local_store_uri) {
-		CamelProvider *provider;
-		CamelURL *local_store_url = camel_url_new (local_store_uri, NULL);
-
-		provider = camel_service_get_provider (service);
-		camel_url_set_protocol (local_store_url, url->protocol);
-		camel_url_set_host (local_store_url, url->host);
-
-		local_store->is_main_store =
-			provider && provider->url_equal ?
-			provider->url_equal (url, local_store_url) :
-			camel_url_equal (url, local_store_url);
-		camel_url_free (local_store_url);
-	}
-
-	g_free (local_store_uri);
-	g_free (local_store_path);
-
-	return TRUE;
-}
-
 const gchar *
 camel_local_store_get_toplevel_dir (CamelLocalStore *store)
 {
diff --git a/camel/providers/local/camel-mh-store.c b/camel/providers/local/camel-mh-store.c
index de41092..6c33f7f 100644
--- a/camel/providers/local/camel-mh-store.c
+++ b/camel/providers/local/camel-mh-store.c
@@ -416,25 +416,23 @@ inode_free (gpointer k, gpointer v, gpointer d)
 	g_free (k);
 }
 
-static gboolean
-mh_folder_store_construct (CamelService *service,
-                           CamelSession *session,
-                           CamelProvider *provider,
-                           CamelURL *url,
-                           GError **error)
+static void
+mh_store_constructed (GObject *object)
 {
-	CamelServiceClass *service_class;
-	CamelMhStore *mh_store = (CamelMhStore *)service;
+	CamelMhStore *mh_store;
+	CamelService *service;
+	CamelURL *url;
 
-	/* Chain up to parent's construct() method. */
-	service_class = CAMEL_SERVICE_CLASS (camel_mh_store_parent_class);
-	if (!service_class->construct (service, session, provider, url, error))
-		return FALSE;
+	mh_store = CAMEL_MH_STORE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (camel_mh_store_parent_class)->constructed (object);
+
+	service = CAMEL_SERVICE (object);
+	url = camel_service_get_camel_url (service);
 
 	if (camel_url_get_param(url, "dotfolders"))
 		mh_store->flags |= CAMEL_MH_DOTFOLDERS;
-
-	return TRUE;
 }
 
 static CamelFolder *
@@ -625,11 +623,11 @@ mh_store_rename_folder_sync (CamelStore *store,
 static void
 camel_mh_store_class_init (CamelMhStoreClass *class)
 {
-	CamelServiceClass *service_class;
+	GObjectClass *object_class;
 	CamelStoreClass *store_class;
 
-	service_class = CAMEL_SERVICE_CLASS (class);
-	service_class->construct = mh_folder_store_construct;
+	object_class = G_OBJECT_CLASS (class);
+	object_class->constructed = mh_store_constructed;
 
 	store_class = CAMEL_STORE_CLASS (class);
 	store_class->get_folder_sync = mh_store_get_folder_sync;
diff --git a/camel/providers/local/camel-spool-store.c b/camel/providers/local/camel-spool-store.c
index 539d1c2..0675eb4 100644
--- a/camel/providers/local/camel-spool-store.c
+++ b/camel/providers/local/camel-spool-store.c
@@ -40,7 +40,15 @@
 
 #define d(x)
 
-G_DEFINE_TYPE (CamelSpoolStore, camel_spool_store, CAMEL_TYPE_MBOX_STORE)
+static GInitableIface *parent_initable_interface;
+
+/* Forward Declarations */
+static void camel_spool_store_initable_init (GInitableIface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	CamelSpoolStore, camel_spool_store, CAMEL_TYPE_MBOX_STORE,
+	G_IMPLEMENT_INTERFACE (
+		G_TYPE_INITABLE, camel_spool_store_initable_init))
 
 /* partially copied from mbox */
 static void
@@ -297,59 +305,6 @@ get_folder_info_mbox (CamelStore *store,
 	return fi;
 }
 
-static gboolean
-spool_store_construct (CamelService *service,
-                       CamelSession *session,
-                       CamelProvider *provider,
-                       CamelURL *url,
-                       GError **error)
-{
-	CamelServiceClass *service_class;
-	struct stat st;
-
-	d(printf("constructing store of type %s '%s:%s'\n",
-		 G_OBJECT_CLASS_NAME (((CamelObject *)service)->s.type), url->protocol, url->path));
-
-	/* Chain up to parent's construct() method. */
-	service_class = CAMEL_SERVICE_CLASS (camel_spool_store_parent_class);
-	if (!service_class->construct (service, session, provider, url, error))
-		return FALSE;
-
-	if (url->path[0] != '/') {
-		g_set_error (
-			error, CAMEL_STORE_ERROR,
-			CAMEL_STORE_ERROR_NO_FOLDER,
-			_("Store root %s is not an absolute path"),
-			url->path);
-		return FALSE;
-	}
-
-	if (g_stat (url->path, &st) == -1) {
-		g_set_error (
-			error, G_IO_ERROR,
-			g_io_error_from_errno (errno),
-			_("Spool '%s' cannot be opened: %s"),
-			url->path, g_strerror (errno));
-		return FALSE;
-	}
-
-	if (S_ISREG (st.st_mode))
-		((CamelSpoolStore *)service)->type = CAMEL_SPOOL_STORE_MBOX;
-	else if (S_ISDIR (st.st_mode))
-		/* we could check here for slight variations */
-		((CamelSpoolStore *)service)->type = CAMEL_SPOOL_STORE_ELM;
-	else {
-		g_set_error (
-			error, CAMEL_STORE_ERROR,
-			CAMEL_STORE_ERROR_NO_FOLDER,
-			_("Spool '%s' is not a regular file or directory"),
-			url->path);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
 static gchar *
 spool_store_get_name (CamelService *service,
                       gboolean brief)
@@ -526,25 +481,71 @@ spool_store_get_meta_path (CamelLocalStore *ls,
 {
 	CamelService *service;
 	CamelSession *session;
-	gchar *root;
+	const gchar *user_data_dir;
 	gchar *path, *key;
 
 	service = CAMEL_SERVICE (ls);
 	session = camel_service_get_session (service);
-	root = camel_session_get_storage_path (session, service, NULL);
-
-	if (root == NULL)
-		return NULL;
+	user_data_dir = camel_service_get_user_data_dir (service);
 
-	g_mkdir_with_parents (root, 0700);
 	key = camel_file_util_safe_filename (full_name);
-	path = g_strdup_printf ("%s/%s%s", root, key, ext);
+	path = g_strdup_printf ("%s/%s%s", user_data_dir, key, ext);
 	g_free (key);
-	g_free (root);
 
 	return path;
 }
 
+static gboolean
+spool_store_initable_init (GInitable *initable,
+                           GCancellable *cancellable,
+                           GError **error)
+{
+	CamelService *service;
+	CamelURL *url;
+	struct stat st;
+
+	/* Chain up to parent interface's init() method. */
+	if (!parent_initable_interface->init (initable, cancellable, error))
+		return FALSE;
+
+	service = CAMEL_SERVICE (initable);
+	url = camel_service_get_camel_url (service);
+
+	if (url->path[0] != '/') {
+		g_set_error (
+			error, CAMEL_STORE_ERROR,
+			CAMEL_STORE_ERROR_NO_FOLDER,
+			_("Store root %s is not an absolute path"),
+			url->path);
+		return FALSE;
+	}
+
+	if (g_stat (url->path, &st) == -1) {
+		g_set_error (
+			error, G_IO_ERROR,
+			g_io_error_from_errno (errno),
+			_("Spool '%s' cannot be opened: %s"),
+			url->path, g_strerror (errno));
+		return FALSE;
+	}
+
+	if (S_ISREG (st.st_mode))
+		((CamelSpoolStore *)service)->type = CAMEL_SPOOL_STORE_MBOX;
+	else if (S_ISDIR (st.st_mode))
+		/* we could check here for slight variations */
+		((CamelSpoolStore *)service)->type = CAMEL_SPOOL_STORE_ELM;
+	else {
+		g_set_error (
+			error, CAMEL_STORE_ERROR,
+			CAMEL_STORE_ERROR_NO_FOLDER,
+			_("Spool '%s' is not a regular file or directory"),
+			url->path);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 static void
 camel_spool_store_class_init (CamelSpoolStoreClass *class)
 {
@@ -553,7 +554,6 @@ camel_spool_store_class_init (CamelSpoolStoreClass *class)
 	CamelLocalStoreClass *local_store_class;
 
 	service_class = CAMEL_SERVICE_CLASS (class);
-	service_class->construct = spool_store_construct;
 	service_class->get_name = spool_store_get_name;
 
 	store_class = CAMEL_STORE_CLASS (class);
@@ -570,6 +570,14 @@ camel_spool_store_class_init (CamelSpoolStoreClass *class)
 }
 
 static void
+camel_spool_store_initable_init (GInitableIface *interface)
+{
+	parent_initable_interface = g_type_interface_peek_parent (interface);
+
+	interface->init = spool_store_initable_init;
+}
+
+static void
 camel_spool_store_init (CamelSpoolStore *spool_store)
 {
 }
diff --git a/camel/providers/nntp/camel-nntp-folder.c b/camel/providers/nntp/camel-nntp-folder.c
index f5651d0..18823fa 100644
--- a/camel/providers/nntp/camel-nntp-folder.c
+++ b/camel/providers/nntp/camel-nntp-folder.c
@@ -658,17 +658,12 @@ camel_nntp_folder_new (CamelStore *parent,
 	CamelService *service;
 	CamelSession *session;
 	CamelStoreInfo *si;
+	const gchar *user_data_dir;
 	gboolean subscribed = TRUE;
 
 	service = CAMEL_SERVICE (parent);
 	session = camel_service_get_session (service);
-
-	root = camel_session_get_storage_path (session, service, error);
-	if (root == NULL)
-		return NULL;
-
-	/* If this doesn't work, stuff wont save, but let it continue anyway */
-	g_mkdir_with_parents (root, 0700);
+	user_data_dir = camel_service_get_user_data_dir (service);
 
 	folder = g_object_new (
 		CAMEL_TYPE_NNTP_FOLDER,
@@ -677,10 +672,12 @@ camel_nntp_folder_new (CamelStore *parent,
 		"parent-store", parent, NULL);
 	nntp_folder = (CamelNNTPFolder *)folder;
 
-	folder->folder_flags |= CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY|CAMEL_FOLDER_HAS_SEARCH_CAPABILITY;
+	folder->folder_flags |=
+		CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY |
+		CAMEL_FOLDER_HAS_SEARCH_CAPABILITY;
 
-	nntp_folder->storage_path = g_build_filename (root, folder_name, NULL);
-	g_free (root);
+	nntp_folder->storage_path =
+		g_build_filename (user_data_dir, folder_name, NULL);
 
 	root = g_strdup_printf ("%s.cmeta", nntp_folder->storage_path);
 	camel_object_set_state_filename (CAMEL_OBJECT (nntp_folder), root);
diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c
index ab83a77..b3741ed 100644
--- a/camel/providers/nntp/camel-nntp-store.c
+++ b/camel/providers/nntp/camel-nntp-store.c
@@ -54,7 +54,15 @@
 
 #define DUMP_EXTENSIONS
 
-G_DEFINE_TYPE (CamelNNTPStore, camel_nntp_store, CAMEL_TYPE_DISCO_STORE)
+static GInitableIface *parent_initable_interface;
+
+/* Forward Declarations */
+static void camel_nntp_store_initable_init (GInitableIface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	CamelNNTPStore, camel_nntp_store, CAMEL_TYPE_DISCO_STORE,
+	G_IMPLEMENT_INTERFACE (
+		G_TYPE_INITABLE, camel_nntp_store_initable_init))
 
 static gint
 camel_nntp_try_authenticate (CamelNNTPStore *store,
@@ -182,7 +190,6 @@ nntp_store_finalize (GObject *object)
 	struct _xover_header *xover, *xn;
 
 	g_free (nntp_store->base_url);
-	g_free (nntp_store->storage_path);
 
 	xover = nntp_store->xover;
 	while (xover) {
@@ -327,6 +334,7 @@ connect_to_server (CamelService *service,
 	gchar *socks_host;
 	gint socks_port;
 	CamelStream *tcp_stream;
+	const gchar *user_data_dir;
 	gboolean retval = FALSE;
 	guchar *buf;
 	guint len;
@@ -334,8 +342,9 @@ connect_to_server (CamelService *service,
 
 	url = camel_service_get_camel_url (service);
 	session = camel_service_get_session (service);
+	user_data_dir = camel_service_get_user_data_dir (service);
 
-	camel_service_lock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+	camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	if (ssl_mode != MODE_CLEAR) {
 #ifdef CAMEL_HAVE_SSL
@@ -416,7 +425,7 @@ connect_to_server (CamelService *service,
 		goto fail;
 
 	if (!disco_store->diary) {
-		path = g_build_filename (store->storage_path, ".ev-journal", NULL);
+		path = g_build_filename (user_data_dir, ".ev-journal", NULL);
 		disco_store->diary = camel_disco_diary_new (disco_store, path, error);
 		g_free (path);
 	}
@@ -427,7 +436,7 @@ connect_to_server (CamelService *service,
 	store->current_folder = NULL;
 
  fail:
-	camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+	camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 	return retval;
 }
 
@@ -514,14 +523,14 @@ nntp_connect_offline (CamelService *service,
 {
 	CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (service);
 	CamelDiscoStore *disco_store = (CamelDiscoStore *) nntp_store;
+	const gchar *user_data_dir;
 	gchar *path;
 
-	if (nntp_store->storage_path == NULL)
-		return FALSE;
+	user_data_dir = camel_service_get_user_data_dir (service);
 
 	/* setup store-wide cache */
 	if (nntp_store->cache == NULL) {
-		nntp_store->cache = camel_data_cache_new (nntp_store->storage_path, error);
+		nntp_store->cache = camel_data_cache_new (user_data_dir, error);
 		if (nntp_store->cache == NULL)
 			return FALSE;
 
@@ -533,7 +542,7 @@ nntp_connect_offline (CamelService *service,
 	if (disco_store->diary)
 		return TRUE;
 
-	path = g_build_filename (nntp_store->storage_path, ".ev-journal", NULL);
+	path = g_build_filename (user_data_dir, ".ev-journal", NULL);
 	disco_store->diary = camel_disco_diary_new (disco_store, path, error);
 	g_free (path);
 
@@ -1361,35 +1370,36 @@ nntp_can_refresh_folder (CamelStore *store, CamelFolderInfo *info, GError **erro
 	return TRUE;
 }
 
-/* construction function in which we set some basic store properties */
 static gboolean
-nntp_construct (CamelService *service,
-                CamelSession *session,
-                CamelProvider *provider,
-                CamelURL *url,
-                GError **error)
+nntp_store_initable_init (GInitable *initable,
+                          GCancellable *cancellable,
+                          GError **error)
 {
-	CamelServiceClass *service_class;
-	CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (service);
+	CamelNNTPStore *nntp_store;
+	CamelService *service;
+	CamelSession *session;
 	CamelURL *summary_url;
+	CamelURL *url;
+	const gchar *user_data_dir;
 	gchar *tmp;
 
-	/* construct the parent first */
-	service_class = CAMEL_SERVICE_CLASS (camel_nntp_store_parent_class);
-	if (!service_class->construct (service, session, provider, url, error))
-		return FALSE;
+	nntp_store = CAMEL_NNTP_STORE (initable);
 
-	/* find out the storage path, base url */
-	nntp_store->storage_path = camel_session_get_storage_path (session, service, error);
-	if (!nntp_store->storage_path)
+	/* Chain up to parent interface's init() method. */
+	if (!parent_initable_interface->init (initable, cancellable, error))
 		return FALSE;
 
+	service = CAMEL_SERVICE (initable);
+	url = camel_service_get_camel_url (service);
+	session = camel_service_get_session (service);
+	user_data_dir = camel_service_get_user_data_dir (service);
+
 	/* FIXME */
 	nntp_store->base_url = camel_url_to_string (
 		url, CAMEL_URL_HIDE_PASSWORD |
 		CAMEL_URL_HIDE_PARAMS | CAMEL_URL_HIDE_AUTH);
 
-	tmp = g_build_filename (nntp_store->storage_path, ".ev-store-summary", NULL);
+	tmp = g_build_filename (user_data_dir, ".ev-store-summary", NULL);
 	nntp_store->summary = camel_nntp_store_summary_new ();
 	camel_store_summary_set_filename ((CamelStoreSummary *) nntp_store->summary, tmp);
 	summary_url = camel_url_new (nntp_store->base_url, NULL);
@@ -1410,7 +1420,7 @@ nntp_construct (CamelService *service,
 		nntp_store->folder_hierarchy_relative = FALSE;
 
 	/* setup store-wide cache */
-	nntp_store->cache = camel_data_cache_new (nntp_store->storage_path, error);
+	nntp_store->cache = camel_data_cache_new (user_data_dir, error);
 	if (nntp_store->cache == NULL)
 		return FALSE;
 
@@ -1436,7 +1446,6 @@ camel_nntp_store_class_init (CamelNNTPStoreClass *class)
 	object_class->finalize = nntp_store_finalize;
 
 	service_class = CAMEL_SERVICE_CLASS (class);
-	service_class->construct = nntp_construct;
 	service_class->get_name = nntp_store_get_name;
 	service_class->query_auth_types_sync = nntp_store_query_auth_types_sync;
 
@@ -1465,6 +1474,14 @@ camel_nntp_store_class_init (CamelNNTPStoreClass *class)
 }
 
 static void
+camel_nntp_store_initable_init (GInitableIface *interface)
+{
+	parent_initable_interface = g_type_interface_peek_parent (interface);
+
+	interface->init = nntp_store_initable_init;
+}
+
+static void
 camel_nntp_store_init (CamelNNTPStore *nntp_store)
 {
 	CamelStore *store = CAMEL_STORE (nntp_store);
diff --git a/camel/providers/nntp/camel-nntp-store.h b/camel/providers/nntp/camel-nntp-store.h
index cc6a36b..7d58ad7 100644
--- a/camel/providers/nntp/camel-nntp-store.h
+++ b/camel/providers/nntp/camel-nntp-store.h
@@ -102,7 +102,7 @@ struct _CamelNNTPStore {
 
 	struct _CamelDataCache *cache;
 
-	gchar *current_folder, *storage_path, *base_url;
+	gchar *current_folder, *base_url;
 
 	struct _xover_header *xover;
 	guint32 capabilities; /* bit-or of nntp_capabilities */
diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c
index 51e1f96..27cdfd9 100644
--- a/camel/providers/pop3/camel-pop3-store.c
+++ b/camel/providers/pop3/camel-pop3-store.c
@@ -589,26 +589,21 @@ pop3_store_connect_sync (CamelService *service,
 {
 	CamelPOP3Store *store = (CamelPOP3Store *)service;
 	gboolean reprompt = FALSE;
-	CamelSession *session;
 	CamelURL *url;
+	const gchar *user_data_dir;
 	gchar *errbuf = NULL;
 	GError *local_error = NULL;
 
 	url = camel_service_get_camel_url (service);
-	session = camel_service_get_session (service);
+	user_data_dir = camel_service_get_user_data_dir (service);
 
 	if (store->cache == NULL) {
-		gchar *root;
-
-		root = camel_session_get_storage_path (session, service, error);
-		if (root) {
-			store->cache = camel_data_cache_new (root, error);
-			g_free (root);
-			if (store->cache) {
-				/* Ensure cache will never expire, otherwise it causes redownload of messages */
-				camel_data_cache_set_expire_age (store->cache, -1);
-				camel_data_cache_set_expire_access (store->cache, -1);
-			}
+		store->cache = camel_data_cache_new (user_data_dir, error);
+		if (store->cache) {
+			/* Ensure cache will never expire, otherwise
+			 * it causes redownload of messages. */
+			camel_data_cache_set_expire_age (store->cache, -1);
+			camel_data_cache_set_expire_access (store->cache, -1);
 		}
 	}
 
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index d94d791..64912a2 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -1876,11 +1876,11 @@ CAMEL_SERVICE_ERROR
 CamelServiceError
 CamelServiceConnectionStatus
 CamelServiceAuthType
-camel_service_construct
+camel_service_get_user_data_dir
 camel_service_get_name
-camel_service_get_path
 camel_service_get_provider
 camel_service_get_session
+camel_service_get_uid
 camel_service_get_camel_url
 camel_service_get_url
 camel_service_cancel_connect
@@ -1913,14 +1913,13 @@ CamelTimeoutCallback
 CamelSessionAlertType
 CamelSessionThreadOps
 CamelSessionThreadMsg
-camel_session_construct
+camel_session_get_user_data_dir
 camel_session_set_socks_proxy
 camel_session_get_socks_proxy
+camel_session_add_service
 camel_session_get_service
-camel_session_get_service_connected
-camel_session_get_store
-camel_session_get_transport
-camel_session_get_storage_path
+camel_session_get_service_by_url
+camel_session_list_services
 camel_session_get_password
 camel_session_forget_password
 camel_session_alert_user
diff --git a/docs/reference/camel/tmpl/camel-cipher-context.sgml b/docs/reference/camel/tmpl/camel-cipher-context.sgml
index 8d450dc..dfff463 100644
--- a/docs/reference/camel/tmpl/camel-cipher-context.sgml
+++ b/docs/reference/camel/tmpl/camel-cipher-context.sgml
@@ -732,6 +732,16 @@ CamelCipherContext
 @gpointer cert_data: 
 @gpointer cert_data:
 @gpointer cert_data: 
+ gpointer cert_data:
+ gpointer cert_data: 
+ gpointer cert_data:
+ gpointer cert_data: 
+ gpointer cert_data:
+ gpointer cert_data: 
+ gpointer cert_data:
+ gpointer cert_data: 
+ gpointer cert_data:
+ gpointer cert_data: 
 @gpointer cert_data: 
 
 
diff --git a/docs/reference/camel/tmpl/camel-provider.sgml b/docs/reference/camel/tmpl/camel-provider.sgml
index 92cd567..fd7e795 100644
--- a/docs/reference/camel/tmpl/camel-provider.sgml
+++ b/docs/reference/camel/tmpl/camel-provider.sgml
@@ -36,7 +36,6 @@ camel-provider
 @auto_detect: 
 @object_types: 
 @authtypes: 
- service_cache: 
 @url_hash: 
 @url_equal: 
 @translation_domain: 
@@ -268,7 +267,6 @@ camel-provider
 @auto_detect: 
 @object_types: 
 @authtypes: 
- service_cache: 
 @url_hash: 
 @url_equal: 
 @translation_domain: 
diff --git a/docs/reference/camel/tmpl/camel-service.sgml b/docs/reference/camel/tmpl/camel-service.sgml
index 2716896..6720693 100644
--- a/docs/reference/camel/tmpl/camel-service.sgml
+++ b/docs/reference/camel/tmpl/camel-service.sgml
@@ -26,6 +26,26 @@ CamelService
 </para>
 
 
+<!-- ##### ARG CamelService:provider ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG CamelService:session ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG CamelService:uid ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG CamelService:url ##### -->
+<para>
+
+</para>
+
 <!-- ##### MACRO CAMEL_SERVICE_ERROR ##### -->
 <para>
 
@@ -64,16 +84,12 @@ CamelService
 @authproto: 
 @need_password: 
 
-<!-- ##### FUNCTION camel_service_construct ##### -->
+<!-- ##### FUNCTION camel_service_get_user_data_dir ##### -->
 <para>
 
 </para>
 
 @service: 
- session: 
- provider: 
- url: 
- error: 
 @Returns: 
 
 
@@ -87,7 +103,7 @@ CamelService
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_service_get_path ##### -->
+<!-- ##### FUNCTION camel_service_get_provider ##### -->
 <para>
 
 </para>
@@ -96,7 +112,7 @@ CamelService
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_service_get_provider ##### -->
+<!-- ##### FUNCTION camel_service_get_session ##### -->
 <para>
 
 </para>
@@ -105,7 +121,7 @@ CamelService
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_service_get_session ##### -->
+<!-- ##### FUNCTION camel_service_get_uid ##### -->
 <para>
 
 </para>
diff --git a/docs/reference/camel/tmpl/camel-session.sgml b/docs/reference/camel/tmpl/camel-session.sgml
index 7070939..f2c94f1 100644
--- a/docs/reference/camel/tmpl/camel-session.sgml
+++ b/docs/reference/camel/tmpl/camel-session.sgml
@@ -41,6 +41,11 @@ CamelSession
 
 </para>
 
+<!-- ##### ARG CamelSession:user-data-dir ##### -->
+<para>
+
+</para>
+
 <!-- ##### USER_FUNCTION CamelTimeoutCallback ##### -->
 <para>
 
@@ -80,13 +85,13 @@ CamelSession
 @session: 
 @data: 
 
-<!-- ##### FUNCTION camel_session_construct ##### -->
+<!-- ##### FUNCTION camel_session_get_user_data_dir ##### -->
 <para>
 
 </para>
 
 @session: 
- storage_path: 
+ Returns: 
 
 
 <!-- ##### FUNCTION camel_session_set_socks_proxy ##### -->
@@ -109,58 +114,45 @@ CamelSession
 @port_ret: 
 
 
-<!-- ##### FUNCTION camel_session_get_service ##### -->
+<!-- ##### FUNCTION camel_session_add_service ##### -->
 <para>
 
 </para>
 
 @session: 
- url_string: 
+ uid: 
+ uri_string: 
 @type: 
 @error: 
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_session_get_service_connected ##### -->
+<!-- ##### FUNCTION camel_session_get_service ##### -->
 <para>
 
 </para>
 
 @session: 
- url_string: 
- type: 
- error: 
+ uid: 
 @Returns: 
 
 
-<!-- ##### MACRO camel_session_get_store ##### -->
+<!-- ##### FUNCTION camel_session_get_service_by_url ##### -->
 <para>
 
 </para>
 
 @session: 
- url_string: 
- error: 
-
-
-<!-- ##### MACRO camel_session_get_transport ##### -->
-<para>
-
-</para>
-
- session: 
- url_string: 
- error: 
+ url: 
+ Returns: 
 
 
-<!-- ##### FUNCTION camel_session_get_storage_path ##### -->
+<!-- ##### FUNCTION camel_session_list_services ##### -->
 <para>
 
 </para>
 
 @session: 
- service: 
- error: 
 @Returns: 
 
 
diff --git a/docs/reference/camel/tmpl/camel-unused.sgml b/docs/reference/camel/tmpl/camel-unused.sgml
index 9953772..c4200f6 100644
--- a/docs/reference/camel/tmpl/camel-unused.sgml
+++ b/docs/reference/camel/tmpl/camel-unused.sgml
@@ -4387,6 +4387,12 @@ streams
 
 @parent: 
 
+<!-- ##### ARG CamelSession:data-dir ##### -->
+<para>
+
+</para>
+
+
 <!-- ##### STRUCT CamelSimpleDataWrapper ##### -->
 <para>
 
@@ -8500,6 +8506,18 @@ streams
 @error: 
 @Returns: 
 
+<!-- ##### FUNCTION camel_service_construct ##### -->
+<para>
+
+</para>
+
+ service: 
+ session: 
+ provider: 
+ url: 
+ error: 
+ Returns: 
+
 <!-- ##### FUNCTION camel_service_disconnect ##### -->
 <para>
 
@@ -8510,6 +8528,14 @@ streams
 @error: 
 @Returns: 
 
+<!-- ##### FUNCTION camel_service_get_path ##### -->
+<para>
+
+</para>
+
+ service: 
+ Returns: 
+
 <!-- ##### FUNCTION camel_service_query_auth_types ##### -->
 <para>
 
@@ -8528,6 +8554,22 @@ streams
 @session: 
 @Returns: 
 
+<!-- ##### FUNCTION camel_session_construct ##### -->
+<para>
+
+</para>
+
+ session: 
+ storage_path: 
+
+<!-- ##### FUNCTION camel_session_get_data_dir ##### -->
+<para>
+
+</para>
+
+ session: 
+ Returns: 
+
 <!-- ##### FUNCTION camel_session_get_network_state ##### -->
 <para>
 
@@ -8536,6 +8578,44 @@ streams
 @session: 
 @Returns: 
 
+<!-- ##### FUNCTION camel_session_get_service_connected ##### -->
+<para>
+
+</para>
+
+ session: 
+ uid: 
+ error: 
+ Returns: 
+
+<!-- ##### FUNCTION camel_session_get_storage_path ##### -->
+<para>
+
+</para>
+
+ session: 
+ service: 
+ error: 
+ Returns: 
+
+<!-- ##### MACRO camel_session_get_store ##### -->
+<para>
+
+</para>
+
+ session: 
+ uid: 
+ error: 
+
+<!-- ##### MACRO camel_session_get_transport ##### -->
+<para>
+
+</para>
+
+ session: 
+ uid: 
+ error: 
+
 <!-- ##### FUNCTION camel_session_is_online ##### -->
 <para>
 



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