mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-31 04:04:21 -04:00
212 lines
7.1 KiB
C#
212 lines
7.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Autofac;
|
|
using Kyoo.Abstractions;
|
|
using Kyoo.Abstractions.Controllers;
|
|
using Kyoo.Authentication;
|
|
using Kyoo.Core.Controllers;
|
|
using Kyoo.Core.Models.Options;
|
|
using Kyoo.Core.Tasks;
|
|
using Kyoo.Postgresql;
|
|
using Kyoo.SqLite;
|
|
using Kyoo.TheMovieDb;
|
|
using Kyoo.TheTvdb;
|
|
using Kyoo.Utils;
|
|
using Kyoo.WebApp;
|
|
using Microsoft.AspNetCore.Builder;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace Kyoo.Core
|
|
{
|
|
/// <summary>
|
|
/// The Startup class is used to configure the AspNet's webhost.
|
|
/// </summary>
|
|
public class PluginsStartup
|
|
{
|
|
/// <summary>
|
|
/// A plugin manager used to load plugins and allow them to configure services / asp net.
|
|
/// </summary>
|
|
private readonly IPluginManager _plugins;
|
|
|
|
/// <summary>
|
|
/// The configuration used to register <see cref="IOptions{TOptions}"/> and so on for plugin's specified types.
|
|
/// </summary>
|
|
private readonly IConfiguration _configuration;
|
|
|
|
/// <summary>
|
|
/// Created from the DI container, those services are needed to load information and instantiate plugins.s
|
|
/// </summary>
|
|
/// <param name="plugins">The plugin manager to use to load new plugins and configure the host.</param>
|
|
/// <param name="configuration">
|
|
/// The configuration used to register <see cref="IOptions{TOptions}"/> and so on for plugin's specified types.
|
|
/// </param>
|
|
public PluginsStartup(IPluginManager plugins, IConfiguration configuration)
|
|
{
|
|
_plugins = plugins;
|
|
_configuration = configuration;
|
|
_plugins.LoadPlugins(
|
|
typeof(CoreModule),
|
|
typeof(WebAppModule),
|
|
typeof(AuthenticationModule),
|
|
typeof(PostgresModule),
|
|
typeof(SqLiteModule),
|
|
typeof(PluginTvdb),
|
|
typeof(PluginTmdb)
|
|
);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configure the services context via the <see cref="PluginManager"/>.
|
|
/// </summary>
|
|
/// <param name="services">The service collection to fill.</param>
|
|
public void ConfigureServices(IServiceCollection services)
|
|
{
|
|
foreach (IPlugin plugin in _plugins.GetAllPlugins())
|
|
plugin.Configure(services);
|
|
|
|
IEnumerable<KeyValuePair<string, Type>> configTypes = _plugins.GetAllPlugins()
|
|
.SelectMany(x => x.Configuration)
|
|
.Where(x => x.Value != null);
|
|
foreach ((string path, Type type) in configTypes)
|
|
{
|
|
Utility.RunGenericMethod<object>(
|
|
typeof(OptionsConfigurationServiceCollectionExtensions),
|
|
nameof(OptionsConfigurationServiceCollectionExtensions.Configure),
|
|
type,
|
|
services, _configuration.GetSection(path)
|
|
);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configure the autofac container via the <see cref="PluginManager"/>.
|
|
/// </summary>
|
|
/// <param name="builder">The builder to configure.</param>
|
|
public void ConfigureContainer(ContainerBuilder builder)
|
|
{
|
|
builder.RegisterInstance(_plugins).As<IPluginManager>().ExternallyOwned();
|
|
builder.RegisterTask<PluginInitializer>();
|
|
|
|
foreach (IPlugin plugin in _plugins.GetAllPlugins())
|
|
plugin.Configure(builder);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configure the asp net host.
|
|
/// </summary>
|
|
/// <param name="app">The asp net host to configure</param>
|
|
/// <param name="container">An autofac container used to create a new scope to configure asp-net.</param>
|
|
/// <param name="config">The configuration manager used to register strongly typed config.</param>
|
|
public void Configure(IApplicationBuilder app, ILifetimeScope container, IConfigurationManager config)
|
|
{
|
|
IEnumerable<IStartupAction> steps = _plugins.GetAllPlugins()
|
|
.SelectMany(x => x.ConfigureSteps)
|
|
.OrderByDescending(x => x.Priority);
|
|
|
|
using ILifetimeScope scope = container.BeginLifetimeScope(x =>
|
|
x.RegisterInstance(app).SingleInstance().ExternallyOwned());
|
|
IServiceProvider provider = scope.Resolve<IServiceProvider>();
|
|
foreach (IStartupAction step in steps)
|
|
step.Run(provider);
|
|
|
|
IEnumerable<KeyValuePair<string, Type>> pluginConfig = _plugins.GetAllPlugins()
|
|
.SelectMany(x => x.Configuration)
|
|
.GroupBy(x => x.Key.Split(':').First())
|
|
.Select(x => x
|
|
.OrderBy(y => y.Key.Length)
|
|
.First()
|
|
);
|
|
foreach ((string path, Type type) in pluginConfig)
|
|
config.Register(path, type);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Create a new <see cref="PluginsStartup"/> from a webhost.
|
|
/// This is meant to be used from <see cref="WebHostBuilderExtensions.UseStartup"/>.
|
|
/// </summary>
|
|
/// <param name="host">The context of the web host.</param>
|
|
/// <param name="logger">
|
|
/// The logger factory used to log while the application is setting itself up.
|
|
/// </param>
|
|
/// <returns>A new <see cref="PluginsStartup"/>.</returns>
|
|
public static PluginsStartup FromWebHost(WebHostBuilderContext host,
|
|
ILoggerFactory logger)
|
|
{
|
|
HostServiceProvider hostProvider = new(host.HostingEnvironment, host.Configuration, logger);
|
|
PluginManager plugins = new(
|
|
hostProvider,
|
|
Options.Create(host.Configuration.GetSection(BasicOptions.Path).Get<BasicOptions>()),
|
|
logger.CreateLogger<PluginManager>()
|
|
);
|
|
return new PluginsStartup(plugins, host.Configuration);
|
|
}
|
|
|
|
/// <summary>
|
|
/// A simple host service provider used to activate plugins instance.
|
|
/// The same services as a generic host are available and an <see cref="ILoggerFactory"/> has been added.
|
|
/// </summary>
|
|
private class HostServiceProvider : IServiceProvider
|
|
{
|
|
/// <summary>
|
|
/// The host environment that could be used by plugins to configure themself.
|
|
/// </summary>
|
|
private readonly IWebHostEnvironment _hostEnvironment;
|
|
|
|
/// <summary>
|
|
/// The configuration context.
|
|
/// </summary>
|
|
private readonly IConfiguration _configuration;
|
|
|
|
/// <summary>
|
|
/// A logger factory used to create a logger for the plugin manager.
|
|
/// </summary>
|
|
private readonly ILoggerFactory _loggerFactory;
|
|
|
|
|
|
/// <summary>
|
|
/// Create a new <see cref="HostServiceProvider"/> that will return given services when asked.
|
|
/// </summary>
|
|
/// <param name="hostEnvironment">
|
|
/// The host environment that could be used by plugins to configure themself.
|
|
/// </param>
|
|
/// <param name="configuration">The configuration context</param>
|
|
/// <param name="loggerFactory">A logger factory used to create a logger for the plugin manager.</param>
|
|
public HostServiceProvider(IWebHostEnvironment hostEnvironment,
|
|
IConfiguration configuration,
|
|
ILoggerFactory loggerFactory)
|
|
{
|
|
_hostEnvironment = hostEnvironment;
|
|
_configuration = configuration;
|
|
_loggerFactory = loggerFactory;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public object GetService(Type serviceType)
|
|
{
|
|
if (serviceType == typeof(IWebHostEnvironment) || serviceType == typeof(IHostEnvironment))
|
|
return _hostEnvironment;
|
|
if (serviceType == typeof(IConfiguration))
|
|
return _configuration;
|
|
if (serviceType.GetGenericTypeDefinition() == typeof(ILogger<>))
|
|
{
|
|
return Utility.RunGenericMethod<object>(
|
|
typeof(LoggerFactoryExtensions),
|
|
nameof(LoggerFactoryExtensions.CreateLogger),
|
|
serviceType.GetGenericArguments().First(),
|
|
_loggerFactory
|
|
);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|