/**
 * infinoted_plugin_manager_load:
 * @manager: A #InfinotedPluginManager.
 * @plugin_path: The path from which to load plugins.
 * @plugins: A list of plugins to load, or %NULL.
 * @options: A #GKeyFile with configuration options for the plugins.
 * @error: Location to store error information, if any, or %NULL.
 *
 * Loads all plugins specified in @plugins from the location at @plugin_path.
 * If loading one of the module fails the function sets @error and returns
 * %FALSE, and the object ends up with no plugins loaded. If @plugins is
 * %NULL, no plugins are loaded.
 * 
 * If this function is called while there are already plugins loaded, all
 * existing plugins are unloaded first.
 *
 * Returns: %TRUE on success or %FALSE on error.
 */
gboolean
infinoted_plugin_manager_load(InfinotedPluginManager* manager,
                              const gchar* plugin_path,
                              const gchar* const* plugins,
                              GKeyFile* options,
                              GError** error)
{
  InfinotedPluginManagerPrivate* priv;
  const gchar* const* plugin;
  gboolean result;

  g_return_val_if_fail(INFINOTED_IS_PLUGIN_MANAGER(manager), FALSE);
  g_return_val_if_fail(plugin_path != NULL, FALSE);
  g_return_val_if_fail(options != NULL, FALSE);
  g_return_val_if_fail(error == NULL || *error == NULL, FALSE);

  priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager);

  /* Unload existing plugins */
  g_free(priv->path);
  while(priv->plugins != NULL)
  {
    infinoted_plugin_manager_unload_plugin(
      manager,
      (InfinotedPluginInstance*)priv->plugins->data
    );
  }

  /* Load new plugins */
  priv->path = g_strdup(plugin_path);

  if(plugins != NULL)
  {
    for(plugin = plugins; *plugin != NULL; ++plugin)
    {
      result = infinoted_plugin_manager_load_plugin(
        manager,
        plugin_path,
        *plugin,
        options,
        error
      );

      if(result == FALSE)
      {
        while(priv->plugins != NULL)
        {
          infinoted_plugin_manager_unload_plugin(
            manager,
            (InfinotedPluginInstance*)priv->plugins->data
          );
        }

        return FALSE;
      }
    }
  }

  return TRUE;
}
static void
infinoted_plugin_manager_dispose(GObject* object)
{
  InfinotedPluginManager* manager;
  InfinotedPluginManagerPrivate* priv;

  manager = INFINOTED_PLUGIN_MANAGER(object);
  priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager);

  while(priv->plugins != NULL)
  {
    infinoted_plugin_manager_unload_plugin(
      manager,
      (InfinotedPluginInstance*)priv->plugins->data
    );
  }

  if(priv->directory != NULL)
    infinoted_plugin_manager_set_directory(manager, NULL);

  if(priv->log != NULL)
  {
    g_object_unref(priv->log);
    priv->log = NULL;
  }

  if(priv->credentials != NULL)
  {
    inf_certificate_credentials_unref(priv->credentials);
    priv->credentials = NULL;
  }

  G_OBJECT_CLASS(parent_class)->dispose(object);
}
/**
 * infinoted_plugin_manager_free:
 * @manager: A #InfinotedPluginManager.
 *
 * Unloads all plugins and releases all resources associated with @manager.
 */
void
infinoted_plugin_manager_free(InfinotedPluginManager* manager)
{
  GSList* item;

  inf_signal_handlers_disconnect_by_func(
    G_OBJECT(manager->directory),
    G_CALLBACK(infinoted_plugin_manager_connection_added_cb),
    manager
  );

  inf_signal_handlers_disconnect_by_func(
    G_OBJECT(manager->directory),
    G_CALLBACK(infinoted_plugin_manager_connection_removed_cb),
    manager
  );

  inf_signal_handlers_disconnect_by_func(
    G_OBJECT(manager->directory),
    G_CALLBACK(infinoted_plugin_manager_subscribe_session_cb),
    manager
  );

  inf_signal_handlers_disconnect_by_func(
    G_OBJECT(manager->directory),
    G_CALLBACK(infinoted_plugin_manager_unsubscribe_session_cb),
    manager
  );

  while(manager->plugins != NULL)
  {
    infinoted_plugin_manager_unload_plugin(
      manager,
      (InfinotedPluginInstance*)manager->plugins->data
    );
  }

  g_assert(g_hash_table_size(manager->connections) == 0);
  g_hash_table_unref(manager->connections);

  g_assert(g_hash_table_size(manager->sessions) == 0);
  g_hash_table_unref(manager->sessions);

  g_free(manager->path);

  if(manager->credentials != NULL)
    inf_certificate_credentials_unref(manager->credentials);

  g_object_unref(manager->directory);
  g_object_unref(manager->log);

  g_slice_free(InfinotedPluginManager, manager);
}