build-basic-autotools:bgo#688293 - build-basic-autotools: Fix invalid read
[anjuta.git] / libanjuta / anjuta-plugin-handle.c
bloba6fc5f96733216eb9cf2d2d05ba31e8f54b71391
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-plugin-handle.c
4 * Copyright (C) Naba Kumar <naba@gnome.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 /**
22 * SECTION:anjuta-plugin-handle
23 * @short_description: Handle used by plugin manager to keep track of plugins.
24 * @see_also: #AnjutaPluginManager, #AnjutaPluginDescription, #AnjutaPlugin
25 * @stability: Unstable
26 * @include: libanjuta/anjuta-plugin-handle.h
28 * Plugin handle is wrapper for installed plugins. For each installed plugin
29 * there will be one corresponding plugin handle. It is mainly used by
30 * plugin manager to keep track of loading and unloading of plugins.
33 #include <string.h>
34 #include <glib/gi18n.h>
35 #include "anjuta-plugin-handle.h"
36 #include "resources.h"
37 #include "anjuta-debug.h"
39 enum
41 PROP_0,
43 PROP_ID,
44 PROP_NAME,
45 PROP_ABOUT,
46 PROP_ICON_PATH,
47 PROP_USER_ACTIVATABLE,
48 PROP_RESIDENT,
49 PROP_LANGUAGE,
50 PROP_DESCRIPTION,
51 PROP_DEPENDENCY_NAMES,
52 PROP_DEPENDENCIES,
53 PROP_DEPENDENTS,
54 PROP_INTERFACES,
55 PROP_CAN_LOAD,
56 PROP_CHECKED,
57 PROP_RESOLVE_PASS,
58 PROP_PATH
61 struct _AnjutaPluginHandlePriv
63 char *id;
64 char *name;
65 char *about;
66 char *icon_path;
67 char *path;
68 gboolean user_activatable;
69 gboolean resident;
70 char *language;
72 AnjutaPluginDescription *description;
74 /* The dependencies listed in the oaf file */
75 GList *dependency_names;
77 /* Interfaces exported by this plugin */
78 GList *interfaces;
80 /* Attributes defined for this plugin */
81 /* GHashTable *attributes; */
83 /* The keys of these tables represent the dependencies and dependents
84 * of the module. The values point back at the plugins */
85 GHashTable *dependencies;
86 GHashTable *dependents;
88 gboolean can_load;
89 gboolean checked;
91 /* The pass on which the module was resolved, or -1 if
92 * unresolved */
93 int resolve_pass;
96 static GObjectClass* parent_class = NULL;
98 static void
99 anjuta_plugin_handle_init (AnjutaPluginHandle *object)
101 object->priv = g_new0 (AnjutaPluginHandlePriv, 1);
103 object->priv->resolve_pass = -1;
105 object->priv->dependencies = g_hash_table_new (g_direct_hash,
106 g_direct_equal);
107 object->priv->dependents = g_hash_table_new (g_direct_hash,
108 g_direct_equal);
111 static void
112 anjuta_plugin_handle_finalize (GObject *object)
114 AnjutaPluginHandlePriv *priv;
116 priv = ANJUTA_PLUGIN_HANDLE (object)->priv;
118 g_free (priv->id);
119 priv->id = NULL;
120 g_free (priv->name);
121 priv->name = NULL;
122 g_free (priv->icon_path);
123 priv->icon_path = NULL;
124 g_free (priv->path);
125 priv->path = NULL;
126 g_free (priv->language);
127 priv->language = NULL;
129 g_list_foreach (priv->dependency_names, (GFunc)g_free, NULL);
130 g_list_free (priv->dependency_names);
131 priv->dependency_names = NULL;
133 g_list_foreach (priv->interfaces, (GFunc)g_free, NULL);
134 g_list_free (priv->dependency_names);
135 priv->dependency_names = NULL;
137 g_hash_table_destroy (priv->dependencies);
138 priv->dependencies = NULL;
139 g_hash_table_destroy (priv->dependents);
140 priv->dependents = NULL;
142 g_free (priv);
144 G_OBJECT_CLASS (parent_class)->finalize (object);
147 static void
148 anjuta_plugin_handle_set_property (GObject *object, guint prop_id,
149 const GValue *value, GParamSpec *pspec)
151 g_return_if_fail (ANJUTA_IS_PLUGIN_HANDLE (object));
153 switch (prop_id)
155 #if 0
156 case PROP_ID:
157 /* TODO: Add setter for "id" property here */
158 break;
159 case PROP_NAME:
160 /* TODO: Add setter for "name" property here */
161 break;
162 case PROP_ABOUT:
163 /* TODO: Add setter for "about" property here */
164 break;
165 case PROP_ICON_PATH:
166 /* TODO: Add setter for "icon-path" property here */
167 break;
168 case PROP_PATH:
169 /* TODO: Add setter for "path" property here */
170 break;
171 case PROP_USER_ACTIVATABLE:
172 /* TODO: Add setter for "user-activatable" property here */
173 break;
174 case PROP_RESIDENT:
175 /* TODO: Add setter for "resident" property here */
176 break;
177 case PROP_LANGUAGE:
178 /* TODO: Add setter for "language" property here */
179 break;
180 case PROP_DESCRIPTION:
181 /* TODO: Add setter for "description" property here */
182 break;
183 case PROP_DEPENDENCY_NAMES:
184 /* TODO: Add setter for "dependency-names" property here */
185 break;
186 case PROP_DEPENDENCIES:
187 /* TODO: Add setter for "dependencies" property here */
188 break;
189 case PROP_DEPENDENTS:
190 /* TODO: Add setter for "dependents" property here */
191 break;
192 case PROP_INTERFACES:
193 /* TODO: Add setter for "interfaces" property here */
194 break;
195 case PROP_CAN_LOAD:
196 /* TODO: Add setter for "can-load" property here */
197 break;
198 case PROP_CHECKED:
199 /* TODO: Add setter for "checked" property here */
200 break;
201 case PROP_RESOLVE_PASS:
202 /* TODO: Add setter for "resolve-pass" property here */
203 break;
204 #endif
205 default:
206 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
207 break;
211 static void
212 anjuta_plugin_handle_get_property (GObject *object, guint prop_id,
213 GValue *value, GParamSpec *pspec)
215 AnjutaPluginHandlePriv *priv;
217 g_return_if_fail (ANJUTA_IS_PLUGIN_HANDLE (object));
218 priv = ANJUTA_PLUGIN_HANDLE (object)->priv;
219 switch (prop_id)
221 case PROP_ID:
222 g_value_set_string (value, priv->id);
223 break;
224 case PROP_NAME:
225 g_value_set_string (value, priv->name);
226 break;
227 case PROP_ABOUT:
228 g_value_set_string (value, priv->about);
229 break;
230 case PROP_ICON_PATH:
231 g_value_set_string (value, priv->icon_path);
232 break;
233 case PROP_PATH:
234 g_value_set_string (value, priv->path);
235 break;
236 case PROP_USER_ACTIVATABLE:
237 g_value_set_boolean (value, priv->user_activatable);
238 break;
239 case PROP_RESIDENT:
240 g_value_set_boolean (value, priv->resident);
241 break;
242 case PROP_LANGUAGE:
243 g_value_set_string (value, priv->language);
244 break;
245 case PROP_DESCRIPTION:
246 g_value_set_pointer (value, priv->description);
247 break;
248 case PROP_DEPENDENCY_NAMES:
249 g_value_set_pointer (value, priv->dependency_names);
250 break;
251 case PROP_DEPENDENCIES:
252 g_value_set_pointer (value, priv->dependencies);
253 break;
254 case PROP_DEPENDENTS:
255 g_value_set_pointer (value, priv->dependents);
256 break;
257 case PROP_INTERFACES:
258 g_value_set_pointer (value, priv->interfaces);
259 break;
260 case PROP_CAN_LOAD:
261 g_value_set_boolean (value, priv->can_load);
262 break;
263 case PROP_CHECKED:
264 g_value_set_boolean (value, priv->checked);
265 break;
266 case PROP_RESOLVE_PASS:
267 g_value_set_int (value, priv->resolve_pass);
268 break;
269 default:
270 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
271 break;
275 static void
276 anjuta_plugin_handle_class_init (AnjutaPluginHandleClass *klass)
278 GObjectClass* object_class = G_OBJECT_CLASS (klass);
279 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
281 object_class->finalize = anjuta_plugin_handle_finalize;
282 object_class->set_property = anjuta_plugin_handle_set_property;
283 object_class->get_property = anjuta_plugin_handle_get_property;
285 g_object_class_install_property (object_class,
286 PROP_ID,
287 g_param_spec_string ("id",
288 "ID",
289 "Unique plugin ID",
290 NULL,
291 G_PARAM_READABLE));
293 g_object_class_install_property (object_class,
294 PROP_NAME,
295 g_param_spec_string ("name",
296 "Name",
297 "Plugin name",
298 NULL,
299 G_PARAM_READABLE));
301 g_object_class_install_property (object_class,
302 PROP_ABOUT,
303 g_param_spec_string ("about",
304 "About Plugin",
305 "About description of the plugin",
306 NULL,
307 G_PARAM_READABLE));
309 g_object_class_install_property (object_class,
310 PROP_ICON_PATH,
311 g_param_spec_string ("icon-path",
312 "Icon Path",
313 "Icon path of the plugin",
314 NULL,
315 G_PARAM_READABLE));
317 g_object_class_install_property (object_class,
318 PROP_PATH,
319 g_param_spec_string ("path",
320 "Path",
321 "Path of the plugin",
322 NULL,
323 G_PARAM_READABLE));
325 g_object_class_install_property (object_class,
326 PROP_USER_ACTIVATABLE,
327 g_param_spec_boolean ("user-activatable",
328 "User Activatable",
329 "If the plugin is user activatable",
330 FALSE,
331 G_PARAM_READABLE));
333 g_object_class_install_property (object_class,
334 PROP_RESIDENT,
335 g_param_spec_boolean ("resident",
336 "Resident",
337 "If the plugin cannot be unloaded",
338 FALSE,
339 G_PARAM_READABLE));
341 g_object_class_install_property (object_class,
342 PROP_LANGUAGE,
343 g_param_spec_string ("language",
344 "Language",
345 "Language used to write the plugin",
346 NULL,
347 G_PARAM_READABLE));
349 g_object_class_install_property (object_class,
350 PROP_DESCRIPTION,
351 g_param_spec_pointer ("description",
352 "Description",
353 "Plugin description",
354 G_PARAM_READABLE));
356 g_object_class_install_property (object_class,
357 PROP_DEPENDENCY_NAMES,
358 g_param_spec_pointer ("dependency-names",
359 "Dependency names",
360 "Plugin dependency names listed in oaf file",
361 G_PARAM_READABLE));
363 g_object_class_install_property (object_class,
364 PROP_DEPENDENCIES,
365 g_param_spec_pointer ("dependencies",
366 "Dependencies",
367 "Plugin dependencies",
368 G_PARAM_READABLE));
370 g_object_class_install_property (object_class,
371 PROP_DEPENDENTS,
372 g_param_spec_pointer ("dependents",
373 "Dependents",
374 "Plugin dependents",
375 G_PARAM_READABLE));
377 g_object_class_install_property (object_class,
378 PROP_INTERFACES,
379 g_param_spec_pointer ("interfaces",
380 "Interfaces",
381 "Interfaces exported by the plugin",
382 G_PARAM_READABLE));
384 g_object_class_install_property (object_class,
385 PROP_CAN_LOAD,
386 g_param_spec_boolean ("can-load",
387 "Can Load",
388 "If the plugin can be loaded",
389 FALSE,
390 G_PARAM_READABLE));
392 g_object_class_install_property (object_class,
393 PROP_CHECKED,
394 g_param_spec_boolean ("checked",
395 "Checked",
396 "If the plugin is checked in UI",
397 FALSE,
398 G_PARAM_READABLE));
400 g_object_class_install_property (object_class,
401 PROP_RESOLVE_PASS,
402 g_param_spec_int ("resolve-pass",
403 "Resolve Pass",
404 "Dependency resolution pass",
405 G_MININT, /* TODO: Adjust minimum property value */
406 G_MAXINT, /* TODO: Adjust maximum property value */
408 G_PARAM_READABLE));
411 GType
412 anjuta_plugin_handle_get_type (void)
414 static GType our_type = 0;
416 if(our_type == 0)
418 static const GTypeInfo our_info =
420 sizeof (AnjutaPluginHandleClass), /* class_size */
421 (GBaseInitFunc) NULL, /* base_init */
422 (GBaseFinalizeFunc) NULL, /* base_finalize */
423 (GClassInitFunc) anjuta_plugin_handle_class_init, /* class_init */
424 (GClassFinalizeFunc) NULL, /* class_finalize */
425 NULL /* class_data */,
426 sizeof (AnjutaPluginHandle), /* instance_size */
427 0, /* n_preallocs */
428 (GInstanceInitFunc) anjuta_plugin_handle_init, /* instance_init */
429 NULL /* value_table */
432 our_type = g_type_register_static (G_TYPE_OBJECT, "AnjutaPluginHandle",
433 &our_info, 0);
436 return our_type;
440 static char *
441 get_icon_path (char *icon_name)
443 char *ret;
445 if (g_path_is_absolute (icon_name)) {
446 ret = g_strdup (icon_name);
447 } else {
448 ret = anjuta_res_get_pixmap_file (icon_name);
451 return ret;
454 static GList *
455 property_to_list (const char *value)
457 GList *l = NULL;
458 char **split_str;
459 char **p;
461 split_str = g_strsplit (value, ",", -1);
462 for (p = split_str; *p != NULL; p++) {
463 l = g_list_prepend (l, g_strdup (g_strstrip (*p)));
465 g_strfreev (split_str);
466 return l;
469 AnjutaPluginHandle*
470 anjuta_plugin_handle_new (const gchar *plugin_desc_path)
472 AnjutaPluginHandle *plugin_handle;
473 AnjutaPluginDescription *desc;
474 char *str;
475 gboolean enable;
476 gchar *contents = NULL;
477 gboolean success = TRUE;
479 /* Load file content */
480 if (g_file_get_contents (plugin_desc_path, &contents, NULL, NULL)) {
482 desc = anjuta_plugin_description_new_from_string (contents, NULL);
483 g_free (contents);
484 if (!desc) {
485 g_warning ("Bad plugin file: %s\n", plugin_desc_path);
486 return NULL;
489 else
491 return NULL;
494 plugin_handle = g_object_new (ANJUTA_TYPE_PLUGIN_HANDLE, NULL);
496 /* Initialize plugin handle */
497 plugin_handle->priv->description = desc;
498 plugin_handle->priv->user_activatable = TRUE;
499 plugin_handle->priv->resident = TRUE;
500 plugin_handle->priv->path = g_path_get_dirname (plugin_desc_path);
502 if (anjuta_plugin_description_get_string (desc, "Anjuta Plugin",
503 "Location", &str)) {
504 plugin_handle->priv->id = str;
505 } else {
506 g_warning ("Couldn't find 'Location'");
507 success = FALSE;
510 if (anjuta_plugin_description_get_locale_string (desc, "Anjuta Plugin",
511 "Name", &str)) {
512 plugin_handle->priv->name = str;
513 } else {
514 g_warning ("couldn't find 'Name' attribute.");
515 success = FALSE;
518 if (anjuta_plugin_description_get_locale_string (desc, "Anjuta Plugin",
519 "Description", &str)) {
520 plugin_handle->priv->about = str;
521 } else {
522 g_warning ("Couldn't find 'Description' attribute.");
523 success = FALSE;
526 if (anjuta_plugin_description_get_string (desc, "Anjuta Plugin",
527 "Icon", &str)) {
528 plugin_handle->priv->icon_path = get_icon_path (str);
529 g_free (str);
532 if (anjuta_plugin_description_get_string (desc, "Anjuta Plugin",
533 "Dependencies",
534 &str)) {
535 plugin_handle->priv->dependency_names = property_to_list (str);
536 g_free (str);
539 if (anjuta_plugin_description_get_string (desc, "Anjuta Plugin",
540 "Interfaces",
541 &str)) {
542 plugin_handle->priv->interfaces = property_to_list (str);
543 g_free (str);
546 if (anjuta_plugin_description_get_boolean (desc, "Anjuta Plugin",
547 "UserActivatable", &enable)) {
548 plugin_handle->priv->user_activatable = enable;
550 DEBUG_PRINT ("Plugin '%s' is not user activatable",
551 plugin_handle->priv->name?
552 plugin_handle->priv->name : "Unknown");
556 if (anjuta_plugin_description_get_string (desc, "Anjuta Plugin",
557 "Resident", &str)) {
558 if (str && strcasecmp (str, "no") == 0)
560 plugin_handle->priv->resident = FALSE;
562 g_free (str);
565 if (anjuta_plugin_description_get_string (desc, "Anjuta Plugin",
566 "Language", &str)) {
567 plugin_handle->priv->language = str;
570 if (!success) {
571 g_object_unref (plugin_handle);
572 plugin_handle = NULL;
575 return plugin_handle;
578 const char*
579 anjuta_plugin_handle_get_id (AnjutaPluginHandle *plugin_handle)
581 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), NULL);
582 return plugin_handle->priv->id;
585 const char*
586 anjuta_plugin_handle_get_name (AnjutaPluginHandle *plugin_handle)
588 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), NULL);
589 return plugin_handle->priv->name;
592 const char*
593 anjuta_plugin_handle_get_about (AnjutaPluginHandle *plugin_handle)
595 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), NULL);
596 return _(plugin_handle->priv->about);
599 const char*
600 anjuta_plugin_handle_get_icon_path (AnjutaPluginHandle *plugin_handle)
602 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), NULL);
603 return plugin_handle->priv->icon_path;
606 const char*
607 anjuta_plugin_handle_get_path (AnjutaPluginHandle *plugin_handle)
609 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), NULL);
610 return plugin_handle->priv->path;
613 gboolean
614 anjuta_plugin_handle_get_user_activatable (AnjutaPluginHandle *plugin_handle)
616 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), FALSE);
617 return plugin_handle->priv->user_activatable;
620 gboolean
621 anjuta_plugin_handle_get_resident (AnjutaPluginHandle *plugin_handle)
623 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), FALSE);
624 return plugin_handle->priv->resident;
627 const char*
628 anjuta_plugin_handle_get_language (AnjutaPluginHandle *plugin_handle)
630 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), NULL);
631 return plugin_handle->priv->language;
634 AnjutaPluginDescription*
635 anjuta_plugin_handle_get_description (AnjutaPluginHandle *plugin_handle)
637 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), NULL);
638 return plugin_handle->priv->description;
641 GList*
642 anjuta_plugin_handle_get_dependency_names (AnjutaPluginHandle *plugin_handle)
644 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), NULL);
645 return plugin_handle->priv->dependency_names;
648 GHashTable*
649 anjuta_plugin_handle_get_dependencies (AnjutaPluginHandle *plugin_handle)
651 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), NULL);
652 return plugin_handle->priv->dependencies;
655 GHashTable*
656 anjuta_plugin_handle_get_dependents (AnjutaPluginHandle *plugin_handle)
658 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), NULL);
659 return plugin_handle->priv->dependents;
662 GList*
663 anjuta_plugin_handle_get_interfaces (AnjutaPluginHandle *plugin_handle)
665 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), NULL);
666 return plugin_handle->priv->interfaces;
669 gboolean
670 anjuta_plugin_handle_get_can_load (AnjutaPluginHandle *plugin_handle)
672 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), FALSE);
673 return plugin_handle->priv->can_load;
676 gboolean
677 anjuta_plugin_handle_get_checked (AnjutaPluginHandle *plugin_handle)
679 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), FALSE);
680 return plugin_handle->priv->checked;
683 gint
684 anjuta_plugin_handle_get_resolve_pass (AnjutaPluginHandle *plugin_handle)
686 g_return_val_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle), 0);
687 return plugin_handle->priv->resolve_pass;
690 void
691 anjuta_plugin_handle_set_can_load (AnjutaPluginHandle *plugin_handle,
692 gboolean can_load)
694 g_return_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle));
695 plugin_handle->priv->can_load = can_load;
698 void
699 anjuta_plugin_handle_set_checked (AnjutaPluginHandle *plugin_handle,
700 gboolean checked)
702 g_return_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle));
703 plugin_handle->priv->checked = checked;
706 void
707 anjuta_plugin_handle_set_resolve_pass (AnjutaPluginHandle *plugin_handle,
708 gboolean resolve_pass)
710 g_return_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle));
711 plugin_handle->priv->resolve_pass = resolve_pass;
714 static gboolean
715 g_hashtable_foreach_true (gpointer key, gpointer value, gpointer user_data)
717 return TRUE;
720 void
721 anjuta_plugin_handle_unresolve_dependencies (AnjutaPluginHandle *plugin_handle)
723 AnjutaPluginHandlePriv *priv;
725 g_return_if_fail (ANJUTA_IS_PLUGIN_HANDLE (plugin_handle));
726 priv = plugin_handle->priv;
728 g_hash_table_foreach_remove (priv->dependencies, g_hashtable_foreach_true,
729 NULL);
730 g_hash_table_foreach_remove (priv->dependents, g_hashtable_foreach_true,
731 NULL);
732 priv->can_load = TRUE;
733 priv->resolve_pass = -1;