Frontend gaps fill work. Testing fixes work. Auditing in progress.
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Integrations.Contracts;
|
||||
using StellaOps.Integrations.Core;
|
||||
using StellaOps.Plugin;
|
||||
using StellaOps.Plugin.Hosting;
|
||||
|
||||
namespace StellaOps.Integrations.WebService;
|
||||
|
||||
/// <summary>
|
||||
/// Loads and manages integration connector plugins.
|
||||
/// </summary>
|
||||
public sealed class IntegrationPluginLoader
|
||||
{
|
||||
private readonly ILogger<IntegrationPluginLoader>? _logger;
|
||||
private readonly List<IIntegrationConnectorPlugin> _plugins = [];
|
||||
|
||||
public IntegrationPluginLoader(ILogger<IntegrationPluginLoader>? logger = null)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all loaded plugins.
|
||||
/// </summary>
|
||||
public IReadOnlyList<IIntegrationConnectorPlugin> Plugins => _plugins;
|
||||
|
||||
/// <summary>
|
||||
/// Discovers and loads integration connector plugins from the specified directory.
|
||||
/// </summary>
|
||||
public IReadOnlyList<IIntegrationConnectorPlugin> LoadFromDirectory(
|
||||
string pluginDirectory,
|
||||
string searchPattern = "StellaOps.Integrations.Plugin.*.dll")
|
||||
{
|
||||
if (!Directory.Exists(pluginDirectory))
|
||||
{
|
||||
_logger?.LogWarning("Plugin directory does not exist: {Directory}", pluginDirectory);
|
||||
return [];
|
||||
}
|
||||
|
||||
var options = new PluginHostOptions
|
||||
{
|
||||
PluginsDirectory = pluginDirectory,
|
||||
EnsureDirectoryExists = false,
|
||||
RecursiveSearch = false
|
||||
};
|
||||
options.SearchPatterns.Add(searchPattern);
|
||||
|
||||
var result = PluginHost.LoadPlugins(options);
|
||||
var loadedPlugins = new List<IIntegrationConnectorPlugin>();
|
||||
|
||||
foreach (var pluginAssembly in result.Plugins)
|
||||
{
|
||||
var connectorPlugins = PluginLoader.LoadPlugins<IIntegrationConnectorPlugin>(new[] { pluginAssembly.Assembly });
|
||||
loadedPlugins.AddRange(connectorPlugins);
|
||||
|
||||
foreach (var plugin in connectorPlugins)
|
||||
{
|
||||
_logger?.LogDebug("Loaded integration connector plugin: {Name} ({Provider}) from {Assembly}",
|
||||
plugin.Name, plugin.Provider, pluginAssembly.Assembly.GetName().Name);
|
||||
}
|
||||
}
|
||||
|
||||
_plugins.AddRange(loadedPlugins);
|
||||
return loadedPlugins;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads integration connector plugins from the specified assemblies.
|
||||
/// </summary>
|
||||
public IReadOnlyList<IIntegrationConnectorPlugin> LoadFromAssemblies(IEnumerable<Assembly> assemblies)
|
||||
{
|
||||
var loadedPlugins = PluginLoader.LoadPlugins<IIntegrationConnectorPlugin>(assemblies);
|
||||
_plugins.AddRange(loadedPlugins);
|
||||
return loadedPlugins;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a plugin by provider.
|
||||
/// </summary>
|
||||
public IIntegrationConnectorPlugin? GetByProvider(IntegrationProvider provider)
|
||||
{
|
||||
return _plugins.FirstOrDefault(p => p.Provider == provider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all plugins for a given type.
|
||||
/// </summary>
|
||||
public IReadOnlyList<IIntegrationConnectorPlugin> GetByType(IntegrationType type)
|
||||
{
|
||||
return _plugins.Where(p => p.Type == type).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all available plugins (checking IsAvailable).
|
||||
/// </summary>
|
||||
public IReadOnlyList<IIntegrationConnectorPlugin> GetAvailable(IServiceProvider services)
|
||||
{
|
||||
return _plugins.Where(p =>
|
||||
{
|
||||
try { return p.IsAvailable(services); }
|
||||
catch { return false; }
|
||||
}).ToList();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user