2014-04-30 11:07:02 -04:00
using MediaBrowser.Common.Configuration ;
2013-03-07 00:34:00 -05:00
using MediaBrowser.Common.Events ;
2013-09-24 20:54:51 -04:00
using MediaBrowser.Common.Implementations.Archiving ;
2014-09-06 13:46:09 -04:00
using MediaBrowser.Common.Implementations.Devices ;
2013-09-30 18:18:44 -04:00
using MediaBrowser.Common.Implementations.IO ;
2013-03-04 00:43:06 -05:00
using MediaBrowser.Common.Implementations.ScheduledTasks ;
using MediaBrowser.Common.Implementations.Security ;
using MediaBrowser.Common.Implementations.Serialization ;
2013-02-27 12:07:12 -05:00
using MediaBrowser.Common.Implementations.Updates ;
2013-10-31 10:03:23 -04:00
using MediaBrowser.Common.IO ;
2013-02-27 11:46:48 -05:00
using MediaBrowser.Common.Net ;
2013-03-02 21:47:04 -05:00
using MediaBrowser.Common.Plugins ;
2013-12-13 10:48:35 -05:00
using MediaBrowser.Common.Progress ;
2013-02-27 11:46:48 -05:00
using MediaBrowser.Common.ScheduledTasks ;
2013-03-04 00:43:06 -05:00
using MediaBrowser.Common.Security ;
2013-02-27 09:39:11 -05:00
using MediaBrowser.Common.Updates ;
2014-05-08 16:09:53 -04:00
using MediaBrowser.Model.Events ;
2013-09-24 20:54:51 -04:00
using MediaBrowser.Model.IO ;
2013-02-25 22:43:04 -05:00
using MediaBrowser.Model.Logging ;
using MediaBrowser.Model.Serialization ;
2013-03-04 00:43:06 -05:00
using MediaBrowser.Model.Updates ;
2013-12-07 20:42:15 -05:00
using ServiceStack ;
2013-02-25 22:43:04 -05:00
using SimpleInjector ;
using System ;
using System.Collections.Generic ;
2013-02-26 23:19:05 -05:00
using System.IO ;
using System.Linq ;
2013-10-31 10:03:23 -04:00
using System.Net ;
2013-02-26 23:19:05 -05:00
using System.Reflection ;
2014-04-30 11:07:02 -04:00
using System.Text ;
2013-02-25 22:43:04 -05:00
using System.Threading ;
2013-03-04 00:43:06 -05:00
using System.Threading.Tasks ;
2013-02-25 22:43:04 -05:00
namespace MediaBrowser.Common.Implementations
{
2013-03-10 01:45:16 -05:00
/// <summary>
/// Class BaseApplicationHost
/// </summary>
/// <typeparam name="TApplicationPathsType">The type of the T application paths type.</typeparam>
2014-02-06 16:18:40 -05:00
public abstract class BaseApplicationHost < TApplicationPathsType > : IApplicationHost , IDependencyContainer
2013-12-04 09:52:38 -05:00
where TApplicationPathsType : class , IApplicationPaths
2013-02-25 22:43:04 -05:00
{
2013-03-07 00:34:00 -05:00
/// <summary>
/// Occurs when [has pending restart changed].
/// </summary>
public event EventHandler HasPendingRestartChanged ;
/// <summary>
/// Occurs when [application updated].
/// </summary>
2014-04-30 11:07:02 -04:00
public event EventHandler < GenericEventArgs < PackageVersionInfo > > ApplicationUpdated ;
2013-03-07 00:34:00 -05:00
/// <summary>
/// Gets or sets a value indicating whether this instance has changes that require the entire application to restart.
/// </summary>
/// <value><c>true</c> if this instance has pending application restart; otherwise, <c>false</c>.</value>
public bool HasPendingRestart { get ; private set ; }
2013-02-25 22:43:04 -05:00
/// <summary>
/// Gets or sets the logger.
/// </summary>
/// <value>The logger.</value>
2013-03-04 00:43:06 -05:00
protected ILogger Logger { get ; private set ; }
2013-02-25 22:43:04 -05:00
2013-03-02 21:47:04 -05:00
/// <summary>
/// Gets or sets the plugins.
/// </summary>
/// <value>The plugins.</value>
public IEnumerable < IPlugin > Plugins { get ; protected set ; }
2013-02-26 12:21:18 -05:00
/// <summary>
/// Gets or sets the log manager.
/// </summary>
/// <value>The log manager.</value>
public ILogManager LogManager { get ; protected set ; }
/// <summary>
/// Gets the application paths.
/// </summary>
/// <value>The application paths.</value>
2013-09-20 21:04:14 -04:00
protected TApplicationPathsType ApplicationPaths { get ; private set ; }
2013-02-26 12:21:18 -05:00
2013-02-25 22:43:04 -05:00
/// <summary>
/// The container
/// </summary>
protected readonly Container Container = new Container ( ) ;
2013-03-03 02:27:40 -05:00
2013-03-04 00:43:06 -05:00
/// <summary>
/// The json serializer
/// </summary>
2013-12-04 09:52:38 -05:00
public IJsonSerializer JsonSerializer { get ; private set ; }
2013-03-04 00:43:06 -05:00
/// <summary>
/// The _XML serializer
/// </summary>
protected readonly IXmlSerializer XmlSerializer = new XmlSerializer ( ) ;
2013-02-25 22:43:04 -05:00
/// <summary>
/// Gets assemblies that failed to load
/// </summary>
2013-03-10 01:45:16 -05:00
/// <value>The failed assemblies.</value>
2013-02-25 22:43:04 -05:00
public List < string > FailedAssemblies { get ; protected set ; }
/// <summary>
/// Gets all types within all running assemblies
/// </summary>
/// <value>All types.</value>
public Type [ ] AllTypes { get ; protected set ; }
/// <summary>
/// Gets all concrete types.
/// </summary>
/// <value>All concrete types.</value>
public Type [ ] AllConcreteTypes { get ; protected set ; }
/// <summary>
/// The disposable parts
/// </summary>
protected readonly List < IDisposable > DisposableParts = new List < IDisposable > ( ) ;
2013-02-26 12:21:18 -05:00
/// <summary>
/// Gets a value indicating whether this instance is first run.
/// </summary>
/// <value><c>true</c> if this instance is first run; otherwise, <c>false</c>.</value>
public bool IsFirstRun { get ; private set ; }
2013-03-04 00:43:06 -05:00
/// <summary>
/// Gets the kernel.
/// </summary>
/// <value>The kernel.</value>
protected ITaskManager TaskManager { get ; private set ; }
2013-03-10 01:45:16 -05:00
/// <summary>
/// Gets the security manager.
/// </summary>
/// <value>The security manager.</value>
2013-03-04 00:43:06 -05:00
protected ISecurityManager SecurityManager { get ; private set ; }
2013-03-10 01:45:16 -05:00
/// <summary>
/// Gets the HTTP client.
/// </summary>
/// <value>The HTTP client.</value>
2013-03-04 23:25:27 -05:00
protected IHttpClient HttpClient { get ; private set ; }
2013-03-10 01:45:16 -05:00
/// <summary>
/// Gets the network manager.
/// </summary>
/// <value>The network manager.</value>
2013-03-07 00:34:00 -05:00
protected INetworkManager NetworkManager { get ; private set ; }
2013-03-04 00:43:06 -05:00
2013-03-10 01:45:16 -05:00
/// <summary>
/// Gets the configuration manager.
/// </summary>
/// <value>The configuration manager.</value>
2013-03-04 00:43:06 -05:00
protected IConfigurationManager ConfigurationManager { get ; private set ; }
2013-06-30 22:27:50 -04:00
/// <summary>
/// Gets or sets the installation manager.
/// </summary>
/// <value>The installation manager.</value>
2013-10-31 10:03:23 -04:00
protected IInstallationManager InstallationManager { get ; private set ; }
2013-09-13 21:56:03 -04:00
2013-10-31 10:03:23 -04:00
protected IFileSystem FileSystemManager { get ; private set ; }
2013-12-04 09:52:38 -05:00
2013-09-24 20:54:51 -04:00
/// <summary>
/// Gets or sets the zip client.
/// </summary>
/// <value>The zip client.</value>
2013-10-31 10:03:23 -04:00
protected IZipClient ZipClient { get ; private set ; }
2013-09-30 18:18:44 -04:00
2013-10-31 10:03:23 -04:00
protected IIsoManager IsoManager { get ; private set ; }
2013-10-02 12:20:11 -04:00
2014-01-25 16:07:19 -05:00
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public abstract string Name { get ; }
2014-01-29 19:22:59 -05:00
/// <summary>
/// Gets a value indicating whether this instance is running as service.
/// </summary>
/// <value><c>true</c> if this instance is running as service; otherwise, <c>false</c>.</value>
public abstract bool IsRunningAsService { get ; }
2014-02-15 11:36:09 -05:00
2014-09-06 13:46:09 -04:00
private DeviceId _deviceId ;
public string SystemId
{
get
{
if ( _deviceId = = null )
{
2015-01-05 22:25:23 -05:00
_deviceId = new DeviceId ( ApplicationPaths , LogManager . GetLogger ( "SystemId" ) ) ;
2014-09-06 13:46:09 -04:00
}
return _deviceId . Value ;
}
}
2014-11-23 18:10:41 -05:00
public virtual string OperatingSystemDisplayName
{
get { return Environment . OSVersion . VersionString ; }
}
2013-02-25 22:43:04 -05:00
/// <summary>
2013-04-10 11:45:15 -04:00
/// Initializes a new instance of the <see cref="BaseApplicationHost{TApplicationPathsType}"/> class.
2013-02-25 22:43:04 -05:00
/// </summary>
2014-10-06 19:58:46 -04:00
protected BaseApplicationHost ( TApplicationPathsType applicationPaths ,
ILogManager logManager ,
IFileSystem fileSystem )
2013-02-25 22:43:04 -05:00
{
FailedAssemblies = new List < string > ( ) ;
2013-03-04 00:43:06 -05:00
2013-09-20 21:04:14 -04:00
ApplicationPaths = applicationPaths ;
LogManager = logManager ;
2014-10-06 19:58:46 -04:00
FileSystemManager = fileSystem ;
2013-03-04 00:43:06 -05:00
ConfigurationManager = GetConfigurationManager ( ) ;
2014-11-23 15:08:52 -05:00
// Initialize this early in case the -v command line option is used
Logger = LogManager . GetLogger ( "App" ) ;
2013-03-03 02:27:40 -05:00
}
2013-02-26 12:21:18 -05:00
2013-03-03 02:27:40 -05:00
/// <summary>
/// Inits this instance.
/// </summary>
/// <returns>Task.</returns>
2013-12-13 10:48:35 -05:00
public virtual async Task Init ( IProgress < double > progress )
2013-03-03 02:27:40 -05:00
{
2013-12-09 12:52:00 -05:00
try
{
// https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Web.config#L4
Licensing . RegisterLicense ( "1001-e1JlZjoxMDAxLE5hbWU6VGVzdCBCdXNpbmVzcyxUeXBlOkJ1c2luZXNzLEhhc2g6UHVNTVRPclhvT2ZIbjQ5MG5LZE1mUTd5RUMzQnBucTFEbTE3TDczVEF4QUNMT1FhNXJMOWkzVjFGL2ZkVTE3Q2pDNENqTkQyUktRWmhvUVBhYTBiekJGUUZ3ZE5aZHFDYm9hL3lydGlwUHI5K1JsaTBYbzNsUC85cjVJNHE5QVhldDN6QkE4aTlvdldrdTgyTk1relY2eis2dFFqTThYN2lmc0JveHgycFdjPSxFeHBpcnk6MjAxMy0wMS0wMX0=" ) ;
}
catch
{
// Failing under mono
}
2013-12-13 10:48:35 -05:00
progress . Report ( 1 ) ;
2013-12-09 12:52:00 -05:00
2013-12-04 09:52:38 -05:00
JsonSerializer = CreateJsonSerializer ( ) ;
2014-07-20 00:46:29 -04:00
OnLoggerLoaded ( true ) ;
LogManager . LoggerLoaded + = ( s , e ) = > OnLoggerLoaded ( false ) ;
2014-01-08 15:29:09 -05:00
2013-03-04 13:13:47 -05:00
IsFirstRun = ! ConfigurationManager . CommonConfiguration . IsStartupWizardCompleted ;
2013-12-13 10:48:35 -05:00
progress . Report ( 2 ) ;
2013-02-26 12:21:18 -05:00
2013-09-20 21:04:14 -04:00
LogManager . LogSeverity = ConfigurationManager . CommonConfiguration . EnableDebugLevelLogging
? LogSeverity . Debug
: LogSeverity . Info ;
2014-01-08 15:29:09 -05:00
2013-12-13 10:48:35 -05:00
progress . Report ( 3 ) ;
2013-03-04 00:43:06 -05:00
2013-03-05 18:11:32 -05:00
DiscoverTypes ( ) ;
2013-12-13 10:48:35 -05:00
progress . Report ( 14 ) ;
2013-03-05 18:11:32 -05:00
2013-10-05 21:38:36 -04:00
SetHttpLimit ( ) ;
2013-12-13 10:48:35 -05:00
progress . Report ( 15 ) ;
var innerProgress = new ActionableProgress < double > ( ) ;
innerProgress . RegisterAction ( p = > progress . Report ( ( . 8 * p ) + 15 ) ) ;
2013-10-05 21:38:36 -04:00
2013-12-13 10:48:35 -05:00
await RegisterResources ( innerProgress ) . ConfigureAwait ( false ) ;
2013-03-04 00:43:06 -05:00
2013-03-04 13:13:47 -05:00
FindParts ( ) ;
2013-12-13 10:48:35 -05:00
progress . Report ( 95 ) ;
2013-09-30 18:18:44 -04:00
await InstallIsoMounters ( CancellationToken . None ) . ConfigureAwait ( false ) ;
2013-09-13 21:56:03 -04:00
2013-12-13 10:48:35 -05:00
progress . Report ( 100 ) ;
2013-04-08 12:45:40 -04:00
}
2014-07-20 00:46:29 -04:00
protected virtual void OnLoggerLoaded ( bool isFirstLoad )
{
Logger . Info ( "Application version: {0}" , ApplicationVersion ) ;
if ( ! isFirstLoad )
{
2014-11-14 01:27:10 -05:00
LogEnvironmentInfo ( Logger , ApplicationPaths , false ) ;
2014-07-20 00:46:29 -04:00
}
// Put the app config in the log for troubleshooting purposes
Logger . LogMultiline ( "Application configuration:" , LogSeverity . Info , new StringBuilder ( JsonSerializer . SerializeToString ( ConfigurationManager . CommonConfiguration ) ) ) ;
if ( Plugins ! = null )
{
var pluginBuilder = new StringBuilder ( ) ;
foreach ( var plugin in Plugins )
{
pluginBuilder . AppendLine ( string . Format ( "{0} {1}" , plugin . Name , plugin . Version ) ) ;
}
Logger . LogMultiline ( "Plugins:" , LogSeverity . Info , pluginBuilder ) ;
}
}
2014-11-14 01:27:10 -05:00
public static void LogEnvironmentInfo ( ILogger logger , IApplicationPaths appPaths , bool isStartup )
2014-07-20 00:46:29 -04:00
{
2014-12-17 17:39:17 -05:00
logger . LogMultiline ( "Media Browser" , LogSeverity . Info , GetBaseExceptionMessage ( appPaths ) ) ;
}
2014-11-14 01:27:10 -05:00
2014-12-17 17:39:17 -05:00
protected static StringBuilder GetBaseExceptionMessage ( IApplicationPaths appPaths )
{
var builder = new StringBuilder ( ) ;
2014-07-20 00:46:29 -04:00
2014-12-17 17:39:17 -05:00
builder . AppendLine ( string . Format ( "Command line: {0}" , string . Join ( " " , Environment . GetCommandLineArgs ( ) ) ) ) ;
builder . AppendLine ( string . Format ( "Operating system: {0}" , Environment . OSVersion ) ) ;
builder . AppendLine ( string . Format ( "Processor count: {0}" , Environment . ProcessorCount ) ) ;
builder . AppendLine ( string . Format ( "64-Bit OS: {0}" , Environment . Is64BitOperatingSystem ) ) ;
builder . AppendLine ( string . Format ( "64-Bit Process: {0}" , Environment . Is64BitProcess ) ) ;
builder . AppendLine ( string . Format ( "Program data path: {0}" , appPaths . ProgramDataPath ) ) ;
2014-07-20 00:46:29 -04:00
2014-10-20 23:41:11 -04:00
Type type = Type . GetType ( "Mono.Runtime" ) ;
if ( type ! = null )
{
MethodInfo displayName = type . GetMethod ( "GetDisplayName" , BindingFlags . NonPublic | BindingFlags . Static ) ;
if ( displayName ! = null )
{
2014-12-17 17:39:17 -05:00
builder . AppendLine ( "Mono: " + displayName . Invoke ( null , null ) ) ;
2014-10-20 23:41:11 -04:00
}
2014-12-17 17:39:17 -05:00
}
builder . AppendLine ( string . Format ( "Application Path: {0}" , appPaths . ApplicationPath ) ) ;
2014-07-20 00:46:29 -04:00
2014-12-17 17:39:17 -05:00
return builder ;
2014-07-20 00:46:29 -04:00
}
2013-12-04 09:52:38 -05:00
protected virtual IJsonSerializer CreateJsonSerializer ( )
{
return new JsonSerializer ( ) ;
}
2013-10-05 21:38:36 -04:00
private void SetHttpLimit ( )
{
try
{
2013-10-05 23:03:08 -04:00
// Increase the max http request limit
2013-11-29 11:58:24 -05:00
ServicePointManager . DefaultConnectionLimit = Math . Max ( 96 , ServicePointManager . DefaultConnectionLimit ) ;
2013-10-05 21:38:36 -04:00
}
catch ( Exception ex )
{
Logger . ErrorException ( "Error setting http limit" , ex ) ;
}
}
2013-12-04 09:52:38 -05:00
2013-09-30 18:18:44 -04:00
/// <summary>
/// Installs the iso mounters.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private async Task InstallIsoMounters ( CancellationToken cancellationToken )
{
var list = new List < IIsoMounter > ( ) ;
foreach ( var isoMounter in GetExports < IIsoMounter > ( ) )
{
try
{
if ( isoMounter . RequiresInstallation & & ! isoMounter . IsInstalled )
{
Logger . Info ( "Installing {0}" , isoMounter . Name ) ;
await isoMounter . Install ( cancellationToken ) . ConfigureAwait ( false ) ;
}
list . Add ( isoMounter ) ;
}
catch ( Exception ex )
{
Logger . ErrorException ( "{0} failed to load." , ex , isoMounter . Name ) ;
}
}
IsoManager . AddParts ( list ) ;
}
2013-03-10 01:45:16 -05:00
/// <summary>
/// Runs the startup tasks.
/// </summary>
/// <returns>Task.</returns>
2013-10-02 12:20:11 -04:00
public virtual Task RunStartupTasks ( )
2013-03-10 01:45:16 -05:00
{
2014-11-26 22:10:44 -05:00
Resolve < ITaskManager > ( ) . AddTasks ( GetExports < IScheduledTask > ( false ) ) ;
ConfigureAutorun ( ) ;
2013-03-10 01:45:16 -05:00
2014-11-26 22:10:44 -05:00
ConfigurationManager . ConfigurationUpdated + = OnConfigurationUpdated ;
2013-03-13 18:33:09 -04:00
2014-11-26 22:10:44 -05:00
return Task . FromResult ( true ) ;
2013-02-25 22:43:04 -05:00
}
2013-09-24 20:54:51 -04:00
/// <summary>
/// Configures the autorun.
/// </summary>
private void ConfigureAutorun ( )
{
try
{
ConfigureAutoRunAtStartup ( ConfigurationManager . CommonConfiguration . RunAtStartup ) ;
}
catch ( Exception ex )
{
Logger . ErrorException ( "Error configuring autorun" , ex ) ;
}
}
2013-02-25 22:43:04 -05:00
/// <summary>
/// Gets the composable part assemblies.
/// </summary>
/// <returns>IEnumerable{Assembly}.</returns>
protected abstract IEnumerable < Assembly > GetComposablePartAssemblies ( ) ;
2013-03-10 01:45:16 -05:00
/// <summary>
/// Gets the configuration manager.
/// </summary>
/// <returns>IConfigurationManager.</returns>
2013-03-04 00:43:06 -05:00
protected abstract IConfigurationManager GetConfigurationManager ( ) ;
2013-02-27 11:46:48 -05:00
/// <summary>
/// Finds the parts.
/// </summary>
protected virtual void FindParts ( )
{
2014-06-29 13:35:05 -04:00
ConfigurationManager . AddParts ( GetExports < IConfigurationFactory > ( ) ) ;
2013-03-02 21:47:04 -05:00
Plugins = GetExports < IPlugin > ( ) ;
2013-02-27 11:46:48 -05:00
}
2013-03-03 02:27:40 -05:00
2013-02-25 22:43:04 -05:00
/// <summary>
/// Discovers the types.
/// </summary>
protected void DiscoverTypes ( )
{
FailedAssemblies . Clear ( ) ;
2013-09-19 20:53:18 -04:00
var assemblies = GetComposablePartAssemblies ( ) . ToList ( ) ;
2013-03-05 18:11:32 -05:00
2013-04-08 17:05:00 -04:00
foreach ( var assembly in assemblies )
{
Logger . Info ( "Loading {0}" , assembly . FullName ) ;
}
2013-03-05 18:11:32 -05:00
AllTypes = assemblies . SelectMany ( GetTypes ) . ToArray ( ) ;
2013-02-25 22:43:04 -05:00
AllConcreteTypes = AllTypes . Where ( t = > t . IsClass & & ! t . IsAbstract & & ! t . IsInterface & & ! t . IsGenericType ) . ToArray ( ) ;
}
2013-02-27 11:46:48 -05:00
/// <summary>
/// Registers resources that classes will depend on
/// </summary>
2013-03-10 01:45:16 -05:00
/// <returns>Task.</returns>
2013-12-13 10:48:35 -05:00
protected virtual Task RegisterResources ( IProgress < double > progress )
2013-02-27 11:46:48 -05:00
{
2014-11-28 12:40:20 -05:00
RegisterSingleInstance ( ConfigurationManager ) ;
RegisterSingleInstance < IApplicationHost > ( this ) ;
2013-03-04 00:43:06 -05:00
2014-11-28 12:40:20 -05:00
RegisterSingleInstance < IApplicationPaths > ( ApplicationPaths ) ;
2013-03-04 00:43:06 -05:00
2014-11-28 12:40:20 -05:00
TaskManager = new TaskManager ( ApplicationPaths , JsonSerializer , Logger ) ;
2013-03-04 00:43:06 -05:00
2014-11-28 12:40:20 -05:00
RegisterSingleInstance ( JsonSerializer ) ;
RegisterSingleInstance ( XmlSerializer ) ;
2013-03-04 00:43:06 -05:00
2014-11-28 12:40:20 -05:00
RegisterSingleInstance ( LogManager ) ;
RegisterSingleInstance ( Logger ) ;
2013-02-27 11:46:48 -05:00
2014-11-28 12:40:20 -05:00
RegisterSingleInstance ( TaskManager ) ;
2013-02-27 11:46:48 -05:00
2014-11-28 12:40:20 -05:00
RegisterSingleInstance ( FileSystemManager ) ;
2013-10-31 10:03:23 -04:00
2014-12-30 11:36:49 -05:00
HttpClient = new HttpClientManager . HttpClientManager ( ApplicationPaths , Logger , FileSystemManager ) ;
2014-11-28 12:40:20 -05:00
RegisterSingleInstance ( HttpClient ) ;
2013-03-04 00:43:06 -05:00
2014-11-28 12:40:20 -05:00
NetworkManager = CreateNetworkManager ( LogManager . GetLogger ( "NetworkManager" ) ) ;
RegisterSingleInstance ( NetworkManager ) ;
2013-03-07 00:34:00 -05:00
2015-01-10 14:42:14 -05:00
SecurityManager = new PluginSecurityManager ( this , HttpClient , JsonSerializer , ApplicationPaths , LogManager ) ;
2014-11-28 12:40:20 -05:00
RegisterSingleInstance ( SecurityManager ) ;
2013-03-04 00:43:06 -05:00
2015-01-12 22:46:44 -05:00
InstallationManager = new InstallationManager ( Logger , this , ApplicationPaths , HttpClient , JsonSerializer , SecurityManager , ConfigurationManager , FileSystemManager ) ;
2014-11-28 12:40:20 -05:00
RegisterSingleInstance ( InstallationManager ) ;
2013-09-24 20:54:51 -04:00
2014-11-28 12:40:20 -05:00
ZipClient = new ZipClient ( ) ;
RegisterSingleInstance ( ZipClient ) ;
2013-09-30 18:18:44 -04:00
2014-11-28 12:40:20 -05:00
IsoManager = new IsoManager ( ) ;
RegisterSingleInstance ( IsoManager ) ;
2014-02-06 16:18:40 -05:00
2014-11-28 12:40:20 -05:00
RegisterModules ( ) ;
return Task . FromResult ( true ) ;
2013-02-27 11:46:48 -05:00
}
2013-03-03 02:27:40 -05:00
2014-02-06 16:18:40 -05:00
private void RegisterModules ( )
{
var moduleTypes = GetExportTypes < IDependencyModule > ( ) ;
foreach ( var type in moduleTypes )
{
try
{
var instance = Activator . CreateInstance ( type ) as IDependencyModule ;
if ( instance ! = null )
instance . BindDependencies ( this ) ;
}
catch ( Exception ex )
{
Logger . ErrorException ( "Error setting up dependency bindings for " + type . Name , ex ) ;
}
}
}
2013-02-25 22:43:04 -05:00
/// <summary>
/// Gets a list of types within an assembly
/// This will handle situations that would normally throw an exception - such as a type within the assembly that depends on some other non-existant reference
/// </summary>
/// <param name="assembly">The assembly.</param>
/// <returns>IEnumerable{Type}.</returns>
/// <exception cref="System.ArgumentNullException">assembly</exception>
protected IEnumerable < Type > GetTypes ( Assembly assembly )
{
if ( assembly = = null )
{
throw new ArgumentNullException ( "assembly" ) ;
}
try
{
return assembly . GetTypes ( ) ;
}
catch ( ReflectionTypeLoadException ex )
{
// If it fails we can still get a list of the Types it was able to resolve
return ex . Types . Where ( t = > t ! = null ) ;
}
}
2014-08-19 18:28:35 -04:00
protected abstract INetworkManager CreateNetworkManager ( ILogger logger ) ;
2013-10-05 13:13:32 -04:00
2013-02-25 22:43:04 -05:00
/// <summary>
/// Creates an instance of type and resolves all constructor dependancies
/// </summary>
/// <param name="type">The type.</param>
/// <returns>System.Object.</returns>
2013-10-03 10:14:40 -04:00
public object CreateInstance ( Type type )
2013-02-25 22:43:04 -05:00
{
try
{
return Container . GetInstance ( type ) ;
}
2013-04-23 17:05:21 -04:00
catch ( Exception ex )
2013-02-25 22:43:04 -05:00
{
2013-04-23 17:05:21 -04:00
Logger . Error ( "Error creating {0}" , ex , type . Name ) ;
2013-02-25 22:43:04 -05:00
throw ;
}
}
2013-10-02 12:20:11 -04:00
/// <summary>
/// Creates the instance safe.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>System.Object.</returns>
protected object CreateInstanceSafe ( Type type )
{
try
{
return Container . GetInstance ( type ) ;
}
catch ( Exception ex )
{
Logger . Error ( "Error creating {0}" , ex , type . Name ) ;
2013-10-02 15:08:58 -04:00
// Don't blow up in release mode
2013-10-02 12:20:11 -04:00
return null ;
}
}
2014-02-06 16:18:40 -05:00
void IDependencyContainer . RegisterSingleInstance < T > ( T obj , bool manageLifetime )
{
RegisterSingleInstance ( obj , manageLifetime ) ;
}
2013-02-25 22:43:04 -05:00
/// <summary>
/// Registers the specified obj.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj">The obj.</param>
2013-02-26 11:10:55 -05:00
/// <param name="manageLifetime">if set to <c>true</c> [manage lifetime].</param>
protected void RegisterSingleInstance < T > ( T obj , bool manageLifetime = true )
2013-02-25 22:43:04 -05:00
where T : class
{
Container . RegisterSingle ( obj ) ;
2013-02-26 11:10:55 -05:00
if ( manageLifetime )
{
var disposable = obj as IDisposable ;
if ( disposable ! = null )
{
DisposableParts . Add ( disposable ) ;
}
}
2013-02-25 22:43:04 -05:00
}
2014-02-06 16:18:40 -05:00
void IDependencyContainer . RegisterSingleInstance < T > ( Func < T > func )
{
RegisterSingleInstance ( func ) ;
}
2013-02-25 22:43:04 -05:00
/// <summary>
/// Registers the single instance.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="func">The func.</param>
protected void RegisterSingleInstance < T > ( Func < T > func )
where T : class
{
Container . RegisterSingle ( func ) ;
}
2014-02-06 16:18:40 -05:00
void IDependencyContainer . Register ( Type typeInterface , Type typeImplementation )
{
Container . Register ( typeInterface , typeImplementation ) ;
}
2014-02-15 11:36:09 -05:00
2013-02-25 22:43:04 -05:00
/// <summary>
/// Resolves this instance.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>``0.</returns>
public T Resolve < T > ( )
{
return ( T ) Container . GetRegistration ( typeof ( T ) , true ) . GetInstance ( ) ;
}
/// <summary>
/// Resolves this instance.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>``0.</returns>
public T TryResolve < T > ( )
{
var result = Container . GetRegistration ( typeof ( T ) , false ) ;
if ( result = = null )
{
return default ( T ) ;
}
return ( T ) result . GetInstance ( ) ;
}
/// <summary>
/// Loads the assembly.
/// </summary>
/// <param name="file">The file.</param>
/// <returns>Assembly.</returns>
protected Assembly LoadAssembly ( string file )
{
try
{
return Assembly . Load ( File . ReadAllBytes ( ( file ) ) ) ;
}
catch ( Exception ex )
{
FailedAssemblies . Add ( file ) ;
Logger . ErrorException ( "Error loading assembly {0}" , ex , file ) ;
return null ;
}
}
2013-06-20 12:44:24 -04:00
/// <summary>
/// Gets the export types.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>IEnumerable{Type}.</returns>
public IEnumerable < Type > GetExportTypes < T > ( )
{
var currentType = typeof ( T ) ;
return AllConcreteTypes . AsParallel ( ) . Where ( currentType . IsAssignableFrom ) ;
}
2013-02-25 22:43:04 -05:00
/// <summary>
/// Gets the exports.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="manageLiftime">if set to <c>true</c> [manage liftime].</param>
/// <returns>IEnumerable{``0}.</returns>
public IEnumerable < T > GetExports < T > ( bool manageLiftime = true )
{
2013-10-02 12:20:11 -04:00
var parts = GetExportTypes < T > ( )
. Select ( CreateInstanceSafe )
. Where ( i = > i ! = null )
. Cast < T > ( )
. ToList ( ) ;
2013-02-25 22:43:04 -05:00
if ( manageLiftime )
{
2013-03-14 21:40:38 -04:00
lock ( DisposableParts )
{
DisposableParts . AddRange ( parts . OfType < IDisposable > ( ) ) ;
}
2013-02-25 22:43:04 -05:00
}
return parts ;
}
/// <summary>
2014-11-14 01:27:10 -05:00
/// Gets the application version.
2013-02-25 22:43:04 -05:00
/// </summary>
/// <value>The application version.</value>
2014-11-14 01:27:10 -05:00
public abstract Version ApplicationVersion { get ; }
2013-02-25 22:43:04 -05:00
2013-03-13 18:33:09 -04:00
/// <summary>
/// Handles the ConfigurationUpdated event of the ConfigurationManager control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
/// <exception cref="System.NotImplementedException"></exception>
2013-05-07 15:07:51 -04:00
protected virtual void OnConfigurationUpdated ( object sender , EventArgs e )
2013-03-13 18:33:09 -04:00
{
2013-09-24 20:54:51 -04:00
ConfigureAutorun ( ) ;
2013-03-13 18:33:09 -04:00
}
2013-09-13 21:56:03 -04:00
2013-09-24 20:54:51 -04:00
protected abstract void ConfigureAutoRunAtStartup ( bool autorun ) ;
2013-02-27 16:07:51 -05:00
2013-03-02 21:47:04 -05:00
/// <summary>
/// Removes the plugin.
/// </summary>
/// <param name="plugin">The plugin.</param>
public void RemovePlugin ( IPlugin plugin )
{
var list = Plugins . ToList ( ) ;
list . Remove ( plugin ) ;
Plugins = list ;
}
2013-10-07 10:38:31 -04:00
/// <summary>
/// Gets a value indicating whether this instance can self restart.
/// </summary>
/// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value>
public abstract bool CanSelfRestart { get ; }
2013-03-07 00:34:00 -05:00
/// <summary>
/// Notifies that the kernel that a change has been made that requires a restart
/// </summary>
public void NotifyPendingRestart ( )
{
2014-06-07 15:46:24 -04:00
var changed = ! HasPendingRestart ;
2013-03-07 00:34:00 -05:00
HasPendingRestart = true ;
2014-06-07 15:46:24 -04:00
if ( changed )
{
EventHelper . QueueEventIfNotNull ( HasPendingRestartChanged , this , EventArgs . Empty , Logger ) ;
}
2013-03-07 00:34:00 -05:00
}
2013-02-25 22:43:04 -05:00
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose ( )
{
Dispose ( true ) ;
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose ( bool dispose )
{
2013-02-26 23:19:05 -05:00
if ( dispose )
{
var type = GetType ( ) ;
2013-02-26 11:10:55 -05:00
2013-02-26 23:19:05 -05:00
Logger . Info ( "Disposing " + type . Name ) ;
2013-02-26 11:10:55 -05:00
2013-02-26 23:19:05 -05:00
var parts = DisposableParts . Distinct ( ) . Where ( i = > i . GetType ( ) ! = type ) . ToList ( ) ;
DisposableParts . Clear ( ) ;
2013-02-26 11:10:55 -05:00
2013-02-26 23:19:05 -05:00
foreach ( var part in parts )
{
Logger . Info ( "Disposing " + part . GetType ( ) . Name ) ;
2013-02-25 22:43:04 -05:00
2014-02-15 11:36:09 -05:00
try
{
part . Dispose ( ) ;
}
catch ( Exception ex )
{
Logger . ErrorException ( "Error disposing {0}" , ex , part . GetType ( ) . Name ) ;
}
2013-02-26 23:19:05 -05:00
}
}
2013-02-25 22:43:04 -05:00
}
2013-03-04 00:43:06 -05:00
2013-03-10 01:45:16 -05:00
/// <summary>
/// Restarts this instance.
/// </summary>
2013-09-20 13:32:10 -04:00
public abstract Task Restart ( ) ;
2013-03-04 00:43:06 -05:00
2013-03-10 01:45:16 -05:00
/// <summary>
/// Gets or sets a value indicating whether this instance can self update.
/// </summary>
/// <value><c>true</c> if this instance can self update; otherwise, <c>false</c>.</value>
2013-03-04 00:43:06 -05:00
public abstract bool CanSelfUpdate { get ; }
2013-03-10 01:45:16 -05:00
/// <summary>
/// Checks for update.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="progress">The progress.</param>
/// <returns>Task{CheckForUpdateResult}.</returns>
2013-09-13 21:56:03 -04:00
public abstract Task < CheckForUpdateResult > CheckForApplicationUpdate ( CancellationToken cancellationToken ,
IProgress < double > progress ) ;
2013-08-16 14:43:11 -04:00
/// <summary>
2013-09-13 21:56:03 -04:00
/// Updates the application.
2013-08-16 14:43:11 -04:00
/// </summary>
2013-09-13 21:56:03 -04:00
/// <param name="package">The package that contains the update</param>
2013-08-16 14:43:11 -04:00
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="progress">The progress.</param>
2013-09-13 21:56:03 -04:00
/// <returns>Task.</returns>
public abstract Task UpdateApplication ( PackageVersionInfo package , CancellationToken cancellationToken ,
IProgress < double > progress ) ;
2013-08-16 14:43:11 -04:00
/// <summary>
2013-09-13 21:56:03 -04:00
/// Shuts down.
2013-08-16 14:43:11 -04:00
/// </summary>
2013-09-20 13:32:10 -04:00
public abstract Task Shutdown ( ) ;
2013-03-04 00:43:06 -05:00
2013-03-07 00:34:00 -05:00
/// <summary>
2013-09-13 21:56:03 -04:00
/// Called when [application updated].
2013-03-07 00:34:00 -05:00
/// </summary>
2014-04-30 11:07:02 -04:00
/// <param name="package">The package.</param>
protected void OnApplicationUpdated ( PackageVersionInfo package )
2013-03-07 00:34:00 -05:00
{
2014-04-30 11:07:02 -04:00
Logger . Info ( "Application has been updated to version {0}" , package . versionStr ) ;
2013-09-29 20:51:04 -04:00
2014-05-13 20:46:45 -04:00
EventHelper . FireEventIfNotNull ( ApplicationUpdated , this , new GenericEventArgs < PackageVersionInfo >
2014-04-30 11:07:02 -04:00
{
Argument = package
} , Logger ) ;
2013-03-11 15:36:32 -04:00
NotifyPendingRestart ( ) ;
2013-03-07 00:34:00 -05:00
}
2013-02-25 22:43:04 -05:00
}
}