aboutsummaryrefslogtreecommitdiffstats
path: root/e-util/e-module.c
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2009-05-07 19:21:57 +0800
committerMatthew Barnes <mbarnes@redhat.com>2009-05-07 19:21:57 +0800
commitcaa862135195b828d2e8355436fdd6eb0ec2443e (patch)
tree40198708ccf89ca4246c7da11a718fa5cc39de52 /e-util/e-module.c
parent19b29348068e367efc105732e9707cdb4132b4ee (diff)
downloadgsoc2013-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/e-module.c')
-rw-r--r--e-util/e-module.c318
1 files changed, 318 insertions, 0 deletions
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;
+}