diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2009-05-07 19:21:57 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2009-05-07 19:21:57 +0800 |
commit | caa862135195b828d2e8355436fdd6eb0ec2443e (patch) | |
tree | 40198708ccf89ca4246c7da11a718fa5cc39de52 /e-util | |
parent | 19b29348068e367efc105732e9707cdb4132b4ee (diff) | |
download | gsoc2013-evolution-caa862135195b828d2e8355436fdd6eb0ec2443e.tar.gz gsoc2013-evolution-caa862135195b828d2e8355436fdd6eb0ec2443e.tar.zst gsoc2013-evolution-caa862135195b828d2e8355436fdd6eb0ec2443e.zip |
Convert EShellModule to EShellBackend
Split the GTypeModule loader out of EShellModule as EModule, and rename
EShellModule to EShellBackend. Backends (formerly modules) should now
subclass EShellBackend.
This commit converts EShell but breaks all the shell backends.
Diffstat (limited to 'e-util')
-rw-r--r-- | e-util/Makefile.am | 2 | ||||
-rw-r--r-- | e-util/e-module.c | 318 | ||||
-rw-r--r-- | e-util/e-module.h | 81 |
3 files changed, 401 insertions, 0 deletions
diff --git a/e-util/Makefile.am b/e-util/Makefile.am index 384db63296..d06a349174 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -60,6 +60,7 @@ eutilinclude_HEADERS = \ e-marshal.h \ e-menu.h \ e-mktemp.h \ + e-module.h \ e-non-intrusive-error-dialog.h \ e-print.h \ e-plugin.h \ @@ -101,6 +102,7 @@ libeutil_la_SOURCES = \ e-marshal.c \ e-menu.c \ e-mktemp.c \ + e-module.c \ e-non-intrusive-error-dialog.c \ e-plugin-ui.c \ e-plugin.c \ diff --git a/e-util/e-module.c b/e-util/e-module.c new file mode 100644 index 0000000000..51e1e18bd6 --- /dev/null +++ b/e-util/e-module.c @@ -0,0 +1,318 @@ +/* + * e-module.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-module.h" + +#include <glib/gi18n.h> + +/* This is the symbol we call when loading a module. */ +#define LOAD_SYMBOL "e_module_load" + +/* This is the symbol we call when unloading a module. */ +#define UNLOAD_SYMBOL "e_module_unload" + +#define E_MODULE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MODULE, EModulePrivate)) + +struct _EModulePrivate { + GModule *module; + gchar *filename; + + void (*load) (GTypeModule *type_module); + void (*unload) (GTypeModule *type_module); +}; + +enum { + PROP_0, + PROP_FILENAME +}; + +static gpointer parent_class; + +static void +module_set_filename (EModule *module, + const gchar *filename) +{ + g_return_if_fail (module->priv->filename == NULL); + + module->priv->filename = g_strdup (filename); +} + +static void +module_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FILENAME: + module_set_filename ( + E_MODULE (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +module_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FILENAME: + g_value_set_string ( + value, e_module_get_filename ( + E_MODULE (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +module_finalize (GObject *object) +{ + EModulePrivate *priv; + + priv = E_MODULE_GET_PRIVATE (object); + + g_free (priv->filename); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +module_load (GTypeModule *type_module) +{ + EModulePrivate *priv; + gpointer symbol; + + priv = E_MODULE_GET_PRIVATE (type_module); + + g_return_val_if_fail (priv->filename != NULL, FALSE); + priv->module = g_module_open (priv->filename, 0); + + if (priv->module == NULL) + goto fail; + + if (!g_module_symbol (priv->module, LOAD_SYMBOL, &symbol)) + goto fail; + + priv->load = symbol; + + if (!g_module_symbol (priv->module, UNLOAD_SYMBOL, &symbol)) + goto fail; + + priv->unload = symbol; + + priv->load (type_module); + + return TRUE; + +fail: + g_warning ("%s", g_module_error ()); + + if (priv->module != NULL) + g_module_close (priv->module); + + return FALSE; +} + +static void +module_unload (GTypeModule *type_module) +{ + EModulePrivate *priv; + + priv = E_MODULE_GET_PRIVATE (type_module); + + priv->unload (type_module); + + g_module_close (priv->module); + priv->module = NULL; + + priv->load = NULL; + priv->unload = NULL; +} + +static void +module_class_init (EModuleClass *class) +{ + GObjectClass *object_class; + GTypeModuleClass *type_module_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EModulePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = module_set_property; + object_class->get_property = module_get_property; + object_class->finalize = module_finalize; + + type_module_class = G_TYPE_MODULE_CLASS (class); + type_module_class->load = module_load; + type_module_class->unload = module_unload; + + /** + * EModule:filename + * + * The filename of the module. + **/ + g_object_class_install_property ( + object_class, + PROP_FILENAME, + g_param_spec_string ( + "filename", + _("Filename"), + _("The filename of the module"), + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); +} + +static void +module_init (EModule *module) +{ + module->priv = E_MODULE_GET_PRIVATE (module); +} + +GType +e_module_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + const GTypeInfo type_info = { + sizeof (EModuleClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) module_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EModule), + 0, /* n_preallocs */ + (GInstanceInitFunc) module_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_TYPE_MODULE, "EModule", &type_info, 0); + } + + return type; +} + +/** + * e_module_new: + * @filename: filename of the shared library module + * + * Creates a new #EModule that will load the specific shared library + * when in use. + * + * Returns: a new #EModule for @filename + **/ +EModule * +e_module_new (const gchar *filename) +{ + g_return_val_if_fail (filename != NULL, NULL); + + return g_object_new (E_TYPE_MODULE, "filename", filename, NULL); +} + +/** + * e_module_get_filename: + * @module: an #EModule + * + * Returns the filename of the shared library for @module. The + * string is owned by @module and should not be modified or freed. + * + * Returns: the filename for @module + **/ +const gchar * +e_module_get_filename (EModule *module) +{ + g_return_val_if_fail (E_IS_MODULE (module), NULL); + + return module->priv->filename; +} + +/** + * e_module_load_all_in_directory: + * @dirname: pathname for a directory containing modules to load + * + * Loads all the modules in the specified directory into memory. If + * you want to unload them (enabling on-demand loading) you must call + * g_type_module_unuse() on all the modules. Free the returned list + * with g_list_free(). + * + * Returns: a list of #EModules loaded from @dirname + **/ +GList * +e_module_load_all_in_directory (const gchar *dirname) +{ + GDir *dir; + const gchar *basename; + GList *loaded_modules = NULL; + GError *error = NULL; + + g_return_val_if_fail (dirname != NULL, NULL); + + if (!g_module_supported ()) + return NULL; + + dir = g_dir_open (dirname, 0, &error); + if (dir == NULL) { + g_warning ("%s", error->message); + g_error_free (error); + return NULL; + } + + while ((basename = g_dir_read_name (dir)) != NULL) { + EModule *module; + gchar *filename; + + if (!g_str_has_suffix (basename, "." G_MODULE_SUFFIX)) + continue; + + filename = g_build_filename (dirname, basename, NULL); + + module = e_module_new (filename); + + if (!g_type_module_use (G_TYPE_MODULE (module))) { + g_printerr ("Failed to load module: %s\n", filename); + g_object_unref (module); + g_free (filename); + continue; + } + + g_free (filename); + + loaded_modules = g_list_prepend (loaded_modules, module); + } + + g_dir_close (dir); + + return loaded_modules; +} diff --git a/e-util/e-module.h b/e-util/e-module.h new file mode 100644 index 0000000000..022769dc1c --- /dev/null +++ b/e-util/e-module.h @@ -0,0 +1,81 @@ +/* + * e-module.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/** + * SECTION: e-module + * @short_description: generic module loader + * @include: e-util/e-module.h + **/ + +#ifndef E_MODULE_H +#define E_MODULE_H + +#include <gmodule.h> +#include <glib-object.h> + +/* Standard GObject macros */ +#define E_TYPE_MODULE \ + (e_module_get_type ()) +#define E_MODULE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MODULE, EModule)) +#define E_MODULE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MODULE, EModuleClass)) +#define E_IS_MODULE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MODULE)) +#define E_IS_MODULE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MODULE)) +#define E_MODULE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MODULE, EModuleClass)) + +G_BEGIN_DECLS + +typedef struct _EModule EModule; +typedef struct _EModuleClass EModuleClass; +typedef struct _EModulePrivate EModulePrivate; + +/** + * EModule: + * + * Contains only private data that should be read and manipulated using the + * functions below. + **/ +struct _EModule { + GTypeModule parent; + EModulePrivate *priv; +}; + +struct _EModuleClass { + GTypeModuleClass parent_class; +}; + +GType e_module_get_type (void); +EModule * e_module_new (const gchar *filename); +const gchar * e_module_get_filename (EModule *module); +GList * e_module_load_all_in_directory (const gchar *dirname); + +G_END_DECLS + +#endif /* E_MODULE_H */ |