From 05e0ef6fea2f2feec010109142c8305c69e64c57 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Thu, 19 Feb 2004 07:27:49 +0000 Subject: Fixes for api changes. 2004-02-19 Not Zed * providers/*/camel-*-provider.c (camel_provider_module_init): Fixes for api changes. * camel-provider.c (camel_provider_load): no longer take session argument. the providers are global resources. (camel_provider_init): dont return anything anymore. (error?) call from camel_init now. Use a recursive lock too. * camel-session.c (camel_session_register_provider) (camel_session_list_providers, camel_session_get_provider): Moved to camel-provider, camel_provider_register/list/get. (vee_provider): moved to camel-provider.c svn path=/trunk/; revision=24794 --- camel/camel-provider.c | 232 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 215 insertions(+), 17 deletions(-) (limited to 'camel/camel-provider.c') diff --git a/camel/camel-provider.c b/camel/camel-provider.c index 1b8ef2cab5..be15aed046 100644 --- a/camel/camel-provider.c +++ b/camel/camel-provider.c @@ -1,7 +1,5 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-provider.c: provider framework */ - -/* +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * camel-provider.c: provider framework * * Authors: * Bertrand Guiheneuf @@ -25,7 +23,6 @@ * USA */ - /* FIXME: Shouldn't we add a version number to providers ? */ #ifdef HAVE_CONFIG_H @@ -43,7 +40,33 @@ #include "camel-provider.h" #include "camel-exception.h" #include "camel-string-utils.h" +#include "camel-vee-store.h" + +#include "e-util/e-msgport.h" +/* table of CamelProviderModule's */ +static GHashTable *module_table; +/* table of CamelProvider's */ +static GHashTable *provider_table; +static EMutex *provider_lock; + +#define LOCK() e_mutex_lock(provider_lock); +#define UNLOCK() e_mutex_unlock(provider_lock); + +/* The vfolder provider is always available */ +static CamelProvider vee_provider = { + "vfolder", + N_("Virtual folder email provider"), + + N_("For reading mail as a query of another set of folders"), + + "vfolder", + + CAMEL_PROVIDER_IS_STORAGE, + CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH, + + /* ... */ +}; /** * camel_provider_init: @@ -55,25 +78,35 @@ * A .urls file has the same initial prefix as the shared library it * correspond to, and consists of a series of lines containing the URL * protocols that that library handles. - * - * Return value: a hash table mapping URLs to module names **/ -GHashTable * +void camel_provider_init (void) { - GHashTable *providers; DIR *dir; struct dirent *d; char *p, *name, buf[80]; CamelProviderModule *m; + static int init = 0; + + if (init) + return; + + init = 1; + + provider_lock = e_mutex_new(E_MUTEX_REC); + module_table = g_hash_table_new(camel_strcase_hash, camel_strcase_equal); + provider_table = g_hash_table_new(camel_strcase_hash, camel_strcase_equal); + + vee_provider.object_types[CAMEL_PROVIDER_STORE] = camel_vee_store_get_type (); + vee_provider.url_hash = camel_url_hash; + vee_provider.url_equal = camel_url_equal; + camel_provider_register(&vee_provider); - providers = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - dir = opendir (CAMEL_PROVIDERDIR); if (!dir) { g_error ("Could not open camel provider directory (%s): %s", CAMEL_PROVIDERDIR, g_strerror (errno)); - return NULL; + return; } while ((d = readdir (dir))) { @@ -108,7 +141,7 @@ camel_provider_init (void) char *protocol = g_strdup(buf); m->types = g_slist_prepend(m->types, protocol); - g_hash_table_insert(providers, protocol, m); + g_hash_table_insert(module_table, protocol, m); } } @@ -116,7 +149,6 @@ camel_provider_init (void) } closedir (dir); - return providers; } /** @@ -130,10 +162,10 @@ camel_provider_init (void) * itself with @session. **/ void -camel_provider_load (CamelSession *session, const char *path, CamelException *ex) +camel_provider_load(const char *path, CamelException *ex) { GModule *module; - CamelProvider *(*camel_provider_module_init) (); + CamelProvider *(*camel_provider_module_init) (void); if (!g_module_supported ()) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, @@ -160,7 +192,173 @@ camel_provider_load (CamelSession *session, const char *path, CamelException *ex return; } - camel_provider_module_init (session); + camel_provider_module_init (); +} + +/** + * camel_provider_register: + * @provider: provider object + * + * Registers a provider. + **/ +void +camel_provider_register(CamelProvider *provider) +{ + int i; + CamelProviderConfEntry *conf; + GList *l; + + g_return_if_fail (provider != NULL); + + LOCK(); + + if (g_hash_table_lookup(provider_table, provider->protocol) != NULL) { + g_warning("Trying to re-register camel provider for protocol '%s'", provider->protocol); + UNLOCK(); + 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) + + provider->name = P_(provider->name); + provider->description = P_(provider->description); + conf = provider->extra_conf; + if (conf) { + for (i=0;conf[i].type != CAMEL_PROVIDER_CONF_END;i++) { + if (conf[i].text) + conf[i].text = P_(conf[i].text); + } + } + + l = provider->authtypes; + while (l) { + CamelServiceAuthType *auth = l->data; + + auth->name = P_(auth->name); + auth->description = P_(auth->description); + l = l->next; + } + + g_hash_table_insert(provider_table, provider->protocol, provider); + + UNLOCK(); +} + +static gint +provider_compare (gconstpointer a, gconstpointer b) +{ + const CamelProvider *cpa = (const CamelProvider *)a; + const CamelProvider *cpb = (const CamelProvider *)b; + + return strcmp (cpa->name, cpb->name); +} + +static void +add_to_list (gpointer key, gpointer value, gpointer user_data) +{ + GList **list = user_data; + + *list = g_list_prepend(*list, value); +} + +/** + * camel_session_list_providers: + * @session: the session + * @load: whether or not to load in providers that are not already loaded + * + * This returns a list of available providers in this session. If @load + * is %TRUE, it will first load in all available providers that haven't + * yet been loaded. + * + * Return value: a GList of providers, which the caller must free. + **/ +GList * +camel_provider_list(gboolean load) +{ + GList *list; + + LOCK(); + + if (load) { + GList *w; + + g_hash_table_foreach(module_table, add_to_list, &list); + for (w = list;w;w = w->next) { + CamelProviderModule *m = w->data; + + if (!m->loaded) { + camel_provider_load(m->path, NULL); + m->loaded = 1; + } + } + g_list_free(list); + list = NULL; + } + + g_hash_table_foreach(provider_table, add_to_list, &list); + + UNLOCK(); + + list = g_list_sort(list, provider_compare); + + return list; +} + +/** + * camel_provider_get: + * @url_string: the URL for the service whose provider you want + * @ex: a CamelException + * + * This returns the CamelProvider that would be used to handle + * @url_string, loading it in from disk if necessary. + * + * Return value: the provider, or %NULL, in which case @ex will be set. + **/ +CamelProvider * +camel_provider_get(const char *url_string, CamelException *ex) +{ + CamelProvider *provider = NULL; + char *protocol; + size_t len; + + g_return_val_if_fail(url_string != NULL, NULL); + + len = strcspn(url_string, ":"); + protocol = g_alloca(len+1); + memcpy(protocol, url_string, len); + protocol[len] = 0; + + LOCK(); + + provider = g_hash_table_lookup(provider_table, protocol); + if (!provider) { + CamelProviderModule *m; + + m = g_hash_table_lookup(module_table, protocol); + if (m && !m->loaded) { + m->loaded = 1; + camel_provider_load(m->path, ex); + if (camel_exception_is_set (ex)) + goto fail; + } + provider = g_hash_table_lookup(provider_table, protocol); + } + + if (provider == NULL) + camel_exception_setv(ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, + _("No provider available for protocol `%s'"), + protocol); +fail: + UNLOCK(); + + return provider; } -- cgit v1.2.3