* Fixes invalid unrefs when comparing merge folders
[modest] / src / modest-plugin-factory.c
1 /* Copyright (c) 2008, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "modest-plugin-factory.h"
31 #include "modest-protocol-registry.h"
32 #include "modest-plugin.h"
33 #include "modest-module.h"
34 #include <gmodule.h>
35 /* include other impl specific header files */
36
37 #define PLUGIN_EXT      ".modest-mail-plugin"
38
39 /* 'private'/'protected' functions */
40 static void modest_plugin_factory_class_init (ModestPluginFactoryClass *klass);
41 static void modest_plugin_factory_init       (ModestPluginFactory *obj);
42 static void modest_plugin_factory_finalize   (GObject *obj);
43
44 static ModestPlugin* modest_plugin_factory_load     (const gchar *file);
45
46 typedef GType (*ModestModuleRegisterFunc) (GTypeModule *);
47
48 typedef struct _ModestPluginFactoryPrivate ModestPluginFactoryPrivate;
49 struct _ModestPluginFactoryPrivate {
50         GSList *plugins;
51 };
52
53 #define MODEST_PLUGIN_FACTORY_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
54                                                         MODEST_TYPE_PLUGIN_FACTORY, \
55                                                         ModestPluginFactoryPrivate))
56 /* globals */
57 static GObjectClass *parent_class = NULL;
58
59 GType
60 modest_plugin_factory_get_type (void)
61 {
62         static GType my_type = 0;
63         if (!my_type) {
64                 static const GTypeInfo my_info = {
65                         sizeof(ModestPluginFactoryClass),
66                         NULL,           /* base init */
67                         NULL,           /* base finalize */
68                         (GClassInitFunc) modest_plugin_factory_class_init,
69                         NULL,           /* class finalize */
70                         NULL,           /* class data */
71                         sizeof(ModestPluginFactory),
72                         1,              /* n_preallocs */
73                         (GInstanceInitFunc) modest_plugin_factory_init,
74                         NULL
75                 };
76                 my_type = g_type_register_static (G_TYPE_OBJECT,
77                                                   "ModestPluginFactory",
78                                                   &my_info, 0);
79         }
80         return my_type;
81 }
82
83 static void
84 modest_plugin_factory_class_init (ModestPluginFactoryClass *klass)
85 {
86         GObjectClass *gobject_class;
87         gobject_class = (GObjectClass*) klass;
88
89         parent_class            = g_type_class_peek_parent (klass);
90         gobject_class->finalize = modest_plugin_factory_finalize;
91
92         g_type_class_add_private (gobject_class, sizeof(ModestPluginFactoryPrivate));
93 }
94
95 static void
96 modest_plugin_factory_init (ModestPluginFactory *obj)
97 {
98         ModestPluginFactoryPrivate *priv = MODEST_PLUGIN_FACTORY_GET_PRIVATE(obj);
99
100         if (!g_module_supported ()) {
101                 g_warning ("unable to initialize the plugin factory");
102                 return;
103         }
104
105         priv->plugins = NULL;
106         g_module_open (NULL, 0);
107 }
108
109 static void
110 modest_plugin_factory_finalize (GObject *obj)
111 {
112         ModestPluginFactoryPrivate *priv;
113         GSList *iter;
114
115         priv = MODEST_PLUGIN_FACTORY_GET_PRIVATE (obj);
116
117         /* Free the plugin list */
118         for (iter = priv->plugins; iter; iter = g_slist_next (iter))
119                 g_module_close ((GModule*) iter->data);
120
121         g_slist_free (priv->plugins);
122         priv->plugins = NULL;
123
124         G_OBJECT_CLASS(parent_class)->finalize (obj);
125 }
126
127 ModestPluginFactory*
128 modest_plugin_factory_new (void)
129 {
130         ModestPluginFactory *self;
131         ModestPluginFactoryPrivate *priv;
132
133         self = MODEST_PLUGIN_FACTORY (g_object_new (MODEST_TYPE_PLUGIN_FACTORY, NULL));
134         priv = MODEST_PLUGIN_FACTORY_GET_PRIVATE(self);
135
136 /*      if (priv->plugins == NULL) { */
137 /*              g_critical ("%s, no mail plugins detected", __FUNCTION__); */
138 /*              g_object_unref (self); */
139 /*              self = NULL; */
140 /*      } */
141         return self;
142 }
143
144 void
145 modest_plugin_factory_load_all (ModestPluginFactory *self) 
146 {
147         ModestPluginFactoryPrivate *priv;
148         GError *error = NULL;
149         GDir *d;
150         const gchar *dirent;
151         ModestProtocolRegistry *pr;
152
153         pr = modest_plugin_get_protocol_registry ();
154
155         priv = MODEST_PLUGIN_FACTORY_GET_PRIVATE(self);
156
157         if (!g_file_test (MODEST_MAILPLUGINDIR, G_FILE_TEST_IS_DIR)) {
158                 return;
159         }
160
161         d = g_dir_open (MODEST_MAILPLUGINDIR, 0, &error);
162
163         if (!d) {
164                 g_warning ("%s", error->message);
165                 g_error_free (error);
166
167                 return;
168         }
169
170         while ((dirent = g_dir_read_name (d))) {
171                 if (g_str_has_suffix (dirent, PLUGIN_EXT)) {
172                         gchar *plugin_file;
173                         ModestPlugin *plugin;
174                         
175                         plugin_file = g_build_filename (MODEST_MAILPLUGINDIR, dirent, NULL);
176                         plugin = modest_plugin_factory_load (plugin_file);
177                         g_free (plugin_file);
178
179                         if (plugin)
180                                 priv->plugins = g_slist_prepend (priv->plugins, plugin);
181                 }
182         }
183
184         priv->plugins = g_slist_reverse (priv->plugins);
185
186         g_dir_close (d);
187 }
188
189 static ModestPlugin*
190 modest_plugin_factory_load (const gchar *file)
191 {
192         ModestPlugin *plugin = NULL;
193         GKeyFile *plugin_file = NULL;
194         gchar *plugin_name, *dir, *path;
195         GTypeModule *type_module;
196
197         g_return_val_if_fail (file != NULL, NULL);
198
199         plugin_file = g_key_file_new ();
200
201         if (!g_key_file_load_from_file (plugin_file, file, G_KEY_FILE_NONE, NULL)) {
202                 g_warning ("Bad plugin file: %s", file);
203                 goto error;
204         }
205
206         /* Get Location */
207         plugin_name = g_key_file_get_string (plugin_file,
208                                              "Modest Mail Plugin",
209                                              "Module",
210                                              NULL);
211
212         if ((plugin_name == NULL) || (*plugin_name == '\0')) {
213                 g_warning ("Could not find 'Module' in %s", file);
214                 goto error;
215         }
216
217         g_key_file_free (plugin_file);
218
219         /* Build path to plugin */
220         dir = g_path_get_dirname (file);        
221         path = g_module_build_path (dir, plugin_name);
222         g_free (dir);
223
224         /* plugin = g_module_open (path, G_MODULE_BIND_LAZY); */
225         g_message ("PLUGIN TYPE IS %d", (gint) modest_plugin_get_type ());
226         type_module = G_TYPE_MODULE (modest_module_new (path));
227         if (type_module) {
228                 g_type_module_use (type_module);
229                 plugin = MODEST_PLUGIN (modest_module_new_object (MODEST_MODULE (type_module)));
230         }
231         g_free (path);
232
233         return plugin;
234 error:
235         g_key_file_free (plugin_file);
236
237         return NULL;
238 }