using BDInfo; using MediaBrowser.ClickOnce; using MediaBrowser.Common.Implementations; using MediaBrowser.Common.Implementations.ScheduledTasks; using MediaBrowser.Common.Implementations.Serialization; using MediaBrowser.Common.IO; using MediaBrowser.Common.Kernel; using MediaBrowser.Common.Net; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller; using MediaBrowser.IsoMounter; using MediaBrowser.Logging.Nlog; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.System; using MediaBrowser.Model.Updates; using MediaBrowser.Networking.HttpManager; using MediaBrowser.Networking.HttpServer; using MediaBrowser.Networking.Management; using MediaBrowser.Networking.Udp; using MediaBrowser.Networking.WebSocket; using MediaBrowser.Server.Implementations; using MediaBrowser.ServerApplication.Implementations; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.ServerApplication { /// /// Class CompositionRoot /// public class ApplicationHost : BaseApplicationHost, IApplicationHost { /// /// Gets or sets the log file path. /// /// The log file path. public string LogFilePath { get; private set; } /// /// Gets or sets the kernel. /// /// The kernel. internal Kernel Kernel { get; private set; } /// /// The json serializer /// private readonly IJsonSerializer _jsonSerializer = new JsonSerializer(); /// /// The _XML serializer /// private readonly IXmlSerializer _xmlSerializer = new XmlSerializer(); /// /// The _application paths /// private readonly IServerApplicationPaths _applicationPaths = new ServerApplicationPaths(); /// /// The _task manager /// private readonly ITaskManager _taskManager; /// /// The _task manager /// private readonly IHttpServer _httpServer; /// /// Gets a value indicating whether this instance is first run. /// /// true if this instance is first run; otherwise, false. public bool IsFirstRun { get; private set; } /// /// Initializes a new instance of the class. /// /// The logger. public ApplicationHost() : base() { IsFirstRun = !File.Exists(_applicationPaths.SystemConfigurationFilePath); Logger = new NLogger("App"); DiscoverTypes(); _taskManager = new TaskManager(_applicationPaths, _jsonSerializer, Logger); Kernel = new Kernel(this, _applicationPaths, _xmlSerializer, _taskManager, Logger); ReloadLogger(); Logger.Info("Version {0} initializing", ApplicationVersion); _httpServer = ServerFactory.CreateServer(this, ProtobufSerializer, Logger, "Media Browser", "index.html"); RegisterResources(); FindParts(); } /// /// Registers resources that classes will depend on /// private void RegisterResources() { RegisterSingleInstance(Kernel); RegisterSingleInstance(Kernel); RegisterSingleInstance(this); RegisterSingleInstance(Logger); RegisterSingleInstance(_applicationPaths); RegisterSingleInstance(_applicationPaths); RegisterSingleInstance(_taskManager); RegisterSingleInstance(new PismoIsoManager(Logger)); RegisterSingleInstance(new BdInfoExaminer()); RegisterSingleInstance(new HttpManager(_applicationPaths, Logger)); RegisterSingleInstance(new NetworkManager()); RegisterSingleInstance(new DotNetZipClient()); RegisterSingleInstance(() => new AlchemyServer(Logger)); RegisterSingleInstance(_jsonSerializer); RegisterSingleInstance(_xmlSerializer); RegisterSingleInstance(ProtobufSerializer); RegisterSingleInstance(new UdpServer()); RegisterSingleInstance(_httpServer); } /// /// Finds the parts. /// private void FindParts() { _taskManager.AddTasks(GetExports(false)); _httpServer.Init(GetExports(false)); } /// /// Restarts this instance. /// /// public void Restart() { App.Instance.Restart(); } /// /// Reloads the logger. /// /// public void ReloadLogger() { LogFilePath = Path.Combine(_applicationPaths.LogDirectoryPath, "Server-" + DateTime.Now.Ticks + ".log"); NlogManager.AddFileTarget(LogFilePath, Kernel.Configuration.EnableDebugLevelLogging); } /// /// Gets or sets a value indicating whether this instance can self update. /// /// true if this instance can self update; otherwise, false. public bool CanSelfUpdate { get { return ClickOnceHelper.IsNetworkDeployed; } } /// /// Checks for update. /// /// The cancellation token. /// The progress. /// Task{CheckForUpdateResult}. public Task CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress progress) { return new ApplicationUpdateCheck().CheckForApplicationUpdate(cancellationToken, progress); } /// /// Updates the application. /// /// The cancellation token. /// The progress. /// Task. public Task UpdateApplication(CancellationToken cancellationToken, IProgress progress) { return new ApplicationUpdater().UpdateApplication(cancellationToken, progress); } /// /// Gets the composable part assemblies. /// /// IEnumerable{Assembly}. protected override IEnumerable GetComposablePartAssemblies() { // Gets all plugin assemblies by first reading all bytes of the .dll and calling Assembly.Load against that // This will prevent the .dll file from getting locked, and allow us to replace it when needed foreach (var pluginAssembly in Directory .EnumerateFiles(_applicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly) .Select(LoadAssembly).Where(a => a != null)) { yield return pluginAssembly; } var runningDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName); var corePluginDirectory = Path.Combine(runningDirectory, "CorePlugins"); // This will prevent the .dll file from getting locked, and allow us to replace it when needed foreach (var pluginAssembly in Directory .EnumerateFiles(corePluginDirectory, "*.dll", SearchOption.TopDirectoryOnly) .Select(LoadAssembly).Where(a => a != null)) { yield return pluginAssembly; } // Include composable parts in the Model assembly yield return typeof(SystemInfo).Assembly; // Include composable parts in the Common assembly yield return typeof(IKernel).Assembly; // Include composable parts in the Controller assembly yield return typeof(Kernel).Assembly; // Common implementations yield return typeof(TaskManager).Assembly; // Server implementations yield return typeof(ServerApplicationPaths).Assembly; // Include composable parts in the running assembly yield return GetType().Assembly; } } }