Rework how CamelServices are added to CamelSession.
authorMatthew Barnes <mbarnes@redhat.com>
Tue, 19 Apr 2011 19:32:47 +0000 (15:32 -0400)
committerMatthew Barnes <mbarnes@redhat.com>
Thu, 21 Apr 2011 11:19:29 +0000 (07:19 -0400)
* 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.

35 files changed:
camel/camel-disco-store.c
camel/camel-offline-store.c
camel/camel-provider.c
camel/camel-provider.h
camel/camel-sasl-popb4smtp.c
camel/camel-service.c
camel/camel-service.h
camel/camel-session.c
camel/camel-session.h
camel/camel-store.c
camel/camel-vee-store.c
camel/providers/groupwise/camel-groupwise-folder.c
camel/providers/groupwise/camel-groupwise-store.c
camel/providers/groupwise/camel-groupwise-store.h
camel/providers/groupwise/camel-groupwise-transport.c
camel/providers/groupwise/camel-groupwise-transport.h
camel/providers/imap/camel-imap-folder.c
camel/providers/imap/camel-imap-store.c
camel/providers/imap/camel-imap-store.h
camel/providers/imapx/camel-imapx-store.c
camel/providers/imapx/camel-imapx-store.h
camel/providers/imapx/test-imapx.c
camel/providers/local/camel-local-store.c
camel/providers/local/camel-mh-store.c
camel/providers/local/camel-spool-store.c
camel/providers/nntp/camel-nntp-folder.c
camel/providers/nntp/camel-nntp-store.c
camel/providers/nntp/camel-nntp-store.h
camel/providers/pop3/camel-pop3-store.c
docs/reference/camel/camel-sections.txt
docs/reference/camel/tmpl/camel-cipher-context.sgml
docs/reference/camel/tmpl/camel-provider.sgml
docs/reference/camel/tmpl/camel-service.sgml
docs/reference/camel/tmpl/camel-session.sgml
docs/reference/camel/tmpl/camel-unused.sgml

index d6e6306..fb3c1db 100644 (file)
 
 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;
index eb4e608..e5f5b12 100644 (file)
 #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);
 }
 
 /**
index edea3ae..67f45bf 100644 (file)
@@ -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)
 
index e98dd8c..8645685 100644 (file)
@@ -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;
 
index 24caa99..0f2de6e 100644 (file)
@@ -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;
 }
index e844cb8..181c910 100644 (file)
@@ -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>
 #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;
 }
 
 /**
index fd37ce0..f70472c 100644 (file)
@@ -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);
index 20b2a0d..85701b0 100644 (file)
 #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).
index 59893fa..0d40c35 100644 (file)
@@ -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,
index 1f0b5ee..92132ef 100644 (file)
@@ -27,6 +27,7 @@
 #include <config.h>
 #endif
 
+#include <errno.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #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;
index 4ebed62..bca8ae0 100644 (file)
@@ -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);
index 2982f4e..b9bfd16 100644 (file)
@@ -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);
 
index 7f2e06f..cd3f607 100644 (file)
@@ -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 (
index 7e901c3..6a72357 100644 (file)
@@ -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);
index 6f2876d..54b3af9 100644 (file)
 
 #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);
 }
index 9abf71a..ee9d21c 100644 (file)
@@ -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
 
index c4bd8c5..77519cd 100644 (file)
@@ -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);
index 74c1fc8..dc8cd8e 100644 (file)
@@ -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;
 }
index eacacae..59024a0 100644 (file)
@@ -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;
index 5ccb1b4..bb644ad 100644 (file)
 
 #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);
index be5ce65..b4dcbe6 100644 (file)
@@ -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;
 
index 7f3d270..20c2b66 100644 (file)
@@ -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 (
index 7d81a29..5b88d9c 100644 (file)
@@ -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)
 {
index de41092..6c33f7f 100644 (file)
@@ -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;
index 539d1c2..0675eb4 100644 (file)
 
 #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)
 {
 }
index f5651d0..18823fa 100644 (file)
@@ -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);
index ab83a77..b3741ed 100644 (file)
 
 #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);
index cc6a36b..7d58ad7 100644 (file)
@@ -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 */
index 51e1f96..27cdfd9 100644 (file)
@@ -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);
                }
        }
 
index d94d791..64912a2 100644 (file)
@@ -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
index 8d450dc..dfff463 100644 (file)
@@ -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: 
 
 
index 92cd567..fd7e795 100644 (file)
@@ -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: 
index 2716896..6720693 100644 (file)
@@ -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>
index 7070939..f2c94f1 100644 (file)
@@ -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: 
 
 
index 9953772..c4200f6 100644 (file)
@@ -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>