plugins: add plugin enumeration and getters for available plugins and plugin mechanisms
authorAlexander Kanavin <alex.kanavin@gmail.com>
Wed, 20 Feb 2013 22:48:29 +0000 (00:48 +0200)
committerAlexander Kanavin <alexander.kanavin@intel.com>
Thu, 21 Feb 2013 14:33:35 +0000 (16:33 +0200)
src/daemon/plugins/gsignond-plugin-proxy-factory.c
src/daemon/plugins/gsignond-plugin-proxy-factory.h
test/plugins/pluginproxytest.c

index a30f864..ecf5a3f 100644 (file)
@@ -24,6 +24,8 @@
  */
 
 #include "gsignond-plugin-proxy-factory.h"
+#include <string.h>
+#include <gsignond/gsignond-plugin-loader.h>
 
 G_DEFINE_TYPE (GSignondPluginProxyFactory, gsignond_plugin_proxy_factory, G_TYPE_OBJECT);
 
@@ -39,6 +41,62 @@ enum
 
 static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
 
+static void _enumerate_plugins(GSignondPluginProxyFactory* self)
+{
+    self->methods = g_malloc0(sizeof(gchar*));
+    self->mechanisms = g_hash_table_new_full ((GHashFunc)g_str_hash,
+                            (GEqualFunc)g_str_equal,
+                            (GDestroyNotify)g_free,
+                            (GDestroyNotify)g_strfreev);
+
+    GDir* plugin_dir = g_dir_open(gsignond_config_get_string (self->config, 
+        GSIGNOND_CONFIG_GENERAL_PLUGINS_DIR), 0, NULL);
+    if (plugin_dir == NULL)
+        return;
+        
+    int n_plugins = 0;
+    while (g_dir_read_name(plugin_dir) != NULL)
+        n_plugins++;
+    g_dir_rewind(plugin_dir);
+    
+    g_free(self->methods);
+    self->methods = g_malloc0(sizeof(gchar*) * (n_plugins + 1));
+
+    int i = 0;
+    while (1) {
+        const gchar* plugin_soname = g_dir_read_name(plugin_dir);
+        if (plugin_soname == NULL)
+            break;
+        if (g_str_has_prefix(plugin_soname, "lib") && 
+            g_str_has_suffix(plugin_soname, ".so")) {
+            gchar* plugin_name = g_strndup(plugin_soname+3, 
+                strlen(plugin_soname) - 6);
+            GSignondPlugin* plugin = gsignond_load_plugin(
+                self->config, plugin_name);
+            if (plugin != NULL) {
+                gchar* plugin_type;
+                gchar** mechanisms;
+                g_object_get(plugin, 
+                    "type", &plugin_type, 
+                    "mechanisms", &mechanisms, 
+                    NULL);
+                if (g_strcmp0 (plugin_type, plugin_name) == 0) {
+                    self->methods[i] = plugin_type;
+                    g_hash_table_insert(self->mechanisms,
+                        plugin_type, mechanisms);
+                    i++;
+                } else {
+                    g_free(plugin_type);
+                    g_strfreev(mechanisms);
+                }
+                g_object_unref(plugin);
+            }
+            g_free(plugin_name);
+        }
+    }
+    g_dir_close(plugin_dir);
+}
+
 static GObject *
 gsignond_plugin_proxy_factory_constructor (GType                  gtype,
                                    guint                  n_properties,
@@ -55,7 +113,7 @@ gsignond_plugin_proxy_factory_constructor (GType                  gtype,
   /* update the object state depending on constructor properties */
   GSignondPluginProxyFactory* self = GSIGNOND_PLUGIN_PROXY_FACTORY(obj);
   
-  (void) self;
+  _enumerate_plugins(self);
 
   return obj;
 }
@@ -118,6 +176,8 @@ gsignond_plugin_proxy_factory_finalize (GObject *gobject)
     GSignondPluginProxyFactory *self = GSIGNOND_PLUGIN_PROXY_FACTORY (gobject);
 
     g_hash_table_destroy (self->plugins);
+    g_hash_table_destroy (self->mechanisms);
+    g_strfreev(self->methods);
 
     /* Chain up to the parent class */
     G_OBJECT_CLASS (gsignond_plugin_proxy_factory_parent_class)->finalize (gobject);
@@ -156,7 +216,6 @@ gsignond_plugin_proxy_factory_init (GSignondPluginProxyFactory *self)
                             (GEqualFunc)g_str_equal,
                             (GDestroyNotify)g_free,
                             (GDestroyNotify)g_object_unref);
