mirror of https://github.com/winsw/winsw
165 lines
5.6 KiB
C#
165 lines
5.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Xml;
|
|
using System.Reflection;
|
|
using System.Diagnostics;
|
|
using winsw.Util;
|
|
using log4net;
|
|
|
|
namespace winsw.Extensions
|
|
{
|
|
public class WinSWExtensionManager
|
|
{
|
|
public Dictionary<string, IWinSWExtension> Extensions { private set; get; }
|
|
public ServiceDescriptor ServiceDescriptor { private set; get; }
|
|
|
|
private static readonly ILog Log = LogManager.GetLogger(typeof(WinSWExtensionManager));
|
|
|
|
public WinSWExtensionManager(ServiceDescriptor serviceDescriptor)
|
|
{
|
|
ServiceDescriptor = serviceDescriptor;
|
|
Extensions = new Dictionary<string, IWinSWExtension>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Starts all extensions
|
|
/// </summary>
|
|
/// <exception cref="ExtensionException">Start failure</exception>
|
|
public void OnStart(IEventWriter logger)
|
|
{
|
|
foreach (var ext in Extensions)
|
|
{
|
|
ext.Value.OnStart(logger);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops all extensions
|
|
/// </summary>
|
|
/// <exception cref="ExtensionException">Stop failure</exception>
|
|
public void OnStop(IEventWriter logger)
|
|
{
|
|
foreach (var ext in Extensions)
|
|
{
|
|
ext.Value.OnStop(logger);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handler, which is being invoked once the child process is started.
|
|
/// </summary>
|
|
/// <param name="process">Process</param>
|
|
public void FireOnProcessStarted(System.Diagnostics.Process process)
|
|
{
|
|
foreach (var ext in Extensions)
|
|
{
|
|
try
|
|
{
|
|
ext.Value.OnProcessStarted(process);
|
|
}
|
|
catch (ExtensionException ex)
|
|
{
|
|
Log.Error("onProcessStarted() handler failed for " + ext.Value.DisplayName, ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handler, which is being invoked once the child process is terminated.
|
|
/// </summary>
|
|
/// <param name="process">Process</param>
|
|
public void FireOnProcessTerminated(System.Diagnostics.Process process)
|
|
{
|
|
foreach (var ext in Extensions)
|
|
{
|
|
try
|
|
{
|
|
ext.Value.OnProcessTerminated(process);
|
|
}
|
|
catch (ExtensionException ex)
|
|
{
|
|
Log.Error("onProcessTerminated() handler failed for " + ext.Value.DisplayName, ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
//TODO: Implement loading of external extensions. Current version supports internal hack
|
|
#region Extension load management
|
|
|
|
public void LoadExtensions(IEventWriter logger)
|
|
{
|
|
var extensionIds = ServiceDescriptor.ExtensionIds;
|
|
foreach (String extensionId in extensionIds)
|
|
{
|
|
LoadExtension(extensionId, logger);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads extensions from the configuration file
|
|
/// </summary>
|
|
/// <param name="id">Extension ID</param>
|
|
/// <param name="logger">Logger</param>
|
|
/// <exception cref="ExtensionException">Loading failure</exception>
|
|
private void LoadExtension(string id, IEventWriter logger)
|
|
{
|
|
if (Extensions.ContainsKey(id))
|
|
{
|
|
throw new ExtensionException(id, "Extension has been already loaded");
|
|
}
|
|
|
|
var extensionsConfig = ServiceDescriptor.ExtensionsConfiguration;
|
|
XmlElement configNode =(extensionsConfig != null) ? extensionsConfig.SelectSingleNode("extension[@id='"+id+"'][1]") as XmlElement : null;
|
|
if (configNode == null)
|
|
{
|
|
throw new ExtensionException(id, "Cannot get the configuration entry");
|
|
}
|
|
|
|
var descriptor = WinSWExtensionDescriptor.FromXml(configNode);
|
|
if (descriptor.Enabled)
|
|
{
|
|
IWinSWExtension extension = CreateExtensionInstance(descriptor.Id, descriptor.ClassName);
|
|
extension.Descriptor = descriptor;
|
|
extension.Configure(ServiceDescriptor, configNode, logger);
|
|
Extensions.Add(id, extension);
|
|
logger.LogEvent("Extension loaded: "+id, EventLogEntryType.Information);
|
|
}
|
|
else
|
|
{
|
|
logger.LogEvent("Extension is disabled: " + id, EventLogEntryType.Warning);
|
|
}
|
|
|
|
}
|
|
|
|
private IWinSWExtension CreateExtensionInstance(string id, string className)
|
|
{
|
|
ActivationContext ac = AppDomain.CurrentDomain.ActivationContext;
|
|
Assembly assembly = Assembly.GetCallingAssembly();
|
|
Object created;
|
|
|
|
try
|
|
{
|
|
Type t = Type.GetType(className);
|
|
if (t == null)
|
|
{
|
|
throw new ExtensionException(id, "Class "+className+" does not exist");
|
|
}
|
|
created = Activator.CreateInstance(t);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new ExtensionException(id, "Cannot load the class by name: "+className, ex);
|
|
}
|
|
|
|
var extension = created as IWinSWExtension;
|
|
if (extension == null)
|
|
{
|
|
throw new ExtensionException(id, "The loaded class is not a WinSW extension: " + className + ". Type is " + created.GetType());
|
|
}
|
|
return extension;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|