-    
 }
 
 GSignondPluginProxyFactory* 
@@ -216,6 +275,18 @@ gboolean gsignond_plugin_proxy_factory_add_plugin(
     g_hash_table_insert(factory->plugins, key, proxy);
 
     return TRUE;
-        
-    
+}
+
+const gchar** 
+gsignond_plugin_proxy_factory_get_plugin_types(
+   GSignondPluginProxyFactory* factory)
+{
+    return (gpointer)factory->methods;
+}
+   
+const gchar**
+gsignond_plugin_proxy_factory_get_plugin_mechanisms(
+   GSignondPluginProxyFactory* factory, const gchar* plugin_type)
+{
+    return g_hash_table_lookup(factory->mechanisms, plugin_type);
 }
index 8701215..9c960d8 100644 (file)
@@ -48,6 +48,9 @@ struct _GSignondPluginProxyFactory
     /* Private */
     GSignondConfig *config;
     GHashTable* plugins;
+    
+    gchar** methods;
+    GHashTable* mechanisms;
 };
 
 struct _GSignondPluginProxyFactoryClass
@@ -69,5 +72,14 @@ gboolean gsignond_plugin_proxy_factory_add_plugin(
     GSignondPluginProxyFactory* factory,
     guint32 identity_id,
     GSignondPluginProxy* proxy);
+    
+const gchar** 
+gsignond_plugin_proxy_factory_get_plugin_types(
+   GSignondPluginProxyFactory* factory);
+   
+const gchar**
+gsignond_plugin_proxy_factory_get_plugin_mechanisms(
+   GSignondPluginProxyFactory* factory, const gchar* plugin_type);
+   
 
-#endif /* __GSIGNOND_PLUGIN_PROXY_FACTORY_H__ */
\ No newline at end of file
+#endif /* __GSIGNOND_PLUGIN_PROXY_FACTORY_H__ */
index f1f49b7..205f92f 100644 (file)
@@ -305,6 +305,30 @@ START_TEST (test_pluginproxy_process_queue_cancel)
 }
 END_TEST
 
+START_TEST (test_pluginproxyfactory_methods_and_mechanisms)
+{
+    GSignondConfig* config = gsignond_config_new();
+    fail_if(config == NULL);
+    
+    GSignondPluginProxyFactory* factory = gsignond_plugin_proxy_factory_new(config);
+    fail_if(factory == NULL);
+    
+    const gchar** methods = gsignond_plugin_proxy_factory_get_plugin_types(factory);
+    fail_if(methods == NULL);
+    fail_if(strcmp(methods[0], "password") != 0);
+    fail_if(methods[1] != NULL);
+    
+    const gchar** mechanisms = gsignond_plugin_proxy_factory_get_plugin_mechanisms(factory, methods[0]);
+    fail_if(mechanisms == NULL);
+    fail_if(strcmp(mechanisms[0], "password") != 0);
+    fail_if(mechanisms[1] != NULL);
+    
+
+    g_object_unref(factory);
+    g_object_unref(config);
+}
+END_TEST
+
 START_TEST (test_pluginproxyfactory_get)
 {
     GSignondConfig* config = gsignond_config_new();
@@ -366,6 +390,7 @@ Suite* pluginproxy_suite (void)
     // cancellation and queueuing. Password plugin is totally synchronous.
     tcase_add_test (tc_core, test_pluginproxy_process_queue);
     tcase_add_test (tc_core, test_pluginproxy_process_queue_cancel);
+    tcase_add_test (tc_core, test_pluginproxyfactory_methods_and_mechanisms);
     tcase_add_test (tc_core, test_pluginproxyfactory_get);
     tcase_add_test (tc_core, test_pluginproxyfactory_add);
     suite_add_tcase (s, tc_core);